diff options
Diffstat (limited to 'sound')
-rw-r--r-- | sound/core/jack.c | 9 | ||||
-rw-r--r-- | sound/pci/Kconfig | 124 | ||||
-rw-r--r-- | sound/pci/hda/Kconfig | 188 | ||||
-rw-r--r-- | sound/pci/hda/Makefile | 75 | ||||
-rw-r--r-- | sound/pci/hda/hda_beep.c | 2 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.c | 781 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 107 | ||||
-rw-r--r-- | sound/pci/hda/hda_eld.c | 590 | ||||
-rw-r--r-- | sound/pci/hda/hda_generic.c | 21 | ||||
-rw-r--r-- | sound/pci/hda/hda_hwdep.c | 234 | ||||
-rw-r--r-- | sound/pci/hda/hda_intel.c | 340 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 100 | ||||
-rw-r--r-- | sound/pci/hda/hda_patch.h | 22 | ||||
-rw-r--r-- | sound/pci/hda/hda_proc.c | 91 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 132 | ||||
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 40 | ||||
-rw-r--r-- | sound/pci/hda/patch_cmedia.c | 27 | ||||
-rw-r--r-- | sound/pci/hda/patch_conexant.c | 39 | ||||
-rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 711 | ||||
-rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 32 | ||||
-rw-r--r-- | sound/pci/hda/patch_realtek.c | 1663 | ||||
-rw-r--r-- | sound/pci/hda/patch_si3054.c | 35 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 1305 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 171 |
24 files changed, 4813 insertions, 2026 deletions
diff --git a/sound/core/jack.c b/sound/core/jack.c index bd2d9e6b55e..284432f427f 100644 --- a/sound/core/jack.c +++ b/sound/core/jack.c @@ -34,6 +34,7 @@ static int snd_jack_dev_free(struct snd_device *device) else input_free_device(jack->input_dev); + kfree(jack->id); kfree(jack); return 0; @@ -87,7 +88,7 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, if (jack == NULL) return -ENOMEM; - jack->id = id; + jack->id = kstrdup(id, GFP_KERNEL); jack->input_dev = input_allocate_device(); if (jack->input_dev == NULL) { @@ -102,6 +103,9 @@ int snd_jack_new(struct snd_card *card, const char *id, int type, if (type & SND_JACK_HEADPHONE) input_set_capability(jack->input_dev, EV_SW, SW_HEADPHONE_INSERT); + if (type & SND_JACK_LINEOUT) + input_set_capability(jack->input_dev, EV_SW, + SW_LINEOUT_INSERT); if (type & SND_JACK_MICROPHONE) input_set_capability(jack->input_dev, EV_SW, SW_MICROPHONE_INSERT); @@ -153,6 +157,9 @@ void snd_jack_report(struct snd_jack *jack, int status) if (jack->type & SND_JACK_HEADPHONE) input_report_switch(jack->input_dev, SW_HEADPHONE_INSERT, status & SND_JACK_HEADPHONE); + if (jack->type & SND_JACK_LINEOUT) + input_report_switch(jack->input_dev, SW_LINEOUT_INSERT, + status & SND_JACK_LINEOUT); if (jack->type & SND_JACK_MICROPHONE) input_report_switch(jack->input_dev, SW_MICROPHONE_INSERT, status & SND_JACK_MICROPHONE); diff --git a/sound/pci/Kconfig b/sound/pci/Kconfig index 7003711f4fc..caebf296b62 100644 --- a/sound/pci/Kconfig +++ b/sound/pci/Kconfig @@ -497,129 +497,7 @@ config SND_FM801_TEA575X depends on SND_FM801_TEA575X_BOOL default SND_FM801 -config SND_HDA_INTEL - tristate "Intel HD Audio" - select SND_PCM - select SND_VMASTER - help - Say Y here to include support for Intel "High Definition - Audio" (Azalia) motherboard devices. - - To compile this driver as a module, choose M here: the module - will be called snd-hda-intel. - -config SND_HDA_HWDEP - bool "Build hwdep interface for HD-audio driver" - depends on SND_HDA_INTEL - select SND_HWDEP - help - Say Y here to build a hwdep interface for HD-audio driver. - This interface can be used for out-of-band communication - with codecs for debugging purposes. - -config SND_HDA_INPUT_BEEP - bool "Support digital beep via input layer" - depends on SND_HDA_INTEL - depends on INPUT=y || INPUT=SND_HDA_INTEL - help - Say Y here to build a digital beep interface for HD-audio - driver. This interface is used to generate digital beeps. - -config SND_HDA_CODEC_REALTEK - bool "Build Realtek HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Realtek HD-audio codec support in - snd-hda-intel driver, such as ALC880. - -config SND_HDA_CODEC_ANALOG - bool "Build Analog Device HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Analog Device HD-audio codec support in - snd-hda-intel driver, such as AD1986A. - -config SND_HDA_CODEC_SIGMATEL - bool "Build IDT/Sigmatel HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include IDT (Sigmatel) HD-audio codec support in - snd-hda-intel driver, such as STAC9200. - -config SND_HDA_CODEC_VIA - bool "Build VIA HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include VIA HD-audio codec support in - snd-hda-intel driver, such as VT1708. - -config SND_HDA_CODEC_ATIHDMI - bool "Build ATI HDMI HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include ATI HDMI HD-audio codec support in - snd-hda-intel driver, such as ATI RS600 HDMI. - -config SND_HDA_CODEC_NVHDMI - bool "Build NVIDIA HDMI HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include NVIDIA HDMI HD-audio codec support in - snd-hda-intel driver, such as NVIDIA MCP78 HDMI. - -config SND_HDA_CODEC_CONEXANT - bool "Build Conexant HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Conexant HD-audio codec support in - snd-hda-intel driver, such as CX20549. - -config SND_HDA_CODEC_CMEDIA - bool "Build C-Media HD-audio codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include C-Media HD-audio codec support in - snd-hda-intel driver, such as CMI9880. - -config SND_HDA_CODEC_SI3054 - bool "Build Silicon Labs 3054 HD-modem codec support" - depends on SND_HDA_INTEL - default y - help - Say Y here to include Silicon Labs 3054 HD-modem codec - (and compatibles) support in snd-hda-intel driver. - -config SND_HDA_GENERIC - bool "Enable generic HD-audio codec parser" - depends on SND_HDA_INTEL - default y - help - Say Y here to enable the generic HD-audio codec parser - in snd-hda-intel driver. - -config SND_HDA_POWER_SAVE - bool "Aggressive power-saving on HD-audio" - depends on SND_HDA_INTEL && EXPERIMENTAL - help - Say Y here to enable more aggressive power-saving mode on - HD-audio driver. The power-saving timeout can be configured - via power_save option or over sysfs on-the-fly. - -config SND_HDA_POWER_SAVE_DEFAULT - int "Default time-out for HD-audio power-save mode" - depends on SND_HDA_POWER_SAVE - default 0 - help - The default time-out value in seconds for HD-audio automatic - power-save mode. 0 means to disable the power-save mode. +source "sound/pci/hda/Kconfig" config SND_HDSP tristate "RME Hammerfall DSP Audio" diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig new file mode 100644 index 00000000000..eb2a19b894a --- /dev/null +++ b/sound/pci/hda/Kconfig @@ -0,0 +1,188 @@ +menuconfig SND_HDA_INTEL + tristate "Intel HD Audio" + select SND_PCM + select SND_VMASTER + select SND_JACK if INPUT=y || INPUT=SND + help + Say Y here to include support for Intel "High Definition + Audio" (Azalia) and its compatible devices. + + This option enables the HD-audio controller. Don't forget + to choose the appropriate codec options below. + + To compile this driver as a module, choose M here: the module + will be called snd-hda-intel. + +if SND_HDA_INTEL + +config SND_HDA_HWDEP + bool "Build hwdep interface for HD-audio driver" + select SND_HWDEP + help + Say Y here to build a hwdep interface for HD-audio driver. + This interface can be used for out-of-band communication + with codecs for debugging purposes. + +config SND_HDA_RECONFIG + bool "Allow dynamic codec reconfiguration (EXPERIMENTAL)" + depends on SND_HDA_HWDEP && EXPERIMENTAL + help + Say Y here to enable the HD-audio codec re-configuration feature. + This adds the sysfs interfaces to allow user to clear the whole + codec configuration, change the codec setup, add extra verbs, + and re-configure the codec dynamically. + +config SND_HDA_INPUT_BEEP + bool "Support digital beep via input layer" + depends on INPUT=y || INPUT=SND_HDA_INTEL + help + Say Y here to build a digital beep interface for HD-audio + driver. This interface is used to generate digital beeps. + +config SND_HDA_CODEC_REALTEK + bool "Build Realtek HD-audio codec support" + default y + help + Say Y here to include Realtek HD-audio codec support in + snd-hda-intel driver, such as ALC880. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-realtek. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_ANALOG + bool "Build Analog Device HD-audio codec support" + default y + help + Say Y here to include Analog Device HD-audio codec support in + snd-hda-intel driver, such as AD1986A. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-analog. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_SIGMATEL + bool "Build IDT/Sigmatel HD-audio codec support" + default y + help + Say Y here to include IDT (Sigmatel) HD-audio codec support in + snd-hda-intel driver, such as STAC9200. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-idt. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_VIA + bool "Build VIA HD-audio codec support" + default y + help + Say Y here to include VIA HD-audio codec support in + snd-hda-intel driver, such as VT1708. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-via. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_ATIHDMI + bool "Build ATI HDMI HD-audio codec support" + default y + help + Say Y here to include ATI HDMI HD-audio codec support in + snd-hda-intel driver, such as ATI RS600 HDMI. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-atihdmi. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_NVHDMI + bool "Build NVIDIA HDMI HD-audio codec support" + default y + help + Say Y here to include NVIDIA HDMI HD-audio codec support in + snd-hda-intel driver, such as NVIDIA MCP78 HDMI. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-nvhdmi. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_INTELHDMI + bool "Build INTEL HDMI HD-audio codec support" + default y + help + Say Y here to include INTEL HDMI HD-audio codec support in + snd-hda-intel driver, such as Eaglelake integrated HDMI. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-intelhdmi. + This module is automatically loaded at probing. + +config SND_HDA_ELD + def_bool y + depends on SND_HDA_CODEC_INTELHDMI + +config SND_HDA_CODEC_CONEXANT + bool "Build Conexant HD-audio codec support" + default y + help + Say Y here to include Conexant HD-audio codec support in + snd-hda-intel driver, such as CX20549. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-conexant. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_CMEDIA + bool "Build C-Media HD-audio codec support" + default y + help + Say Y here to include C-Media HD-audio codec support in + snd-hda-intel driver, such as CMI9880. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-cmedia. + This module is automatically loaded at probing. + +config SND_HDA_CODEC_SI3054 + bool "Build Silicon Labs 3054 HD-modem codec support" + default y + help + Say Y here to include Silicon Labs 3054 HD-modem codec + (and compatibles) support in snd-hda-intel driver. + + When the HD-audio driver is built as a module, the codec + support code is also built as another module, + snd-hda-codec-si3054. + This module is automatically loaded at probing. + +config SND_HDA_GENERIC + bool "Enable generic HD-audio codec parser" + default y + help + Say Y here to enable the generic HD-audio codec parser + in snd-hda-intel driver. + +config SND_HDA_POWER_SAVE + bool "Aggressive power-saving on HD-audio" + help + Say Y here to enable more aggressive power-saving mode on + HD-audio driver. The power-saving timeout can be configured + via power_save option or over sysfs on-the-fly. + +config SND_HDA_POWER_SAVE_DEFAULT + int "Default time-out for HD-audio power-save mode" + depends on SND_HDA_POWER_SAVE + default 0 + help + The default time-out value in seconds for HD-audio automatic + power-save mode. 0 means to disable the power-save mode. + +endif diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 1980c6d207e..50f9d096725 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile @@ -1,20 +1,59 @@ -snd-hda-intel-y := hda_intel.o -# since snd-hda-intel is the only driver using hda-codec, -# merge it into a single module although it was originally -# designed to be individual modules -snd-hda-intel-y += hda_codec.o -snd-hda-intel-$(CONFIG_PROC_FS) += hda_proc.o -snd-hda-intel-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o -snd-hda-intel-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o -snd-hda-intel-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_REALTEK) += patch_realtek.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CMEDIA) += patch_cmedia.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ANALOG) += patch_analog.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SIGMATEL) += patch_sigmatel.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_SI3054) += patch_si3054.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_ATIHDMI) += patch_atihdmi.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_CONEXANT) += patch_conexant.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_VIA) += patch_via.o -snd-hda-intel-$(CONFIG_SND_HDA_CODEC_NVHDMI) += patch_nvhdmi.o +snd-hda-intel-objs := hda_intel.o +snd-hda-codec-y := hda_codec.o +snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o +snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o +# snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o +snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o +snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o + +snd-hda-codec-realtek-objs := patch_realtek.o +snd-hda-codec-cmedia-objs := patch_cmedia.o +snd-hda-codec-analog-objs := patch_analog.o +snd-hda-codec-idt-objs := patch_sigmatel.o +snd-hda-codec-si3054-objs := patch_si3054.o +snd-hda-codec-atihdmi-objs := patch_atihdmi.o +snd-hda-codec-conexant-objs := patch_conexant.o +snd-hda-codec-via-objs := patch_via.o +snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o +snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o hda_eld.o + +# common driver +obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o + +# codec drivers (note: CONFIG_SND_HDA_CODEC_XXX are booleans) +ifdef CONFIG_SND_HDA_CODEC_REALTEK +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-realtek.o +endif +ifdef CONFIG_SND_HDA_CODEC_CMEDIA +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cmedia.o +endif +ifdef CONFIG_SND_HDA_CODEC_ANALOG +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-analog.o +endif +ifdef CONFIG_SND_HDA_CODEC_SIGMATEL +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-idt.o +endif +ifdef CONFIG_SND_HDA_CODEC_SI3054 +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o +endif +ifdef CONFIG_SND_HDA_CODEC_ATIHDMI +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o +endif +ifdef CONFIG_SND_HDA_CODEC_CONEXANT +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-conexant.o +endif +ifdef CONFIG_SND_HDA_CODEC_VIA +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o +endif +ifdef CONFIG_SND_HDA_CODEC_NVHDMI +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o +endif +ifdef CONFIG_SND_HDA_CODEC_INTELHDMI +obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o +endif + +# this must be the last entry after codec drivers; +# otherwise the codec patches won't be hooked before the PCI probe +# when built in kernel obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-intel.o diff --git a/sound/pci/hda/hda_beep.c b/sound/pci/hda/hda_beep.c index 3ecd7e797de..e00421c0d8b 100644 --- a/sound/pci/hda/hda_beep.c +++ b/sound/pci/hda/hda_beep.c @@ -128,6 +128,7 @@ int snd_hda_attach_beep_device(struct hda_codec *codec, int nid) INIT_WORK(&beep->beep_work, &snd_hda_generate_beep); return 0; } +EXPORT_SYMBOL_HDA(snd_hda_attach_beep_device); void snd_hda_detach_beep_device(struct hda_codec *codec) { @@ -140,3 +141,4 @@ void snd_hda_detach_beep_device(struct hda_codec *codec) kfree(beep); } } +EXPORT_SYMBOL_HDA(snd_hda_detach_beep_device); diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index eb9164176da..e16cf63821a 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c @@ -31,15 +31,6 @@ #include <sound/initval.h> #include "hda_local.h" #include <sound/hda_hwdep.h> -#include "hda_patch.h" /* codec presets */ - -#ifdef CONFIG_SND_HDA_POWER_SAVE -/* define this option here to hide as static */ -static int power_save = CONFIG_SND_HDA_POWER_SAVE_DEFAULT; -module_param(power_save, int, 0644); -MODULE_PARM_DESC(power_save, "Automatic power-saving timeout " - "(in second, 0 = disable)."); -#endif /* * vendor / preset table @@ -55,6 +46,7 @@ static struct hda_vendor_id hda_vendor_ids[] = { { 0x1002, "ATI" }, { 0x1057, "Motorola" }, { 0x1095, "Silicon Image" }, + { 0x10de, "Nvidia" }, { 0x10ec, "Realtek" }, { 0x1106, "VIA" }, { 0x111d, "IDT" }, @@ -66,40 +58,31 @@ static struct hda_vendor_id hda_vendor_ids[] = { { 0x1854, "LG" }, { 0x1aec, "Wolfson Microelectronics" }, { 0x434d, "C-Media" }, + { 0x8086, "Intel" }, { 0x8384, "SigmaTel" }, {} /* terminator */ }; -static const struct hda_codec_preset *hda_preset_tables[] = { -#ifdef CONFIG_SND_HDA_CODEC_REALTEK - snd_hda_preset_realtek, -#endif -#ifdef CONFIG_SND_HDA_CODEC_CMEDIA - snd_hda_preset_cmedia, -#endif -#ifdef CONFIG_SND_HDA_CODEC_ANALOG - snd_hda_preset_analog, -#endif -#ifdef CONFIG_SND_HDA_CODEC_SIGMATEL - snd_hda_preset_sigmatel, -#endif -#ifdef CONFIG_SND_HDA_CODEC_SI3054 - snd_hda_preset_si3054, -#endif -#ifdef CONFIG_SND_HDA_CODEC_ATIHDMI - snd_hda_preset_atihdmi, -#endif -#ifdef CONFIG_SND_HDA_CODEC_CONEXANT - snd_hda_preset_conexant, -#endif -#ifdef CONFIG_SND_HDA_CODEC_VIA - snd_hda_preset_via, -#endif -#ifdef CONFIG_SND_HDA_CODEC_NVHDMI - snd_hda_preset_nvhdmi, -#endif - NULL -}; +static DEFINE_MUTEX(preset_mutex); +static LIST_HEAD(hda_preset_tables); + +int snd_hda_add_codec_preset(struct hda_codec_preset_list *preset) +{ + mutex_lock(&preset_mutex); + list_add_tail(&preset->list, &hda_preset_tables); + mutex_unlock(&preset_mutex); + return 0; +} +EXPORT_SYMBOL_HDA(snd_hda_add_codec_preset); + +int snd_hda_delete_codec_preset(struct hda_codec_preset_list *preset) +{ + mutex_lock(&preset_mutex); + list_del(&preset->list); + mutex_unlock(&preset_mutex); + return 0; +} +EXPORT_SYMBOL_HDA(snd_hda_delete_codec_preset); #ifdef CONFIG_SND_HDA_POWER_SAVE static void hda_power_work(struct work_struct *work); @@ -108,6 +91,72 @@ static void hda_keep_power_on(struct hda_codec *codec); static inline void hda_keep_power_on(struct hda_codec *codec) {} #endif +const char *snd_hda_get_jack_location(u32 cfg) +{ + static char *bases[7] = { + "N/A", "Rear", "Front", "Left", "Right", "Top", "Bottom", + }; + static unsigned char specials_idx[] = { + 0x07, 0x08, + 0x17, 0x18, 0x19, + 0x37, 0x38 + }; + static char *specials[] = { + "Rear Panel", "Drive Bar", + "Riser", "HDMI", "ATAPI", + "Mobile-In", "Mobile-Out" + }; + int i; + cfg = (cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT; + if ((cfg & 0x0f) < 7) + return bases[cfg & 0x0f]; + for (i = 0; i < ARRAY_SIZE(specials_idx); i++) { + if (cfg == specials_idx[i]) + return specials[i]; + } + return "UNKNOWN"; +} +EXPORT_SYMBOL_HDA(snd_hda_get_jack_location); + +const char *snd_hda_get_jack_connectivity(u32 cfg) +{ + static char *jack_locations[4] = { "Ext", "Int", "Sep", "Oth" }; + + return jack_locations[(cfg >> (AC_DEFCFG_LOCATION_SHIFT + 4)) & 3]; +} +EXPORT_SYMBOL_HDA(snd_hda_get_jack_connectivity); + +const char *snd_hda_get_jack_type(u32 cfg) +{ + static char *jack_types[16] = { + "Line Out", "Speaker", "HP Out", "CD", + "SPDIF Out", "Digital Out", "Modem Line", "Modem Hand", + "Line In", "Aux", "Mic", "Telephony", + "SPDIF In", "Digitial In", "Reserved", "Other" + }; + + return jack_types[(cfg & AC_DEFCFG_DEVICE) + >> AC_DEFCFG_DEVICE_SHIFT]; +} +EXPORT_SYMBOL_HDA(snd_hda_get_jack_type); + +/* + * Compose a 32bit command word to be sent to the HD-audio controller + */ +static inline unsigned int +make_codec_cmd(struct hda_codec *codec, hda_nid_t nid, int direct, + unsigned int verb, unsigned int parm) +{ + u32 val; + + val = (u32)(codec->addr & 0x0f) << 28; + val |= (u32)direct << 27; + val |= (u32)nid << 20; + val |= verb << 8; + val |= parm; + return val; +} + /** * snd_hda_codec_read - send a command and get the response * @codec: the HDA codec @@ -124,17 +173,21 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { + struct hda_bus *bus = codec->bus; unsigned int res; + + res = make_codec_cmd(codec, nid, direct, verb, parm); snd_hda_power_up(codec); - mutex_lock(&codec->bus->cmd_mutex); - if (!codec->bus->ops.command(codec, nid, direct, verb, parm)) - res = codec->bus->ops.get_response(codec); + mutex_lock(&bus->cmd_mutex); + if (!bus->ops.command(bus, res)) + res = bus->ops.get_response(bus); else res = (unsigned int)-1; - mutex_unlock(&codec->bus->cmd_mutex); + mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); return res; } +EXPORT_SYMBOL_HDA(snd_hda_codec_read); /** * snd_hda_codec_write - send a single command without waiting for response @@ -151,14 +204,19 @@ unsigned int snd_hda_codec_read(struct hda_codec *codec, hda_nid_t nid, int snd_hda_codec_write(struct hda_codec *codec, hda_nid_t nid, int direct, unsigned int verb, unsigned int parm) { + struct hda_bus *bus = codec->bus; + unsigned int res; int err; + + res = make_codec_cmd(codec, nid, direct, verb, parm); snd_hda_power_up(codec); - mutex_lock(&codec->bus->cmd_mutex); - err = codec->bus->ops.command(codec, nid, direct, verb, parm); - mutex_unlock(&codec->bus->cmd_mutex); + mutex_lock(&bus->cmd_mutex); + err = bus->ops.command(bus, res); + mutex_unlock(&bus->cmd_mutex); snd_hda_power_down(codec); return err; } +EXPORT_SYMBOL_HDA(snd_hda_codec_write); /** * snd_hda_sequence_write - sequence writes @@ -173,6 +231,7 @@ void snd_hda_sequence_write(struct hda_codec *codec, const struct hda_verb *seq) for (; seq->nid; seq++) snd_hda_codec_write(codec, seq->nid, 0, seq->verb, seq->param); } +EXPORT_SYMBOL_HDA(snd_hda_sequence_write); /** * snd_hda_get_sub_nodes - get the range of sub nodes @@ -194,6 +253,7 @@ int snd_hda_get_sub_nodes(struct hda_codec *codec, hda_nid_t nid, *start_id = (parm >> 16) & 0x7fff; return (int)(parm & 0x7fff); } +EXPORT_SYMBOL_HDA(snd_hda_get_sub_nodes); /** * snd_hda_get_connections - get connection list @@ -282,6 +342,7 @@ int snd_hda_get_connections(struct hda_codec *codec, hda_nid_t nid, } return conns; } +EXPORT_SYMBOL_HDA(snd_hda_get_connections); /** @@ -316,6 +377,7 @@ int snd_hda_queue_unsol_event(struct hda_bus *bus, u32 res, u32 res_ex) return 0; } +EXPORT_SYMBOL_HDA(snd_hda_queue_unsol_event); /* * process queued unsolicited events @@ -345,7 +407,7 @@ static void process_unsol_events(struct work_struct *work) /* * initialize unsolicited queue */ -static int __devinit init_unsol_queue(struct hda_bus *bus) +static int init_unsol_queue(struct hda_bus *bus) { struct hda_bus_unsolicited *unsol; @@ -391,9 +453,24 @@ static int snd_hda_bus_free(struct hda_bus *bus) static int snd_hda_bus_dev_free(struct snd_device *device) { struct hda_bus *bus = device->device_data; + bus->shutdown = 1; return snd_hda_bus_free(bus); } +#ifdef CONFIG_SND_HDA_HWDEP +static int snd_hda_bus_dev_register(struct snd_device *device) +{ + struct hda_bus *bus = device->device_data; + struct hda_codec *codec; + list_for_each_entry(codec, &bus->codec_list, list) { + snd_hda_hwdep_add_sysfs(codec); + } + return 0; +} +#else +#define snd_hda_bus_dev_register NULL +#endif + /** * snd_hda_bus_new - create a HDA bus * @card: the card entry @@ -402,13 +479,14 @@ static int snd_hda_bus_dev_free(struct snd_device *device) * * Returns 0 if successful, or a negative error code. */ -int __devinit snd_hda_bus_new(struct snd_card *card, +int /*__devinit*/ snd_hda_bus_new(struct snd_card *card, const struct hda_bus_template *temp, struct hda_bus **busp) { struct hda_bus *bus; int err; static struct snd_device_ops dev_ops = { + .dev_register = snd_hda_bus_dev_register, .dev_free = snd_hda_bus_dev_free, }; @@ -430,6 +508,7 @@ int __devinit snd_hda_bus_new(struct snd_card *card, bus->private_data = temp->private_data; bus->pci = temp->pci; bus->modelname = temp->modelname; + bus->power_save = temp->power_save; bus->ops = temp->ops; mutex_init(&bus->cmd_mutex); @@ -444,27 +523,42 @@ int __devinit snd_hda_bus_new(struct snd_card *card, *busp = bus; return 0; } +EXPORT_SYMBOL_HDA(snd_hda_bus_new); #ifdef CONFIG_SND_HDA_GENERIC #define is_generic_config(codec) \ - (codec->bus->modelname && !strcmp(codec->bus->modelname, "generic")) + (codec->modelname && !strcmp(codec->modelname, "generic")) #else #define is_generic_config(codec) 0 #endif +#ifdef MODULE +#define HDA_MODREQ_MAX_COUNT 2 /* two request_modules()'s */ +#else +#define HDA_MODREQ_MAX_COUNT 0 /* all presets are statically linked */ +#endif + /* * find a matching codec preset */ -static const struct hda_codec_preset __devinit * +static const struct hda_codec_preset * find_codec_preset(struct hda_codec *codec) { - const struct hda_codec_preset **tbl, *preset; + struct hda_codec_preset_list *tbl; + const struct hda_codec_preset *preset; + int mod_requested = 0; if (is_generic_config(codec)) return NULL; /* use the generic parser */ - for (tbl = hda_preset_tables; *tbl; tbl++) { - for (preset = *tbl; preset->id; preset++) { + again: + mutex_lock(&preset_mutex); + list_for_each_entry(tbl, &hda_preset_tables, list) { + if (!try_module_get(tbl->owner)) { + snd_printk(KERN_ERR "hda_codec: cannot module_get\n"); + continue; + } + for (preset = tbl->preset; preset->id; preset++) { u32 mask = preset->mask; if (preset->afg && preset->afg != codec->afg) continue; @@ -474,23 +568,40 @@ find_codec_preset(struct hda_codec *codec) mask = ~0; if (preset->id == (codec->vendor_id & mask) && (!preset->rev || - preset->rev == codec->revision_id)) + preset->rev == codec->revision_id)) { + mutex_unlock(&preset_mutex); + codec->owner = tbl->owner; return preset; + } } + module_put(tbl->owner); + } + mutex_unlock(&preset_mutex); + + if (mod_requested < HDA_MODREQ_MAX_COUNT) { + char name[32]; + if (!mod_requested) + snprintf(name, sizeof(name), "snd-hda-codec-id:%08x", + codec->vendor_id); + else + snprintf(name, sizeof(name), "snd-hda-codec-id:%04x*", + (codec->vendor_id >> 16) & 0xffff); + request_module(name); + mod_requested++; + goto again; } return NULL; } /* - * snd_hda_get_codec_name - store the codec name + * get_codec_name - store the codec name */ -void snd_hda_get_codec_name(struct hda_codec *codec, - char *name, int namelen) +static int get_codec_name(struct hda_codec *codec) { const struct hda_vendor_id *c; const char *vendor = NULL; u16 vendor_id = codec->vendor_id >> 16; - char tmp[16]; + char tmp[16], name[32]; for (c = hda_vendor_ids; c->id; c++) { if (c->id == vendor_id) { @@ -503,16 +614,21 @@ void snd_hda_get_codec_name(struct hda_codec *codec, vendor = tmp; } if (codec->preset && codec->preset->name) - snprintf(name, namelen, "%s %s", vendor, codec->preset->name); + snprintf(name, sizeof(name), "%s %s", vendor, + codec->preset->name); else - snprintf(name, namelen, "%s ID %x", vendor, + snprintf(name, sizeof(name), "%s ID %x", vendor, codec->vendor_id & 0xffff); + codec->name = kstrdup(name, GFP_KERNEL); + if (!codec->name) + return -ENOMEM; + return 0; } /* * look for an AFG and MFG nodes */ -static void __devinit setup_fg_nodes(struct hda_codec *codec) +static void /*__devinit*/ setup_fg_nodes(struct hda_codec *codec) { int i, total_nodes; hda_nid_t nid; @@ -571,11 +687,15 @@ static void snd_hda_codec_free(struct hda_codec *codec) flush_scheduled_work(); #endif list_del(&codec->list); + snd_array_free(&codec->mixers); codec->bus->caddr_tbl[codec->addr] = NULL; if (codec->patch_ |