diff options
| -rw-r--r-- | Documentation/sound/alsa/HD-Audio.txt | 8 | ||||
| -rw-r--r-- | include/sound/tlv.h | 4 | ||||
| -rw-r--r-- | sound/pci/hda/Kconfig | 39 | ||||
| -rw-r--r-- | sound/pci/hda/Makefile | 15 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.c | 271 | ||||
| -rw-r--r-- | sound/pci/hda/hda_codec.h | 13 | ||||
| -rw-r--r-- | sound/pci/hda/hda_eld.c | 7 | ||||
| -rw-r--r-- | sound/pci/hda/hda_generic.c | 41 | ||||
| -rw-r--r-- | sound/pci/hda/hda_intel.c | 101 | ||||
| -rw-r--r-- | sound/pci/hda/hda_local.h | 51 | ||||
| -rw-r--r-- | sound/pci/hda/patch_analog.c | 48 | ||||
| -rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 224 | ||||
| -rw-r--r-- | sound/pci/hda/patch_ca0110.c | 10 | ||||
| -rw-r--r-- | sound/pci/hda/patch_cirrus.c | 94 | ||||
| -rw-r--r-- | sound/pci/hda/patch_conexant.c | 651 | ||||
| -rw-r--r-- | sound/pci/hda/patch_hdmi.c | 797 | ||||
| -rw-r--r-- | sound/pci/hda/patch_intelhdmi.c | 220 | ||||
| -rw-r--r-- | sound/pci/hda/patch_nvhdmi.c | 608 | ||||
| -rw-r--r-- | sound/pci/hda/patch_realtek.c | 908 | ||||
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 379 | ||||
| -rw-r--r-- | sound/pci/hda/patch_via.c | 587 |
21 files changed, 2837 insertions, 2239 deletions
diff --git a/Documentation/sound/alsa/HD-Audio.txt b/Documentation/sound/alsa/HD-Audio.txt index 278cc2122ea0..c82beb007634 100644 --- a/Documentation/sound/alsa/HD-Audio.txt +++ b/Documentation/sound/alsa/HD-Audio.txt | |||
| @@ -57,9 +57,11 @@ dead. However, this detection isn't perfect on some devices. In such | |||
| 57 | a case, you can change the default method via `position_fix` option. | 57 | a case, you can change the default method via `position_fix` option. |
| 58 | 58 | ||
| 59 | `position_fix=1` means to use LPIB method explicitly. | 59 | `position_fix=1` means to use LPIB method explicitly. |
| 60 | `position_fix=2` means to use the position-buffer. 0 is the default | 60 | `position_fix=2` means to use the position-buffer. |
| 61 | value, the automatic check and fallback to LPIB as described in the | 61 | `position_fix=3` means to use a combination of both methods, needed |
| 62 | above. If you get a problem of repeated sounds, this option might | 62 | for some VIA and ATI controllers. 0 is the default value for all other |
| 63 | controllers, the automatic check and fallback to LPIB as described in | ||
| 64 | the above. If you get a problem of repeated sounds, this option might | ||
| 63 | help. | 65 | help. |
| 64 | 66 | ||
| 65 | In addition to that, every controller is known to be broken regarding | 67 | In addition to that, every controller is known to be broken regarding |
diff --git a/include/sound/tlv.h b/include/sound/tlv.h index 9fd5b19ccf5c..7067e2dfb0b9 100644 --- a/include/sound/tlv.h +++ b/include/sound/tlv.h | |||
| @@ -38,9 +38,11 @@ | |||
| 38 | #define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ | 38 | #define SNDRV_CTL_TLVT_DB_MINMAX 4 /* dB scale with min/max */ |
| 39 | #define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ | 39 | #define SNDRV_CTL_TLVT_DB_MINMAX_MUTE 5 /* dB scale with min/max with mute */ |
| 40 | 40 | ||
| 41 | #define TLV_DB_SCALE_MASK 0xffff | ||
| 42 | #define TLV_DB_SCALE_MUTE 0x10000 | ||
| 41 | #define TLV_DB_SCALE_ITEM(min, step, mute) \ | 43 | #define TLV_DB_SCALE_ITEM(min, step, mute) \ |
| 42 | SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ | 44 | SNDRV_CTL_TLVT_DB_SCALE, 2 * sizeof(unsigned int), \ |
| 43 | (min), ((step) & 0xffff) | ((mute) ? 0x10000 : 0) | 45 | (min), ((step) & TLV_DB_SCALE_MASK) | ((mute) ? TLV_DB_SCALE_MUTE : 0) |
| 44 | #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ | 46 | #define DECLARE_TLV_DB_SCALE(name, min, step, mute) \ |
| 45 | unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } | 47 | unsigned int name[] = { TLV_DB_SCALE_ITEM(min, step, mute) } |
| 46 | 48 | ||
diff --git a/sound/pci/hda/Kconfig b/sound/pci/hda/Kconfig index 9194c3c1d04a..0ea5cc60ac78 100644 --- a/sound/pci/hda/Kconfig +++ b/sound/pci/hda/Kconfig | |||
| @@ -119,47 +119,20 @@ config SND_HDA_CODEC_VIA | |||
| 119 | snd-hda-codec-via. | 119 | snd-hda-codec-via. |
| 120 | This module is automatically loaded at probing. | 120 | This module is automatically loaded at probing. |
| 121 | 121 | ||
| 122 | config SND_HDA_CODEC_ATIHDMI | 122 | config SND_HDA_CODEC_HDMI |
| 123 | bool "Build ATI HDMI HD-audio codec support" | 123 | bool "Build HDMI/DisplayPort HD-audio codec support" |
| 124 | default y | ||
| 125 | help | ||
| 126 | Say Y here to include ATI HDMI HD-audio codec support in | ||
| 127 | snd-hda-intel driver, such as ATI RS600 HDMI. | ||
| 128 | |||
| 129 | When the HD-audio driver is built as a module, the codec | ||
| 130 | support code is also built as another module, | ||
| 131 | snd-hda-codec-atihdmi. | ||
| 132 | This module is automatically loaded at probing. | ||
| 133 | |||
| 134 | config SND_HDA_CODEC_NVHDMI | ||
| 135 | bool "Build NVIDIA HDMI HD-audio codec support" | ||
| 136 | default y | ||
| 137 | help | ||
| 138 | Say Y here to include NVIDIA HDMI HD-audio codec support in | ||
| 139 | snd-hda-intel driver, such as NVIDIA MCP78 HDMI. | ||
| 140 | |||
| 141 | When the HD-audio driver is built as a module, the codec | ||
| 142 | support code is also built as another module, | ||
| 143 | snd-hda-codec-nvhdmi. | ||
| 144 | This module is automatically loaded at probing. | ||
| 145 | |||
| 146 | config SND_HDA_CODEC_INTELHDMI | ||
| 147 | bool "Build INTEL HDMI HD-audio codec support" | ||
| 148 | select SND_DYNAMIC_MINORS | 124 | select SND_DYNAMIC_MINORS |
| 149 | default y | 125 | default y |
| 150 | help | 126 | help |
| 151 | Say Y here to include INTEL HDMI HD-audio codec support in | 127 | Say Y here to include HDMI and DisplayPort HD-audio codec |
| 152 | snd-hda-intel driver, such as Eaglelake integrated HDMI. | 128 | support in snd-hda-intel driver. This includes all AMD/ATI, |
| 129 | Intel and Nvidia HDMI/DisplayPort codecs. | ||
| 153 | 130 | ||
| 154 | When the HD-audio driver is built as a module, the codec | 131 | When the HD-audio driver is built as a module, the codec |
| 155 | support code is also built as another module, | 132 | support code is also built as another module, |
| 156 | snd-hda-codec-intelhdmi. | 133 | snd-hda-codec-hdmi. |
| 157 | This module is automatically loaded at probing. | 134 | This module is automatically loaded at probing. |
| 158 | 135 | ||
| 159 | config SND_HDA_ELD | ||
| 160 | def_bool y | ||
| 161 | depends on SND_HDA_CODEC_INTELHDMI || SND_HDA_CODEC_NVHDMI | ||
| 162 | |||
| 163 | config SND_HDA_CODEC_CIRRUS | 136 | config SND_HDA_CODEC_CIRRUS |
| 164 | bool "Build Cirrus Logic codec support" | 137 | bool "Build Cirrus Logic codec support" |
| 165 | depends on SND_HDA_INTEL | 138 | depends on SND_HDA_INTEL |
diff --git a/sound/pci/hda/Makefile b/sound/pci/hda/Makefile index 24bc195b02da..17ef3658f34b 100644 --- a/sound/pci/hda/Makefile +++ b/sound/pci/hda/Makefile | |||
| @@ -3,7 +3,6 @@ snd-hda-intel-objs := hda_intel.o | |||
| 3 | snd-hda-codec-y := hda_codec.o | 3 | snd-hda-codec-y := hda_codec.o |
| 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o | 4 | snd-hda-codec-$(CONFIG_SND_HDA_GENERIC) += hda_generic.o |
| 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o | 5 | snd-hda-codec-$(CONFIG_PROC_FS) += hda_proc.o |
| 6 | snd-hda-codec-$(CONFIG_SND_HDA_ELD) += hda_eld.o | ||
| 7 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o | 6 | snd-hda-codec-$(CONFIG_SND_HDA_HWDEP) += hda_hwdep.o |
| 8 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o | 7 | snd-hda-codec-$(CONFIG_SND_HDA_INPUT_BEEP) += hda_beep.o |
| 9 | 8 | ||
| @@ -12,13 +11,11 @@ snd-hda-codec-cmedia-objs := patch_cmedia.o | |||
| 12 | snd-hda-codec-analog-objs := patch_analog.o | 11 | snd-hda-codec-analog-objs := patch_analog.o |
| 13 | snd-hda-codec-idt-objs := patch_sigmatel.o | 12 | snd-hda-codec-idt-objs := patch_sigmatel.o |
| 14 | snd-hda-codec-si3054-objs := patch_si3054.o | 13 | snd-hda-codec-si3054-objs := patch_si3054.o |
| 15 | snd-hda-codec-atihdmi-objs := patch_atihdmi.o | ||
| 16 | snd-hda-codec-cirrus-objs := patch_cirrus.o | 14 | snd-hda-codec-cirrus-objs := patch_cirrus.o |
| 17 | snd-hda-codec-ca0110-objs := patch_ca0110.o | 15 | snd-hda-codec-ca0110-objs := patch_ca0110.o |
| 18 | snd-hda-codec-conexant-objs := patch_conexant.o | 16 | snd-hda-codec-conexant-objs := patch_conexant.o |
| 19 | snd-hda-codec-via-objs := patch_via.o | 17 | snd-hda-codec-via-objs := patch_via.o |
| 20 | snd-hda-codec-nvhdmi-objs := patch_nvhdmi.o | 18 | snd-hda-codec-hdmi-objs := patch_hdmi.o hda_eld.o |
| 21 | snd-hda-codec-intelhdmi-objs := patch_intelhdmi.o | ||
| 22 | 19 | ||
| 23 | # common driver | 20 | # common driver |
| 24 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o | 21 | obj-$(CONFIG_SND_HDA_INTEL) := snd-hda-codec.o |
| @@ -39,9 +36,6 @@ endif | |||
| 39 | ifdef CONFIG_SND_HDA_CODEC_SI3054 | 36 | ifdef CONFIG_SND_HDA_CODEC_SI3054 |
| 40 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o | 37 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-si3054.o |
| 41 | endif | 38 | endif |
| 42 | ifdef CONFIG_SND_HDA_CODEC_ATIHDMI | ||
| 43 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-atihdmi.o | ||
| 44 | endif | ||
| 45 | ifdef CONFIG_SND_HDA_CODEC_CIRRUS | 39 | ifdef CONFIG_SND_HDA_CODEC_CIRRUS |
| 46 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o | 40 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-cirrus.o |
| 47 | endif | 41 | endif |
| @@ -54,11 +48,8 @@ endif | |||
| 54 | ifdef CONFIG_SND_HDA_CODEC_VIA | 48 | ifdef CONFIG_SND_HDA_CODEC_VIA |
| 55 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o | 49 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-via.o |
| 56 | endif | 50 | endif |
| 57 | ifdef CONFIG_SND_HDA_CODEC_NVHDMI | 51 | ifdef CONFIG_SND_HDA_CODEC_HDMI |
| 58 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-nvhdmi.o | 52 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-hdmi.o |
| 59 | endif | ||
| 60 | ifdef CONFIG_SND_HDA_CODEC_INTELHDMI | ||
| 61 | obj-$(CONFIG_SND_HDA_INTEL) += snd-hda-codec-intelhdmi.o | ||
| 62 | endif | 53 | endif |
| 63 | 54 | ||
| 64 | # this must be the last entry after codec drivers; | 55 | # this must be the last entry after codec drivers; |
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 14829210ef0b..644e3f14f8ca 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
| @@ -1216,6 +1216,7 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
| 1216 | struct hda_codec *c; | 1216 | struct hda_codec *c; |
| 1217 | struct hda_cvt_setup *p; | 1217 | struct hda_cvt_setup *p; |
| 1218 | unsigned int oldval, newval; | 1218 | unsigned int oldval, newval; |
| 1219 | int type; | ||
| 1219 | int i; | 1220 | int i; |
| 1220 | 1221 | ||
| 1221 | if (!nid) | 1222 | if (!nid) |
| @@ -1254,10 +1255,12 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
| 1254 | p->dirty = 0; | 1255 | p->dirty = 0; |
| 1255 | 1256 | ||
| 1256 | /* make other inactive cvts with the same stream-tag dirty */ | 1257 | /* make other inactive cvts with the same stream-tag dirty */ |
| 1258 | type = get_wcaps_type(get_wcaps(codec, nid)); | ||
| 1257 | list_for_each_entry(c, &codec->bus->codec_list, list) { | 1259 | list_for_each_entry(c, &codec->bus->codec_list, list) { |
| 1258 | for (i = 0; i < c->cvt_setups.used; i++) { | 1260 | for (i = 0; i < c->cvt_setups.used; i++) { |
| 1259 | p = snd_array_elem(&c->cvt_setups, i); | 1261 | p = snd_array_elem(&c->cvt_setups, i); |
| 1260 | if (!p->active && p->stream_tag == stream_tag) | 1262 | if (!p->active && p->stream_tag == stream_tag && |
| 1263 | get_wcaps_type(get_wcaps(codec, p->nid)) == type) | ||
| 1261 | p->dirty = 1; | 1264 | p->dirty = 1; |
| 1262 | } | 1265 | } |
| 1263 | } | 1266 | } |
| @@ -1281,6 +1284,9 @@ void __snd_hda_codec_cleanup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
| 1281 | if (!nid) | 1284 | if (!nid) |
| 1282 | return; | 1285 | return; |
| 1283 | 1286 | ||
| 1287 | if (codec->no_sticky_stream) | ||
| 1288 | do_now = 1; | ||
| 1289 | |||
| 1284 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); | 1290 | snd_printdd("hda_codec_cleanup_stream: NID=0x%x\n", nid); |
| 1285 | p = get_hda_cvt_setup(codec, nid); | 1291 | p = get_hda_cvt_setup(codec, nid); |
| 1286 | if (p) { | 1292 | if (p) { |
| @@ -1831,6 +1837,7 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
| 1831 | hda_nid_t nid = get_amp_nid(kcontrol); | 1837 | hda_nid_t nid = get_amp_nid(kcontrol); |
| 1832 | int dir = get_amp_direction(kcontrol); | 1838 | int dir = get_amp_direction(kcontrol); |
| 1833 | unsigned int ofs = get_amp_offset(kcontrol); | 1839 | unsigned int ofs = get_amp_offset(kcontrol); |
| 1840 | bool min_mute = get_amp_min_mute(kcontrol); | ||
| 1834 | u32 caps, val1, val2; | 1841 | u32 caps, val1, val2; |
| 1835 | 1842 | ||
| 1836 | if (size < 4 * sizeof(unsigned int)) | 1843 | if (size < 4 * sizeof(unsigned int)) |
| @@ -1841,6 +1848,8 @@ int snd_hda_mixer_amp_tlv(struct snd_kcontrol *kcontrol, int op_flag, | |||
| 1841 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); | 1848 | val1 = -((caps & AC_AMPCAP_OFFSET) >> AC_AMPCAP_OFFSET_SHIFT); |
| 1842 | val1 += ofs; | 1849 | val1 += ofs; |
| 1843 | val1 = ((int)val1) * ((int)val2); | 1850 | val1 = ((int)val1) * ((int)val2); |
| 1851 | if (min_mute) | ||
| 1852 | val2 |= TLV_DB_SCALE_MUTE; | ||
| 1844 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) | 1853 | if (put_user(SNDRV_CTL_TLVT_DB_SCALE, _tlv)) |
| 1845 | return -EFAULT; | 1854 | return -EFAULT; |
| 1846 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) | 1855 | if (put_user(2 * sizeof(unsigned int), _tlv + 1)) |
| @@ -2228,10 +2237,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
| 2228 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 2237 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
| 2229 | HDA_AMP_MUTE, | 2238 | HDA_AMP_MUTE, |
| 2230 | *valp ? 0 : HDA_AMP_MUTE); | 2239 | *valp ? 0 : HDA_AMP_MUTE); |
| 2231 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2240 | hda_call_check_power_status(codec, nid); |
| 2232 | if (codec->patch_ops.check_power_status) | ||
| 2233 | codec->patch_ops.check_power_status(codec, nid); | ||
| 2234 | #endif | ||
| 2235 | snd_hda_power_down(codec); | 2241 | snd_hda_power_down(codec); |
| 2236 | return change; | 2242 | return change; |
| 2237 | } | 2243 | } |
| @@ -4372,6 +4378,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
| 4372 | } | 4378 | } |
| 4373 | 4379 | ||
| 4374 | 4380 | ||
| 4381 | /* add the found input-pin to the cfg->inputs[] table */ | ||
| 4382 | static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, | ||
| 4383 | int type) | ||
| 4384 | { | ||
| 4385 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { | ||
| 4386 | cfg->inputs[cfg->num_inputs].pin = nid; | ||
| 4387 | cfg->inputs[cfg->num_inputs].type = type; | ||
| 4388 | cfg->num_inputs++; | ||
| 4389 | } | ||
| 4390 | } | ||
| 4391 | |||
| 4392 | /* sort inputs in the order of AUTO_PIN_* type */ | ||
| 4393 | static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) | ||
| 4394 | { | ||
| 4395 | int i, j; | ||
| 4396 | |||
| 4397 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 4398 | for (j = i + 1; j < cfg->num_inputs; j++) { | ||
| 4399 | if (cfg->inputs[i].type > cfg->inputs[j].type) { | ||
| 4400 | struct auto_pin_cfg_item tmp; | ||
| 4401 | tmp = cfg->inputs[i]; | ||
| 4402 | cfg->inputs[i] = cfg->inputs[j]; | ||
| 4403 | cfg->inputs[j] = tmp; | ||
| 4404 | } | ||
| 4405 | } | ||
| 4406 | } | ||
| 4407 | } | ||
| 4408 | |||
| 4375 | /* | 4409 | /* |
| 4376 | * Parse all pin widgets and store the useful pin nids to cfg | 4410 | * Parse all pin widgets and store the useful pin nids to cfg |
| 4377 | * | 4411 | * |
| @@ -4385,7 +4419,7 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
| 4385 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive | 4419 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
| 4386 | * if any analog output exists. | 4420 | * if any analog output exists. |
| 4387 | * | 4421 | * |
| 4388 | * The analog input pins are assigned to input_pins array. | 4422 | * The analog input pins are assigned to inputs array. |
| 4389 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, | 4423 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
| 4390 | * respectively. | 4424 | * respectively. |
| 4391 | */ | 4425 | */ |
| @@ -4398,6 +4432,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4398 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | 4432 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; |
| 4399 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | 4433 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; |
| 4400 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; | 4434 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; |
| 4435 | int i; | ||
| 4401 | 4436 | ||
| 4402 | memset(cfg, 0, sizeof(*cfg)); | 4437 | memset(cfg, 0, sizeof(*cfg)); |
| 4403 | 4438 | ||
| @@ -4468,33 +4503,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4468 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; | 4503 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; |
| 4469 | cfg->hp_outs++; | 4504 | cfg->hp_outs++; |
| 4470 | break; | 4505 | break; |
| 4471 | case AC_JACK_MIC_IN: { | 4506 | case AC_JACK_MIC_IN: |
| 4472 | int preferred, alt; | 4507 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_MIC); |
| 4473 | if (loc == AC_JACK_LOC_FRONT || | ||
| 4474 | (loc & 0x30) == AC_JACK_LOC_INTERNAL) { | ||
| 4475 | preferred = AUTO_PIN_FRONT_MIC; | ||
| 4476 | alt = AUTO_PIN_MIC; | ||
| 4477 | } else { | ||
| 4478 | preferred = AUTO_PIN_MIC; | ||
| 4479 | alt = AUTO_PIN_FRONT_MIC; | ||
| 4480 | } | ||
| 4481 | if (!cfg->input_pins[preferred]) | ||
| 4482 | cfg->input_pins[preferred] = nid; | ||
| 4483 | else if (!cfg->input_pins[alt]) | ||
| 4484 | cfg->input_pins[alt] = nid; | ||
| 4485 | break; | 4508 | break; |
| 4486 | } | ||
| 4487 | case AC_JACK_LINE_IN: | 4509 | case AC_JACK_LINE_IN: |
| 4488 | if (loc == AC_JACK_LOC_FRONT) | 4510 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_LINE_IN); |
| 4489 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = nid; | ||
| 4490 | else | ||
| 4491 | cfg->input_pins[AUTO_PIN_LINE] = nid; | ||
| 4492 | break; | 4511 | break; |
| 4493 | case AC_JACK_CD: | 4512 | case AC_JACK_CD: |
| 4494 | cfg->input_pins[AUTO_PIN_CD] = nid; | 4513 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); |
| 4495 | break; | 4514 | break; |
| 4496 | case AC_JACK_AUX: | 4515 | case AC_JACK_AUX: |
| 4497 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 4516 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); |
| 4498 | break; | 4517 | break; |
| 4499 | case AC_JACK_SPDIF_OUT: | 4518 | case AC_JACK_SPDIF_OUT: |
| 4500 | case AC_JACK_DIG_OTHER_OUT: | 4519 | case AC_JACK_DIG_OTHER_OUT: |
| @@ -4539,6 +4558,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4539 | memmove(sequences_hp + i, sequences_hp + i + 1, | 4558 | memmove(sequences_hp + i, sequences_hp + i + 1, |
| 4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); | 4559 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); |
| 4541 | } | 4560 | } |
| 4561 | memset(cfg->hp_pins + cfg->hp_outs, 0, | ||
| 4562 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); | ||
| 4542 | } | 4563 | } |
| 4543 | 4564 | ||
| 4544 | /* sort by sequence */ | 4565 | /* sort by sequence */ |
| @@ -4549,21 +4570,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4549 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4570 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
| 4550 | cfg->hp_outs); | 4571 | cfg->hp_outs); |
| 4551 | 4572 | ||
| 4552 | /* if we have only one mic, make it AUTO_PIN_MIC */ | ||
| 4553 | if (!cfg->input_pins[AUTO_PIN_MIC] && | ||
| 4554 | cfg->input_pins[AUTO_PIN_FRONT_MIC]) { | ||
| 4555 | cfg->input_pins[AUTO_PIN_MIC] = | ||
| 4556 | cfg->input_pins[AUTO_PIN_FRONT_MIC]; | ||
| 4557 | cfg->input_pins[AUTO_PIN_FRONT_MIC] = 0; | ||
| 4558 | } | ||
| 4559 | /* ditto for line-in */ | ||
| 4560 | if (!cfg->input_pins[AUTO_PIN_LINE] && | ||
| 4561 | cfg->input_pins[AUTO_PIN_FRONT_LINE]) { | ||
| 4562 | cfg->input_pins[AUTO_PIN_LINE] = | ||
| 4563 | cfg->input_pins[AUTO_PIN_FRONT_LINE]; | ||
| 4564 | cfg->input_pins[AUTO_PIN_FRONT_LINE] = 0; | ||
| 4565 | } | ||
| 4566 | |||
| 4567 | /* | 4573 | /* |
| 4568 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | 4574 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
| 4569 | * as a primary output | 4575 | * as a primary output |
| @@ -4602,6 +4608,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4602 | break; | 4608 | break; |
| 4603 | } | 4609 | } |
| 4604 | 4610 | ||
| 4611 | sort_autocfg_input_pins(cfg); | ||
| 4612 | |||
| 4605 | /* | 4613 | /* |
| 4606 | * debug prints of the parsed results | 4614 | * debug prints of the parsed results |
| 4607 | */ | 4615 | */ |
| @@ -4621,14 +4629,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4621 | if (cfg->dig_outs) | 4629 | if (cfg->dig_outs) |
| 4622 | snd_printd(" dig-out=0x%x/0x%x\n", | 4630 | snd_printd(" dig-out=0x%x/0x%x\n", |
| 4623 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | 4631 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); |
| 4624 | snd_printd(" inputs: mic=0x%x, fmic=0x%x, line=0x%x, fline=0x%x," | 4632 | snd_printd(" inputs:"); |
| 4625 | " cd=0x%x, aux=0x%x\n", | 4633 | for (i = 0; i < cfg->num_inputs; i++) { |
| 4626 | cfg->input_pins[AUTO_PIN_MIC], | 4634 | snd_printdd(" %s=0x%x", |
| 4627 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | 4635 | hda_get_autocfg_input_label(codec, cfg, i), |
| 4628 | cfg->input_pins[AUTO_PIN_LINE], | 4636 | cfg->inputs[i].pin); |
| 4629 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 4637 | } |
| 4630 | cfg->input_pins[AUTO_PIN_CD], | 4638 | snd_printd("\n"); |
| 4631 | cfg->input_pins[AUTO_PIN_AUX]); | ||
| 4632 | if (cfg->dig_in_pin) | 4639 | if (cfg->dig_in_pin) |
| 4633 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | 4640 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); |
| 4634 | 4641 | ||
| @@ -4636,11 +4643,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
| 4636 | } | 4643 | } |
| 4637 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); | 4644 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); |
| 4638 | 4645 | ||
| 4639 | /* labels for input pins */ | 4646 | int snd_hda_get_input_pin_attr(unsigned int def_conf) |
| 4640 | const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { | 4647 | { |
| 4641 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | 4648 | unsigned int loc = get_defcfg_location(def_conf); |
| 4642 | }; | 4649 | unsigned int conn = get_defcfg_connect(def_conf); |
| 4643 | EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); | 4650 | if (conn == AC_JACK_PORT_NONE) |
| 4651 | return INPUT_PIN_ATTR_UNUSED; | ||
| 4652 | /* Windows may claim the internal mic to be BOTH, too */ | ||
| 4653 | if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH) | ||
| 4654 | return INPUT_PIN_ATTR_INT; | ||
| 4655 | if ((loc & 0x30) == AC_JACK_LOC_INTERNAL) | ||
| 4656 | return INPUT_PIN_ATTR_INT; | ||
| 4657 | if ((loc & 0x30) == AC_JACK_LOC_SEPARATE) | ||
| 4658 | return INPUT_PIN_ATTR_DOCK; | ||
| 4659 | if (loc == AC_JACK_LOC_REAR) | ||
| 4660 | return INPUT_PIN_ATTR_REAR; | ||
| 4661 | if (loc == AC_JACK_LOC_FRONT) | ||
| 4662 | return INPUT_PIN_ATTR_FRONT; | ||
| 4663 | return INPUT_PIN_ATTR_NORMAL; | ||
| 4664 | } | ||
| 4665 | EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); | ||
| 4666 | |||
| 4667 | /** | ||
| 4668 | * hda_get_input_pin_label - Give a label for the given input pin | ||
| 4669 | * | ||
| 4670 | * When check_location is true, the function checks the pin location | ||
| 4671 | * for mic and line-in pins, and set an appropriate prefix like "Front", | ||
| 4672 | * "Rear", "Internal". | ||
| 4673 | */ | ||
| 4674 | |||
| 4675 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
| 4676 | int check_location) | ||
| 4677 | { | ||
| 4678 | unsigned int def_conf; | ||
| 4679 | static const char *mic_names[] = { | ||
| 4680 | "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic", | ||
| 4681 | }; | ||
| 4682 | int attr; | ||
| 4683 | |||
| 4684 | def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
| 4685 | |||
| 4686 | switch (get_defcfg_device(def_conf)) { | ||
| 4687 | case AC_JACK_MIC_IN: | ||
| 4688 | if (!check_location) | ||
| 4689 | return "Mic"; | ||
| 4690 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
| 4691 | if (!attr) | ||
| 4692 | return "None"; | ||
| 4693 | return mic_names[attr - 1]; | ||
| 4694 | case AC_JACK_LINE_IN: | ||
| 4695 | if (!check_location) | ||
| 4696 | return "Line"; | ||
| 4697 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
| 4698 | if (!attr) | ||
| 4699 | return "None"; | ||
| 4700 | if (attr == INPUT_PIN_ATTR_DOCK) | ||
| 4701 | return "Dock Line"; | ||
| 4702 | return "Line"; | ||
| 4703 | case AC_JACK_AUX: | ||
| 4704 | return "Aux"; | ||
| 4705 | case AC_JACK_CD: | ||
| 4706 | return "CD"; | ||
| 4707 | case AC_JACK_SPDIF_IN: | ||
| 4708 | return "SPDIF In"; | ||
| 4709 | case AC_JACK_DIG_OTHER_IN: | ||
| 4710 | return "Digital In"; | ||
| 4711 | default: | ||
| 4712 | return "Misc"; | ||
| 4713 | } | ||
| 4714 | } | ||
| 4715 | EXPORT_SYMBOL_HDA(hda_get_input_pin_label); | ||
| 4716 | |||
| 4717 | /* Check whether the location prefix needs to be added to the label. | ||
| 4718 | * If all mic-jacks are in the same location (e.g. rear panel), we don't | ||
| 4719 | * have to put "Front" prefix to each label. In such a case, returns false. | ||
| 4720 | */ | ||
| 4721 | static int check_mic_location_need(struct hda_codec *codec, | ||
| 4722 | const struct auto_pin_cfg *cfg, | ||
| 4723 | int input) | ||
| 4724 | { | ||
| 4725 | unsigned int defc; | ||
| 4726 | int i, attr, attr2; | ||
| 4727 | |||
| 4728 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin); | ||
| 4729 | attr = snd_hda_get_input_pin_attr(defc); | ||
| 4730 | /* for internal or docking mics, we need locations */ | ||
| 4731 | if (attr <= INPUT_PIN_ATTR_NORMAL) | ||
| 4732 | return 1; | ||
| 4733 | |||
| 4734 | attr = 0; | ||
| 4735 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 4736 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); | ||
| 4737 | attr2 = snd_hda_get_input_pin_attr(defc); | ||
| 4738 | if (attr2 >= INPUT_PIN_ATTR_NORMAL) { | ||
| 4739 | if (attr && attr != attr2) | ||
| 4740 | return 1; /* different locations found */ | ||
| 4741 | attr = attr2; | ||
| 4742 | } | ||
| 4743 | } | ||
| 4744 | return 0; | ||
| 4745 | } | ||
| 4746 | |||
| 4747 | /** | ||
| 4748 | * hda_get_autocfg_input_label - Get a label for the given input | ||
| 4749 | * | ||
| 4750 | * Get a label for the given input pin defined by the autocfg item. | ||
| 4751 | * Unlike hda_get_input_pin_label(), this function checks all inputs | ||
| 4752 | * defined in autocfg and avoids the redundant mic/line prefix as much as | ||
| 4753 | * possible. | ||
| 4754 | */ | ||
| 4755 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
| 4756 | const struct auto_pin_cfg *cfg, | ||
| 4757 | int input) | ||
| 4758 | { | ||
| 4759 | int type = cfg->inputs[input].type; | ||
| 4760 | int has_multiple_pins = 0; | ||
| 4761 | |||
| 4762 | if ((input > 0 && cfg->inputs[input - 1].type == type) || | ||
| 4763 | (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type)) | ||
| 4764 | has_multiple_pins = 1; | ||
| 4765 | if (has_multiple_pins && type == AUTO_PIN_MIC) | ||
| 4766 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); | ||
| 4767 | return hda_get_input_pin_label(codec, cfg->inputs[input].pin, | ||
| 4768 | has_multiple_pins); | ||
| 4769 | } | ||
| 4770 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | ||
| 4771 | |||
| 4772 | /** | ||
| 4773 | * snd_hda_add_imux_item - Add an item to input_mux | ||
| 4774 | * | ||
| 4775 | * When the same label is used already in the existing items, the number | ||
| 4776 | * suffix is appended to the label. This label index number is stored | ||
| 4777 | * to type_idx when non-NULL pointer is given. | ||
| 4778 | */ | ||
| 4779 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
| 4780 | int index, int *type_idx) | ||
| 4781 | { | ||
| 4782 | int i, label_idx = 0; | ||
| 4783 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | ||
| 4784 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | ||
| 4785 | return -EINVAL; | ||
| 4786 | } | ||
| 4787 | for (i = 0; i < imux->num_items; i++) { | ||
| 4788 | if (!strncmp(label, imux->items[i].label, strlen(label))) | ||
| 4789 | label_idx++; | ||
| 4790 | } | ||
| 4791 | if (type_idx) | ||
| 4792 | *type_idx = label_idx; | ||
| 4793 | if (label_idx > 0) | ||
| 4794 | snprintf(imux->items[imux->num_items].label, | ||
| 4795 | sizeof(imux->items[imux->num_items].label), | ||
| 4796 | "%s %d", label, label_idx); | ||
| 4797 | else | ||
| 4798 | strlcpy(imux->items[imux->num_items].label, label, | ||
| 4799 | sizeof(imux->items[imux->num_items].label)); | ||
| 4800 | imux->items[imux->num_items].index = index; | ||
| 4801 | imux->num_items++; | ||
| 4802 | return 0; | ||
| 4803 | } | ||
| 4804 | EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | ||
| 4644 | 4805 | ||
| 4645 | 4806 | ||
| 4646 | #ifdef CONFIG_PM | 4807 | #ifdef CONFIG_PM |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 62c702240108..fdf8d44f8b6b 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
| @@ -850,6 +850,7 @@ struct hda_codec { | |||
| 850 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index | 850 | unsigned int pin_amp_workaround:1; /* pin out-amp takes index |
| 851 | * (e.g. Conexant codecs) | 851 | * (e.g. Conexant codecs) |
| 852 | */ | 852 | */ |
| 853 | unsigned int no_sticky_stream:1; /* no sticky-PCM stream assignment */ | ||
| 853 | unsigned int pins_shutup:1; /* pins are shut up */ | 854 | unsigned int pins_shutup:1; /* pins are shut up */ |
| 854 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ | 855 | unsigned int no_trigger_sense:1; /* don't trigger at pin-sensing */ |
| 855 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 856 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| @@ -989,6 +990,18 @@ int snd_hda_suspend(struct hda_bus *bus); | |||
| 989 | int snd_hda_resume(struct hda_bus *bus); | 990 | int snd_hda_resume(struct hda_bus *bus); |
| 990 | #endif | 991 | #endif |
| 991 | 992 | ||
| 993 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 994 | static inline | ||
| 995 | int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
| 996 | { | ||
| 997 | if (codec->patch_ops.check_power_status) | ||
| 998 | return codec->patch_ops.check_power_status(codec, nid); | ||
| 999 | return 0; | ||
| 1000 | } | ||
| 1001 | #else | ||
| 1002 | #define hda_call_check_power_status(codec, nid) 0 | ||
| 1003 | #endif | ||
| 1004 | |||
| 992 | /* | 1005 | /* |
| 993 | * get widget information | 1006 | * get widget information |
| 994 | */ | 1007 | */ |
diff --git a/sound/pci/hda/hda_eld.c b/sound/pci/hda/hda_eld.c index 26c3ade73583..cb0c23a6b473 100644 --- a/sound/pci/hda/hda_eld.c +++ b/sound/pci/hda/hda_eld.c | |||
| @@ -332,7 +332,6 @@ int snd_hdmi_get_eld_size(struct hda_codec *codec, hda_nid_t nid) | |||
| 332 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, | 332 | return snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_HDMI_DIP_SIZE, |
| 333 | AC_DIPSIZE_ELD_BUF); | 333 | AC_DIPSIZE_ELD_BUF); |
| 334 | } | 334 | } |
| 335 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld_size); | ||
| 336 | 335 | ||
| 337 | int snd_hdmi_get_eld(struct hdmi_eld *eld, | 336 | int snd_hdmi_get_eld(struct hdmi_eld *eld, |
| 338 | struct hda_codec *codec, hda_nid_t nid) | 337 | struct hda_codec *codec, hda_nid_t nid) |
| @@ -368,7 +367,6 @@ int snd_hdmi_get_eld(struct hdmi_eld *eld, | |||
| 368 | kfree(buf); | 367 | kfree(buf); |
| 369 | return ret; | 368 | return ret; |
| 370 | } | 369 | } |
| 371 | EXPORT_SYMBOL_HDA(snd_hdmi_get_eld); | ||
| 372 | 370 | ||
| 373 | static void hdmi_show_short_audio_desc(struct cea_sad *a) | 371 | static void hdmi_show_short_audio_desc(struct cea_sad *a) |
| 374 | { | 372 | { |
| @@ -407,7 +405,6 @@ void snd_print_channel_allocation(int spk_alloc, char *buf, int buflen) | |||
| 407 | } | 405 | } |
| 408 | buf[j] = '\0'; /* necessary when j == 0 */ | 406 | buf[j] = '\0'; /* necessary when j == 0 */ |
| 409 | } | 407 | } |
| 410 | EXPORT_SYMBOL_HDA(snd_print_channel_allocation); | ||
| 411 | 408 | ||
| 412 | void snd_hdmi_show_eld(struct hdmi_eld *e) | 409 | void snd_hdmi_show_eld(struct hdmi_eld *e) |
| 413 | { | 410 | { |
| @@ -426,7 +423,6 @@ void snd_hdmi_show_eld(struct hdmi_eld *e) | |||
| 426 | for (i = 0; i < e->sad_count; i++) | 423 | for (i = 0; i < e->sad_count; i++) |
| 427 | hdmi_show_short_audio_desc(e->sad + i); | 424 | hdmi_show_short_audio_desc(e->sad + i); |
| 428 | } | 425 | } |
| 429 | EXPORT_SYMBOL_HDA(snd_hdmi_show_eld); | ||
| 430 | 426 | ||
| 431 | #ifdef CONFIG_PROC_FS | 427 | #ifdef CONFIG_PROC_FS |
| 432 | 428 | ||
| @@ -585,7 +581,6 @@ int snd_hda_eld_proc_new(struct hda_codec *codec, struct hdmi_eld *eld, | |||
| 585 | 581 | ||
| 586 | return 0; | 582 | return 0; |
| 587 | } | 583 | } |
| 588 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_new); | ||
| 589 | 584 | ||
| 590 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | 585 | void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) |
| 591 | { | 586 | { |
| @@ -594,7 +589,6 @@ void snd_hda_eld_proc_free(struct hda_codec *codec, struct hdmi_eld *eld) | |||
| 594 | eld->proc_entry = NULL; | 589 | eld->proc_entry = NULL; |
| 595 | } | 590 | } |
| 596 | } | 591 | } |
| 597 | EXPORT_SYMBOL_HDA(snd_hda_eld_proc_free); | ||
| 598 | 592 | ||
| 599 | #endif /* CONFIG_PROC_FS */ | 593 | #endif /* CONFIG_PROC_FS */ |
| 600 | 594 | ||
| @@ -645,4 +639,3 @@ void hdmi_eld_update_pcm_info(struct hdmi_eld *eld, struct hda_pcm_stream *pcm, | |||
| 645 | pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); | 639 | pcm->channels_max = min(pcm->channels_max, codec_pars->channels_max); |
| 646 | pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); | 640 | pcm->maxbps = min(pcm->maxbps, codec_pars->maxbps); |
| 647 | } | 641 | } |
| 648 | EXPORT_SYMBOL_HDA(hdmi_eld_update_pcm_info); | ||
diff --git a/sound/pci/hda/hda_generic.c b/sound/pci/hda/hda_generic.c index 5ea21285ee1f..fb0582f8d725 100644 --- a/sound/pci/hda/hda_generic.c +++ b/sound/pci/hda/hda_generic.c | |||
| @@ -61,7 +61,6 @@ struct hda_gspec { | |||
| 61 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ | 61 | struct hda_gnode *cap_vol_node; /* Node for capture volume */ |
| 62 | unsigned int cur_cap_src; /* current capture source */ | 62 | unsigned int cur_cap_src; /* current capture source */ |
| 63 | struct hda_input_mux input_mux; | 63 | struct hda_input_mux input_mux; |
| 64 | char cap_labels[HDA_MAX_NUM_INPUTS][16]; | ||
| 65 | 64 | ||
| 66 | unsigned int def_amp_in_caps; | 65 | unsigned int def_amp_in_caps; |
| 67 | unsigned int def_amp_out_caps; | 66 | unsigned int def_amp_out_caps; |
| @@ -506,11 +505,10 @@ static const char *get_input_type(struct hda_gnode *node, unsigned int *pinctl) | |||
| 506 | * returns 0 if not found, 1 if found, or a negative error code. | 505 | * returns 0 if not found, 1 if found, or a negative error code. |
| 507 | */ | 506 | */ |
| 508 | static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | 507 | static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, |
| 509 | struct hda_gnode *node) | 508 | struct hda_gnode *node, int idx) |
| 510 | { | 509 | { |
| 511 | int i, err; | 510 | int i, err; |
| 512 | unsigned int pinctl; | 511 | unsigned int pinctl; |
| 513 | char *label; | ||
| 514 | const char *type; | 512 | const char *type; |
| 515 | 513 | ||
| 516 | if (node->checked) | 514 | if (node->checked) |
| @@ -523,7 +521,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 523 | child = hda_get_node(spec, node->conn_list[i]); | 521 | child = hda_get_node(spec, node->conn_list[i]); |
| 524 | if (! child) | 522 | if (! child) |
| 525 | continue; | 523 | continue; |
| 526 | err = parse_adc_sub_nodes(codec, spec, child); | 524 | err = parse_adc_sub_nodes(codec, spec, child, idx); |
| 527 | if (err < 0) | 525 | if (err < 0) |
| 528 | return err; | 526 | return err; |
| 529 | if (err > 0) { | 527 | if (err > 0) { |
| @@ -564,9 +562,7 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 564 | return 0; | 562 | return 0; |
| 565 | type = "Input"; | 563 | type = "Input"; |
| 566 | } | 564 | } |
| 567 | label = spec->cap_labels[spec->input_mux.num_items]; | 565 | snd_hda_add_imux_item(&spec->input_mux, type, idx, NULL); |
| 568 | strcpy(label, type); | ||
| 569 | spec->input_mux.items[spec->input_mux.num_items].label = label; | ||
| 570 | 566 | ||
| 571 | /* unmute the PIN external input */ | 567 | /* unmute the PIN external input */ |
| 572 | unmute_input(codec, node, 0); /* index = 0? */ | 568 | unmute_input(codec, node, 0); /* index = 0? */ |
| @@ -577,29 +573,6 @@ static int parse_adc_sub_nodes(struct hda_codec *codec, struct hda_gspec *spec, | |||
| 577 | return 1; /* found */ | 573 | return 1; /* found */ |
| 578 | } | 574 | } |
| 579 | 575 | ||
| 580 | /* add a capture source element */ | ||
| 581 | static void add_cap_src(struct hda_gspec *spec, int idx) | ||
| 582 | { | ||
| 583 | struct hda_input_mux_item *csrc; | ||
| 584 | char *buf; | ||
| 585 | int num, ocap; | ||
| 586 | |||
| 587 | num = spec->input_mux.num_items; | ||
| 588 | csrc = &spec->input_mux.items[num]; | ||
| 589 | buf = spec->cap_labels[num]; | ||
| 590 | for (ocap = 0; ocap < num; ocap++) { | ||
| 591 | if (! strcmp(buf, spec->cap_labels[ocap])) { | ||
| 592 | /* same label already exists, | ||
| 593 | * put the index number to be unique | ||
| 594 | */ | ||
| 595 | sprintf(buf, "%s %d", spec->cap_labels[ocap], num); | ||
| 596 | break; | ||
| 597 | } | ||
| 598 | } | ||
| 599 | csrc->index = idx; | ||
| 600 | spec->input_mux.num_items++; | ||
| 601 | } | ||
| 602 | |||
| 603 | /* | 576 | /* |
| 604 | * parse input | 577 | * parse input |
| 605 | */ | 578 | */ |
| @@ -624,22 +597,18 @@ static int parse_input_path(struct hda_codec *codec, struct hda_gnode *adc_node) | |||
| 624 | for (i = 0; i < adc_node->nconns; i++) { | 597 | for (i = 0; i < adc_node->nconns; i++) { |
| 625 | node = hda_get_node(spec, adc_node->conn_list[i]); | 598 | node = hda_get_node(spec, adc_node->conn_list[i]); |
| 626 | if (node && node->type == AC_WID_PIN) { | 599 | if (node && node->type == AC_WID_PIN) { |
| 627 | err = parse_adc_sub_nodes(codec, spec, node); | 600 | err = parse_adc_sub_nodes(codec, spec, node, i); |
| 628 | if (err < 0) | 601 | if (err < 0) |
| 629 | return err; | 602 | return err; |
| 630 | else if (err > 0) | ||
| 631 | add_cap_src(spec, i); | ||
| 632 | } | 603 | } |
| 633 | } | 604 | } |
| 634 | /* ... then check the rests, more complicated connections */ | 605 | /* ... then check the rests, more complicated connections */ |
| 635 | for (i = 0; i < adc_node->nconns; i++) { | 606 | for (i = 0; i < adc_node->nconns; i++) { |
| 636 | node = hda_get_node(spec, adc_node->conn_list[i]); | 607 | node = hda_get_node(spec, adc_node->conn_list[i]); |
| 637 | if (node && node->type != AC_WID_PIN) { | 608 | if (node && node->type != AC_WID_PIN) { |
| 638 | err = parse_adc_sub_nodes(codec, spec, node); | 609 | err = parse_adc_sub_nodes(codec, spec, node, i); |
| 639 | if (err < 0) | 610 | if (err < 0) |
| 640 | return err; | 611 | return err; |
| 641 | else if (err > 0) | ||
| 642 | add_cap_src(spec, i); | ||
| 643 | } | 612 | } |
| 644 | } | 613 | } |
| 645 | 614 | ||
diff --git a/sound/pci/hda/hda_intel.c b/sound/pci/hda/hda_intel.c index 34940a079051..21aa9b0e28f6 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
| @@ -78,8 +78,8 @@ MODULE_PARM_DESC(enable, "Enable Intel HD audio interface."); | |||
| 78 | module_param_array(model, charp, NULL, 0444); | 78 | module_param_array(model, charp, NULL, 0444); |
| 79 | MODULE_PARM_DESC(model, "Use the given board model."); | 79 | MODULE_PARM_DESC(model, "Use the given board model."); |
| 80 | module_param_array(position_fix, int, NULL, 0444); | 80 | module_param_array(position_fix, int, NULL, 0444); |
| 81 | MODULE_PARM_DESC(position_fix, "Fix DMA pointer " | 81 | MODULE_PARM_DESC(position_fix, "DMA pointer read method." |
| 82 | "(0 = auto, 1 = none, 2 = POSBUF)."); | 82 | "(0 = auto, 1 = LPIB, 2 = POSBUF, 3 = VIACOMBO)."); |
| 83 | module_param_array(bdl_pos_adj, int, NULL, 0644); | 83 | module_param_array(bdl_pos_adj, int, NULL, 0644); |
| 84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); | 84 | MODULE_PARM_DESC(bdl_pos_adj, "BDL position adjustment offset."); |
| 85 | module_param_array(probe_mask, int, NULL, 0444); | 85 | module_param_array(probe_mask, int, NULL, 0444); |
| @@ -305,6 +305,7 @@ enum { | |||
| 305 | POS_FIX_AUTO, | 305 | POS_FIX_AUTO, |
| 306 | POS_FIX_LPIB, | 306 | POS_FIX_LPIB, |
| 307 | POS_FIX_POSBUF, | 307 | POS_FIX_POSBUF, |
| 308 | POS_FIX_VIACOMBO, | ||
| 308 | }; | 309 | }; |
| 309 | 310 | ||
| 310 | /* Defines for ATI HD Audio support in SB450 south bridge */ | 311 | /* Defines for ATI HD Audio support in SB450 south bridge */ |
| @@ -433,7 +434,6 @@ struct azx { | |||
| 433 | unsigned int polling_mode :1; | 434 | unsigned int polling_mode :1; |
| 434 | unsigned int msi :1; | 435 | unsigned int msi :1; |
| 435 | unsigned int irq_pending_warned :1; | 436 | unsigned int irq_pending_warned :1; |
| 436 | unsigned int via_dmapos_patch :1; /* enable DMA-position fix for VIA */ | ||
| 437 | unsigned int probing :1; /* codec probing phase */ | 437 | unsigned int probing :1; /* codec probing phase */ |
| 438 | 438 | ||
| 439 | /* for debugging */ | 439 | /* for debugging */ |
| @@ -458,6 +458,7 @@ enum { | |||
| 458 | AZX_DRIVER_ULI, | 458 | AZX_DRIVER_ULI, |
| 459 | AZX_DRIVER_NVIDIA, | 459 | AZX_DRIVER_NVIDIA, |
| 460 | AZX_DRIVER_TERA, | 460 | AZX_DRIVER_TERA, |
| 461 | AZX_DRIVER_CTX, | ||
| 461 | AZX_DRIVER_GENERIC, | 462 | AZX_DRIVER_GENERIC, |
| 462 | AZX_NUM_DRIVERS, /* keep this as last entry */ | 463 | AZX_NUM_DRIVERS, /* keep this as last entry */ |
| 463 | }; | 464 | }; |
| @@ -473,6 +474,7 @@ static char *driver_short_names[] __devinitdata = { | |||
| 473 | [AZX_DRIVER_ULI] = "HDA ULI M5461", | 474 | [AZX_DRIVER_ULI] = "HDA ULI M5461", |
| 474 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", | 475 | [AZX_DRIVER_NVIDIA] = "HDA NVidia", |
| 475 | [AZX_DRIVER_TERA] = "HDA Teradici", | 476 | [AZX_DRIVER_TERA] = "HDA Teradici", |
| 477 | [AZX_DRIVER_CTX] = "HDA Creative", | ||
| 476 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", | 478 | [AZX_DRIVER_GENERIC] = "HD-Audio Generic", |
| 477 | }; | 479 | }; |
| 478 | 480 | ||
| @@ -563,7 +565,10 @@ static void azx_init_cmd_io(struct azx *chip) | |||
| 563 | /* reset the rirb hw write pointer */ | 565 | /* reset the rirb hw write pointer */ |
| 564 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); | 566 | azx_writew(chip, RIRBWP, ICH6_RIRBWP_RST); |
| 565 | /* set N=1, get RIRB response interrupt for new entry */ | 567 | /* set N=1, get RIRB response interrupt for new entry */ |
| 566 | azx_writew(chip, RINTCNT, 1); | 568 | if (chip->driver_type == AZX_DRIVER_CTX) |
| 569 | azx_writew(chip, RINTCNT, 0xc0); | ||
| 570 | else | ||
| 571 | azx_writew(chip, RINTCNT, 1); | ||
| 567 | /* enable rirb dma and response irq */ | 572 | /* enable rirb dma and response irq */ |
| 568 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); | 573 | azx_writeb(chip, RIRBCTL, ICH6_RBCTL_DMA_EN | ICH6_RBCTL_IRQ_EN); |
| 569 | spin_unlock_irq(&chip->reg_lock); | 574 | spin_unlock_irq(&chip->reg_lock); |
| @@ -1136,8 +1141,11 @@ static irqreturn_t azx_interrupt(int irq, void *dev_id) | |||
| 1136 | /* clear rirb int */ | 1141 | /* clear rirb int */ |
| 1137 | status = azx_readb(chip, RIRBSTS); | 1142 | status = azx_readb(chip, RIRBSTS); |
| 1138 | if (status & RIRB_INT_MASK) { | 1143 | if (status & RIRB_INT_MASK) { |
| 1139 | if (status & RIRB_INT_RESPONSE) | 1144 | if (status & RIRB_INT_RESPONSE) { |
| 1145 | if (chip->driver_type == AZX_DRIVER_CTX) | ||
| 1146 | udelay(80); | ||
| 1140 | azx_update_rirb(chip); | 1147 | azx_update_rirb(chip); |
| 1148 | } | ||
| 1141 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); | 1149 | azx_writeb(chip, RIRBSTS, RIRB_INT_MASK); |
| 1142 | } | 1150 | } |
| 1143 | 1151 | ||
| @@ -1309,11 +1317,8 @@ static int azx_setup_controller(struct azx *chip, struct azx_dev *azx_dev) | |||
| 1309 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); | 1317 | azx_sd_writel(azx_dev, SD_BDLPU, upper_32_bits(azx_dev->bdl.addr)); |
| 1310 | 1318 | ||
| 1311 | /* enable the position buffer */ | 1319 | /* enable the position buffer */ |
| 1312 | if (chip->position_fix[0] == POS_FIX_POSBUF || | 1320 | if (chip->position_fix[0] != POS_FIX_LPIB || |
| 1313 | chip->position_fix[0] == POS_FIX_AUTO || | 1321 | chip->position_fix[1] != POS_FIX_LPIB) { |
| 1314 | chip->position_fix[1] == POS_FIX_POSBUF || | ||
| 1315 | chip->position_fix[1] == POS_FIX_AUTO || | ||
| 1316 | chip->via_dmapos_patch) { | ||
| 1317 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) | 1322 | if (!(azx_readl(chip, DPLBASE) & ICH6_DPLBASE_ENABLE)) |
| 1318 | azx_writel(chip, DPLBASE, | 1323 | azx_writel(chip, DPLBASE, |
| 1319 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); | 1324 | (u32)chip->posbuf.addr | ICH6_DPLBASE_ENABLE); |
| @@ -1647,7 +1652,7 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 1647 | struct azx_dev *azx_dev = get_azx_dev(substream); | 1652 | struct azx_dev *azx_dev = get_azx_dev(substream); |
| 1648 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; | 1653 | struct hda_pcm_stream *hinfo = apcm->hinfo[substream->stream]; |
| 1649 | struct snd_pcm_runtime *runtime = substream->runtime; | 1654 | struct snd_pcm_runtime *runtime = substream->runtime; |
| 1650 | unsigned int bufsize, period_bytes, format_val; | 1655 | unsigned int bufsize, period_bytes, format_val, stream_tag; |
| 1651 | int err; | 1656 | int err; |
| 1652 | 1657 | ||
| 1653 | azx_stream_reset(chip, azx_dev); | 1658 | azx_stream_reset(chip, azx_dev); |
| @@ -1689,7 +1694,12 @@ static int azx_pcm_prepare(struct snd_pcm_substream *substream) | |||
| 1689 | else | 1694 | else |
| 1690 | azx_dev->fifo_size = 0; | 1695 | azx_dev->fifo_size = 0; |
| 1691 | 1696 | ||
| 1692 | return snd_hda_codec_prepare(apcm->codec, hinfo, azx_dev->stream_tag, | 1697 | stream_tag = azx_dev->stream_tag; |
| 1698 | /* CA-IBG chips need the playback stream starting from 1 */ | ||
| 1699 | if (chip->driver_type == AZX_DRIVER_CTX && | ||
| 1700 | stream_tag > chip->capture_streams) | ||
| 1701 | stream_tag -= chip->capture_streams; | ||
| 1702 | return snd_hda_codec_prepare(apcm->codec, hinfo, stream_tag, | ||
| 1693 | azx_dev->format_val, substream); | 1703 | azx_dev->format_val, substream); |
| 1694 | } | 1704 | } |
| 1695 | 1705 | ||
| @@ -1852,20 +1862,21 @@ static unsigned int azx_get_position(struct azx *chip, | |||
| 1852 | struct azx_dev *azx_dev) | 1862 | struct azx_dev *azx_dev) |
| 1853 | { | 1863 | { |
| 1854 | unsigned int pos; | 1864 | unsigned int pos; |
| 1865 | int stream = azx_dev->substream->stream; | ||
| 1855 | 1866 | ||
| 1856 | if (chip->via_dmapos_patch) | 1867 | switch (chip->position_fix[stream]) { |
| 1868 | case POS_FIX_LPIB: | ||
| 1869 | /* read LPIB */ | ||
| 1870 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
| 1871 | break; | ||
| 1872 | case POS_FIX_VIACOMBO: | ||
| 1857 | pos = azx_via_get_position(chip, azx_dev); | 1873 | pos = azx_via_get_position(chip, azx_dev); |
| 1858 | else { | 1874 | break; |
| 1859 | int stream = azx_dev->substream->stream; | 1875 | default: |
| 1860 | if (chip->position_fix[stream] == POS_FIX_POSBUF || | 1876 | /* use the position buffer */ |
| 1861 | chip->position_fix[stream] == POS_FIX_AUTO) { | 1877 | pos = le32_to_cpu(*azx_dev->posbuf); |
| 1862 | /* use the position buffer */ | ||
| 1863 | pos = le32_to_cpu(*azx_dev->posbuf); | ||
| 1864 | } else { | ||
| 1865 | /* read LPIB */ | ||
| 1866 | pos = azx_sd_readl(azx_dev, SD_LPIB); | ||
| 1867 | } | ||
| 1868 | } | 1878 | } |
| 1879 | |||
| 1869 | if (pos >= azx_dev->bufsize) | 1880 | if (pos >= azx_dev->bufsize) |
| 1870 | pos = 0; | 1881 | pos = 0; |
| 1871 | return pos; | 1882 | return pos; |
| @@ -2313,19 +2324,10 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
| 2313 | switch (fix) { | 2324 | switch (fix) { |
| 2314 | case POS_FIX_LPIB: | 2325 | case POS_FIX_LPIB: |
| 2315 | case POS_FIX_POSBUF: | 2326 | case POS_FIX_POSBUF: |
| 2327 | case POS_FIX_VIACOMBO: | ||
| 2316 | return fix; | 2328 | return fix; |
| 2317 | } | 2329 | } |
| 2318 | 2330 | ||
| 2319 | /* Check VIA/ATI HD Audio Controller exist */ | ||
| 2320 | switch (chip->driver_type) { | ||
| 2321 | case AZX_DRIVER_VIA: | ||
| 2322 | case AZX_DRIVER_ATI: | ||
| 2323 | chip->via_dmapos_patch = 1; | ||
| 2324 | /* Use link position directly, avoid any transfer problem. */ | ||
| 2325 | return POS_FIX_LPIB; | ||
| 2326 | } | ||
| 2327 | chip->via_dmapos_patch = 0; | ||
| 2328 | |||
| 2329 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); | 2331 | q = snd_pci_quirk_lookup(chip->pci, position_fix_list); |
| 2330 | if (q) { | 2332 | if (q) { |
| 2331 | printk(KERN_INFO | 2333 | printk(KERN_INFO |
| @@ -2334,6 +2336,15 @@ static int __devinit check_position_fix(struct azx *chip, int fix) | |||
| 2334 | q->value, q->subvendor, q->subdevice); | 2336 | q->value, q->subvendor, q->subdevice); |
| 2335 | return q->value; | 2337 | return q->value; |
| 2336 | } | 2338 | } |
| 2339 | |||
| 2340 | /* Check VIA/ATI HD Audio Controller exist */ | ||
| 2341 | switch (chip->driver_type) { | ||
| 2342 | case AZX_DRIVER_VIA: | ||
| 2343 | case AZX_DRIVER_ATI: | ||
| 2344 | /* Use link position directly, avoid any transfer problem. */ | ||
| 2345 | return POS_FIX_VIACOMBO; | ||
| 2346 | } | ||
| 2347 | |||
| 2337 | return POS_FIX_AUTO; | 2348 | return POS_FIX_AUTO; |
| 2338 | } | 2349 | } |
| 2339 | 2350 | ||
| @@ -2735,25 +2746,17 @@ static void __devexit azx_remove(struct pci_dev *pci) | |||
| 2735 | 2746 | ||
| 2736 | /* PCI IDs */ | 2747 | /* PCI IDs */ |
| 2737 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | 2748 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { |
| 2738 | /* ICH 6..10 */ | ||
| 2739 | { PCI_DEVICE(0x8086, 0x2668), .driver_data = AZX_DRIVER_ICH }, | ||
| 2740 | { PCI_DEVICE(0x8086, 0x27d8), .driver_data = AZX_DRIVER_ICH }, | ||
| 2741 | { PCI_DEVICE(0x8086, 0x269a), .driver_data = AZX_DRIVER_ICH }, | ||
| 2742 | { PCI_DEVICE(0x8086, 0x284b), .driver_data = AZX_DRIVER_ICH }, | ||
| 2743 | { PCI_DEVICE(0x8086, 0x2911), .driver_data = AZX_DRIVER_ICH }, | ||
| 2744 | { PCI_DEVICE(0x8086, 0x293e), .driver_data = AZX_DRIVER_ICH }, | ||
| 2745 | { PCI_DEVICE(0x8086, 0x293f), .driver_data = AZX_DRIVER_ICH }, | ||
| 2746 | { PCI_DEVICE(0x8086, 0x3a3e), .driver_data = AZX_DRIVER_ICH }, | ||
| 2747 | { PCI_DEVICE(0x8086, 0x3a6e), .driver_data = AZX_DRIVER_ICH }, | ||
| 2748 | /* PCH */ | ||
| 2749 | { PCI_DEVICE(0x8086, 0x3b56), .driver_data = AZX_DRIVER_ICH }, | ||
| 2750 | { PCI_DEVICE(0x8086, 0x3b57), .driver_data = AZX_DRIVER_ICH }, | ||
| 2751 | /* CPT */ | 2749 | /* CPT */ |
| 2752 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | 2750 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, |
| 2753 | /* PBG */ | 2751 | /* PBG */ |
| 2754 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, | 2752 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, |
| 2755 | /* SCH */ | 2753 | /* SCH */ |
| 2756 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, | 2754 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, |
| 2755 | /* Generic Intel */ | ||
| 2756 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), | ||
| 2757 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | ||
| 2758 | .class_mask = 0xffffff, | ||
| 2759 | .driver_data = AZX_DRIVER_ICH }, | ||
| 2757 | /* ATI SB 450/600 */ | 2760 | /* ATI SB 450/600 */ |
| 2758 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, | 2761 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, |
| 2759 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, | 2762 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, |
| @@ -2794,11 +2797,13 @@ static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | |||
| 2794 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), | 2797 | { PCI_DEVICE(PCI_VENDOR_ID_CREATIVE, PCI_ANY_ID), |
| 2795 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | 2798 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
| 2796 | .class_mask = 0xffffff, | 2799 | .class_mask = 0xffffff, |
| 2797 | .driver_data = AZX_DRIVER_GENERIC }, | 2800 | .driver_data = AZX_DRIVER_CTX }, |
| 2798 | #else | 2801 | #else |
| 2799 | /* this entry seems still valid -- i.e. without emu20kx chip */ | 2802 | /* this entry seems still valid -- i.e. without emu20kx chip */ |
| 2800 | { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_GENERIC }, | 2803 | { PCI_DEVICE(0x1102, 0x0009), .driver_data = AZX_DRIVER_CTX }, |
| 2801 | #endif | 2804 | #endif |
| 2805 | /* Vortex86MX */ | ||
| 2806 | { PCI_DEVICE(0x17f3, 0x3010), .driver_data = AZX_DRIVER_GENERIC }, | ||
| 2802 | /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ | 2807 | /* AMD/ATI Generic, PCI class code and Vendor ID for HD Audio */ |
| 2803 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), | 2808 | { PCI_DEVICE(PCI_VENDOR_ID_ATI, PCI_ANY_ID), |
| 2804 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | 2809 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 28ab4aead48f..46bbefe2e4a9 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
| @@ -38,10 +38,11 @@ | |||
| 38 | */ | 38 | */ |
| 39 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ | 39 | #define HDA_COMPOSE_AMP_VAL_OFS(nid,chs,idx,dir,ofs) \ |
| 40 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) | 40 | ((nid) | ((chs)<<16) | ((dir)<<18) | ((idx)<<19) | ((ofs)<<23)) |
| 41 | #define HDA_AMP_VAL_MIN_MUTE (1<<29) | ||
| 41 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ | 42 | #define HDA_COMPOSE_AMP_VAL(nid,chs,idx,dir) \ |
| 42 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) | 43 | HDA_COMPOSE_AMP_VAL_OFS(nid, chs, idx, dir, 0) |
| 43 | /* mono volume with index (index=0,1,...) (channel=1,2) */ | 44 | /* mono volume with index (index=0,1,...) (channel=1,2) */ |
| 44 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 45 | #define HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, channel, xindex, dir, flags) \ |
| 45 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 46 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
| 46 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ | 47 | .subdevice = HDA_SUBDEV_AMP_FLAG, \ |
| 47 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ | 48 | .access = SNDRV_CTL_ELEM_ACCESS_READWRITE | \ |
| @@ -51,16 +52,20 @@ | |||
| 51 | .get = snd_hda_mixer_amp_volume_get, \ | 52 | .get = snd_hda_mixer_amp_volume_get, \ |
| 52 | .put = snd_hda_mixer_amp_volume_put, \ | 53 | .put = snd_hda_mixer_amp_volume_put, \ |
| 53 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ | 54 | .tlv = { .c = snd_hda_mixer_amp_tlv }, \ |
| 54 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, direction) } | 55 | .private_value = HDA_COMPOSE_AMP_VAL(nid, channel, xindex, dir) | flags } |
| 55 | /* stereo volume with index */ | 56 | /* stereo volume with index */ |
| 56 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ | 57 | #define HDA_CODEC_VOLUME_IDX(xname, xcidx, nid, xindex, direction) \ |
| 57 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction) | 58 | HDA_CODEC_VOLUME_MONO_IDX(xname, xcidx, nid, 3, xindex, direction, 0) |
| 58 | /* mono volume */ | 59 | /* mono volume */ |
| 59 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ | 60 | #define HDA_CODEC_VOLUME_MONO(xname, nid, channel, xindex, direction) \ |
| 60 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction) | 61 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, channel, xindex, direction, 0) |
| 61 | /* stereo volume */ | 62 | /* stereo volume */ |
| 62 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ | 63 | #define HDA_CODEC_VOLUME(xname, nid, xindex, direction) \ |
| 63 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) | 64 | HDA_CODEC_VOLUME_MONO(xname, nid, 3, xindex, direction) |
| 65 | /* stereo volume with min=mute */ | ||
| 66 | #define HDA_CODEC_VOLUME_MIN_MUTE(xname, nid, xindex, direction) \ | ||
| 67 | HDA_CODEC_VOLUME_MONO_IDX(xname, 0, nid, 3, xindex, direction, \ | ||
| 68 | HDA_AMP_VAL_MIN_MUTE) | ||
| 64 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ | 69 | /* mono mute switch with index (index=0,1,...) (channel=1,2) */ |
| 65 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ | 70 | #define HDA_CODEC_MUTE_MONO_IDX(xname, xcidx, nid, channel, xindex, direction) \ |
| 66 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ | 71 | { .iface = SNDRV_CTL_ELEM_IFACE_MIXER, .name = xname, .index = xcidx, \ |
| @@ -215,7 +220,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | |||
| 215 | */ | 220 | */ |
| 216 | #define HDA_MAX_NUM_INPUTS 16 | 221 | #define HDA_MAX_NUM_INPUTS 16 |
| 217 | struct hda_input_mux_item { | 222 | struct hda_input_mux_item { |
| 218 | const char *label; | 223 | char label[32]; |
| 219 | unsigned int index; | 224 | unsigned int index; |
| 220 | }; | 225 | }; |
| 221 | struct hda_input_mux { | 226 | struct hda_input_mux { |
| @@ -366,9 +371,7 @@ struct hda_bus_unsolicited { | |||
| 366 | 371 | ||
| 367 | enum { | 372 | enum { |
| 368 | AUTO_PIN_MIC, | 373 | AUTO_PIN_MIC, |
| 369 | AUTO_PIN_FRONT_MIC, | 374 | AUTO_PIN_LINE_IN, |
| 370 | AUTO_PIN_LINE, | ||
| 371 | AUTO_PIN_FRONT_LINE, | ||
| 372 | AUTO_PIN_CD, | 375 | AUTO_PIN_CD, |
| 373 | AUTO_PIN_AUX, | 376 | AUTO_PIN_AUX, |
| 374 | AUTO_PIN_LAST | 377 | AUTO_PIN_LAST |
| @@ -380,9 +383,33 @@ enum { | |||
| 380 | AUTO_PIN_HP_OUT | 383 | AUTO_PIN_HP_OUT |
| 381 | }; | 384 | }; |
| 382 | 385 | ||
| 383 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | ||
| 384 | |||
| 385 | #define AUTO_CFG_MAX_OUTS 5 | 386 | #define AUTO_CFG_MAX_OUTS 5 |
| 387 | #define AUTO_CFG_MAX_INS 8 | ||
| 388 | |||
| 389 | struct auto_pin_cfg_item { | ||
| 390 | hda_nid_t pin; | ||
| 391 | int type; | ||
| 392 | }; | ||
| 393 | |||
| 394 | struct auto_pin_cfg; | ||
| 395 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
| 396 | int check_location); | ||
| 397 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
| 398 | const struct auto_pin_cfg *cfg, | ||
| 399 | int input); | ||
| 400 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
| 401 | int index, int *type_index_ret); | ||
| 402 | |||
| 403 | enum { | ||
| 404 | INPUT_PIN_ATTR_UNUSED, /* pin not connected */ | ||
| 405 | INPUT_PIN_ATTR_INT, /* internal mic/line-in */ | ||
| 406 | INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */ | ||
| 407 | INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */ | ||
| 408 | INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */ | ||
| 409 | INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */ | ||
| 410 | }; | ||
| 411 | |||
| 412 | int snd_hda_get_input_pin_attr(unsigned int def_conf); | ||
| 386 | 413 | ||
| 387 | struct auto_pin_cfg { | 414 | struct auto_pin_cfg { |
| 388 | int line_outs; | 415 | int line_outs; |
| @@ -393,7 +420,8 @@ struct auto_pin_cfg { | |||
| 393 | int hp_outs; | 420 | int hp_outs; |
| 394 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | 421 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
| 395 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 422 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; |
| 396 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 423 | int num_inputs; |
| 424 | struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS]; | ||
| 397 | int dig_outs; | 425 | int dig_outs; |
| 398 | hda_nid_t dig_out_pins[2]; | 426 | hda_nid_t dig_out_pins[2]; |
| 399 | hda_nid_t dig_in_pin; | 427 | hda_nid_t dig_in_pin; |
| @@ -558,6 +586,7 @@ int snd_hda_check_amp_list_power(struct hda_codec *codec, | |||
| 558 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) | 586 | #define get_amp_direction(kc) (((kc)->private_value >> 18) & 0x1) |
| 559 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) | 587 | #define get_amp_index(kc) (((kc)->private_value >> 19) & 0xf) |
| 560 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) | 588 | #define get_amp_offset(kc) (((kc)->private_value >> 23) & 0x3f) |
| 589 | #define get_amp_min_mute(kc) (((kc)->private_value >> 29) & 0x1) | ||
| 561 | 590 | ||
| 562 | /* | 591 | /* |
| 563 | * CEA Short Audio Descriptor data | 592 | * CEA Short Audio Descriptor data |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 10bbbaf6ebc3..f7ff3f7ccb8e 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
| @@ -1276,6 +1276,7 @@ static int patch_ad1986a(struct hda_codec *codec) | |||
| 1276 | spec->multiout.no_share_stream = 1; | 1276 | spec->multiout.no_share_stream = 1; |
| 1277 | 1277 | ||
| 1278 | codec->no_trigger_sense = 1; | 1278 | codec->no_trigger_sense = 1; |
| 1279 | codec->no_sticky_stream = 1; | ||
| 1279 | 1280 | ||
| 1280 | return 0; | 1281 | return 0; |
| 1281 | } | 1282 | } |
| @@ -1463,6 +1464,7 @@ static int patch_ad1983(struct hda_codec *codec) | |||
| 1463 | codec->patch_ops = ad198x_patch_ops; | 1464 | codec->patch_ops = ad198x_patch_ops; |
| 1464 | 1465 | ||
| 1465 | codec->no_trigger_sense = 1; | 1466 | codec->no_trigger_sense = 1; |
| 1467 | codec->no_sticky_stream = 1; | ||
| 1466 | 1468 | ||
| 1467 | return 0; | 1469 | return 0; |
| 1468 | } | 1470 | } |
| @@ -1917,6 +1919,7 @@ static int patch_ad1981(struct hda_codec *codec) | |||
| 1917 | } | 1919 | } |
| 1918 | 1920 | ||
| 1919 | codec->no_trigger_sense = 1; | 1921 | codec->no_trigger_sense = 1; |
| 1922 | codec->no_sticky_stream = 1; | ||
| 1920 | 1923 | ||
| 1921 | return 0; | 1924 | return 0; |
| 1922 | } | 1925 | } |
| @@ -2880,7 +2883,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
| 2880 | 2883 | ||
| 2881 | /* create input playback/capture controls for the given pin */ | 2884 | /* create input playback/capture controls for the given pin */ |
| 2882 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | 2885 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, |
| 2883 | const char *ctlname, int boost) | 2886 | const char *ctlname, int ctlidx, int boost) |
| 2884 | { | 2887 | { |
| 2885 | char name[32]; | 2888 | char name[32]; |
| 2886 | int err, idx; | 2889 | int err, idx; |
| @@ -2909,25 +2912,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | |||
| 2909 | } | 2912 | } |
| 2910 | 2913 | ||
| 2911 | /* create playback/capture controls for input pins */ | 2914 | /* create playback/capture controls for input pins */ |
| 2912 | static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, | 2915 | static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 2913 | const struct auto_pin_cfg *cfg) | 2916 | const struct auto_pin_cfg *cfg) |
| 2914 | { | 2917 | { |
| 2918 | struct ad198x_spec *spec = codec->spec; | ||
| 2915 | struct hda_input_mux *imux = &spec->private_imux; | 2919 | struct hda_input_mux *imux = &spec->private_imux; |
| 2916 | int i, err; | 2920 | int i, err, type, type_idx; |
| 2917 | 2921 | ||
| 2918 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 2922 | for (i = 0; i < cfg->num_inputs; i++) { |
| 2919 | err = new_analog_input(spec, cfg->input_pins[i], | 2923 | const char *label; |
| 2920 | auto_pin_cfg_labels[i], | 2924 | type = cfg->inputs[i].type; |
| 2921 | i <= AUTO_PIN_FRONT_MIC); | 2925 | label = hda_get_autocfg_input_label(codec, cfg, i); |
| 2926 | snd_hda_add_imux_item(imux, label, | ||
| 2927 | ad1988_pin_to_adc_idx(cfg->inputs[i].pin), | ||
| 2928 | &type_idx); | ||
| 2929 | err = new_analog_input(spec, cfg->inputs[i].pin, | ||
| 2930 | label, type_idx, | ||
| 2931 | type == AUTO_PIN_MIC); | ||
| 2922 | if (err < 0) | 2932 | if (err < 0) |
| 2923 | return err; | 2933 | return err; |
| 2924 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
| 2925 | imux->items[imux->num_items].index = ad1988_pin_to_adc_idx(cfg->input_pins[i]); | ||
| 2926 | imux->num_items++; | ||
| 2927 | } | 2934 | } |
| 2928 | imux->items[imux->num_items].label = "Mix"; | 2935 | snd_hda_add_imux_item(imux, "Mix", 9, NULL); |
| 2929 | imux->items[imux->num_items].index = 9; | ||
| 2930 | imux->num_items++; | ||
| 2931 | 2936 | ||
| 2932 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, | 2937 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, |
| 2933 | "Analog Mix Playback Volume", | 2938 | "Analog Mix Playback Volume", |
| @@ -2994,12 +2999,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
| 2994 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) | 2999 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) |
| 2995 | { | 3000 | { |
| 2996 | struct ad198x_spec *spec = codec->spec; | 3001 | struct ad198x_spec *spec = codec->spec; |
| 3002 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 2997 | int i, idx; | 3003 | int i, idx; |
| 2998 | 3004 | ||
| 2999 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3005 | for (i = 0; i < cfg->num_inputs; i++) { |
| 3000 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 3006 | hda_nid_t nid = cfg->inputs[i].pin; |
| 3001 | if (! nid) | ||
| 3002 | continue; | ||
| 3003 | switch (nid) { | 3007 | switch (nid) { |
| 3004 | case 0x15: /* port-C */ | 3008 | case 0x15: /* port-C */ |
| 3005 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); | 3009 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); |
| @@ -3009,7 +3013,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec) | |||
| 3009 | break; | 3013 | break; |
| 3010 | } | 3014 | } |
| 3011 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 3015 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 3012 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 3016 | i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN); |
| 3013 | if (nid != AD1988_PIN_CD_NID) | 3017 | if (nid != AD1988_PIN_CD_NID) |
| 3014 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3018 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
| 3015 | AMP_OUT_MUTE); | 3019 | AMP_OUT_MUTE); |
| @@ -3040,7 +3044,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
| 3040 | "Speaker")) < 0 || | 3044 | "Speaker")) < 0 || |
| 3041 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], | 3045 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
| 3042 | "Headphone")) < 0 || | 3046 | "Headphone")) < 0 || |
| 3043 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 3047 | (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
| 3044 | return err; | 3048 | return err; |
| 3045 | 3049 | ||
| 3046 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3050 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
| @@ -3235,6 +3239,7 @@ static int patch_ad1988(struct hda_codec *codec) | |||
| 3235 | spec->vmaster_nid = 0x04; | 3239 | spec->vmaster_nid = 0x04; |
| 3236 | 3240 | ||
| 3237 | codec->no_trigger_sense = 1; | 3241 | codec->no_trigger_sense = 1; |
| 3242 | codec->no_sticky_stream = 1; | ||
| 3238 | 3243 | ||
| 3239 | return 0; | 3244 | return 0; |
| 3240 | } | 3245 | } |
| @@ -3449,6 +3454,7 @@ static int patch_ad1884(struct hda_codec *codec) | |||
| 3449 | codec->patch_ops = ad198x_patch_ops; | 3454 | codec->patch_ops = ad198x_patch_ops; |
| 3450 | 3455 | ||
| 3451 | codec->no_trigger_sense = 1; | 3456 | codec->no_trigger_sense = 1; |
| 3457 | codec->no_sticky_stream = 1; | ||
| 3452 | 3458 | ||
| 3453 | return 0; | 3459 | return 0; |
| 3454 | } | 3460 | } |
| @@ -4422,6 +4428,7 @@ static int patch_ad1884a(struct hda_codec *codec) | |||
| 4422 | } | 4428 | } |
| 4423 | 4429 | ||
| 4424 | codec->no_trigger_sense = 1; | 4430 | codec->no_trigger_sense = 1; |
| 4431 | codec->no_sticky_stream = 1; | ||
| 4425 | 4432 | ||
| 4426 | return 0; | 4433 | return 0; |
| 4427 | } | 4434 | } |
| @@ -4761,6 +4768,7 @@ static int patch_ad1882(struct hda_codec *codec) | |||
| 4761 | } | 4768 | } |
| 4762 | 4769 | ||
| 4763 | codec->no_trigger_sense = 1; | 4770 | codec->no_trigger_sense = 1; |
| 4771 | codec->no_sticky_stream = 1; | ||
| 4764 | 4772 | ||
| 4765 | return 0; | 4773 | return 0; |
| 4766 | } | 4774 | } |
diff --git a/sound/pci/hda/patch_atihdmi.c b/sound/pci/hda/patch_atihdmi.c deleted file mode 100644 index fb684f00156b..000000000000 --- a/sound/pci/hda/patch_atihdmi.c +++ /dev/null | |||
| @@ -1,224 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Universal Interface for Intel High Definition Audio Codec | ||
| 3 | * | ||
| 4 | * HD audio interface patch for ATI HDMI codecs | ||
| 5 | * | ||
| 6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
| 7 | * | ||
| 8 | * | ||
| 9 | * This driver is free software; you can redistribute it and/or modify | ||
| 10 | * it under the terms of the GNU General Public License as published by | ||
| 11 | * the Free Software Foundation; either version 2 of the License, or | ||
| 12 | * (at your option) any later version. | ||
| 13 | * | ||
| 14 | * This driver is distributed in the hope that it will be useful, | ||
| 15 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 16 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 17 | * GNU General Public License for more details. | ||
| 18 | * | ||
| 19 | * You should have received a copy of the GNU General Public License | ||
| 20 | * along with this program; if not, write to the Free Software | ||
| 21 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 22 | */ | ||
| 23 | |||
| 24 | #include <linux/init.h> | ||
| 25 | #include <linux/delay.h> | ||
| 26 | #include <linux/slab.h> | ||
| 27 | #include <sound/core.h> | ||
| 28 | #include "hda_codec.h" | ||
| 29 | #include "hda_local.h" | ||
| 30 | |||
| 31 | struct atihdmi_spec { | ||
| 32 | struct hda_multi_out multiout; | ||
| 33 | |||
| 34 | struct hda_pcm pcm_rec; | ||
| 35 | }; | ||
| 36 | |||
| 37 | #define CVT_NID 0x02 /* audio converter */ | ||
| 38 | #define PIN_NID 0x03 /* HDMI output pin */ | ||
| 39 | |||
| 40 | static struct hda_verb atihdmi_basic_init[] = { | ||
| 41 | /* enable digital output on pin widget */ | ||
| 42 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
| 43 | {} /* terminator */ | ||
| 44 | }; | ||
| 45 | |||
| 46 | /* | ||
| 47 | * Controls | ||
| 48 | */ | ||
| 49 | static int atihdmi_build_controls(struct hda_codec *codec) | ||
| 50 | { | ||
| 51 | struct atihdmi_spec *spec = codec->spec; | ||
| 52 | int err; | ||
| 53 | |||
| 54 | err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid); | ||
| 55 | if (err < 0) | ||
| 56 | return err; | ||
| 57 | |||
| 58 | return 0; | ||
| 59 | } | ||
| 60 | |||
| 61 | static int atihdmi_init(struct hda_codec *codec) | ||
| 62 | { | ||
| 63 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
| 64 | /* SI codec requires to unmute the pin */ | ||
| 65 | if (get_wcaps(codec, PIN_NID) & AC_WCAP_OUT_AMP) | ||
| 66 | snd_hda_codec_write(codec, PIN_NID, 0, | ||
| 67 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
| 68 | AMP_OUT_UNMUTE); | ||
| 69 | return 0; | ||
| 70 | } | ||
| 71 | |||
| 72 | /* | ||
| 73 | * Digital out | ||
| 74 | */ | ||
| 75 | static int atihdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
| 76 | struct hda_codec *codec, | ||
| 77 | struct snd_pcm_substream *substream) | ||
| 78 | { | ||
| 79 | struct atihdmi_spec *spec = codec->spec; | ||
| 80 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
| 81 | } | ||
| 82 | |||
| 83 | static int atihdmi_dig_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
| 84 | struct hda_codec *codec, | ||
| 85 | struct snd_pcm_substream *substream) | ||
| 86 | { | ||
| 87 | struct atihdmi_spec *spec = codec->spec; | ||
| 88 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
| 89 | } | ||
| 90 | |||
| 91 | static int atihdmi_dig_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 92 | struct hda_codec *codec, | ||
| 93 | unsigned int stream_tag, | ||
| 94 | unsigned int format, | ||
| 95 | struct snd_pcm_substream *substream) | ||
| 96 | { | ||
| 97 | struct atihdmi_spec *spec = codec->spec; | ||
| 98 | int chans = substream->runtime->channels; | ||
| 99 | int i, err; | ||
| 100 | |||
| 101 | err = snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
| 102 | format, substream); | ||
| 103 | if (err < 0) | ||
| 104 | return err; | ||
| 105 | snd_hda_codec_write(codec, CVT_NID, 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
| 106 | chans - 1); | ||
| 107 | /* FIXME: XXX */ | ||
| 108 | for (i = 0; i < chans; i++) { | ||
| 109 | snd_hda_codec_write(codec, CVT_NID, 0, | ||
| 110 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
| 111 | (i << 4) | i); | ||
| 112 | } | ||
| 113 | return 0; | ||
| 114 | } | ||
| 115 | |||
| 116 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
| 117 | .substreams = 1, | ||
| 118 | .channels_min = 2, | ||
| 119 | .channels_max = 2, | ||
| 120 | .nid = CVT_NID, /* NID to query formats and rates and setup streams */ | ||
| 121 | .ops = { | ||
| 122 | .open = atihdmi_dig_playback_pcm_open, | ||
| 123 | .close = atihdmi_dig_playback_pcm_close, | ||
| 124 | .prepare = atihdmi_dig_playback_pcm_prepare | ||
| 125 | }, | ||
| 126 | }; | ||
| 127 | |||
| 128 | static int atihdmi_build_pcms(struct hda_codec *codec) | ||
| 129 | { | ||
| 130 | struct atihdmi_spec *spec = codec->spec; | ||
| 131 | struct hda_pcm *info = &spec->pcm_rec; | ||
| 132 | unsigned int chans; | ||
| 133 | |||
| 134 | codec->num_pcms = 1; | ||
| 135 | codec->pcm_info = info; | ||
| 136 | |||
| 137 | info->name = "ATI HDMI"; | ||
| 138 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 139 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = atihdmi_pcm_digital_playback; | ||
| 140 | |||
| 141 | /* FIXME: we must check ELD and change the PCM parameters dynamically | ||
| 142 | */ | ||
| 143 | chans = get_wcaps(codec, CVT_NID); | ||
| 144 | chans = get_wcaps_channels(chans); | ||
| 145 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
| 146 | |||
| 147 | return 0; | ||
| 148 | } | ||
| 149 | |||
| 150 | static void atihdmi_free(struct hda_codec *codec) | ||
| 151 | { | ||
| 152 | kfree(codec->spec); | ||
| 153 | } | ||
| 154 | |||
| 155 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
| 156 | .build_controls = atihdmi_build_controls, | ||
| 157 | .build_pcms = atihdmi_build_pcms, | ||
| 158 | .init = atihdmi_init, | ||
| 159 | .free = atihdmi_free, | ||
| 160 | }; | ||
| 161 | |||
| 162 | static int patch_atihdmi(struct hda_codec *codec) | ||
| 163 | { | ||
| 164 | struct atihdmi_spec *spec; | ||
| 165 | |||
| 166 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 167 | if (spec == NULL) | ||
| 168 | return -ENOMEM; | ||
| 169 | |||
| 170 | codec->spec = spec; | ||
| 171 | |||
| 172 | spec->multiout.num_dacs = 0; /* no analog */ | ||
| 173 | spec->multiout.max_channels = 2; | ||
| 174 | /* NID for copying analog to digital, | ||
| 175 | * seems to be unused in pure-digital | ||
| 176 | * case. | ||
| 177 | */ | ||
| 178 | spec->multiout.dig_out_nid = CVT_NID; | ||
| 179 | |||
| 180 | codec->patch_ops = atihdmi_patch_ops; | ||
| 181 | |||
| 182 | return 0; | ||
| 183 | } | ||
| 184 | |||
| 185 | /* | ||
| 186 | * patch entries | ||
| 187 | */ | ||
| 188 | static struct hda_codec_preset snd_hda_preset_atihdmi[] = { | ||
| 189 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
| 190 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
| 191 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
| 192 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | ||
| 193 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_atihdmi }, | ||
| 194 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_atihdmi }, | ||
| 195 | {} /* terminator */ | ||
| 196 | }; | ||
| 197 | |||
| 198 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
| 199 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
| 200 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
| 201 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
| 202 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
| 203 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
| 204 | |||
| 205 | MODULE_LICENSE("GPL"); | ||
| 206 | MODULE_DESCRIPTION("ATI HDMI HD-audio codec"); | ||
| 207 | |||
| 208 | static struct hda_codec_preset_list atihdmi_list = { | ||
| 209 | .preset = snd_hda_preset_atihdmi, | ||
| 210 | .owner = THIS_MODULE, | ||
| 211 | }; | ||
| 212 | |||
| 213 | static int __init patch_atihdmi_init(void) | ||
| 214 | { | ||
| 215 | return snd_hda_add_codec_preset(&atihdmi_list); | ||
| 216 | } | ||
| 217 | |||
| 218 | static void __exit patch_atihdmi_exit(void) | ||
| 219 | { | ||
| 220 | snd_hda_delete_codec_preset(&atihdmi_list); | ||
| 221 | } | ||
| 222 | |||
| 223 | module_init(patch_atihdmi_init) | ||
| 224 | module_exit(patch_atihdmi_exit) | ||
diff --git a/sound/pci/hda/patch_ca0110.c b/sound/pci/hda/patch_ca0110.c index af478019088e..46c8bf48c31f 100644 --- a/sound/pci/hda/patch_ca0110.c +++ b/sound/pci/hda/patch_ca0110.c | |||
| @@ -468,13 +468,13 @@ static void parse_input(struct hda_codec *codec) | |||
| 468 | spec->dig_in = nid; | 468 | spec->dig_in = nid; |
| 469 | continue; | 469 | continue; |
| 470 | } | 470 | } |
| 471 | for (j = 0; j < AUTO_PIN_LAST; j++) | 471 | for (j = 0; j < cfg->num_inputs; j++) |
| 472 | if (cfg->input_pins[j] == pin) | 472 | if (cfg->inputs[j].pin == pin) |
| 473 | break; | 473 | break; |
| 474 | if (j >= AUTO_PIN_LAST) | 474 | if (j >= cfg->num_inputs) |
| 475 | continue; | 475 | continue; |
| 476 | spec->input_pins[n] = pin; | 476 | spec->input_pins[n] = pin; |
| 477 | spec->input_labels[n] = auto_pin_cfg_labels[j]; | 477 | spec->input_labels[n] = hda_get_input_pin_label(codec, pin, 1); |
| 478 | spec->adcs[n] = nid; | 478 | spec->adcs[n] = nid; |
| 479 | n++; | 479 | n++; |
| 480 | } | 480 | } |
| @@ -489,7 +489,7 @@ static void parse_digital(struct hda_codec *codec) | |||
| 489 | if (cfg->dig_outs && | 489 | if (cfg->dig_outs && |
| 490 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], | 490 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], |
| 491 | &spec->dig_out, 1) == 1) | 491 | &spec->dig_out, 1) == 1) |
| 492 | spec->multiout.dig_out_nid = cfg->dig_out_pins[0]; | 492 | spec->multiout.dig_out_nid = spec->dig_out; |
| 493 | } | 493 | } |
| 494 | 494 | ||
| 495 | static int ca0110_parse_auto_config(struct hda_codec *codec) | 495 | static int ca0110_parse_auto_config(struct hda_codec *codec) |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 488fd9ade1ba..460fb2ef7e39 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
| @@ -65,6 +65,7 @@ struct cs_spec { | |||
| 65 | 65 | ||
| 66 | /* available models */ | 66 | /* available models */ |
| 67 | enum { | 67 | enum { |
| 68 | CS420X_MBP53, | ||
| 68 | CS420X_MBP55, | 69 | CS420X_MBP55, |
| 69 | CS420X_IMAC27, | 70 | CS420X_IMAC27, |
| 70 | CS420X_AUTO, | 71 | CS420X_AUTO, |
| @@ -329,12 +330,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) | |||
| 329 | { | 330 | { |
| 330 | struct cs_spec *spec = codec->spec; | 331 | struct cs_spec *spec = codec->spec; |
| 331 | struct auto_pin_cfg *cfg = &spec->autocfg; | 332 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 332 | hda_nid_t pin = cfg->input_pins[idx]; | 333 | hda_nid_t pin = cfg->inputs[idx].pin; |
| 333 | unsigned int val = snd_hda_query_pin_caps(codec, pin); | 334 | unsigned int val = snd_hda_query_pin_caps(codec, pin); |
| 334 | if (!(val & AC_PINCAP_PRES_DETECT)) | 335 | if (!(val & AC_PINCAP_PRES_DETECT)) |
| 335 | return 0; | 336 | return 0; |
| 336 | val = snd_hda_codec_get_pincfg(codec, pin); | 337 | val = snd_hda_codec_get_pincfg(codec, pin); |
| 337 | return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); | 338 | return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT); |
| 338 | } | 339 | } |
| 339 | 340 | ||
| 340 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | 341 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, |
| @@ -424,10 +425,8 @@ static int parse_input(struct hda_codec *codec) | |||
| 424 | struct auto_pin_cfg *cfg = &spec->autocfg; | 425 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 425 | int i; | 426 | int i; |
| 426 | 427 | ||
| 427 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 428 | for (i = 0; i < cfg->num_inputs; i++) { |
| 428 | hda_nid_t pin = cfg->input_pins[i]; | 429 | hda_nid_t pin = cfg->inputs[i].pin; |
| 429 | if (!pin) | ||
| 430 | continue; | ||
| 431 | spec->input_idx[spec->num_inputs] = i; | 430 | spec->input_idx[spec->num_inputs] = i; |
| 432 | spec->capsrc_idx[i] = spec->num_inputs++; | 431 | spec->capsrc_idx[i] = spec->num_inputs++; |
| 433 | spec->cur_input = i; | 432 | spec->cur_input = i; |
| @@ -438,16 +437,17 @@ static int parse_input(struct hda_codec *codec) | |||
| 438 | 437 | ||
| 439 | /* check whether the automatic mic switch is available */ | 438 | /* check whether the automatic mic switch is available */ |
| 440 | if (spec->num_inputs == 2 && | 439 | if (spec->num_inputs == 2 && |
| 441 | spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { | 440 | cfg->inputs[0].type == AUTO_PIN_MIC && |
| 442 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { | 441 | cfg->inputs[1].type == AUTO_PIN_MIC) { |
| 443 | if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 442 | if (is_ext_mic(codec, cfg->inputs[0].pin)) { |
| 443 | if (!is_ext_mic(codec, cfg->inputs[1].pin)) { | ||
| 444 | spec->mic_detect = 1; | 444 | spec->mic_detect = 1; |
| 445 | spec->automic_idx = AUTO_PIN_FRONT_MIC; | 445 | spec->automic_idx = 0; |
| 446 | } | 446 | } |
| 447 | } else { | 447 | } else { |
| 448 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 448 | if (is_ext_mic(codec, cfg->inputs[1].pin)) { |
| 449 | spec->mic_detect = 1; | 449 | spec->mic_detect = 1; |
| 450 | spec->automic_idx = AUTO_PIN_MIC; | 450 | spec->automic_idx = 1; |
| 451 | } | 451 | } |
| 452 | } | 452 | } |
| 453 | } | 453 | } |
| @@ -674,6 +674,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
| 674 | { | 674 | { |
| 675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 676 | struct cs_spec *spec = codec->spec; | 676 | struct cs_spec *spec = codec->spec; |
| 677 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 677 | unsigned int idx; | 678 | unsigned int idx; |
| 678 | 679 | ||
| 679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 680 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
| @@ -682,7 +683,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
| 682 | if (uinfo->value.enumerated.item >= spec->num_inputs) | 683 | if (uinfo->value.enumerated.item >= spec->num_inputs) |
| 683 | uinfo->value.enumerated.item = spec->num_inputs - 1; | 684 | uinfo->value.enumerated.item = spec->num_inputs - 1; |
| 684 | idx = spec->input_idx[uinfo->value.enumerated.item]; | 685 | idx = spec->input_idx[uinfo->value.enumerated.item]; |
| 685 | strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); | 686 | strcpy(uinfo->value.enumerated.name, |
| 687 | hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1)); | ||
| 686 | return 0; | 688 | return 0; |
| 687 | } | 689 | } |
| 688 | 690 | ||
| @@ -740,6 +742,27 @@ static struct hda_bind_ctls *make_bind_capture(struct hda_codec *codec, | |||
| 740 | return bind; | 742 | return bind; |
| 741 | } | 743 | } |
| 742 | 744 | ||
| 745 | /* add a (input-boost) volume control to the given input pin */ | ||
| 746 | static int add_input_volume_control(struct hda_codec *codec, | ||
| 747 | struct auto_pin_cfg *cfg, | ||
| 748 | int item) | ||
| 749 | { | ||
| 750 | hda_nid_t pin = cfg->inputs[item].pin; | ||
| 751 | u32 caps; | ||
| 752 | const char *label; | ||
| 753 | struct snd_kcontrol *kctl; | ||
| 754 | |||
| 755 | if (!(get_wcaps(codec, pin) & AC_WCAP_IN_AMP)) | ||
| 756 | return 0; | ||
| 757 | caps = query_amp_caps(codec, pin, HDA_INPUT); | ||
| 758 | caps = (caps & AC_AMPCAP_NUM_STEPS) >> AC_AMPCAP_NUM_STEPS_SHIFT; | ||
| 759 | if (caps <= 1) | ||
| 760 | return 0; | ||
| 761 | label = hda_get_autocfg_input_label(codec, cfg, item); | ||
| 762 | return add_volume(codec, label, 0, | ||
| 763 | HDA_COMPOSE_AMP_VAL(pin, 3, 0, HDA_INPUT), 1, &kctl); | ||
| 764 | } | ||
| 765 | |||
| 743 | static int build_input(struct hda_codec *codec) | 766 | static int build_input(struct hda_codec *codec) |
| 744 | { | 767 | { |
| 745 | struct cs_spec *spec = codec->spec; | 768 | struct cs_spec *spec = codec->spec; |
| @@ -779,6 +802,12 @@ static int build_input(struct hda_codec *codec) | |||
| 779 | return err; | 802 | return err; |
| 780 | } | 803 | } |
| 781 | 804 | ||
| 805 | for (i = 0; i < spec->num_inputs; i++) { | ||
| 806 | err = add_input_volume_control(codec, &spec->autocfg, i); | ||
| 807 | if (err < 0) | ||
| 808 | return err; | ||
| 809 | } | ||
| 810 | |||
| 782 | return 0; | 811 | return 0; |
| 783 | } | 812 | } |
| 784 | 813 | ||
| @@ -838,7 +867,8 @@ static void cs_automute(struct hda_codec *codec) | |||
| 838 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 867 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 839 | hp_present ? 0 : PIN_OUT); | 868 | hp_present ? 0 : PIN_OUT); |
| 840 | } | 869 | } |
| 841 | if (spec->board_config == CS420X_MBP55 || | 870 | if (spec->board_config == CS420X_MBP53 || |
| 871 | spec->board_config == CS420X_MBP55 || | ||
| 842 | spec->board_config == CS420X_IMAC27) { | 872 | spec->board_config == CS420X_IMAC27) { |
| 843 | unsigned int gpio = hp_present ? 0x02 : 0x08; | 873 | unsigned int gpio = hp_present ? 0x02 : 0x08; |
| 844 | snd_hda_codec_write(codec, 0x01, 0, | 874 | snd_hda_codec_write(codec, 0x01, 0, |
| @@ -853,15 +883,12 @@ static void cs_automic(struct hda_codec *codec) | |||
| 853 | hda_nid_t nid; | 883 | hda_nid_t nid; |
| 854 | unsigned int present; | 884 | unsigned int present; |
| 855 | 885 | ||
| 856 | nid = cfg->input_pins[spec->automic_idx]; | 886 | nid = cfg->inputs[spec->automic_idx].pin; |
| 857 | present = snd_hda_jack_detect(codec, nid); | 887 | present = snd_hda_jack_detect(codec, nid); |
| 858 | if (present) | 888 | if (present) |
| 859 | change_cur_input(codec, spec->automic_idx, 0); | 889 | change_cur_input(codec, spec->automic_idx, 0); |
| 860 | else { | 890 | else |
| 861 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? | 891 | change_cur_input(codec, !spec->automic_idx, 0); |
| 862 | AUTO_PIN_FRONT_MIC : AUTO_PIN_MIC; | ||
| 863 | change_cur_input(codec, imic, 0); | ||
| 864 | } | ||
| 865 | } | 892 | } |
| 866 | 893 | ||
| 867 | /* | 894 | /* |
| @@ -918,14 +945,14 @@ static void init_input(struct hda_codec *codec) | |||
| 918 | unsigned int coef; | 945 | unsigned int coef; |
| 919 | int i; | 946 | int i; |
| 920 | 947 | ||
| 921 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 948 | for (i = 0; i < cfg->num_inputs; i++) { |
| 922 | unsigned int ctl; | 949 | unsigned int ctl; |
| 923 | hda_nid_t pin = cfg->input_pins[i]; | 950 | hda_nid_t pin = cfg->inputs[i].pin; |
| 924 | if (!pin || !spec->adc_nid[i]) | 951 | if (!spec->adc_nid[i]) |
| 925 | continue; | 952 | continue; |
| 926 | /* set appropriate pin control and mute first */ | 953 | /* set appropriate pin control and mute first */ |
| 927 | ctl = PIN_IN; | 954 | ctl = PIN_IN; |
| 928 | if (i <= AUTO_PIN_FRONT_MIC) { | 955 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
| 929 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); | 956 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); |
| 930 | caps >>= AC_PINCAP_VREF_SHIFT; | 957 | caps >>= AC_PINCAP_VREF_SHIFT; |
| 931 | if (caps & AC_PINCAP_VREF_80) | 958 | if (caps & AC_PINCAP_VREF_80) |
| @@ -1130,6 +1157,7 @@ static int cs_parse_auto_config(struct hda_codec *codec) | |||
| 1130 | } | 1157 | } |
| 1131 | 1158 | ||
| 1132 | static const char *cs420x_models[CS420X_MODELS] = { | 1159 | static const char *cs420x_models[CS420X_MODELS] = { |
| 1160 | [CS420X_MBP53] = "mbp53", | ||
| 1133 | [CS420X_MBP55] = "mbp55", | 1161 | [CS420X_MBP55] = "mbp55", |
| 1134 | [CS420X_IMAC27] = "imac27", | 1162 | [CS420X_IMAC27] = "imac27", |
| 1135 | [CS420X_AUTO] = "auto", | 1163 | [CS420X_AUTO] = "auto", |
| @@ -1137,7 +1165,9 @@ static const char *cs420x_models[CS420X_MODELS] = { | |||
| 1137 | 1165 | ||
| 1138 | 1166 | ||
| 1139 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { | 1167 | static struct snd_pci_quirk cs420x_cfg_tbl[] = { |
| 1168 | SND_PCI_QUIRK(0x10de, 0x0ac0, "MacBookPro 5,3", CS420X_MBP53), | ||
| 1140 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), | 1169 | SND_PCI_QUIRK(0x10de, 0xcb79, "MacBookPro 5,5", CS420X_MBP55), |
| 1170 | SND_PCI_QUIRK(0x10de, 0xcb89, "MacBookPro 7,1", CS420X_MBP55), | ||
| 1141 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), | 1171 | SND_PCI_QUIRK(0x8086, 0x7270, "IMac 27 Inch", CS420X_IMAC27), |
| 1142 | {} /* terminator */ | 1172 | {} /* terminator */ |
| 1143 | }; | 1173 | }; |
| @@ -1147,6 +1177,20 @@ struct cs_pincfg { | |||
| 1147 | u32 val; | 1177 | u32 val; |
| 1148 | }; | 1178 | }; |
| 1149 | 1179 | ||
| 1180 | static struct cs_pincfg mbp53_pincfgs[] = { | ||
| 1181 | { 0x09, 0x012b4050 }, | ||
| 1182 | { 0x0a, 0x90100141 }, | ||
| 1183 | { 0x0b, 0x90100140 }, | ||
| 1184 | { 0x0c, 0x018b3020 }, | ||
| 1185 | { 0x0d, 0x90a00110 }, | ||
| 1186 | { 0x0e, 0x400000f0 }, | ||
| 1187 | { 0x0f, 0x01cbe030 }, | ||
| 1188 | { 0x10, 0x014be060 }, | ||
| 1189 | { 0x12, 0x400000f0 }, | ||
| 1190 | { 0x15, 0x400000f0 }, | ||
| 1191 | {} /* terminator */ | ||
| 1192 | }; | ||
| 1193 | |||
| 1150 | static struct cs_pincfg mbp55_pincfgs[] = { | 1194 | static struct cs_pincfg mbp55_pincfgs[] = { |
| 1151 | { 0x09, 0x012b4030 }, | 1195 | { 0x09, 0x012b4030 }, |
| 1152 | { 0x0a, 0x90100121 }, | 1196 | { 0x0a, 0x90100121 }, |
| @@ -1176,6 +1220,7 @@ static struct cs_pincfg imac27_pincfgs[] = { | |||
| 1176 | }; | 1220 | }; |
| 1177 | 1221 | ||
| 1178 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { | 1222 | static struct cs_pincfg *cs_pincfgs[CS420X_MODELS] = { |
| 1223 | [CS420X_MBP53] = mbp53_pincfgs, | ||
| 1179 | [CS420X_MBP55] = mbp55_pincfgs, | 1224 | [CS420X_MBP55] = mbp55_pincfgs, |
| 1180 | [CS420X_IMAC27] = imac27_pincfgs, | 1225 | [CS420X_IMAC27] = imac27_pincfgs, |
| 1181 | }; | 1226 | }; |
| @@ -1208,6 +1253,7 @@ static int patch_cs420x(struct hda_codec *codec) | |||
| 1208 | 1253 | ||
| 1209 | switch (spec->board_config) { | 1254 | switch (spec->board_config) { |
| 1210 | case CS420X_IMAC27: | 1255 | case CS420X_IMAC27: |
| 1256 | case CS420X_MBP53: | ||
| 1211 | case CS420X_MBP55: | 1257 | case CS420X_MBP55: |
| 1212 | /* GPIO1 = headphones */ | 1258 | /* GPIO1 = headphones */ |
| 1213 | /* GPIO3 = speakers */ | 1259 | /* GPIO3 = speakers */ |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 972e7c453b3d..6361f752b5f3 100644 --- a/sound/pci/hda/patch_conexant.c +++ b/sound/pci/hda/patch_conexant.c | |||
| @@ -57,6 +57,12 @@ struct conexant_jack { | |||
| 57 | 57 | ||
| 58 | }; | 58 | }; |
| 59 | 59 | ||
| 60 | struct pin_dac_pair { | ||
| 61 | hda_nid_t pin; | ||
| 62 | hda_nid_t dac; | ||
| 63 | int type; | ||
| 64 | }; | ||
| 65 | |||
| 60 | struct conexant_spec { | 66 | struct conexant_spec { |
| 61 | 67 | ||
| 62 | struct snd_kcontrol_new *mixers[5]; | 68 | struct snd_kcontrol_new *mixers[5]; |
| @@ -77,6 +83,7 @@ struct conexant_spec { | |||
| 77 | unsigned int cur_eapd; | 83 | unsigned int cur_eapd; |
| 78 | unsigned int hp_present; | 84 | unsigned int hp_present; |
| 79 | unsigned int auto_mic; | 85 | unsigned int auto_mic; |
| 86 | int auto_mic_ext; /* autocfg.inputs[] index for ext mic */ | ||
| 80 | unsigned int need_dac_fix; | 87 | unsigned int need_dac_fix; |
| 81 | 88 | ||
| 82 | /* capture */ | 89 | /* capture */ |
| @@ -110,9 +117,12 @@ struct conexant_spec { | |||
| 110 | struct auto_pin_cfg autocfg; | 117 | struct auto_pin_cfg autocfg; |
| 111 | struct hda_input_mux private_imux; | 118 | struct hda_input_mux private_imux; |
| 112 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; | 119 | hda_nid_t private_dac_nids[AUTO_CFG_MAX_OUTS]; |
| 120 | struct pin_dac_pair dac_info[8]; | ||
| 121 | int dac_info_filled; | ||
| 113 | 122 | ||
| 114 | unsigned int dell_automute; | ||
| 115 | unsigned int port_d_mode; | 123 | unsigned int port_d_mode; |
| 124 | unsigned int auto_mute:1; /* used in auto-parser */ | ||
| 125 | unsigned int dell_automute:1; | ||
| 116 | unsigned int dell_vostro:1; | 126 | unsigned int dell_vostro:1; |
| 117 | unsigned int ideapad:1; | 127 | unsigned int ideapad:1; |
| 118 | unsigned int thinkpad:1; | 128 | unsigned int thinkpad:1; |
| @@ -3065,7 +3075,7 @@ enum { | |||
| 3065 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ | 3075 | CXT5066_LAPTOP, /* Laptops w/ EAPD support */ |
| 3066 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ | 3076 | CXT5066_DELL_LAPTOP, /* Dell Laptop */ |
| 3067 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ | 3077 | CXT5066_OLPC_XO_1_5, /* OLPC XO 1.5 */ |
| 3068 | CXT5066_DELL_VOSTO, /* Dell Vostro 1015i */ | 3078 | CXT5066_DELL_VOSTRO, /* Dell Vostro 1015i */ |
| 3069 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ | 3079 | CXT5066_IDEAPAD, /* Lenovo IdeaPad U150 */ |
| 3070 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ | 3080 | CXT5066_THINKPAD, /* Lenovo ThinkPad T410s, others? */ |
| 3071 | CXT5066_HP_LAPTOP, /* HP Laptop */ | 3081 | CXT5066_HP_LAPTOP, /* HP Laptop */ |
| @@ -3076,25 +3086,26 @@ static const char *cxt5066_models[CXT5066_MODELS] = { | |||
| 3076 | [CXT5066_LAPTOP] = "laptop", | 3086 | [CXT5066_LAPTOP] = "laptop", |
| 3077 | [CXT5066_DELL_LAPTOP] = "dell-laptop", | 3087 | [CXT5066_DELL_LAPTOP] = "dell-laptop", |
| 3078 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", | 3088 | [CXT5066_OLPC_XO_1_5] = "olpc-xo-1_5", |
| 3079 | [CXT5066_DELL_VOSTO] = "dell-vostro", | 3089 | [CXT5066_DELL_VOSTRO] = "dell-vostro", |
| 3080 | [CXT5066_IDEAPAD] = "ideapad", | 3090 | [CXT5066_IDEAPAD] = "ideapad", |
| 3081 | [CXT5066_THINKPAD] = "thinkpad", | 3091 | [CXT5066_THINKPAD] = "thinkpad", |
| 3082 | [CXT5066_HP_LAPTOP] = "hp-laptop", | 3092 | [CXT5066_HP_LAPTOP] = "hp-laptop", |
| 3083 | }; | 3093 | }; |
| 3084 | 3094 | ||
| 3085 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { | 3095 | static struct snd_pci_quirk cxt5066_cfg_tbl[] = { |
| 3086 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | 3096 | SND_PCI_QUIRK_MASK(0x1025, 0xff00, 0x0400, "Acer", CXT5066_IDEAPAD), |
| 3087 | CXT5066_LAPTOP), | 3097 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTRO), |
| 3088 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", | 3098 | SND_PCI_QUIRK(0x1028, 0x02f5, "Dell", |
| 3089 | CXT5066_DELL_LAPTOP), | 3099 | CXT5066_DELL_LAPTOP), |
| 3090 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | 3100 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTRO), |
| 3091 | SND_PCI_QUIRK(0x1028, 0x02d8, "Dell Vostro", CXT5066_DELL_VOSTO), | ||
| 3092 | SND_PCI_QUIRK(0x1028, 0x0402, "Dell Vostro", CXT5066_DELL_VOSTO), | ||
| 3093 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), | 3101 | SND_PCI_QUIRK(0x1028, 0x0408, "Dell Inspiron One 19T", CXT5066_IDEAPAD), |
| 3094 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), | 3102 | SND_PCI_QUIRK(0x103c, 0x360b, "HP G60", CXT5066_HP_LAPTOP), |
| 3095 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), | 3103 | SND_PCI_QUIRK(0x1179, 0xff1e, "Toshiba Satellite C650D", CXT5066_IDEAPAD), |
| 3096 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), | 3104 | SND_PCI_QUIRK(0x1179, 0xff50, "Toshiba Satellite P500-PSPGSC-01800T", CXT5066_OLPC_XO_1_5), |
| 3097 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), | 3105 | SND_PCI_QUIRK(0x1179, 0xffe0, "Toshiba Satellite Pro T130-15F", CXT5066_OLPC_XO_1_5), |
| 3106 | SND_PCI_QUIRK(0x14f1, 0x0101, "Conexant Reference board", | ||
| 3107 | CXT5066_LAPTOP), | ||
| 3108 | SND_PCI_QUIRK(0x152d, 0x0833, "OLPC XO-1.5", CXT5066_OLPC_XO_1_5), | ||
| 3098 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), | 3109 | SND_PCI_QUIRK(0x17aa, 0x20f2, "Lenovo T400s", CXT5066_THINKPAD), |
| 3099 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), | 3110 | SND_PCI_QUIRK(0x17aa, 0x21b2, "Thinkpad X100e", CXT5066_IDEAPAD), |
| 3100 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), | 3111 | SND_PCI_QUIRK(0x17aa, 0x21b3, "Thinkpad Edge 13 (197)", CXT5066_IDEAPAD), |
| @@ -3196,7 +3207,7 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 3196 | spec->capture_prepare = cxt5066_olpc_capture_prepare; | 3207 | spec->capture_prepare = cxt5066_olpc_capture_prepare; |
| 3197 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; | 3208 | spec->capture_cleanup = cxt5066_olpc_capture_cleanup; |
| 3198 | break; | 3209 | break; |
| 3199 | case CXT5066_DELL_VOSTO: | 3210 | case CXT5066_DELL_VOSTRO: |
| 3200 | codec->patch_ops.init = cxt5066_init; | 3211 | codec->patch_ops.init = cxt5066_init; |
| 3201 | codec->patch_ops.unsol_event = cxt5066_vostro_event; | 3212 | codec->patch_ops.unsol_event = cxt5066_vostro_event; |
| 3202 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; | 3213 | spec->init_verbs[0] = cxt5066_init_verbs_vostro; |
| @@ -3254,6 +3265,604 @@ static int patch_cxt5066(struct hda_codec *codec) | |||
| 3254 | } | 3265 | } |
| 3255 | 3266 | ||
| 3256 | /* | 3267 | /* |
| 3268 | * Automatic parser for CX20641 & co | ||
| 3269 | */ | ||
| 3270 | |||
| 3271 | static hda_nid_t cx_auto_adc_nids[] = { 0x14 }; | ||
| 3272 | |||
| 3273 | /* get the connection index of @nid in the widget @mux */ | ||
| 3274 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | ||
| 3275 | hda_nid_t nid) | ||
| 3276 | { | ||
| 3277 | hda_nid_t conn[HDA_MAX_NUM_INPUTS]; | ||
| 3278 | int i, nums; | ||
| 3279 | |||
| 3280 | nums = snd_hda_get_connections(codec, mux, conn, ARRAY_SIZE(conn)); | ||
| 3281 | for (i = 0; i < nums; i++) | ||
| 3282 | if (conn[i] == nid) | ||
| 3283 | return i; | ||
| 3284 | return -1; | ||
| 3285 | } | ||
| 3286 | |||
| 3287 | /* get an unassigned DAC from the given list. | ||
| 3288 | * Return the nid if found and reduce the DAC list, or return zero if | ||
| 3289 | * not found | ||
| 3290 | */ | ||
| 3291 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t pin, | ||
| 3292 | hda_nid_t *dacs, int *num_dacs) | ||
| 3293 | { | ||
| 3294 | int i, nums = *num_dacs; | ||
| 3295 | hda_nid_t ret = 0; | ||
| 3296 | |||
| 3297 | for (i = 0; i < nums; i++) { | ||
| 3298 | if (get_connection_index(codec, pin, dacs[i]) >= 0) { | ||
| 3299 | ret = dacs[i]; | ||
| 3300 | break; | ||
| 3301 | } | ||
| 3302 | } | ||
| 3303 | if (!ret) | ||
| 3304 | return 0; | ||
| 3305 | if (--nums > 0) | ||
| 3306 | memmove(dacs, dacs + 1, nums * sizeof(hda_nid_t)); | ||
| 3307 | *num_dacs = nums; | ||
| 3308 | return ret; | ||
| 3309 | } | ||
| 3310 | |||
| 3311 | #define MAX_AUTO_DACS 5 | ||
| 3312 | |||
| 3313 | /* fill analog DAC list from the widget tree */ | ||
| 3314 | static int fill_cx_auto_dacs(struct hda_codec *codec, hda_nid_t *dacs) | ||
| 3315 | { | ||
| 3316 | hda_nid_t nid, end_nid; | ||
| 3317 | int nums = 0; | ||
| 3318 | |||
| 3319 | end_nid = codec->start_nid + codec->num_nodes; | ||
| 3320 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
| 3321 | unsigned int wcaps = get_wcaps(codec, nid); | ||
| 3322 | unsigned int type = get_wcaps_type(wcaps); | ||
| 3323 | if (type == AC_WID_AUD_OUT && !(wcaps & AC_WCAP_DIGITAL)) { | ||
| 3324 | dacs[nums++] = nid; | ||
| 3325 | if (nums >= MAX_AUTO_DACS) | ||
| 3326 | break; | ||
| 3327 | } | ||
| 3328 | } | ||
| 3329 | return nums; | ||
| 3330 | } | ||
| 3331 | |||
| 3332 | /* fill pin_dac_pair list from the pin and dac list */ | ||
| 3333 | static int fill_dacs_for_pins(struct hda_codec *codec, hda_nid_t *pins, | ||
| 3334 | int num_pins, hda_nid_t *dacs, int *rest, | ||
| 3335 | struct pin_dac_pair *filled, int type) | ||
| 3336 | { | ||
| 3337 | int i, nums; | ||
| 3338 | |||
| 3339 | nums = 0; | ||
| 3340 | for (i = 0; i < num_pins; i++) { | ||
| 3341 | filled[nums].pin = pins[i]; | ||
| 3342 | filled[nums].type = type; | ||
| 3343 | filled[nums].dac = get_unassigned_dac(codec, pins[i], dacs, rest); | ||
| 3344 | nums++; | ||
| 3345 | } | ||
| 3346 | return nums; | ||
| 3347 | } | ||
| 3348 | |||
| 3349 | /* parse analog output paths */ | ||
| 3350 | static void cx_auto_parse_output(struct hda_codec *codec) | ||
| 3351 | { | ||
| 3352 | struct conexant_spec *spec = codec->spec; | ||
| 3353 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3354 | hda_nid_t dacs[MAX_AUTO_DACS]; | ||
| 3355 | int i, j, nums, rest; | ||
| 3356 | |||
| 3357 | rest = fill_cx_auto_dacs(codec, dacs); | ||
| 3358 | /* parse all analog output pins */ | ||
| 3359 | nums = fill_dacs_for_pins(codec, cfg->line_out_pins, cfg->line_outs, | ||
| 3360 | dacs, &rest, spec->dac_info, | ||
| 3361 | AUTO_PIN_LINE_OUT); | ||
| 3362 | nums += fill_dacs_for_pins(codec, cfg->hp_pins, cfg->hp_outs, | ||
| 3363 | dacs, &rest, spec->dac_info + nums, | ||
| 3364 | AUTO_PIN_HP_OUT); | ||
| 3365 | nums += fill_dacs_for_pins(codec, cfg->speaker_pins, cfg->speaker_outs, | ||
| 3366 | dacs, &rest, spec->dac_info + nums, | ||
| 3367 | AUTO_PIN_SPEAKER_OUT); | ||
| 3368 | spec->dac_info_filled = nums; | ||
| 3369 | /* fill multiout struct */ | ||
| 3370 | for (i = 0; i < nums; i++) { | ||
| 3371 | hda_nid_t dac = spec->dac_info[i].dac; | ||
| 3372 | if (!dac) | ||
| 3373 | continue; | ||
| 3374 | switch (spec->dac_info[i].type) { | ||
| 3375 | case AUTO_PIN_LINE_OUT: | ||
| 3376 | spec->private_dac_nids[spec->multiout.num_dacs] = dac; | ||
| 3377 | spec->multiout.num_dacs++; | ||
| 3378 | break; | ||
| 3379 | case AUTO_PIN_HP_OUT: | ||
| 3380 | case AUTO_PIN_SPEAKER_OUT: | ||
| 3381 | if (!spec->multiout.hp_nid) { | ||
| 3382 | spec->multiout.hp_nid = dac; | ||
| 3383 | break; | ||
| 3384 | } | ||
| 3385 | for (j = 0; j < ARRAY_SIZE(spec->multiout.extra_out_nid); j++) | ||
| 3386 | if (!spec->multiout.extra_out_nid[j]) { | ||
| 3387 | spec->multiout.extra_out_nid[j] = dac; | ||
| 3388 | break; | ||
| 3389 | } | ||
| 3390 | break; | ||
| 3391 | } | ||
| 3392 | } | ||
| 3393 | spec->multiout.dac_nids = spec->private_dac_nids; | ||
| 3394 | spec->multiout.max_channels = nums * 2; | ||
| 3395 | |||
| 3396 | if (cfg->hp_outs > 0) | ||
| 3397 | spec->auto_mute = 1; | ||
| 3398 | spec->vmaster_nid = spec->private_dac_nids[0]; | ||
| 3399 | } | ||
| 3400 | |||
| 3401 | /* auto-mute/unmute speaker and line outs according to headphone jack */ | ||
| 3402 | static void cx_auto_hp_automute(struct hda_codec *codec) | ||
| 3403 | { | ||
| 3404 | struct conexant_spec *spec = codec->spec; | ||
| 3405 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3406 | int i, present; | ||
| 3407 | |||
| 3408 | if (!spec->auto_mute) | ||
| 3409 | return; | ||
| 3410 | present = 0; | ||
| 3411 | for (i = 0; i < cfg->hp_outs; i++) { | ||
| 3412 | if (snd_hda_jack_detect(codec, cfg->hp_pins[i])) { | ||
| 3413 | present = 1; | ||
| 3414 | break; | ||
| 3415 | } | ||
| 3416 | } | ||
| 3417 | for (i = 0; i < cfg->line_outs; i++) { | ||
| 3418 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | ||
| 3419 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 3420 | present ? 0 : PIN_OUT); | ||
| 3421 | } | ||
| 3422 | for (i = 0; i < cfg->speaker_outs; i++) { | ||
| 3423 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | ||
| 3424 | AC_VERB_SET_PIN_WIDGET_CONTROL, | ||
| 3425 | present ? 0 : PIN_OUT); | ||
| 3426 | } | ||
| 3427 | } | ||
| 3428 | |||
| 3429 | /* automatic switch internal and external mic */ | ||
| 3430 | static void cx_auto_automic(struct hda_codec *codec) | ||
| 3431 | { | ||
| 3432 | struct conexant_spec *spec = codec->spec; | ||
| 3433 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3434 | struct hda_input_mux *imux = &spec->private_imux; | ||
| 3435 | int ext_idx = spec->auto_mic_ext; | ||
| 3436 | |||
| 3437 | if (!spec->auto_mic) | ||
| 3438 | return; | ||
| 3439 | if (snd_hda_jack_detect(codec, cfg->inputs[ext_idx].pin)) { | ||
| 3440 | snd_hda_codec_write(codec, spec->adc_nids[0], 0, | ||
| 3441 | AC_VERB_SET_CONNECT_SEL, | ||
| 3442 | imux->items[ext_idx].index); | ||
| 3443 | } else { | ||
| 3444 | snd_hda_codec_write(codec, spec->adc_nids[0], 0, | ||
| 3445 | AC_VERB_SET_CONNECT_SEL, | ||
| 3446 | imux->items[!ext_idx].index); | ||
| 3447 | } | ||
| 3448 | } | ||
| 3449 | |||
| 3450 | static void cx_auto_unsol_event(struct hda_codec *codec, unsigned int res) | ||
| 3451 | { | ||
| 3452 | int nid = (res & AC_UNSOL_RES_SUBTAG) >> 20; | ||
| 3453 | switch (res >> 26) { | ||
| 3454 | case CONEXANT_HP_EVENT: | ||
| 3455 | cx_auto_hp_automute(codec); | ||
| 3456 | conexant_report_jack(codec, nid); | ||
| 3457 | break; | ||
| 3458 | case CONEXANT_MIC_EVENT: | ||
| 3459 | cx_auto_automic(codec); | ||
| 3460 | conexant_report_jack(codec, nid); | ||
| 3461 | break; | ||
| 3462 | } | ||
| 3463 | } | ||
| 3464 | |||
| 3465 | /* return true if it's an internal-mic pin */ | ||
| 3466 | static int is_int_mic(struct hda_codec *codec, hda_nid_t pin) | ||
| 3467 | { | ||
| 3468 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
| 3469 | return get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
| 3470 | snd_hda_get_input_pin_attr(def_conf) == INPUT_PIN_ATTR_INT; | ||
| 3471 | } | ||
| 3472 | |||
| 3473 | /* return true if it's an external-mic pin */ | ||
| 3474 | static int is_ext_mic(struct hda_codec *codec, hda_nid_t pin) | ||
| 3475 | { | ||
| 3476 | unsigned int def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
| 3477 | return get_defcfg_device(def_conf) == AC_JACK_MIC_IN && | ||
| 3478 | snd_hda_get_input_pin_attr(def_conf) >= INPUT_PIN_ATTR_NORMAL && | ||
| 3479 | (snd_hda_query_pin_caps(codec, pin) & AC_PINCAP_PRES_DETECT); | ||
| 3480 | } | ||
| 3481 | |||
| 3482 | /* check whether the pin config is suitable for auto-mic switching; | ||
| 3483 | * auto-mic is enabled only when one int-mic and one-ext mic exist | ||
| 3484 | */ | ||
| 3485 | static void cx_auto_check_auto_mic(struct hda_codec *codec) | ||
| 3486 | { | ||
| 3487 | struct conexant_spec *spec = codec->spec; | ||
| 3488 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3489 | |||
| 3490 | if (is_ext_mic(codec, cfg->inputs[0].pin) && | ||
| 3491 | is_int_mic(codec, cfg->inputs[1].pin)) { | ||
| 3492 | spec->auto_mic = 1; | ||
| 3493 | spec->auto_mic_ext = 1; | ||
| 3494 | return; | ||
| 3495 | } | ||
| 3496 | if (is_int_mic(codec, cfg->inputs[1].pin) && | ||
| 3497 | is_ext_mic(codec, cfg->inputs[0].pin)) { | ||
| 3498 | spec->auto_mic = 1; | ||
| 3499 | spec->auto_mic_ext = 0; | ||
| 3500 | return; | ||
| 3501 | } | ||
| 3502 | } | ||
| 3503 | |||
| 3504 | static void cx_auto_parse_input(struct hda_codec *codec) | ||
| 3505 | { | ||
| 3506 | struct conexant_spec *spec = codec->spec; | ||
| 3507 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3508 | struct hda_input_mux *imux; | ||
| 3509 | int i; | ||
| 3510 | |||
| 3511 | imux = &spec->private_imux; | ||
| 3512 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 3513 | int idx = get_connection_index(codec, spec->adc_nids[0], | ||
| 3514 | cfg->inputs[i].pin); | ||
| 3515 | if (idx >= 0) { | ||
| 3516 | const char *label; | ||
| 3517 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 3518 | snd_hda_add_imux_item(imux, label, idx, NULL); | ||
| 3519 | } | ||
| 3520 | } | ||
| 3521 | if (imux->num_items == 2 && cfg->num_inputs == 2) | ||
| 3522 | cx_auto_check_auto_mic(codec); | ||
| 3523 | if (imux->num_items > 1 && !spec->auto_mic) | ||
| 3524 | spec->input_mux = imux; | ||
| 3525 | } | ||
| 3526 | |||
| 3527 | /* get digital-input audio widget corresponding to the given pin */ | ||
| 3528 | static hda_nid_t cx_auto_get_dig_in(struct hda_codec *codec, hda_nid_t pin) | ||
| 3529 | { | ||
| 3530 | hda_nid_t nid, end_nid; | ||
| 3531 | |||
| 3532 | end_nid = codec->start_nid + codec->num_nodes; | ||
| 3533 | for (nid = codec->start_nid; nid < end_nid; nid++) { | ||
| 3534 | unsigned int wcaps = get_wcaps(codec, nid); | ||
| 3535 | unsigned int type = get_wcaps_type(wcaps); | ||
| 3536 | if (type == AC_WID_AUD_IN && (wcaps & AC_WCAP_DIGITAL)) { | ||
| 3537 | if (get_connection_index(codec, nid, pin) >= 0) | ||
| 3538 | return nid; | ||
| 3539 | } | ||
| 3540 | } | ||
| 3541 | return 0; | ||
| 3542 | } | ||
| 3543 | |||
| 3544 | static void cx_auto_parse_digital(struct hda_codec *codec) | ||
| 3545 | { | ||
| 3546 | struct conexant_spec *spec = codec->spec; | ||
| 3547 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3548 | hda_nid_t nid; | ||
| 3549 | |||
| 3550 | if (cfg->dig_outs && | ||
| 3551 | snd_hda_get_connections(codec, cfg->dig_out_pins[0], &nid, 1) == 1) | ||
| 3552 | spec->multiout.dig_out_nid = nid; | ||
| 3553 | if (cfg->dig_in_pin) | ||
| 3554 | spec->dig_in_nid = cx_auto_get_dig_in(codec, cfg->dig_in_pin); | ||
| 3555 | } | ||
| 3556 | |||
| 3557 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
| 3558 | static void cx_auto_parse_beep(struct hda_codec *codec) | ||
| 3559 | { | ||
| 3560 | struct conexant_spec *spec = codec->spec; | ||
| 3561 | hda_nid_t nid, end_nid; | ||
| 3562 | |||
| 3563 | end_nid = codec->start_nid + codec->num_nodes; | ||
| 3564 | for (nid = codec->start_nid; nid < end_nid; nid++) | ||
| 3565 | if (get_wcaps_type(get_wcaps(codec, nid)) == AC_WID_BEEP) { | ||
| 3566 | set_beep_amp(spec, nid, 0, HDA_OUTPUT); | ||
| 3567 | break; | ||
| 3568 | } | ||
| 3569 | } | ||
| 3570 | #else | ||
| 3571 | #define cx_auto_parse_beep(codec) | ||
| 3572 | #endif | ||
| 3573 | |||
| 3574 | static int cx_auto_parse_auto_config(struct hda_codec *codec) | ||
| 3575 | { | ||
| 3576 | struct conexant_spec *spec = codec->spec; | ||
| 3577 | int err; | ||
| 3578 | |||
| 3579 | err = snd_hda_parse_pin_def_config(codec, &spec->autocfg, NULL); | ||
| 3580 | if (err < 0) | ||
| 3581 | return err; | ||
| 3582 | |||
| 3583 | cx_auto_parse_output(codec); | ||
| 3584 | cx_auto_parse_input(codec); | ||
| 3585 | cx_auto_parse_digital(codec); | ||
| 3586 | cx_auto_parse_beep(codec); | ||
| 3587 | return 0; | ||
| 3588 | } | ||
| 3589 | |||
| 3590 | static void cx_auto_turn_on_eapd(struct hda_codec *codec, int num_pins, | ||
| 3591 | hda_nid_t *pins) | ||
| 3592 | { | ||
| 3593 | int i; | ||
| 3594 | for (i = 0; i < num_pins; i++) { | ||
| 3595 | if (snd_hda_query_pin_caps(codec, pins[i]) & AC_PINCAP_EAPD) | ||
| 3596 | snd_hda_codec_write(codec, pins[i], 0, | ||
| 3597 | AC_VERB_SET_EAPD_BTLENABLE, 0x02); | ||
| 3598 | } | ||
| 3599 | } | ||
| 3600 | |||
| 3601 | static void select_connection(struct hda_codec *codec, hda_nid_t pin, | ||
| 3602 | hda_nid_t src) | ||
| 3603 | { | ||
| 3604 | int idx = get_connection_index(codec, pin, src); | ||
| 3605 | if (idx >= 0) | ||
| 3606 | snd_hda_codec_write(codec, pin, 0, | ||
| 3607 | AC_VERB_SET_CONNECT_SEL, idx); | ||
| 3608 | } | ||
| 3609 | |||
| 3610 | static void cx_auto_init_output(struct hda_codec *codec) | ||
| 3611 | { | ||
| 3612 | struct conexant_spec *spec = codec->spec; | ||
| 3613 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3614 | hda_nid_t nid; | ||
| 3615 | int i; | ||
| 3616 | |||
| 3617 | for (i = 0; i < spec->multiout.num_dacs; i++) | ||
| 3618 | snd_hda_codec_write(codec, spec->multiout.dac_nids[i], 0, | ||
| 3619 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE); | ||
| 3620 | |||
| 3621 | for (i = 0; i < cfg->hp_outs; i++) | ||
| 3622 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | ||
| 3623 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_HP); | ||
| 3624 | if (spec->auto_mute) { | ||
| 3625 | for (i = 0; i < cfg->hp_outs; i++) { | ||
| 3626 | snd_hda_codec_write(codec, cfg->hp_pins[i], 0, | ||
| 3627 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 3628 | AC_USRSP_EN | CONEXANT_HP_EVENT); | ||
| 3629 | } | ||
| 3630 | cx_auto_hp_automute(codec); | ||
| 3631 | } else { | ||
| 3632 | for (i = 0; i < cfg->line_outs; i++) | ||
| 3633 | snd_hda_codec_write(codec, cfg->line_out_pins[i], 0, | ||
| 3634 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
| 3635 | for (i = 0; i < cfg->speaker_outs; i++) | ||
| 3636 | snd_hda_codec_write(codec, cfg->speaker_pins[i], 0, | ||
| 3637 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
| 3638 | } | ||
| 3639 | |||
| 3640 | for (i = 0; i < spec->dac_info_filled; i++) { | ||
| 3641 | nid = spec->dac_info[i].dac; | ||
| 3642 | if (!nid) | ||
| 3643 | nid = spec->multiout.dac_nids[0]; | ||
| 3644 | select_connection(codec, spec->dac_info[i].pin, nid); | ||
| 3645 | } | ||
| 3646 | |||
| 3647 | /* turn on EAPD */ | ||
| 3648 | cx_auto_turn_on_eapd(codec, cfg->line_outs, cfg->line_out_pins); | ||
| 3649 | cx_auto_turn_on_eapd(codec, cfg->hp_outs, cfg->hp_pins); | ||
| 3650 | cx_auto_turn_on_eapd(codec, cfg->speaker_outs, cfg->speaker_pins); | ||
| 3651 | } | ||
| 3652 | |||
| 3653 | static void cx_auto_init_input(struct hda_codec *codec) | ||
| 3654 | { | ||
| 3655 | struct conexant_spec *spec = codec->spec; | ||
| 3656 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3657 | int i; | ||
| 3658 | |||
| 3659 | for (i = 0; i < spec->num_adc_nids; i++) | ||
| 3660 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | ||
| 3661 | AC_VERB_SET_AMP_GAIN_MUTE, AMP_IN_MUTE(0)); | ||
| 3662 | |||
| 3663 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 3664 | unsigned int type; | ||
| 3665 | if (cfg->inputs[i].type == AUTO_PIN_MIC) | ||
| 3666 | type = PIN_VREF80; | ||
| 3667 | else | ||
| 3668 | type = PIN_IN; | ||
| 3669 | snd_hda_codec_write(codec, cfg->inputs[i].pin, 0, | ||
| 3670 | AC_VERB_SET_PIN_WIDGET_CONTROL, type); | ||
| 3671 | } | ||
| 3672 | |||
| 3673 | if (spec->auto_mic) { | ||
| 3674 | int ext_idx = spec->auto_mic_ext; | ||
| 3675 | snd_hda_codec_write(codec, cfg->inputs[ext_idx].pin, 0, | ||
| 3676 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 3677 | AC_USRSP_EN | CONEXANT_MIC_EVENT); | ||
| 3678 | cx_auto_automic(codec); | ||
| 3679 | } else { | ||
| 3680 | for (i = 0; i < spec->num_adc_nids; i++) { | ||
| 3681 | snd_hda_codec_write(codec, spec->adc_nids[i], 0, | ||
| 3682 | AC_VERB_SET_CONNECT_SEL, | ||
| 3683 | spec->private_imux.items[0].index); | ||
| 3684 | } | ||
| 3685 | } | ||
| 3686 | } | ||
| 3687 | |||
| 3688 | static void cx_auto_init_digital(struct hda_codec *codec) | ||
| 3689 | { | ||
| 3690 | struct conexant_spec *spec = codec->spec; | ||
| 3691 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3692 | |||
| 3693 | if (spec->multiout.dig_out_nid) | ||
| 3694 | snd_hda_codec_write(codec, cfg->dig_out_pins[0], 0, | ||
| 3695 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
| 3696 | if (spec->dig_in_nid) | ||
| 3697 | snd_hda_codec_write(codec, cfg->dig_in_pin, 0, | ||
| 3698 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_IN); | ||
| 3699 | } | ||
| 3700 | |||
| 3701 | static int cx_auto_init(struct hda_codec *codec) | ||
| 3702 | { | ||
| 3703 | /*snd_hda_sequence_write(codec, cx_auto_init_verbs);*/ | ||
| 3704 | cx_auto_init_output(codec); | ||
| 3705 | cx_auto_init_input(codec); | ||
| 3706 | cx_auto_init_digital(codec); | ||
| 3707 | return 0; | ||
| 3708 | } | ||
| 3709 | |||
| 3710 | static int cx_auto_add_volume(struct hda_codec *codec, const char *basename, | ||
| 3711 | const char *dir, int cidx, | ||
| 3712 | hda_nid_t nid, int hda_dir) | ||
| 3713 | { | ||
| 3714 | static char name[32]; | ||
| 3715 | static struct snd_kcontrol_new knew[] = { | ||
| 3716 | HDA_CODEC_VOLUME(name, 0, 0, 0), | ||
| 3717 | HDA_CODEC_MUTE(name, 0, 0, 0), | ||
| 3718 | }; | ||
| 3719 | static char *sfx[2] = { "Volume", "Switch" }; | ||
| 3720 | int i, err; | ||
| 3721 | |||
| 3722 | for (i = 0; i < 2; i++) { | ||
| 3723 | struct snd_kcontrol *kctl; | ||
| 3724 | knew[i].private_value = HDA_COMPOSE_AMP_VAL(nid, 3, 0, hda_dir); | ||
| 3725 | knew[i].subdevice = HDA_SUBDEV_AMP_FLAG; | ||
| 3726 | knew[i].index = cidx; | ||
| 3727 | snprintf(name, sizeof(name), "%s%s %s", basename, dir, sfx[i]); | ||
| 3728 | kctl = snd_ctl_new1(&knew[i], codec); | ||
| 3729 | if (!kctl) | ||
| 3730 | return -ENOMEM; | ||
| 3731 | err = snd_hda_ctl_add(codec, nid, kctl); | ||
| 3732 | if (err < 0) | ||
| 3733 | return err; | ||
| 3734 | if (!(query_amp_caps(codec, nid, hda_dir) & AC_AMPCAP_MUTE)) | ||
| 3735 | break; | ||
| 3736 | } | ||
| 3737 | return 0; | ||
| 3738 | } | ||
| 3739 | |||
| 3740 | #define cx_auto_add_pb_volume(codec, nid, str, idx) \ | ||
| 3741 | cx_auto_add_volume(codec, str, " Playback", idx, nid, HDA_OUTPUT) | ||
| 3742 | |||
| 3743 | static int cx_auto_build_output_controls(struct hda_codec *codec) | ||
| 3744 | { | ||
| 3745 | struct conexant_spec *spec = codec->spec; | ||
| 3746 | int i, err; | ||
| 3747 | int num_line = 0, num_hp = 0, num_spk = 0; | ||
| 3748 | static const char *texts[3] = { "Front", "Surround", "CLFE" }; | ||
| 3749 | |||
| 3750 | if (spec->dac_info_filled == 1) | ||
| 3751 | return cx_auto_add_pb_volume(codec, spec->dac_info[0].dac, | ||
| 3752 | "Master", 0); | ||
| 3753 | for (i = 0; i < spec->dac_info_filled; i++) { | ||
| 3754 | const char *label; | ||
| 3755 | int idx, type; | ||
| 3756 | if (!spec->dac_info[i].dac) | ||
| 3757 | continue; | ||
| 3758 | type = spec->dac_info[i].type; | ||
| 3759 | if (type == AUTO_PIN_LINE_OUT) | ||
| 3760 | type = spec->autocfg.line_out_type; | ||
| 3761 | switch (type) { | ||
| 3762 | case AUTO_PIN_LINE_OUT: | ||
| 3763 | default: | ||
| 3764 | label = texts[num_line++]; | ||
| 3765 | idx = 0; | ||
| 3766 | break; | ||
| 3767 | case AUTO_PIN_HP_OUT: | ||
| 3768 | label = "Headphone"; | ||
| 3769 | idx = num_hp++; | ||
| 3770 | break; | ||
| 3771 | case AUTO_PIN_SPEAKER_OUT: | ||
| 3772 | label = "Speaker"; | ||
| 3773 | idx = num_spk++; | ||
| 3774 | break; | ||
| 3775 | } | ||
| 3776 | err = cx_auto_add_pb_volume(codec, spec->dac_info[i].dac, | ||
| 3777 | label, idx); | ||
| 3778 | if (err < 0) | ||
| 3779 | return err; | ||
| 3780 | } | ||
| 3781 | return 0; | ||
| 3782 | } | ||
| 3783 | |||
| 3784 | static int cx_auto_build_input_controls(struct hda_codec *codec) | ||
| 3785 | { | ||
| 3786 | struct conexant_spec *spec = codec->spec; | ||
| 3787 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 3788 | static const char *prev_label; | ||
| 3789 | int i, err, cidx; | ||
| 3790 | |||
| 3791 | err = cx_auto_add_volume(codec, "Capture", "", 0, spec->adc_nids[0], | ||
| 3792 | HDA_INPUT); | ||
| 3793 | if (err < 0) | ||
| 3794 | return err; | ||
| 3795 | prev_label = NULL; | ||
| 3796 | cidx = 0; | ||
| 3797 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 3798 | hda_nid_t nid = cfg->inputs[i].pin; | ||
| 3799 | const char *label; | ||
| 3800 | if (!(get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) | ||
| 3801 | continue; | ||
| 3802 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 3803 | if (label == prev_label) | ||
| 3804 | cidx++; | ||
| 3805 | else | ||
| 3806 | cidx = 0; | ||
| 3807 | prev_label = label; | ||
| 3808 | err = cx_auto_add_volume(codec, label, " Capture", cidx, | ||
| 3809 | nid, HDA_INPUT); | ||
| 3810 | if (err < 0) | ||
| 3811 | return err; | ||
| 3812 | } | ||
| 3813 | return 0; | ||
| 3814 | } | ||
| 3815 | |||
| 3816 | static int cx_auto_build_controls(struct hda_codec *codec) | ||
| 3817 | { | ||
| 3818 | int err; | ||
| 3819 | |||
| 3820 | err = cx_auto_build_output_controls(codec); | ||
| 3821 | if (err < 0) | ||
| 3822 | return err; | ||
| 3823 | err = cx_auto_build_input_controls(codec); | ||
| 3824 | if (err < 0) | ||
| 3825 | return err; | ||
| 3826 | return conexant_build_controls(codec); | ||
| 3827 | } | ||
| 3828 | |||
| 3829 | static struct hda_codec_ops cx_auto_patch_ops = { | ||
| 3830 | .build_controls = cx_auto_build_controls, | ||
| 3831 | .build_pcms = conexant_build_pcms, | ||
| 3832 | .init = cx_auto_init, | ||
| 3833 | .free = conexant_free, | ||
| 3834 | .unsol_event = cx_auto_unsol_event, | ||
| 3835 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 3836 | .suspend = conexant_suspend, | ||
| 3837 | #endif | ||
| 3838 | .reboot_notify = snd_hda_shutup_pins, | ||
| 3839 | }; | ||
| 3840 | |||
| 3841 | static int patch_conexant_auto(struct hda_codec *codec) | ||
| 3842 | { | ||
| 3843 | struct conexant_spec *spec; | ||
| 3844 | int err; | ||
| 3845 | |||
| 3846 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 3847 | if (!spec) | ||
| 3848 | return -ENOMEM; | ||
| 3849 | codec->spec = spec; | ||
| 3850 | spec->adc_nids = cx_auto_adc_nids; | ||
| 3851 | spec->num_adc_nids = ARRAY_SIZE(cx_auto_adc_nids); | ||
| 3852 | spec->capsrc_nids = spec->adc_nids; | ||
| 3853 | err = cx_auto_parse_auto_config(codec); | ||
| 3854 | if (err < 0) { | ||
| 3855 | kfree(codec->spec); | ||
| 3856 | codec->spec = NULL; | ||
| 3857 | return err; | ||
| 3858 | } | ||
| 3859 | codec->patch_ops = cx_auto_patch_ops; | ||
| 3860 | if (spec->beep_amp) | ||
| 3861 | snd_hda_attach_beep_device(codec, spec->beep_amp); | ||
| 3862 | return 0; | ||
| 3863 | } | ||
| 3864 | |||
| 3865 | /* | ||
| 3257 | */ | 3866 | */ |
| 3258 | 3867 | ||
| 3259 | static struct hda_codec_preset snd_hda_preset_conexant[] = { | 3868 | static struct hda_codec_preset snd_hda_preset_conexant[] = { |
| @@ -3271,6 +3880,22 @@ static struct hda_codec_preset snd_hda_preset_conexant[] = { | |||
| 3271 | .patch = patch_cxt5066 }, | 3880 | .patch = patch_cxt5066 }, |
| 3272 | { .id = 0x14f15069, .name = "CX20585", | 3881 | { .id = 0x14f15069, .name = "CX20585", |
| 3273 | .patch = patch_cxt5066 }, | 3882 | .patch = patch_cxt5066 }, |
| 3883 | { .id = 0x14f15097, .name = "CX20631", | ||
| 3884 | .patch = patch_conexant_auto }, | ||
| 3885 | { .id = 0x14f15098, .name = "CX20632", | ||
| 3886 | .patch = patch_conexant_auto }, | ||
| 3887 | { .id = 0x14f150a1, .name = "CX20641", | ||
| 3888 | .patch = patch_conexant_auto }, | ||
| 3889 | { .id = 0x14f150a2, .name = "CX20642", | ||
| 3890 | .patch = patch_conexant_auto }, | ||
| 3891 | { .id = 0x14f150ab, .name = "CX20651", | ||
| 3892 | .patch = patch_conexant_auto }, | ||
| 3893 | { .id = 0x14f150ac, .name = "CX20652", | ||
| 3894 | .patch = patch_conexant_auto }, | ||
| 3895 | { .id = 0x14f150b8, .name = "CX20664", | ||
| 3896 | .patch = patch_conexant_auto }, | ||
| 3897 | { .id = 0x14f150b9, .name = "CX20665", | ||
| 3898 | .patch = patch_conexant_auto }, | ||
| 3274 | {} /* terminator */ | 3899 | {} /* terminator */ |
| 3275 | }; | 3900 | }; |
| 3276 | 3901 | ||
| @@ -3281,6 +3906,14 @@ MODULE_ALIAS("snd-hda-codec-id:14f15066"); | |||
| 3281 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); | 3906 | MODULE_ALIAS("snd-hda-codec-id:14f15067"); |
| 3282 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); | 3907 | MODULE_ALIAS("snd-hda-codec-id:14f15068"); |
| 3283 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); | 3908 | MODULE_ALIAS("snd-hda-codec-id:14f15069"); |
| 3909 | MODULE_ALIAS("snd-hda-codec-id:14f15097"); | ||
| 3910 | MODULE_ALIAS("snd-hda-codec-id:14f15098"); | ||
| 3911 | MODULE_ALIAS("snd-hda-codec-id:14f150a1"); | ||
| 3912 | MODULE_ALIAS("snd-hda-codec-id:14f150a2"); | ||
| 3913 | MODULE_ALIAS("snd-hda-codec-id:14f150ab"); | ||
| 3914 | MODULE_ALIAS("snd-hda-codec-id:14f150ac"); | ||
| 3915 | MODULE_ALIAS("snd-hda-codec-id:14f150b8"); | ||
| 3916 | MODULE_ALIAS("snd-hda-codec-id:14f150b9"); | ||
| 3284 | 3917 | ||
| 3285 | MODULE_LICENSE("GPL"); | 3918 | MODULE_LICENSE("GPL"); |
| 3286 | MODULE_DESCRIPTION("Conexant HD-audio codec"); | 3919 | MODULE_DESCRIPTION("Conexant HD-audio codec"); |
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index afd6022a96a7..d3e49aa5b9ec 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
| @@ -3,6 +3,9 @@ | |||
| 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs | 3 | * patch_hdmi.c - routines for HDMI/DisplayPort codecs |
| 4 | * | 4 | * |
| 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. | 5 | * Copyright(c) 2008-2010 Intel Corporation. All rights reserved. |
| 6 | * Copyright (c) 2006 ATI Technologies Inc. | ||
| 7 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | ||
| 8 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | ||
| 6 | * | 9 | * |
| 7 | * Authors: | 10 | * Authors: |
| 8 | * Wu Fengguang <wfg@linux.intel.com> | 11 | * Wu Fengguang <wfg@linux.intel.com> |
| @@ -25,6 +28,22 @@ | |||
| 25 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | 28 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 26 | */ | 29 | */ |
| 27 | 30 | ||
| 31 | #include <linux/init.h> | ||
| 32 | #include <linux/delay.h> | ||
| 33 | #include <linux/slab.h> | ||
| 34 | #include <sound/core.h> | ||
| 35 | #include "hda_codec.h" | ||
| 36 | #include "hda_local.h" | ||
| 37 | |||
| 38 | /* | ||
| 39 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
| 40 | * could support two independent pipes, each of them can be connected to one or | ||
| 41 | * more ports (DVI, HDMI or DisplayPort). | ||
| 42 | * | ||
| 43 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
| 44 | */ | ||
| 45 | #define MAX_HDMI_CVTS 3 | ||
| 46 | #define MAX_HDMI_PINS 3 | ||
| 28 | 47 | ||
| 29 | struct hdmi_spec { | 48 | struct hdmi_spec { |
| 30 | int num_cvts; | 49 | int num_cvts; |
| @@ -49,10 +68,10 @@ struct hdmi_spec { | |||
| 49 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; | 68 | struct hda_pcm_stream codec_pcm_pars[MAX_HDMI_CVTS]; |
| 50 | 69 | ||
| 51 | /* | 70 | /* |
| 52 | * nvhdmi specific | 71 | * ati/nvhdmi specific |
| 53 | */ | 72 | */ |
| 54 | struct hda_multi_out multiout; | 73 | struct hda_multi_out multiout; |
| 55 | unsigned int codec_type; | 74 | struct hda_pcm_stream *pcm_playback; |
| 56 | 75 | ||
| 57 | /* misc flags */ | 76 | /* misc flags */ |
| 58 | /* PD bit indicates only the update, not the current state */ | 77 | /* PD bit indicates only the update, not the current state */ |
| @@ -65,13 +84,25 @@ struct hdmi_audio_infoframe { | |||
| 65 | u8 ver; /* 0x01 */ | 84 | u8 ver; /* 0x01 */ |
| 66 | u8 len; /* 0x0a */ | 85 | u8 len; /* 0x0a */ |
| 67 | 86 | ||
| 68 | u8 checksum; /* PB0 */ | 87 | u8 checksum; |
| 88 | |||
| 69 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ | 89 | u8 CC02_CT47; /* CC in bits 0:2, CT in 4:7 */ |
| 70 | u8 SS01_SF24; | 90 | u8 SS01_SF24; |
| 71 | u8 CXT04; | 91 | u8 CXT04; |
| 72 | u8 CA; | 92 | u8 CA; |
| 73 | u8 LFEPBL01_LSV36_DM_INH7; | 93 | u8 LFEPBL01_LSV36_DM_INH7; |
| 74 | u8 reserved[5]; /* PB6 - PB10 */ | 94 | }; |
| 95 | |||
| 96 | struct dp_audio_infoframe { | ||
| 97 | u8 type; /* 0x84 */ | ||
| 98 | u8 len; /* 0x1b */ | ||
| 99 | u8 ver; /* 0x11 << 2 */ | ||
| 100 | |||
| 101 | u8 CC02_CT47; /* match with HDMI infoframe from this on */ | ||
| 102 | u8 SS01_SF24; | ||
| 103 | u8 CXT04; | ||
| 104 | u8 CA; | ||
| 105 | u8 LFEPBL01_LSV36_DM_INH7; | ||
| 75 | }; | 106 | }; |
| 76 | 107 | ||
| 77 | /* | 108 | /* |
| @@ -162,7 +193,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
| 162 | /* 4ch */ | 193 | /* 4ch */ |
| 163 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, | 194 | [0x03] = { 0x00, 0x11, 0x23, 0x32, 0x44, 0xf5, 0xf6, 0xf7 }, |
| 164 | /* surround41 */ | 195 | /* surround41 */ |
| 165 | [0x09] = { 0x00, 0x11, 0x24, 0x34, 0x43, 0xf2, 0xf6, 0xf7 }, | 196 | [0x09] = { 0x00, 0x11, 0x24, 0x35, 0x42, 0xf3, 0xf6, 0xf7 }, |
| 166 | /* surround50 */ | 197 | /* surround50 */ |
| 167 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, | 198 | [0x0a] = { 0x00, 0x11, 0x24, 0x35, 0x43, 0xf2, 0xf6, 0xf7 }, |
| 168 | /* surround51 */ | 199 | /* surround51 */ |
| @@ -175,7 +206,7 @@ static int hdmi_channel_mapping[0x32][8] = { | |||
| 175 | * This is an ordered list! | 206 | * This is an ordered list! |
| 176 | * | 207 | * |
| 177 | * The preceding ones have better chances to be selected by | 208 | * The preceding ones have better chances to be selected by |
| 178 | * hdmi_setup_channel_allocation(). | 209 | * hdmi_channel_allocation(). |
| 179 | */ | 210 | */ |
| 180 | static struct cea_channel_speaker_allocation channel_allocations[] = { | 211 | static struct cea_channel_speaker_allocation channel_allocations[] = { |
| 181 | /* channel: 7 6 5 4 3 2 1 0 */ | 212 | /* channel: 7 6 5 4 3 2 1 0 */ |
| @@ -352,14 +383,14 @@ static void init_channel_allocations(void) | |||
| 352 | * | 383 | * |
| 353 | * TODO: it could select the wrong CA from multiple candidates. | 384 | * TODO: it could select the wrong CA from multiple candidates. |
| 354 | */ | 385 | */ |
| 355 | static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | 386 | static int hdmi_channel_allocation(struct hda_codec *codec, hda_nid_t nid, |
| 356 | struct hdmi_audio_infoframe *ai) | 387 | int channels) |
| 357 | { | 388 | { |
| 358 | struct hdmi_spec *spec = codec->spec; | 389 | struct hdmi_spec *spec = codec->spec; |
| 359 | struct hdmi_eld *eld; | 390 | struct hdmi_eld *eld; |
| 360 | int i; | 391 | int i; |
| 392 | int ca = 0; | ||
| 361 | int spk_mask = 0; | 393 | int spk_mask = 0; |
| 362 | int channels = 1 + (ai->CC02_CT47 & 0x7); | ||
| 363 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; | 394 | char buf[SND_PRINT_CHANNEL_ALLOCATION_ADVISED_BUFSIZE]; |
| 364 | 395 | ||
| 365 | /* | 396 | /* |
| @@ -397,16 +428,16 @@ static int hdmi_setup_channel_allocation(struct hda_codec *codec, hda_nid_t nid, | |||
| 397 | if (channels == channel_allocations[i].channels && | 428 | if (channels == channel_allocations[i].channels && |
| 398 | (spk_mask & channel_allocations[i].spk_mask) == | 429 | (spk_mask & channel_allocations[i].spk_mask) == |
| 399 | channel_allocations[i].spk_mask) { | 430 | channel_allocations[i].spk_mask) { |
| 400 | ai->CA = channel_allocations[i].ca_index; | 431 | ca = channel_allocations[i].ca_index; |
| 401 | break; | 432 | break; |
| 402 | } | 433 | } |
| 403 | } | 434 | } |
| 404 | 435 | ||
| 405 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); | 436 | snd_print_channel_allocation(eld->spk_alloc, buf, sizeof(buf)); |
| 406 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", | 437 | snd_printdd("HDMI: select CA 0x%x for %d-channel allocation: %s\n", |
| 407 | ai->CA, channels, buf); | 438 | ca, channels, buf); |
| 408 | 439 | ||
| 409 | return ai->CA; | 440 | return ca; |
| 410 | } | 441 | } |
| 411 | 442 | ||
| 412 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, | 443 | static void hdmi_debug_channel_mapping(struct hda_codec *codec, |
| @@ -428,10 +459,9 @@ static void hdmi_debug_channel_mapping(struct hda_codec *codec, | |||
| 428 | 459 | ||
| 429 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, | 460 | static void hdmi_setup_channel_mapping(struct hda_codec *codec, |
| 430 | hda_nid_t pin_nid, | 461 | hda_nid_t pin_nid, |
| 431 | struct hdmi_audio_infoframe *ai) | 462 | int ca) |
| 432 | { | 463 | { |
| 433 | int i; | 464 | int i; |
| 434 | int ca = ai->CA; | ||
| 435 | int err; | 465 | int err; |
| 436 | 466 | ||
| 437 | if (hdmi_channel_mapping[ca][1] == 0) { | 467 | if (hdmi_channel_mapping[ca][1] == 0) { |
| @@ -528,41 +558,37 @@ static void hdmi_clear_dip_buffers(struct hda_codec *codec, hda_nid_t pin_nid) | |||
| 528 | #endif | 558 | #endif |
| 529 | } | 559 | } |
| 530 | 560 | ||
| 531 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *ai) | 561 | static void hdmi_checksum_audio_infoframe(struct hdmi_audio_infoframe *hdmi_ai) |
| 532 | { | 562 | { |
| 533 | u8 *bytes = (u8 *)ai; | 563 | u8 *bytes = (u8 *)hdmi_ai; |
| 534 | u8 sum = 0; | 564 | u8 sum = 0; |
| 535 | int i; | 565 | int i; |
| 536 | 566 | ||
| 537 | ai->checksum = 0; | 567 | hdmi_ai->checksum = 0; |
| 538 | 568 | ||
| 539 | for (i = 0; i < sizeof(*ai); i++) | 569 | for (i = 0; i < sizeof(*hdmi_ai); i++) |
| 540 | sum += bytes[i]; | 570 | sum += bytes[i]; |
| 541 | 571 | ||
| 542 | ai->checksum = -sum; | 572 | hdmi_ai->checksum = -sum; |
| 543 | } | 573 | } |
| 544 | 574 | ||
| 545 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, | 575 | static void hdmi_fill_audio_infoframe(struct hda_codec *codec, |
| 546 | hda_nid_t pin_nid, | 576 | hda_nid_t pin_nid, |
| 547 | struct hdmi_audio_infoframe *ai) | 577 | u8 *dip, int size) |
| 548 | { | 578 | { |
| 549 | u8 *bytes = (u8 *)ai; | ||
| 550 | int i; | 579 | int i; |
| 551 | 580 | ||
| 552 | hdmi_debug_dip_size(codec, pin_nid); | 581 | hdmi_debug_dip_size(codec, pin_nid); |
| 553 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ | 582 | hdmi_clear_dip_buffers(codec, pin_nid); /* be paranoid */ |
| 554 | 583 | ||
| 555 | hdmi_checksum_audio_infoframe(ai); | ||
| 556 | |||
| 557 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 584 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
| 558 | for (i = 0; i < sizeof(*ai); i++) | 585 | for (i = 0; i < size; i++) |
| 559 | hdmi_write_dip_byte(codec, pin_nid, bytes[i]); | 586 | hdmi_write_dip_byte(codec, pin_nid, dip[i]); |
| 560 | } | 587 | } |
| 561 | 588 | ||
| 562 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | 589 | static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, |
| 563 | struct hdmi_audio_infoframe *ai) | 590 | u8 *dip, int size) |
| 564 | { | 591 | { |
| 565 | u8 *bytes = (u8 *)ai; | ||
| 566 | u8 val; | 592 | u8 val; |
| 567 | int i; | 593 | int i; |
| 568 | 594 | ||
| @@ -571,10 +597,10 @@ static bool hdmi_infoframe_uptodate(struct hda_codec *codec, hda_nid_t pin_nid, | |||
| 571 | return false; | 597 | return false; |
| 572 | 598 | ||
| 573 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); | 599 | hdmi_set_dip_index(codec, pin_nid, 0x0, 0x0); |
| 574 | for (i = 0; i < sizeof(*ai); i++) { | 600 | for (i = 0; i < size; i++) { |
| 575 | val = snd_hda_codec_read(codec, pin_nid, 0, | 601 | val = snd_hda_codec_read(codec, pin_nid, 0, |
| 576 | AC_VERB_GET_HDMI_DIP_DATA, 0); | 602 | AC_VERB_GET_HDMI_DIP_DATA, 0); |
| 577 | if (val != bytes[i]) | 603 | if (val != dip[i]) |
| 578 | return false; | 604 | return false; |
| 579 | } | 605 | } |
| 580 | 606 | ||
| @@ -586,15 +612,13 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
| 586 | { | 612 | { |
| 587 | struct hdmi_spec *spec = codec->spec; | 613 | struct hdmi_spec *spec = codec->spec; |
| 588 | hda_nid_t pin_nid; | 614 | hda_nid_t pin_nid; |
| 615 | int channels = substream->runtime->channels; | ||
| 616 | int ca; | ||
| 589 | int i; | 617 | int i; |
| 590 | struct hdmi_audio_infoframe ai = { | 618 | u8 ai[max(sizeof(struct hdmi_audio_infoframe), |
| 591 | .type = 0x84, | 619 | sizeof(struct dp_audio_infoframe))]; |
| 592 | .ver = 0x01, | ||
| 593 | .len = 0x0a, | ||
| 594 | .CC02_CT47 = substream->runtime->channels - 1, | ||
| 595 | }; | ||
| 596 | 620 | ||
| 597 | hdmi_setup_channel_allocation(codec, nid, &ai); | 621 | ca = hdmi_channel_allocation(codec, nid, channels); |
| 598 | 622 | ||
| 599 | for (i = 0; i < spec->num_pins; i++) { | 623 | for (i = 0; i < spec->num_pins; i++) { |
| 600 | if (spec->pin_cvt[i] != nid) | 624 | if (spec->pin_cvt[i] != nid) |
| @@ -603,14 +627,45 @@ static void hdmi_setup_audio_infoframe(struct hda_codec *codec, hda_nid_t nid, | |||
| 603 | continue; | 627 | continue; |
| 604 | 628 | ||
| 605 | pin_nid = spec->pin[i]; | 629 | pin_nid = spec->pin[i]; |
| 606 | if (!hdmi_infoframe_uptodate(codec, pin_nid, &ai)) { | 630 | |
| 631 | memset(ai, 0, sizeof(ai)); | ||
| 632 | if (spec->sink_eld[i].conn_type == 0) { /* HDMI */ | ||
| 633 | struct hdmi_audio_infoframe *hdmi_ai; | ||
| 634 | |||
| 635 | hdmi_ai = (struct hdmi_audio_infoframe *)ai; | ||
| 636 | hdmi_ai->type = 0x84; | ||
| 637 | hdmi_ai->ver = 0x01; | ||
| 638 | hdmi_ai->len = 0x0a; | ||
| 639 | hdmi_ai->CC02_CT47 = channels - 1; | ||
| 640 | hdmi_checksum_audio_infoframe(hdmi_ai); | ||
| 641 | } else if (spec->sink_eld[i].conn_type == 1) { /* DisplayPort */ | ||
| 642 | struct dp_audio_infoframe *dp_ai; | ||
| 643 | |||
| 644 | dp_ai = (struct dp_audio_infoframe *)ai; | ||
| 645 | dp_ai->type = 0x84; | ||
| 646 | dp_ai->len = 0x1b; | ||
| 647 | dp_ai->ver = 0x11 << 2; | ||
| 648 | dp_ai->CC02_CT47 = channels - 1; | ||
| 649 | } else { | ||
| 650 | snd_printd("HDMI: unknown connection type at pin %d\n", | ||
| 651 | pin_nid); | ||
| 652 | continue; | ||
| 653 | } | ||
| 654 | |||
| 655 | /* | ||
| 656 | * sizeof(ai) is used instead of sizeof(*hdmi_ai) or | ||
| 657 | * sizeof(*dp_ai) to avoid partial match/update problems when | ||
| 658 | * the user switches between HDMI/DP monitors. | ||
| 659 | */ | ||
| 660 | if (!hdmi_infoframe_uptodate(codec, pin_nid, ai, sizeof(ai))) { | ||
| 607 | snd_printdd("hdmi_setup_audio_infoframe: " | 661 | snd_printdd("hdmi_setup_audio_infoframe: " |
| 608 | "cvt=%d pin=%d channels=%d\n", | 662 | "cvt=%d pin=%d channels=%d\n", |
| 609 | nid, pin_nid, | 663 | nid, pin_nid, |
| 610 | substream->runtime->channels); | 664 | channels); |
| 611 | hdmi_setup_channel_mapping(codec, pin_nid, &ai); | 665 | hdmi_setup_channel_mapping(codec, pin_nid, ca); |
| 612 | hdmi_stop_infoframe_trans(codec, pin_nid); | 666 | hdmi_stop_infoframe_trans(codec, pin_nid); |
| 613 | hdmi_fill_audio_infoframe(codec, pin_nid, &ai); | 667 | hdmi_fill_audio_infoframe(codec, pin_nid, |
| 668 | ai, sizeof(ai)); | ||
| 614 | hdmi_start_infoframe_trans(codec, pin_nid); | 669 | hdmi_start_infoframe_trans(codec, pin_nid); |
| 615 | } | 670 | } |
| 616 | } | 671 | } |
| @@ -791,7 +846,6 @@ static int hdmi_pcm_open(struct hda_pcm_stream *hinfo, | |||
| 791 | /* | 846 | /* |
| 792 | * HDA/HDMI auto parsing | 847 | * HDA/HDMI auto parsing |
| 793 | */ | 848 | */ |
| 794 | |||
| 795 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) | 849 | static int hdmi_read_pin_conn(struct hda_codec *codec, hda_nid_t pin_nid) |
| 796 | { | 850 | { |
| 797 | struct hdmi_spec *spec = codec->spec; | 851 | struct hdmi_spec *spec = codec->spec; |
| @@ -922,3 +976,664 @@ static int hdmi_parse_codec(struct hda_codec *codec) | |||
| 922 | return 0; | 976 | return 0; |
| 923 | } | 977 | } |
| 924 | 978 | ||
| 979 | /* | ||
| 980 | */ | ||
| 981 | static char *generic_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
| 982 | "HDMI 0", | ||
| 983 | "HDMI 1", | ||
| 984 | "HDMI 2", | ||
| 985 | }; | ||
| 986 | |||
| 987 | /* | ||
| 988 | * HDMI callbacks | ||
| 989 | */ | ||
| 990 | |||
| 991 | static int generic_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 992 | struct hda_codec *codec, | ||
| 993 | unsigned int stream_tag, | ||
| 994 | unsigned int format, | ||
| 995 | struct snd_pcm_substream *substream) | ||
| 996 | { | ||
| 997 | hdmi_set_channel_count(codec, hinfo->nid, | ||
| 998 | substream->runtime->channels); | ||
| 999 | |||
| 1000 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
| 1001 | |||
| 1002 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
| 1003 | } | ||
| 1004 | |||
| 1005 | static struct hda_pcm_stream generic_hdmi_pcm_playback = { | ||
| 1006 | .substreams = 1, | ||
| 1007 | .channels_min = 2, | ||
| 1008 | .ops = { | ||
| 1009 | .open = hdmi_pcm_open, | ||
| 1010 | .prepare = generic_hdmi_playback_pcm_prepare, | ||
| 1011 | }, | ||
| 1012 | }; | ||
| 1013 | |||
| 1014 | static int generic_hdmi_build_pcms(struct hda_codec *codec) | ||
| 1015 | { | ||
| 1016 | struct hdmi_spec *spec = codec->spec; | ||
| 1017 | struct hda_pcm *info = spec->pcm_rec; | ||
| 1018 | int i; | ||
| 1019 | |||
| 1020 | codec->num_pcms = spec->num_cvts; | ||
| 1021 | codec->pcm_info = info; | ||
| 1022 | |||
| 1023 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
| 1024 | unsigned int chans; | ||
| 1025 | struct hda_pcm_stream *pstr; | ||
| 1026 | |||
| 1027 | chans = get_wcaps(codec, spec->cvt[i]); | ||
| 1028 | chans = get_wcaps_channels(chans); | ||
| 1029 | |||
| 1030 | info->name = generic_hdmi_pcm_names[i]; | ||
| 1031 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 1032 | pstr = &info->stream[SNDRV_PCM_STREAM_PLAYBACK]; | ||
| 1033 | if (spec->pcm_playback) | ||
| 1034 | *pstr = *spec->pcm_playback; | ||
| 1035 | else | ||
| 1036 | *pstr = generic_hdmi_pcm_playback; | ||
| 1037 | pstr->nid = spec->cvt[i]; | ||
| 1038 | if (pstr->channels_max <= 2 && chans && chans <= 16) | ||
| 1039 | pstr->channels_max = chans; | ||
| 1040 | } | ||
| 1041 | |||
| 1042 | return 0; | ||
| 1043 | } | ||
| 1044 | |||
| 1045 | static int generic_hdmi_build_controls(struct hda_codec *codec) | ||
| 1046 | { | ||
| 1047 | struct hdmi_spec *spec = codec->spec; | ||
| 1048 | int err; | ||
| 1049 | int i; | ||
| 1050 | |||
| 1051 | for (i = 0; i < codec->num_pcms; i++) { | ||
| 1052 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
| 1053 | if (err < 0) | ||
| 1054 | return err; | ||
| 1055 | } | ||
| 1056 | |||
| 1057 | return 0; | ||
| 1058 | } | ||
| 1059 | |||
| 1060 | static int generic_hdmi_init(struct hda_codec *codec) | ||
| 1061 | { | ||
| 1062 | struct hdmi_spec *spec = codec->spec; | ||
| 1063 | int i; | ||
| 1064 | |||
| 1065 | for (i = 0; spec->pin[i]; i++) { | ||
| 1066 | hdmi_enable_output(codec, spec->pin[i]); | ||
| 1067 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
| 1068 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 1069 | AC_USRSP_EN | spec->pin[i]); | ||
| 1070 | } | ||
| 1071 | return 0; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | static void generic_hdmi_free(struct hda_codec *codec) | ||
| 1075 | { | ||
| 1076 | struct hdmi_spec *spec = codec->spec; | ||
| 1077 | int i; | ||
| 1078 | |||
| 1079 | for (i = 0; i < spec->num_pins; i++) | ||
| 1080 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
| 1081 | |||
| 1082 | kfree(spec); | ||
| 1083 | } | ||
| 1084 | |||
| 1085 | static struct hda_codec_ops generic_hdmi_patch_ops = { | ||
| 1086 | .init = generic_hdmi_init, | ||
| 1087 | .free = generic_hdmi_free, | ||
| 1088 | .build_pcms = generic_hdmi_build_pcms, | ||
| 1089 | .build_controls = generic_hdmi_build_controls, | ||
| 1090 | .unsol_event = hdmi_unsol_event, | ||
| 1091 | }; | ||
| 1092 | |||
| 1093 | static int patch_generic_hdmi(struct hda_codec *codec) | ||
| 1094 | { | ||
| 1095 | struct hdmi_spec *spec; | ||
| 1096 | int i; | ||
| 1097 | |||
| 1098 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 1099 | if (spec == NULL) | ||
| 1100 | return -ENOMEM; | ||
| 1101 | |||
| 1102 | codec->spec = spec; | ||
| 1103 | if (hdmi_parse_codec(codec) < 0) { | ||
| 1104 | codec->spec = NULL; | ||
| 1105 | kfree(spec); | ||
| 1106 | return -EINVAL; | ||
| 1107 | } | ||
| 1108 | codec->patch_ops = generic_hdmi_patch_ops; | ||
| 1109 | |||
| 1110 | for (i = 0; i < spec->num_pins; i++) | ||
| 1111 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
| 1112 | |||
| 1113 | init_channel_allocations(); | ||
| 1114 | |||
| 1115 | return 0; | ||
| 1116 | } | ||
| 1117 | |||
| 1118 | /* | ||
| 1119 | * Nvidia specific implementations | ||
| 1120 | */ | ||
| 1121 | |||
| 1122 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
| 1123 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
| 1124 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
| 1125 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
| 1126 | |||
| 1127 | #define nvhdmi_master_con_nid_7x 0x04 | ||
| 1128 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
| 1129 | |||
| 1130 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
| 1131 | /*front, rear, clfe, rear_surr */ | ||
| 1132 | 0x6, 0x8, 0xa, 0xc, | ||
| 1133 | }; | ||
| 1134 | |||
| 1135 | static struct hda_verb nvhdmi_basic_init_7x[] = { | ||
| 1136 | /* set audio protect on */ | ||
| 1137 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
| 1138 | /* enable digital output on pin widget */ | ||
| 1139 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 1140 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 1141 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 1142 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 1143 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 1144 | {} /* terminator */ | ||
| 1145 | }; | ||
| 1146 | |||
| 1147 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
| 1148 | /* support only the safe format and rate */ | ||
| 1149 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
| 1150 | #define SUPPORTED_MAXBPS 16 | ||
| 1151 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
| 1152 | #else | ||
| 1153 | /* support all rates and formats */ | ||
| 1154 | #define SUPPORTED_RATES \ | ||
| 1155 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
| 1156 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
| 1157 | SNDRV_PCM_RATE_192000) | ||
| 1158 | #define SUPPORTED_MAXBPS 24 | ||
| 1159 | #define SUPPORTED_FORMATS \ | ||
| 1160 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 1161 | #endif | ||
| 1162 | |||
| 1163 | static int nvhdmi_7x_init(struct hda_codec *codec) | ||
| 1164 | { | ||
| 1165 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
| 1166 | return 0; | ||
| 1167 | } | ||
| 1168 | |||
| 1169 | static int simple_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
| 1170 | struct hda_codec *codec, | ||
| 1171 | struct snd_pcm_substream *substream) | ||
| 1172 | { | ||
| 1173 | struct hdmi_spec *spec = codec->spec; | ||
| 1174 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
| 1175 | } | ||
| 1176 | |||
| 1177 | static int simple_playback_pcm_close(struct hda_pcm_stream *hinfo, | ||
| 1178 | struct hda_codec *codec, | ||
| 1179 | struct snd_pcm_substream *substream) | ||
| 1180 | { | ||
| 1181 | struct hdmi_spec *spec = codec->spec; | ||
| 1182 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
| 1183 | } | ||
| 1184 | |||
| 1185 | static int simple_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 1186 | struct hda_codec *codec, | ||
| 1187 | unsigned int stream_tag, | ||
| 1188 | unsigned int format, | ||
| 1189 | struct snd_pcm_substream *substream) | ||
| 1190 | { | ||
| 1191 | struct hdmi_spec *spec = codec->spec; | ||
| 1192 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, | ||
| 1193 | stream_tag, format, substream); | ||
| 1194 | } | ||
| 1195 | |||
| 1196 | static int nvhdmi_8ch_7x_pcm_close(struct hda_pcm_stream *hinfo, | ||
| 1197 | struct hda_codec *codec, | ||
| 1198 | struct snd_pcm_substream *substream) | ||
| 1199 | { | ||
| 1200 | struct hdmi_spec *spec = codec->spec; | ||
| 1201 | int i; | ||
| 1202 | |||
| 1203 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
| 1204 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
| 1205 | for (i = 0; i < 4; i++) { | ||
| 1206 | /* set the stream id */ | ||
| 1207 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
| 1208 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
| 1209 | /* set the stream format */ | ||
| 1210 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
| 1211 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
| 1215 | } | ||
| 1216 | |||
| 1217 | static int nvhdmi_8ch_7x_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 1218 | struct hda_codec *codec, | ||
| 1219 | unsigned int stream_tag, | ||
| 1220 | unsigned int format, | ||
| 1221 | struct snd_pcm_substream *substream) | ||
| 1222 | { | ||
| 1223 | int chs; | ||
| 1224 | unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id; | ||
| 1225 | int i; | ||
| 1226 | |||
| 1227 | mutex_lock(&codec->spdif_mutex); | ||
| 1228 | |||
| 1229 | chs = substream->runtime->channels; | ||
| 1230 | chan = chs ? (chs - 1) : 1; | ||
| 1231 | |||
| 1232 | switch (chs) { | ||
| 1233 | default: | ||
| 1234 | case 0: | ||
| 1235 | case 2: | ||
| 1236 | chanmask = 0x00; | ||
| 1237 | break; | ||
| 1238 | case 4: | ||
| 1239 | chanmask = 0x08; | ||
| 1240 | break; | ||
| 1241 | case 6: | ||
| 1242 | chanmask = 0x0b; | ||
| 1243 | break; | ||
| 1244 | case 8: | ||
| 1245 | chanmask = 0x13; | ||
| 1246 | break; | ||
| 1247 | } | ||
| 1248 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
| 1249 | dataDCC2 = 0x2; | ||
| 1250 | |||
| 1251 | /* set the Audio InforFrame Channel Allocation */ | ||
| 1252 | snd_hda_codec_write(codec, 0x1, 0, | ||
| 1253 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
| 1254 | |||
| 1255 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
| 1256 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
| 1257 | snd_hda_codec_write(codec, | ||
| 1258 | nvhdmi_master_con_nid_7x, | ||
| 1259 | 0, | ||
| 1260 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 1261 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
| 1262 | |||
| 1263 | /* set the stream id */ | ||
| 1264 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
| 1265 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
| 1266 | |||
| 1267 | /* set the stream format */ | ||
| 1268 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
| 1269 | AC_VERB_SET_STREAM_FORMAT, format); | ||
| 1270 | |||
| 1271 | /* turn on again (if needed) */ | ||
| 1272 | /* enable and set the channel status audio/data flag */ | ||
| 1273 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
| 1274 | snd_hda_codec_write(codec, | ||
| 1275 | nvhdmi_master_con_nid_7x, | ||
| 1276 | 0, | ||
| 1277 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 1278 | codec->spdif_ctls & 0xff); | ||
| 1279 | snd_hda_codec_write(codec, | ||
| 1280 | nvhdmi_master_con_nid_7x, | ||
| 1281 | 0, | ||
| 1282 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
| 1283 | } | ||
| 1284 | |||
| 1285 | for (i = 0; i < 4; i++) { | ||
| 1286 | if (chs == 2) | ||
| 1287 | channel_id = 0; | ||
| 1288 | else | ||
| 1289 | channel_id = i * 2; | ||
| 1290 | |||
| 1291 | /* turn off SPDIF once; | ||
| 1292 | *otherwise the IEC958 bits won't be updated | ||
| 1293 | */ | ||
| 1294 | if (codec->spdif_status_reset && | ||
| 1295 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
| 1296 | snd_hda_codec_write(codec, | ||
| 1297 | nvhdmi_con_nids_7x[i], | ||
| 1298 | 0, | ||
| 1299 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 1300 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
| 1301 | /* set the stream id */ | ||
| 1302 | snd_hda_codec_write(codec, | ||
| 1303 | nvhdmi_con_nids_7x[i], | ||
| 1304 | 0, | ||
| 1305 | AC_VERB_SET_CHANNEL_STREAMID, | ||
| 1306 | (stream_tag << 4) | channel_id); | ||
| 1307 | /* set the stream format */ | ||
| 1308 | snd_hda_codec_write(codec, | ||
| 1309 | nvhdmi_con_nids_7x[i], | ||
| 1310 | 0, | ||
| 1311 | AC_VERB_SET_STREAM_FORMAT, | ||
| 1312 | format); | ||
| 1313 | /* turn on again (if needed) */ | ||
| 1314 | /* enable and set the channel status audio/data flag */ | ||
| 1315 | if (codec->spdif_status_reset && | ||
| 1316 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
| 1317 | snd_hda_codec_write(codec, | ||
| 1318 | nvhdmi_con_nids_7x[i], | ||
| 1319 | 0, | ||
| 1320 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 1321 | codec->spdif_ctls & 0xff); | ||
| 1322 | snd_hda_codec_write(codec, | ||
| 1323 | nvhdmi_con_nids_7x[i], | ||
| 1324 | 0, | ||
| 1325 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
| 1326 | } | ||
| 1327 | } | ||
| 1328 | |||
| 1329 | /* set the Audio Info Frame Checksum */ | ||
| 1330 | snd_hda_codec_write(codec, 0x1, 0, | ||
| 1331 | Nv_VERB_SET_Info_Frame_Checksum, | ||
| 1332 | (0x71 - chan - chanmask)); | ||
| 1333 | |||
| 1334 | mutex_unlock(&codec->spdif_mutex); | ||
| 1335 | return 0; | ||
| 1336 | } | ||
| 1337 | |||
| 1338 | static struct hda_pcm_stream nvhdmi_pcm_playback_8ch_7x = { | ||
| 1339 | .substreams = 1, | ||
| 1340 | .channels_min = 2, | ||
| 1341 | .channels_max = 8, | ||
| 1342 | .nid = nvhdmi_master_con_nid_7x, | ||
| 1343 | .rates = SUPPORTED_RATES, | ||
| 1344 | .maxbps = SUPPORTED_MAXBPS, | ||
| 1345 | .formats = SUPPORTED_FORMATS, | ||
| 1346 | .ops = { | ||
| 1347 | .open = simple_playback_pcm_open, | ||
| 1348 | .close = nvhdmi_8ch_7x_pcm_close, | ||
| 1349 | .prepare = nvhdmi_8ch_7x_pcm_prepare | ||
| 1350 | }, | ||
| 1351 | }; | ||
| 1352 | |||
| 1353 | static struct hda_pcm_stream nvhdmi_pcm_playback_2ch = { | ||
| 1354 | .substreams = 1, | ||
| 1355 | .channels_min = 2, | ||
| 1356 | .channels_max = 2, | ||
| 1357 | .nid = nvhdmi_master_con_nid_7x, | ||
| 1358 | .rates = SUPPORTED_RATES, | ||
| 1359 | .maxbps = SUPPORTED_MAXBPS, | ||
| 1360 | .formats = SUPPORTED_FORMATS, | ||
| 1361 | .ops = { | ||
| 1362 | .open = simple_playback_pcm_open, | ||
| 1363 | .close = simple_playback_pcm_close, | ||
| 1364 | .prepare = simple_playback_pcm_prepare | ||
| 1365 | }, | ||
| 1366 | }; | ||
| 1367 | |||
| 1368 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
| 1369 | .build_controls = generic_hdmi_build_controls, | ||
| 1370 | .build_pcms = generic_hdmi_build_pcms, | ||
| 1371 | .init = nvhdmi_7x_init, | ||
| 1372 | .free = generic_hdmi_free, | ||
| 1373 | }; | ||
| 1374 | |||
| 1375 | static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
| 1376 | .build_controls = generic_hdmi_build_controls, | ||
| 1377 | .build_pcms = generic_hdmi_build_pcms, | ||
| 1378 | .init = nvhdmi_7x_init, | ||
| 1379 | .free = generic_hdmi_free, | ||
| 1380 | }; | ||
| 1381 | |||
| 1382 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | ||
| 1383 | { | ||
| 1384 | struct hdmi_spec *spec; | ||
| 1385 | int err = patch_generic_hdmi(codec); | ||
| 1386 | |||
| 1387 | if (err < 0) | ||
| 1388 | return err; | ||
| 1389 | spec = codec->spec; | ||
| 1390 | spec->old_pin_detect = 1; | ||
| 1391 | return 0; | ||
| 1392 | } | ||
| 1393 | |||
| 1394 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
| 1395 | { | ||
| 1396 | struct hdmi_spec *spec; | ||
| 1397 | |||
| 1398 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 1399 | if (spec == NULL) | ||
| 1400 | return -ENOMEM; | ||
| 1401 | |||
| 1402 | codec->spec = spec; | ||
| 1403 | |||
| 1404 | spec->multiout.num_dacs = 0; /* no analog */ | ||
| 1405 | spec->multiout.max_channels = 2; | ||
| 1406 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
| 1407 | spec->old_pin_detect = 1; | ||
| 1408 | spec->num_cvts = 1; | ||
| 1409 | spec->cvt[0] = nvhdmi_master_con_nid_7x; | ||
| 1410 | spec->pcm_playback = &nvhdmi_pcm_playback_2ch; | ||
| 1411 | |||
| 1412 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
| 1413 | |||
| 1414 | return 0; | ||
| 1415 | } | ||
| 1416 | |||
| 1417 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
| 1418 | { | ||
| 1419 | struct hdmi_spec *spec; | ||
| 1420 | int err = patch_nvhdmi_2ch(codec); | ||
| 1421 | |||
| 1422 | if (err < 0) | ||
| 1423 | return err; | ||
| 1424 | spec = codec->spec; | ||
| 1425 | spec->multiout.max_channels = 8; | ||
| 1426 | spec->pcm_playback = &nvhdmi_pcm_playback_8ch_7x; | ||
| 1427 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
| 1428 | return 0; | ||
| 1429 | } | ||
| 1430 | |||
| 1431 | /* | ||
| 1432 | * ATI-specific implementations | ||
| 1433 | * | ||
| 1434 | * FIXME: we may omit the whole this and use the generic code once after | ||
| 1435 | * it's confirmed to work. | ||
| 1436 | */ | ||
| 1437 | |||
| 1438 | #define ATIHDMI_CVT_NID 0x02 /* audio converter */ | ||
| 1439 | #define ATIHDMI_PIN_NID 0x03 /* HDMI output pin */ | ||
| 1440 | |||
| 1441 | static int atihdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 1442 | struct hda_codec *codec, | ||
| 1443 | unsigned int stream_tag, | ||
| 1444 | unsigned int format, | ||
| 1445 | struct snd_pcm_substream *substream) | ||
| 1446 | { | ||
| 1447 | struct hdmi_spec *spec = codec->spec; | ||
| 1448 | int chans = substream->runtime->channels; | ||
| 1449 | int i, err; | ||
| 1450 | |||
| 1451 | err = simple_playback_pcm_prepare(hinfo, codec, stream_tag, format, | ||
| 1452 | substream); | ||
| 1453 | if (err < 0) | ||
| 1454 | return err; | ||
| 1455 | snd_hda_codec_write(codec, spec->cvt[0], 0, AC_VERB_SET_CVT_CHAN_COUNT, | ||
| 1456 | chans - 1); | ||
| 1457 | /* FIXME: XXX */ | ||
| 1458 | for (i = 0; i < chans; i++) { | ||
| 1459 | snd_hda_codec_write(codec, spec->cvt[0], 0, | ||
| 1460 | AC_VERB_SET_HDMI_CHAN_SLOT, | ||
| 1461 | (i << 4) | i); | ||
| 1462 | } | ||
| 1463 | return 0; | ||
| 1464 | } | ||
| 1465 | |||
| 1466 | static struct hda_pcm_stream atihdmi_pcm_digital_playback = { | ||
| 1467 | .substreams = 1, | ||
| 1468 | .channels_min = 2, | ||
| 1469 | .channels_max = 2, | ||
| 1470 | .nid = ATIHDMI_CVT_NID, | ||
| 1471 | .ops = { | ||
| 1472 | .open = simple_playback_pcm_open, | ||
| 1473 | .close = simple_playback_pcm_close, | ||
| 1474 | .prepare = atihdmi_playback_pcm_prepare | ||
| 1475 | }, | ||
| 1476 | }; | ||
| 1477 | |||
| 1478 | static struct hda_verb atihdmi_basic_init[] = { | ||
| 1479 | /* enable digital output on pin widget */ | ||
| 1480 | { 0x03, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT }, | ||
| 1481 | {} /* terminator */ | ||
| 1482 | }; | ||
| 1483 | |||
| 1484 | static int atihdmi_init(struct hda_codec *codec) | ||
| 1485 | { | ||
| 1486 | struct hdmi_spec *spec = codec->spec; | ||
| 1487 | |||
| 1488 | snd_hda_sequence_write(codec, atihdmi_basic_init); | ||
| 1489 | /* SI codec requires to unmute the pin */ | ||
| 1490 | if (get_wcaps(codec, spec->pin[0]) & AC_WCAP_OUT_AMP) | ||
| 1491 | snd_hda_codec_write(codec, spec->pin[0], 0, | ||
| 1492 | AC_VERB_SET_AMP_GAIN_MUTE, | ||
| 1493 | AMP_OUT_UNMUTE); | ||
| 1494 | return 0; | ||
| 1495 | } | ||
| 1496 | |||
| 1497 | static struct hda_codec_ops atihdmi_patch_ops = { | ||
| 1498 | .build_controls = generic_hdmi_build_controls, | ||
| 1499 | .build_pcms = generic_hdmi_build_pcms, | ||
| 1500 | .init = atihdmi_init, | ||
| 1501 | .free = generic_hdmi_free, | ||
| 1502 | }; | ||
| 1503 | |||
| 1504 | |||
| 1505 | static int patch_atihdmi(struct hda_codec *codec) | ||
| 1506 | { | ||
| 1507 | struct hdmi_spec *spec; | ||
| 1508 | |||
| 1509 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 1510 | if (spec == NULL) | ||
| 1511 | return -ENOMEM; | ||
| 1512 | |||
| 1513 | codec->spec = spec; | ||
| 1514 | |||
| 1515 | spec->multiout.num_dacs = 0; /* no analog */ | ||
| 1516 | spec->multiout.max_channels = 2; | ||
| 1517 | spec->multiout.dig_out_nid = ATIHDMI_CVT_NID; | ||
| 1518 | spec->num_cvts = 1; | ||
| 1519 | spec->cvt[0] = ATIHDMI_CVT_NID; | ||
| 1520 | spec->pin[0] = ATIHDMI_PIN_NID; | ||
| 1521 | spec->pcm_playback = &atihdmi_pcm_digital_playback; | ||
| 1522 | |||
| 1523 | codec->patch_ops = atihdmi_patch_ops; | ||
| 1524 | |||
| 1525 | return 0; | ||
| 1526 | } | ||
| 1527 | |||
| 1528 | |||
| 1529 | /* | ||
| 1530 | * patch entries | ||
| 1531 | */ | ||
| 1532 | static struct hda_codec_preset snd_hda_preset_hdmi[] = { | ||
| 1533 | { .id = 0x1002793c, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
| 1534 | { .id = 0x10027919, .name = "RS600 HDMI", .patch = patch_atihdmi }, | ||
| 1535 | { .id = 0x1002791a, .name = "RS690/780 HDMI", .patch = patch_atihdmi }, | ||
| 1536 | { .id = 0x1002aa01, .name = "R6xx HDMI", .patch = patch_atihdmi }, | ||
| 1537 | { .id = 0x10951390, .name = "SiI1390 HDMI", .patch = patch_generic_hdmi }, | ||
| 1538 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_generic_hdmi }, | ||
| 1539 | { .id = 0x17e80047, .name = "Chrontel HDMI", .patch = patch_generic_hdmi }, | ||
| 1540 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 1541 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 1542 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 1543 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 1544 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 1545 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1546 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1547 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1548 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1549 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1550 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1551 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1552 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1553 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1554 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1555 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1556 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1557 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1558 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1559 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1560 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1561 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1562 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1563 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 1564 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
| 1565 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
| 1566 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
| 1567 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_generic_hdmi }, | ||
| 1568 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_generic_hdmi }, | ||
| 1569 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_generic_hdmi }, | ||
| 1570 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_generic_hdmi }, | ||
| 1571 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_generic_hdmi }, | ||
| 1572 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_generic_hdmi }, | ||
| 1573 | {} /* terminator */ | ||
| 1574 | }; | ||
| 1575 | |||
| 1576 | MODULE_ALIAS("snd-hda-codec-id:1002793c"); | ||
| 1577 | MODULE_ALIAS("snd-hda-codec-id:10027919"); | ||
| 1578 | MODULE_ALIAS("snd-hda-codec-id:1002791a"); | ||
| 1579 | MODULE_ALIAS("snd-hda-codec-id:1002aa01"); | ||
| 1580 | MODULE_ALIAS("snd-hda-codec-id:10951390"); | ||
| 1581 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
| 1582 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
| 1583 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
| 1584 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
| 1585 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
| 1586 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
| 1587 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
| 1588 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
| 1589 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
| 1590 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
| 1591 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
| 1592 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
| 1593 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
| 1594 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
| 1595 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
| 1596 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
| 1597 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
| 1598 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
| 1599 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
| 1600 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
| 1601 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
| 1602 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
| 1603 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
| 1604 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
| 1605 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
| 1606 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
| 1607 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
| 1608 | MODULE_ALIAS("snd-hda-codec-id:17e80047"); | ||
| 1609 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
| 1610 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
| 1611 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
| 1612 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
| 1613 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
| 1614 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
| 1615 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
| 1616 | |||
| 1617 | MODULE_LICENSE("GPL"); | ||
| 1618 | MODULE_DESCRIPTION("HDMI HD-audio codec"); | ||
| 1619 | MODULE_ALIAS("snd-hda-codec-intelhdmi"); | ||
| 1620 | MODULE_ALIAS("snd-hda-codec-nvhdmi"); | ||
| 1621 | MODULE_ALIAS("snd-hda-codec-atihdmi"); | ||
| 1622 | |||
| 1623 | static struct hda_codec_preset_list intel_list = { | ||
| 1624 | .preset = snd_hda_preset_hdmi, | ||
| 1625 | .owner = THIS_MODULE, | ||
| 1626 | }; | ||
| 1627 | |||
| 1628 | static int __init patch_hdmi_init(void) | ||
| 1629 | { | ||
| 1630 | return snd_hda_add_codec_preset(&intel_list); | ||
| 1631 | } | ||
| 1632 | |||
| 1633 | static void __exit patch_hdmi_exit(void) | ||
| 1634 | { | ||
| 1635 | snd_hda_delete_codec_preset(&intel_list); | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | module_init(patch_hdmi_init) | ||
| 1639 | module_exit(patch_hdmi_exit) | ||
diff --git a/sound/pci/hda/patch_intelhdmi.c b/sound/pci/hda/patch_intelhdmi.c deleted file mode 100644 index 36a9b83a6174..000000000000 --- a/sound/pci/hda/patch_intelhdmi.c +++ /dev/null | |||
| @@ -1,220 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * | ||
| 3 | * patch_intelhdmi.c - Patch for Intel HDMI codecs | ||
| 4 | * | ||
| 5 | * Copyright(c) 2008 Intel Corporation. All rights reserved. | ||
| 6 | * | ||
| 7 | * Authors: | ||
| 8 | * Jiang Zhe <zhe.jiang@intel.com> | ||
| 9 | * Wu Fengguang <wfg@linux.intel.com> | ||
| 10 | * | ||
| 11 | * Maintained by: | ||
| 12 | * Wu Fengguang <wfg@linux.intel.com> | ||
| 13 | * | ||
| 14 | * This program is free software; you can redistribute it and/or modify it | ||
| 15 | * under the terms of the GNU General Public License as published by the Free | ||
| 16 | * Software Foundation; either version 2 of the License, or (at your option) | ||
| 17 | * any later version. | ||
| 18 | * | ||
| 19 | * This program is distributed in the hope that it will be useful, but | ||
| 20 | * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY | ||
| 21 | * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | ||
| 22 | * for more details. | ||
| 23 | * | ||
| 24 | * You should have received a copy of the GNU General Public License | ||
| 25 | * along with this program; if not, write to the Free Software Foundation, | ||
| 26 | * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. | ||
| 27 | */ | ||
| 28 | |||
| 29 | #include <linux/init.h> | ||
| 30 | #include <linux/delay.h> | ||
| 31 | #include <linux/slab.h> | ||
| 32 | #include <sound/core.h> | ||
| 33 | #include "hda_codec.h" | ||
| 34 | #include "hda_local.h" | ||
| 35 | |||
| 36 | /* | ||
| 37 | * The HDMI/DisplayPort configuration can be highly dynamic. A graphics device | ||
| 38 | * could support two independent pipes, each of them can be connected to one or | ||
| 39 | * more ports (DVI, HDMI or DisplayPort). | ||
| 40 | * | ||
| 41 | * The HDA correspondence of pipes/ports are converter/pin nodes. | ||
| 42 | */ | ||
| 43 | #define MAX_HDMI_CVTS 3 | ||
| 44 | #define MAX_HDMI_PINS 3 | ||
| 45 | |||
| 46 | #include "patch_hdmi.c" | ||
| 47 | |||
| 48 | static char *intel_hdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
| 49 | "INTEL HDMI 0", | ||
| 50 | "INTEL HDMI 1", | ||
| 51 | "INTEL HDMI 2", | ||
| 52 | }; | ||
| 53 | |||
| 54 | /* | ||
| 55 | * HDMI callbacks | ||
| 56 | */ | ||
| 57 | |||
| 58 | static int intel_hdmi_playback_pcm_prepare(struct hda_pcm_stream *hinfo, | ||
| 59 | struct hda_codec *codec, | ||
| 60 | unsigned int stream_tag, | ||
| 61 | unsigned int format, | ||
| 62 | struct snd_pcm_substream *substream) | ||
| 63 | { | ||
| 64 | hdmi_set_channel_count(codec, hinfo->nid, | ||
| 65 | substream->runtime->channels); | ||
| 66 | |||
| 67 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
| 68 | |||
| 69 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
| 70 | } | ||
| 71 | |||
| 72 | static struct hda_pcm_stream intel_hdmi_pcm_playback = { | ||
| 73 | .substreams = 1, | ||
| 74 | .channels_min = 2, | ||
| 75 | .ops = { | ||
| 76 | .open = hdmi_pcm_open, | ||
| 77 | .prepare = intel_hdmi_playback_pcm_prepare, | ||
| 78 | }, | ||
| 79 | }; | ||
| 80 | |||
| 81 | static int intel_hdmi_build_pcms(struct hda_codec *codec) | ||
| 82 | { | ||
| 83 | struct hdmi_spec *spec = codec->spec; | ||
| 84 | struct hda_pcm *info = spec->pcm_rec; | ||
| 85 | int i; | ||
| 86 | |||
| 87 | codec->num_pcms = spec->num_cvts; | ||
| 88 | codec->pcm_info = info; | ||
| 89 | |||
| 90 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
| 91 | unsigned int chans; | ||
| 92 | |||
| 93 | chans = get_wcaps(codec, spec->cvt[i]); | ||
| 94 | chans = get_wcaps_channels(chans); | ||
| 95 | |||
| 96 | info->name = intel_hdmi_pcm_names[i]; | ||
| 97 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 98 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] = | ||
| 99 | intel_hdmi_pcm_playback; | ||
| 100 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
| 101 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
| 102 | } | ||
| 103 | |||
| 104 | return 0; | ||
| 105 | } | ||
| 106 | |||
| 107 | static int intel_hdmi_build_controls(struct hda_codec *codec) | ||
| 108 | { | ||
| 109 | struct hdmi_spec *spec = codec->spec; | ||
| 110 | int err; | ||
| 111 | int i; | ||
| 112 | |||
| 113 | for (i = 0; i < codec->num_pcms; i++) { | ||
| 114 | err = snd_hda_create_spdif_out_ctls(codec, spec->cvt[i]); | ||
| 115 | if (err < 0) | ||
| 116 | return err; | ||
| 117 | } | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int intel_hdmi_init(struct hda_codec *codec) | ||
| 123 | { | ||
| 124 | struct hdmi_spec *spec = codec->spec; | ||
| 125 | int i; | ||
| 126 | |||
| 127 | for (i = 0; spec->pin[i]; i++) { | ||
| 128 | hdmi_enable_output(codec, spec->pin[i]); | ||
| 129 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
| 130 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 131 | AC_USRSP_EN | spec->pin[i]); | ||
| 132 | } | ||
| 133 | return 0; | ||
| 134 | } | ||
| 135 | |||
| 136 | static void intel_hdmi_free(struct hda_codec *codec) | ||
| 137 | { | ||
| 138 | struct hdmi_spec *spec = codec->spec; | ||
| 139 | int i; | ||
| 140 | |||
| 141 | for (i = 0; i < spec->num_pins; i++) | ||
| 142 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
| 143 | |||
| 144 | kfree(spec); | ||
| 145 | } | ||
| 146 | |||
| 147 | static struct hda_codec_ops intel_hdmi_patch_ops = { | ||
| 148 | .init = intel_hdmi_init, | ||
| 149 | .free = intel_hdmi_free, | ||
| 150 | .build_pcms = intel_hdmi_build_pcms, | ||
| 151 | .build_controls = intel_hdmi_build_controls, | ||
| 152 | .unsol_event = hdmi_unsol_event, | ||
| 153 | }; | ||
| 154 | |||
| 155 | static int patch_intel_hdmi(struct hda_codec *codec) | ||
| 156 | { | ||
| 157 | struct hdmi_spec *spec; | ||
| 158 | int i; | ||
| 159 | |||
| 160 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 161 | if (spec == NULL) | ||
| 162 | return -ENOMEM; | ||
| 163 | |||
| 164 | codec->spec = spec; | ||
| 165 | if (hdmi_parse_codec(codec) < 0) { | ||
| 166 | codec->spec = NULL; | ||
| 167 | kfree(spec); | ||
| 168 | return -EINVAL; | ||
| 169 | } | ||
| 170 | codec->patch_ops = intel_hdmi_patch_ops; | ||
| 171 | |||
| 172 | for (i = 0; i < spec->num_pins; i++) | ||
| 173 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
| 174 | |||
| 175 | init_channel_allocations(); | ||
| 176 | |||
| 177 | return 0; | ||
| 178 | } | ||
| 179 | |||
| 180 | static struct hda_codec_preset snd_hda_preset_intelhdmi[] = { | ||
| 181 | { .id = 0x808629fb, .name = "Crestline HDMI", .patch = patch_intel_hdmi }, | ||
| 182 | { .id = 0x80862801, .name = "Bearlake HDMI", .patch = patch_intel_hdmi }, | ||
| 183 | { .id = 0x80862802, .name = "Cantiga HDMI", .patch = patch_intel_hdmi }, | ||
| 184 | { .id = 0x80862803, .name = "Eaglelake HDMI", .patch = patch_intel_hdmi }, | ||
| 185 | { .id = 0x80862804, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, | ||
| 186 | { .id = 0x80860054, .name = "IbexPeak HDMI", .patch = patch_intel_hdmi }, | ||
| 187 | { .id = 0x80862805, .name = "CougarPoint HDMI", .patch = patch_intel_hdmi }, | ||
| 188 | { .id = 0x10951392, .name = "SiI1392 HDMI", .patch = patch_intel_hdmi }, | ||
| 189 | {} /* terminator */ | ||
| 190 | }; | ||
| 191 | |||
| 192 | MODULE_ALIAS("snd-hda-codec-id:808629fb"); | ||
| 193 | MODULE_ALIAS("snd-hda-codec-id:80862801"); | ||
| 194 | MODULE_ALIAS("snd-hda-codec-id:80862802"); | ||
| 195 | MODULE_ALIAS("snd-hda-codec-id:80862803"); | ||
| 196 | MODULE_ALIAS("snd-hda-codec-id:80862804"); | ||
| 197 | MODULE_ALIAS("snd-hda-codec-id:80862805"); | ||
| 198 | MODULE_ALIAS("snd-hda-codec-id:80860054"); | ||
| 199 | MODULE_ALIAS("snd-hda-codec-id:10951392"); | ||
| 200 | |||
| 201 | MODULE_LICENSE("GPL"); | ||
| 202 | MODULE_DESCRIPTION("Intel HDMI HD-audio codec"); | ||
| 203 | |||
| 204 | static struct hda_codec_preset_list intel_list = { | ||
| 205 | .preset = snd_hda_preset_intelhdmi, | ||
| 206 | .owner = THIS_MODULE, | ||
| 207 | }; | ||
| 208 | |||
| 209 | static int __init patch_intelhdmi_init(void) | ||
| 210 | { | ||
| 211 | return snd_hda_add_codec_preset(&intel_list); | ||
| 212 | } | ||
| 213 | |||
| 214 | static void __exit patch_intelhdmi_exit(void) | ||
| 215 | { | ||
| 216 | snd_hda_delete_codec_preset(&intel_list); | ||
| 217 | } | ||
| 218 | |||
| 219 | module_init(patch_intelhdmi_init) | ||
| 220 | module_exit(patch_intelhdmi_exit) | ||
diff --git a/sound/pci/hda/patch_nvhdmi.c b/sound/pci/hda/patch_nvhdmi.c deleted file mode 100644 index baa108b9d6aa..000000000000 --- a/sound/pci/hda/patch_nvhdmi.c +++ /dev/null | |||
| @@ -1,608 +0,0 @@ | |||
| 1 | /* | ||
| 2 | * Universal Interface for Intel High Definition Audio Codec | ||
| 3 | * | ||
| 4 | * HD audio interface patch for NVIDIA HDMI codecs | ||
| 5 | * | ||
| 6 | * Copyright (c) 2008 NVIDIA Corp. All rights reserved. | ||
| 7 | * Copyright (c) 2008 Wei Ni <wni@nvidia.com> | ||
| 8 | * | ||
| 9 | * | ||
| 10 | * This driver is free software; you can redistribute it and/or modify | ||
| 11 | * it under the terms of the GNU General Public License as published by | ||
| 12 | * the Free Software Foundation; either version 2 of the License, or | ||
| 13 | * (at your option) any later version. | ||
| 14 | * | ||
| 15 | * This driver is distributed in the hope that it will be useful, | ||
| 16 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
| 17 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
| 18 | * GNU General Public License for more details. | ||
| 19 | * | ||
| 20 | * You should have received a copy of the GNU General Public License | ||
| 21 | * along with this program; if not, write to the Free Software | ||
| 22 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA | ||
| 23 | */ | ||
| 24 | |||
| 25 | #include <linux/init.h> | ||
| 26 | #include <linux/delay.h> | ||
| 27 | #include <linux/slab.h> | ||
| 28 | #include <sound/core.h> | ||
| 29 | #include "hda_codec.h" | ||
| 30 | #include "hda_local.h" | ||
| 31 | |||
| 32 | #define MAX_HDMI_CVTS 1 | ||
| 33 | #define MAX_HDMI_PINS 1 | ||
| 34 | |||
| 35 | #include "patch_hdmi.c" | ||
| 36 | |||
| 37 | static char *nvhdmi_pcm_names[MAX_HDMI_CVTS] = { | ||
| 38 | "NVIDIA HDMI", | ||
| 39 | }; | ||
| 40 | |||
| 41 | /* define below to restrict the supported rates and formats */ | ||
| 42 | /* #define LIMITED_RATE_FMT_SUPPORT */ | ||
| 43 | |||
| 44 | enum HDACodec { | ||
| 45 | HDA_CODEC_NVIDIA_MCP7X, | ||
| 46 | HDA_CODEC_NVIDIA_MCP89, | ||
| 47 | HDA_CODEC_NVIDIA_GT21X, | ||
| 48 | HDA_CODEC_INVALID | ||
| 49 | }; | ||
| 50 | |||
| 51 | #define Nv_VERB_SET_Channel_Allocation 0xF79 | ||
| 52 | #define Nv_VERB_SET_Info_Frame_Checksum 0xF7A | ||
| 53 | #define Nv_VERB_SET_Audio_Protection_On 0xF98 | ||
| 54 | #define Nv_VERB_SET_Audio_Protection_Off 0xF99 | ||
| 55 | |||
| 56 | #define nvhdmi_master_con_nid_7x 0x04 | ||
| 57 | #define nvhdmi_master_pin_nid_7x 0x05 | ||
| 58 | |||
| 59 | #define nvhdmi_master_con_nid_89 0x04 | ||
| 60 | #define nvhdmi_master_pin_nid_89 0x05 | ||
| 61 | |||
| 62 | static hda_nid_t nvhdmi_con_nids_7x[4] = { | ||
| 63 | /*front, rear, clfe, rear_surr */ | ||
| 64 | 0x6, 0x8, 0xa, 0xc, | ||
| 65 | }; | ||
| 66 | |||
| 67 | static struct hda_verb nvhdmi_basic_init_7x[] = { | ||
| 68 | /* set audio protect on */ | ||
| 69 | { 0x1, Nv_VERB_SET_Audio_Protection_On, 0x1}, | ||
| 70 | /* enable digital output on pin widget */ | ||
| 71 | { 0x5, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 72 | { 0x7, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 73 | { 0x9, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 74 | { 0xb, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 75 | { 0xd, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT | 0x5 }, | ||
| 76 | {} /* terminator */ | ||
| 77 | }; | ||
| 78 | |||
| 79 | #ifdef LIMITED_RATE_FMT_SUPPORT | ||
| 80 | /* support only the safe format and rate */ | ||
| 81 | #define SUPPORTED_RATES SNDRV_PCM_RATE_48000 | ||
| 82 | #define SUPPORTED_MAXBPS 16 | ||
| 83 | #define SUPPORTED_FORMATS SNDRV_PCM_FMTBIT_S16_LE | ||
| 84 | #else | ||
| 85 | /* support all rates and formats */ | ||
| 86 | #define SUPPORTED_RATES \ | ||
| 87 | (SNDRV_PCM_RATE_32000 | SNDRV_PCM_RATE_44100 | SNDRV_PCM_RATE_48000 |\ | ||
| 88 | SNDRV_PCM_RATE_88200 | SNDRV_PCM_RATE_96000 | SNDRV_PCM_RATE_176400 |\ | ||
| 89 | SNDRV_PCM_RATE_192000) | ||
| 90 | #define SUPPORTED_MAXBPS 24 | ||
| 91 | #define SUPPORTED_FORMATS \ | ||
| 92 | (SNDRV_PCM_FMTBIT_S16_LE | SNDRV_PCM_FMTBIT_S32_LE) | ||
| 93 | #endif | ||
| 94 | |||
| 95 | /* | ||
| 96 | * Controls | ||
| 97 | */ | ||
| 98 | static int nvhdmi_build_controls(struct hda_codec *codec) | ||
| 99 | { | ||
| 100 | struct hdmi_spec *spec = codec->spec; | ||
| 101 | int err; | ||
| 102 | int i; | ||
| 103 | |||
| 104 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
| 105 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
| 106 | for (i = 0; i < codec->num_pcms; i++) { | ||
| 107 | err = snd_hda_create_spdif_out_ctls(codec, | ||
| 108 | spec->cvt[i]); | ||
| 109 | if (err < 0) | ||
| 110 | return err; | ||
| 111 | } | ||
| 112 | } else { | ||
| 113 | err = snd_hda_create_spdif_out_ctls(codec, | ||
| 114 | spec->multiout.dig_out_nid); | ||
| 115 | if (err < 0) | ||
| 116 | return err; | ||
| 117 | } | ||
| 118 | |||
| 119 | return 0; | ||
| 120 | } | ||
| 121 | |||
| 122 | static int nvhdmi_init(struct hda_codec *codec) | ||
| 123 | { | ||
| 124 | struct hdmi_spec *spec = codec->spec; | ||
| 125 | int i; | ||
| 126 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
| 127 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
| 128 | for (i = 0; spec->pin[i]; i++) { | ||
| 129 | hdmi_enable_output(codec, spec->pin[i]); | ||
| 130 | snd_hda_codec_write(codec, spec->pin[i], 0, | ||
| 131 | AC_VERB_SET_UNSOLICITED_ENABLE, | ||
| 132 | AC_USRSP_EN | spec->pin[i]); | ||
| 133 | } | ||
| 134 | } else { | ||
| 135 | snd_hda_sequence_write(codec, nvhdmi_basic_init_7x); | ||
| 136 | } | ||
| 137 | return 0; | ||
| 138 | } | ||
| 139 | |||
| 140 | static void nvhdmi_free(struct hda_codec *codec) | ||
| 141 | { | ||
| 142 | struct hdmi_spec *spec = codec->spec; | ||
| 143 | int i; | ||
| 144 | |||
| 145 | if ((spec->codec_type == HDA_CODEC_NVIDIA_MCP89) | ||
| 146 | || (spec->codec_type == HDA_CODEC_NVIDIA_GT21X)) { | ||
| 147 | for (i = 0; i < spec->num_pins; i++) | ||
| 148 | snd_hda_eld_proc_free(codec, &spec->sink_eld[i]); | ||
| 149 | } | ||
| 150 | |||
| 151 | kfree(spec); | ||
| 152 | } | ||
| 153 | |||
| 154 | /* | ||
| 155 | * Digital out | ||
| 156 | */ | ||
| 157 | static int nvhdmi_dig_playback_pcm_open(struct hda_pcm_stream *hinfo, | ||
| 158 | struct hda_codec *codec, | ||
| 159 | struct snd_pcm_substream *substream) | ||
| 160 | { | ||
| 161 | struct hdmi_spec *spec = codec->spec; | ||
| 162 | return snd_hda_multi_out_dig_open(codec, &spec->multiout); | ||
| 163 | } | ||
| 164 | |||
| 165 | static int nvhdmi_dig_playback_pcm_close_8ch_7x(struct hda_pcm_stream *hinfo, | ||
| 166 | struct hda_codec *codec, | ||
| 167 | struct snd_pcm_substream *substream) | ||
| 168 | { | ||
| 169 | struct hdmi_spec *spec = codec->spec; | ||
| 170 | int i; | ||
| 171 | |||
| 172 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, | ||
| 173 | 0, AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
| 174 | for (i = 0; i < 4; i++) { | ||
| 175 | /* set the stream id */ | ||
| 176 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
| 177 | AC_VERB_SET_CHANNEL_STREAMID, 0); | ||
| 178 | /* set the stream format */ | ||
| 179 | snd_hda_codec_write(codec, nvhdmi_con_nids_7x[i], 0, | ||
| 180 | AC_VERB_SET_STREAM_FORMAT, 0); | ||
| 181 | } | ||
| 182 | |||
| 183 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
| 184 | } | ||
| 185 | |||
| 186 | static int nvhdmi_dig_playback_pcm_close_2ch(struct hda_pcm_stream *hinfo, | ||
| 187 | struct hda_codec *codec, | ||
| 188 | struct snd_pcm_substream *substream) | ||
| 189 | { | ||
| 190 | struct hdmi_spec *spec = codec->spec; | ||
| 191 | return snd_hda_multi_out_dig_close(codec, &spec->multiout); | ||
| 192 | } | ||
| 193 | |||
| 194 | static int nvhdmi_dig_playback_pcm_prepare_8ch_89(struct hda_pcm_stream *hinfo, | ||
| 195 | struct hda_codec *codec, | ||
| 196 | unsigned int stream_tag, | ||
| 197 | unsigned int format, | ||
| 198 | struct snd_pcm_substream *substream) | ||
| 199 | { | ||
| 200 | hdmi_set_channel_count(codec, hinfo->nid, | ||
| 201 | substream->runtime->channels); | ||
| 202 | |||
| 203 | hdmi_setup_audio_infoframe(codec, hinfo->nid, substream); | ||
| 204 | |||
| 205 | return hdmi_setup_stream(codec, hinfo->nid, stream_tag, format); | ||
| 206 | } | ||
| 207 | |||
| 208 | static int nvhdmi_dig_playback_pcm_prepare_8ch(struct hda_pcm_stream *hinfo, | ||
| 209 | struct hda_codec *codec, | ||
| 210 | unsigned int stream_tag, | ||
| 211 | unsigned int format, | ||
| 212 | struct snd_pcm_substream *substream) | ||
| 213 | { | ||
| 214 | int chs; | ||
| 215 | unsigned int dataDCC1, dataDCC2, chan, chanmask, channel_id; | ||
| 216 | int i; | ||
| 217 | |||
| 218 | mutex_lock(&codec->spdif_mutex); | ||
| 219 | |||
| 220 | chs = substream->runtime->channels; | ||
| 221 | chan = chs ? (chs - 1) : 1; | ||
| 222 | |||
| 223 | switch (chs) { | ||
| 224 | default: | ||
| 225 | case 0: | ||
| 226 | case 2: | ||
| 227 | chanmask = 0x00; | ||
| 228 | break; | ||
| 229 | case 4: | ||
| 230 | chanmask = 0x08; | ||
| 231 | break; | ||
| 232 | case 6: | ||
| 233 | chanmask = 0x0b; | ||
| 234 | break; | ||
| 235 | case 8: | ||
| 236 | chanmask = 0x13; | ||
| 237 | break; | ||
| 238 | } | ||
| 239 | dataDCC1 = AC_DIG1_ENABLE | AC_DIG1_COPYRIGHT; | ||
| 240 | dataDCC2 = 0x2; | ||
| 241 | |||
| 242 | /* set the Audio InforFrame Channel Allocation */ | ||
| 243 | snd_hda_codec_write(codec, 0x1, 0, | ||
| 244 | Nv_VERB_SET_Channel_Allocation, chanmask); | ||
| 245 | |||
| 246 | /* turn off SPDIF once; otherwise the IEC958 bits won't be updated */ | ||
| 247 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
| 248 | snd_hda_codec_write(codec, | ||
| 249 | nvhdmi_master_con_nid_7x, | ||
| 250 | 0, | ||
| 251 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 252 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
| 253 | |||
| 254 | /* set the stream id */ | ||
| 255 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
| 256 | AC_VERB_SET_CHANNEL_STREAMID, (stream_tag << 4) | 0x0); | ||
| 257 | |||
| 258 | /* set the stream format */ | ||
| 259 | snd_hda_codec_write(codec, nvhdmi_master_con_nid_7x, 0, | ||
| 260 | AC_VERB_SET_STREAM_FORMAT, format); | ||
| 261 | |||
| 262 | /* turn on again (if needed) */ | ||
| 263 | /* enable and set the channel status audio/data flag */ | ||
| 264 | if (codec->spdif_status_reset && (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
| 265 | snd_hda_codec_write(codec, | ||
| 266 | nvhdmi_master_con_nid_7x, | ||
| 267 | 0, | ||
| 268 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 269 | codec->spdif_ctls & 0xff); | ||
| 270 | snd_hda_codec_write(codec, | ||
| 271 | nvhdmi_master_con_nid_7x, | ||
| 272 | 0, | ||
| 273 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
| 274 | } | ||
| 275 | |||
| 276 | for (i = 0; i < 4; i++) { | ||
| 277 | if (chs == 2) | ||
| 278 | channel_id = 0; | ||
| 279 | else | ||
| 280 | channel_id = i * 2; | ||
| 281 | |||
| 282 | /* turn off SPDIF once; | ||
| 283 | *otherwise the IEC958 bits won't be updated | ||
| 284 | */ | ||
| 285 | if (codec->spdif_status_reset && | ||
| 286 | (codec->spdif_ctls & AC_DIG1_ENABLE)) | ||
| 287 | snd_hda_codec_write(codec, | ||
| 288 | nvhdmi_con_nids_7x[i], | ||
| 289 | 0, | ||
| 290 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 291 | codec->spdif_ctls & ~AC_DIG1_ENABLE & 0xff); | ||
| 292 | /* set the stream id */ | ||
| 293 | snd_hda_codec_write(codec, | ||
| 294 | nvhdmi_con_nids_7x[i], | ||
| 295 | 0, | ||
| 296 | AC_VERB_SET_CHANNEL_STREAMID, | ||
| 297 | (stream_tag << 4) | channel_id); | ||
| 298 | /* set the stream format */ | ||
| 299 | snd_hda_codec_write(codec, | ||
| 300 | nvhdmi_con_nids_7x[i], | ||
| 301 | 0, | ||
| 302 | AC_VERB_SET_STREAM_FORMAT, | ||
| 303 | format); | ||
| 304 | /* turn on again (if needed) */ | ||
| 305 | /* enable and set the channel status audio/data flag */ | ||
| 306 | if (codec->spdif_status_reset && | ||
| 307 | (codec->spdif_ctls & AC_DIG1_ENABLE)) { | ||
| 308 | snd_hda_codec_write(codec, | ||
| 309 | nvhdmi_con_nids_7x[i], | ||
| 310 | 0, | ||
| 311 | AC_VERB_SET_DIGI_CONVERT_1, | ||
| 312 | codec->spdif_ctls & 0xff); | ||
| 313 | snd_hda_codec_write(codec, | ||
| 314 | nvhdmi_con_nids_7x[i], | ||
| 315 | 0, | ||
| 316 | AC_VERB_SET_DIGI_CONVERT_2, dataDCC2); | ||
| 317 | } | ||
| 318 | } | ||
| 319 | |||
| 320 | /* set the Audio Info Frame Checksum */ | ||
| 321 | snd_hda_codec_write(codec, 0x1, 0, | ||
| 322 | Nv_VERB_SET_Info_Frame_Checksum, | ||
| 323 | (0x71 - chan - chanmask)); | ||
| 324 | |||
| 325 | mutex_unlock(&codec->spdif_mutex); | ||
| 326 | return 0; | ||
| 327 | } | ||
| 328 | |||
| 329 | static int nvhdmi_dig_playback_pcm_prepare_2ch(struct hda_pcm_stream *hinfo, | ||
| 330 | struct hda_codec *codec, | ||
| 331 | unsigned int stream_tag, | ||
| 332 | unsigned int format, | ||
| 333 | struct snd_pcm_substream *substream) | ||
| 334 | { | ||
| 335 | struct hdmi_spec *spec = codec->spec; | ||
| 336 | return snd_hda_multi_out_dig_prepare(codec, &spec->multiout, stream_tag, | ||
| 337 | format, substream); | ||
| 338 | } | ||
| 339 | |||
| 340 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_89 = { | ||
| 341 | .substreams = 1, | ||
| 342 | .channels_min = 2, | ||
| 343 | .ops = { | ||
| 344 | .open = hdmi_pcm_open, | ||
| 345 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch_89, | ||
| 346 | }, | ||
| 347 | }; | ||
| 348 | |||
| 349 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_8ch_7x = { | ||
| 350 | .substreams = 1, | ||
| 351 | .channels_min = 2, | ||
| 352 | .channels_max = 8, | ||
| 353 | .nid = nvhdmi_master_con_nid_7x, | ||
| 354 | .rates = SUPPORTED_RATES, | ||
| 355 | .maxbps = SUPPORTED_MAXBPS, | ||
| 356 | .formats = SUPPORTED_FORMATS, | ||
| 357 | .ops = { | ||
| 358 | .open = nvhdmi_dig_playback_pcm_open, | ||
| 359 | .close = nvhdmi_dig_playback_pcm_close_8ch_7x, | ||
| 360 | .prepare = nvhdmi_dig_playback_pcm_prepare_8ch | ||
| 361 | }, | ||
| 362 | }; | ||
| 363 | |||
| 364 | static struct hda_pcm_stream nvhdmi_pcm_digital_playback_2ch = { | ||
| 365 | .substreams = 1, | ||
| 366 | .channels_min = 2, | ||
| 367 | .channels_max = 2, | ||
| 368 | .nid = nvhdmi_master_con_nid_7x, | ||
| 369 | .rates = SUPPORTED_RATES, | ||
| 370 | .maxbps = SUPPORTED_MAXBPS, | ||
| 371 | .formats = SUPPORTED_FORMATS, | ||
| 372 | .ops = { | ||
| 373 | .open = nvhdmi_dig_playback_pcm_open, | ||
| 374 | .close = nvhdmi_dig_playback_pcm_close_2ch, | ||
| 375 | .prepare = nvhdmi_dig_playback_pcm_prepare_2ch | ||
| 376 | }, | ||
| 377 | }; | ||
| 378 | |||
| 379 | static int nvhdmi_build_pcms_8ch_89(struct hda_codec *codec) | ||
| 380 | { | ||
| 381 | struct hdmi_spec *spec = codec->spec; | ||
| 382 | struct hda_pcm *info = spec->pcm_rec; | ||
| 383 | int i; | ||
| 384 | |||
| 385 | codec->num_pcms = spec->num_cvts; | ||
| 386 | codec->pcm_info = info; | ||
| 387 | |||
| 388 | for (i = 0; i < codec->num_pcms; i++, info++) { | ||
| 389 | unsigned int chans; | ||
| 390 | |||
| 391 | chans = get_wcaps(codec, spec->cvt[i]); | ||
| 392 | chans = get_wcaps_channels(chans); | ||
| 393 | |||
| 394 | info->name = nvhdmi_pcm_names[i]; | ||
| 395 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 396 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
| 397 | = nvhdmi_pcm_digital_playback_8ch_89; | ||
| 398 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->cvt[i]; | ||
| 399 | info->stream[SNDRV_PCM_STREAM_PLAYBACK].channels_max = chans; | ||
| 400 | } | ||
| 401 | |||
| 402 | return 0; | ||
| 403 | } | ||
| 404 | |||
| 405 | static int nvhdmi_build_pcms_8ch_7x(struct hda_codec *codec) | ||
| 406 | { | ||
| 407 | struct hdmi_spec *spec = codec->spec; | ||
| 408 | struct hda_pcm *info = spec->pcm_rec; | ||
| 409 | |||
| 410 | codec->num_pcms = 1; | ||
| 411 | codec->pcm_info = info; | ||
| 412 | |||
| 413 | info->name = "NVIDIA HDMI"; | ||
| 414 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 415 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
| 416 | = nvhdmi_pcm_digital_playback_8ch_7x; | ||
| 417 | |||
| 418 | return 0; | ||
| 419 | } | ||
| 420 | |||
| 421 | static int nvhdmi_build_pcms_2ch(struct hda_codec *codec) | ||
| 422 | { | ||
| 423 | struct hdmi_spec *spec = codec->spec; | ||
| 424 | struct hda_pcm *info = spec->pcm_rec; | ||
| 425 | |||
| 426 | codec->num_pcms = 1; | ||
| 427 | codec->pcm_info = info; | ||
| 428 | |||
| 429 | info->name = "NVIDIA HDMI"; | ||
| 430 | info->pcm_type = HDA_PCM_TYPE_HDMI; | ||
| 431 | info->stream[SNDRV_PCM_STREAM_PLAYBACK] | ||
| 432 | = nvhdmi_pcm_digital_playback_2ch; | ||
| 433 | |||
| 434 | return 0; | ||
| 435 | } | ||
| 436 | |||
| 437 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_89 = { | ||
| 438 | .build_controls = nvhdmi_build_controls, | ||
| 439 | .build_pcms = nvhdmi_build_pcms_8ch_89, | ||
| 440 | .init = nvhdmi_init, | ||
| 441 | .free = nvhdmi_free, | ||
| 442 | .unsol_event = hdmi_unsol_event, | ||
| 443 | }; | ||
| 444 | |||
| 445 | static struct hda_codec_ops nvhdmi_patch_ops_8ch_7x = { | ||
| 446 | .build_controls = nvhdmi_build_controls, | ||
| 447 | .build_pcms = nvhdmi_build_pcms_8ch_7x, | ||
| 448 | .init = nvhdmi_init, | ||
| 449 | .free = nvhdmi_free, | ||
| 450 | }; | ||
| 451 | |||
| 452 | static struct hda_codec_ops nvhdmi_patch_ops_2ch = { | ||
| 453 | .build_controls = nvhdmi_build_controls, | ||
| 454 | .build_pcms = nvhdmi_build_pcms_2ch, | ||
| 455 | .init = nvhdmi_init, | ||
| 456 | .free = nvhdmi_free, | ||
| 457 | }; | ||
| 458 | |||
| 459 | static int patch_nvhdmi_8ch_89(struct hda_codec *codec) | ||
| 460 | { | ||
| 461 | struct hdmi_spec *spec; | ||
| 462 | int i; | ||
| 463 | |||
| 464 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 465 | if (spec == NULL) | ||
| 466 | return -ENOMEM; | ||
| 467 | |||
| 468 | codec->spec = spec; | ||
| 469 | spec->codec_type = HDA_CODEC_NVIDIA_MCP89; | ||
| 470 | spec->old_pin_detect = 1; | ||
| 471 | |||
| 472 | if (hdmi_parse_codec(codec) < 0) { | ||
| 473 | codec->spec = NULL; | ||
| 474 | kfree(spec); | ||
| 475 | return -EINVAL; | ||
| 476 | } | ||
| 477 | codec->patch_ops = nvhdmi_patch_ops_8ch_89; | ||
| 478 | |||
| 479 | for (i = 0; i < spec->num_pins; i++) | ||
| 480 | snd_hda_eld_proc_new(codec, &spec->sink_eld[i], i); | ||
| 481 | |||
| 482 | init_channel_allocations(); | ||
| 483 | |||
| 484 | return 0; | ||
| 485 | } | ||
| 486 | |||
| 487 | static int patch_nvhdmi_8ch_7x(struct hda_codec *codec) | ||
| 488 | { | ||
| 489 | struct hdmi_spec *spec; | ||
| 490 | |||
| 491 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 492 | if (spec == NULL) | ||
| 493 | return -ENOMEM; | ||
| 494 | |||
| 495 | codec->spec = spec; | ||
| 496 | |||
| 497 | spec->multiout.num_dacs = 0; /* no analog */ | ||
| 498 | spec->multiout.max_channels = 8; | ||
| 499 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
| 500 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
| 501 | spec->old_pin_detect = 1; | ||
| 502 | |||
| 503 | codec->patch_ops = nvhdmi_patch_ops_8ch_7x; | ||
| 504 | |||
| 505 | return 0; | ||
| 506 | } | ||
| 507 | |||
| 508 | static int patch_nvhdmi_2ch(struct hda_codec *codec) | ||
| 509 | { | ||
| 510 | struct hdmi_spec *spec; | ||
| 511 | |||
| 512 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | ||
| 513 | if (spec == NULL) | ||
| 514 | return -ENOMEM; | ||
| 515 | |||
| 516 | codec->spec = spec; | ||
| 517 | |||
| 518 | spec->multiout.num_dacs = 0; /* no analog */ | ||
| 519 | spec->multiout.max_channels = 2; | ||
| 520 | spec->multiout.dig_out_nid = nvhdmi_master_con_nid_7x; | ||
| 521 | spec->codec_type = HDA_CODEC_NVIDIA_MCP7X; | ||
| 522 | spec->old_pin_detect = 1; | ||
| 523 | |||
| 524 | codec->patch_ops = nvhdmi_patch_ops_2ch; | ||
| 525 | |||
| 526 | return 0; | ||
| 527 | } | ||
| 528 | |||
| 529 | /* | ||
| 530 | * patch entries | ||
| 531 | */ | ||
| 532 | static struct hda_codec_preset snd_hda_preset_nvhdmi[] = { | ||
| 533 | { .id = 0x10de0002, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 534 | { .id = 0x10de0003, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 535 | { .id = 0x10de0005, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 536 | { .id = 0x10de0006, .name = "MCP77/78 HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 537 | { .id = 0x10de0007, .name = "MCP79/7A HDMI", .patch = patch_nvhdmi_8ch_7x }, | ||
| 538 | { .id = 0x10de000a, .name = "GPU 0a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 539 | { .id = 0x10de000b, .name = "GPU 0b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 540 | { .id = 0x10de000c, .name = "MCP89 HDMI", .patch = patch_nvhdmi_8ch_89 }, | ||
| 541 | { .id = 0x10de000d, .name = "GPU 0d HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 542 | { .id = 0x10de0010, .name = "GPU 10 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 543 | { .id = 0x10de0011, .name = "GPU 11 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 544 | { .id = 0x10de0012, .name = "GPU 12 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 545 | { .id = 0x10de0013, .name = "GPU 13 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 546 | { .id = 0x10de0014, .name = "GPU 14 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 547 | { .id = 0x10de0018, .name = "GPU 18 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 548 | { .id = 0x10de0019, .name = "GPU 19 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 549 | { .id = 0x10de001a, .name = "GPU 1a HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 550 | { .id = 0x10de001b, .name = "GPU 1b HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 551 | { .id = 0x10de001c, .name = "GPU 1c HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 552 | { .id = 0x10de0040, .name = "GPU 40 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 553 | { .id = 0x10de0041, .name = "GPU 41 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 554 | { .id = 0x10de0042, .name = "GPU 42 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 555 | { .id = 0x10de0043, .name = "GPU 43 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 556 | { .id = 0x10de0044, .name = "GPU 44 HDMI/DP", .patch = patch_nvhdmi_8ch_89 }, | ||
| 557 | { .id = 0x10de0067, .name = "MCP67 HDMI", .patch = patch_nvhdmi_2ch }, | ||
| 558 | { .id = 0x10de8001, .name = "MCP73 HDMI", .patch = patch_nvhdmi_2ch }, | ||
| 559 | {} /* terminator */ | ||
| 560 | }; | ||
| 561 | |||
| 562 | MODULE_ALIAS("snd-hda-codec-id:10de0002"); | ||
| 563 | MODULE_ALIAS("snd-hda-codec-id:10de0003"); | ||
| 564 | MODULE_ALIAS("snd-hda-codec-id:10de0005"); | ||
| 565 | MODULE_ALIAS("snd-hda-codec-id:10de0006"); | ||
| 566 | MODULE_ALIAS("snd-hda-codec-id:10de0007"); | ||
| 567 | MODULE_ALIAS("snd-hda-codec-id:10de000a"); | ||
| 568 | MODULE_ALIAS("snd-hda-codec-id:10de000b"); | ||
| 569 | MODULE_ALIAS("snd-hda-codec-id:10de000c"); | ||
| 570 | MODULE_ALIAS("snd-hda-codec-id:10de000d"); | ||
| 571 | MODULE_ALIAS("snd-hda-codec-id:10de0010"); | ||
| 572 | MODULE_ALIAS("snd-hda-codec-id:10de0011"); | ||
| 573 | MODULE_ALIAS("snd-hda-codec-id:10de0012"); | ||
| 574 | MODULE_ALIAS("snd-hda-codec-id:10de0013"); | ||
| 575 | MODULE_ALIAS("snd-hda-codec-id:10de0014"); | ||
| 576 | MODULE_ALIAS("snd-hda-codec-id:10de0018"); | ||
| 577 | MODULE_ALIAS("snd-hda-codec-id:10de0019"); | ||
| 578 | MODULE_ALIAS("snd-hda-codec-id:10de001a"); | ||
| 579 | MODULE_ALIAS("snd-hda-codec-id:10de001b"); | ||
| 580 | MODULE_ALIAS("snd-hda-codec-id:10de001c"); | ||
| 581 | MODULE_ALIAS("snd-hda-codec-id:10de0040"); | ||
| 582 | MODULE_ALIAS("snd-hda-codec-id:10de0041"); | ||
| 583 | MODULE_ALIAS("snd-hda-codec-id:10de0042"); | ||
| 584 | MODULE_ALIAS("snd-hda-codec-id:10de0043"); | ||
| 585 | MODULE_ALIAS("snd-hda-codec-id:10de0044"); | ||
| 586 | MODULE_ALIAS("snd-hda-codec-id:10de0067"); | ||
| 587 | MODULE_ALIAS("snd-hda-codec-id:10de8001"); | ||
| 588 | |||
| 589 | MODULE_LICENSE("GPL"); | ||
| 590 | MODULE_DESCRIPTION("NVIDIA HDMI HD-audio codec"); | ||
| 591 | |||
| 592 | static struct hda_codec_preset_list nvhdmi_list = { | ||
| 593 | .preset = snd_hda_preset_nvhdmi, | ||
| 594 | .owner = THIS_MODULE, | ||
| 595 | }; | ||
| 596 | |||
| 597 | static int __init patch_nvhdmi_init(void) | ||
| 598 | { | ||
| 599 | return snd_hda_add_codec_preset(&nvhdmi_list); | ||
| 600 | } | ||
| 601 | |||
| 602 | static void __exit patch_nvhdmi_exit(void) | ||
| 603 | { | ||
| 604 | snd_hda_delete_codec_preset(&nvhdmi_list); | ||
| 605 | } | ||
| 606 | |||
| 607 | module_init(patch_nvhdmi_init) | ||
| 608 | module_exit(patch_nvhdmi_exit) | ||
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c index a432e6efd19b..5f00589cb791 100644 --- a/sound/pci/hda/patch_realtek.c +++ b/sound/pci/hda/patch_realtek.c | |||
| @@ -28,6 +28,7 @@ | |||
| 28 | #include <linux/slab.h> | 28 | #include <linux/slab.h> |
| 29 | #include <linux/pci.h> | 29 | #include <linux/pci.h> |
| 30 | #include <sound/core.h> | 30 | #include <sound/core.h> |
| 31 | #include <sound/jack.h> | ||
| 31 | #include "hda_codec.h" | 32 | #include "hda_codec.h" |
| 32 | #include "hda_local.h" | 33 | #include "hda_local.h" |
| 33 | #include "hda_beep.h" | 34 | #include "hda_beep.h" |
| @@ -282,6 +283,12 @@ struct alc_mic_route { | |||
| 282 | unsigned char amix_idx; | 283 | unsigned char amix_idx; |
| 283 | }; | 284 | }; |
| 284 | 285 | ||
| 286 | struct alc_jack { | ||
| 287 | hda_nid_t nid; | ||
| 288 | int type; | ||
| 289 | struct snd_jack *jack; | ||
| 290 | }; | ||
| 291 | |||
| 285 | #define MUX_IDX_UNDEF ((unsigned char)-1) | 292 | #define MUX_IDX_UNDEF ((unsigned char)-1) |
| 286 | 293 | ||
| 287 | struct alc_customize_define { | 294 | struct alc_customize_define { |
| @@ -294,6 +301,7 @@ struct alc_customize_define { | |||
| 294 | unsigned int platform_type:1; | 301 | unsigned int platform_type:1; |
| 295 | unsigned int swap:1; | 302 | unsigned int swap:1; |
| 296 | unsigned int override:1; | 303 | unsigned int override:1; |
| 304 | unsigned int fixup:1; /* Means that this sku is set by driver, not read from hw */ | ||
| 297 | }; | 305 | }; |
| 298 | 306 | ||
| 299 | struct alc_spec { | 307 | struct alc_spec { |
| @@ -357,6 +365,9 @@ struct alc_spec { | |||
| 357 | /* PCM information */ | 365 | /* PCM information */ |
| 358 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 366 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
| 359 | 367 | ||
| 368 | /* jack detection */ | ||
| 369 | struct snd_array jacks; | ||
| 370 | |||
| 360 | /* dynamic controls, init_verbs and input_mux */ | 371 | /* dynamic controls, init_verbs and input_mux */ |
| 361 | struct auto_pin_cfg autocfg; | 372 | struct auto_pin_cfg autocfg; |
| 362 | struct alc_customize_define cdefine; | 373 | struct alc_customize_define cdefine; |
| @@ -383,6 +394,7 @@ struct alc_spec { | |||
| 383 | unsigned int no_analog :1; /* digital I/O only */ | 394 | unsigned int no_analog :1; /* digital I/O only */ |
| 384 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | 395 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ |
| 385 | int init_amp; | 396 | int init_amp; |
| 397 | int codec_variant; /* flag for other variants */ | ||
| 386 | 398 | ||
| 387 | /* for virtual master */ | 399 | /* for virtual master */ |
| 388 | hda_nid_t vmaster_nid; | 400 | hda_nid_t vmaster_nid; |
| @@ -846,7 +858,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
| 846 | { | 858 | { |
| 847 | unsigned int val = PIN_IN; | 859 | unsigned int val = PIN_IN; |
| 848 | 860 | ||
| 849 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | 861 | if (auto_pin_type == AUTO_PIN_MIC) { |
| 850 | unsigned int pincap; | 862 | unsigned int pincap; |
| 851 | unsigned int oldval; | 863 | unsigned int oldval; |
| 852 | oldval = snd_hda_codec_read(codec, nid, 0, | 864 | oldval = snd_hda_codec_read(codec, nid, 0, |
| @@ -866,6 +878,28 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
| 866 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); | 878 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); |
| 867 | } | 879 | } |
| 868 | 880 | ||
| 881 | static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) | ||
| 882 | { | ||
| 883 | struct alc_spec *spec = codec->spec; | ||
| 884 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 885 | |||
| 886 | if (!cfg->line_outs) { | ||
| 887 | while (cfg->line_outs < AUTO_CFG_MAX_OUTS && | ||
| 888 | cfg->line_out_pins[cfg->line_outs]) | ||
| 889 | cfg->line_outs++; | ||
| 890 | } | ||
| 891 | if (!cfg->speaker_outs) { | ||
| 892 | while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && | ||
| 893 | cfg->speaker_pins[cfg->speaker_outs]) | ||
| 894 | cfg->speaker_outs++; | ||
| 895 | } | ||
| 896 | if (!cfg->hp_outs) { | ||
| 897 | while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && | ||
| 898 | cfg->hp_pins[cfg->hp_outs]) | ||
| 899 | cfg->hp_outs++; | ||
| 900 | } | ||
| 901 | } | ||
| 902 | |||
| 869 | /* | 903 | /* |
| 870 | */ | 904 | */ |
| 871 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | 905 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) |
| @@ -934,6 +968,8 @@ static void setup_preset(struct hda_codec *codec, | |||
| 934 | 968 | ||
| 935 | if (preset->setup) | 969 | if (preset->setup) |
| 936 | preset->setup(codec); | 970 | preset->setup(codec); |
| 971 | |||
| 972 | alc_fixup_autocfg_pin_nums(codec); | ||
| 937 | } | 973 | } |
| 938 | 974 | ||
| 939 | /* Enable GPIO mask and set output */ | 975 | /* Enable GPIO mask and set output */ |
| @@ -990,25 +1026,136 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
| 990 | alc_fix_pll(codec); | 1026 | alc_fix_pll(codec); |
| 991 | } | 1027 | } |
| 992 | 1028 | ||
| 993 | static void alc_automute_pin(struct hda_codec *codec) | 1029 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
| 1030 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
| 1031 | { | ||
| 1032 | struct alc_jack *jacks = jack->private_data; | ||
| 1033 | jacks->nid = 0; | ||
| 1034 | jacks->jack = NULL; | ||
| 1035 | } | ||
| 1036 | |||
| 1037 | static int alc_add_jack(struct hda_codec *codec, | ||
| 1038 | hda_nid_t nid, int type) | ||
| 1039 | { | ||
| 1040 | struct alc_spec *spec; | ||
| 1041 | struct alc_jack *jack; | ||
| 1042 | const char *name; | ||
| 1043 | int err; | ||
| 1044 | |||
| 1045 | spec = codec->spec; | ||
| 1046 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
| 1047 | jack = snd_array_new(&spec->jacks); | ||
| 1048 | if (!jack) | ||
| 1049 | return -ENOMEM; | ||
| 1050 | |||
| 1051 | jack->nid = nid; | ||
| 1052 | jack->type = type; | ||
| 1053 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
| 1054 | |||
| 1055 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
| 1056 | if (err < 0) | ||
| 1057 | return err; | ||
| 1058 | jack->jack->private_data = jack; | ||
| 1059 | jack->jack->private_free = alc_free_jack_priv; | ||
| 1060 | return 0; | ||
| 1061 | } | ||
| 1062 | |||
| 1063 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
| 994 | { | 1064 | { |
| 995 | struct alc_spec *spec = codec->spec; | 1065 | struct alc_spec *spec = codec->spec; |
| 996 | unsigned int nid = spec->autocfg.hp_pins[0]; | 1066 | struct alc_jack *jacks = spec->jacks.list; |
| 1067 | |||
| 1068 | if (jacks) { | ||
| 1069 | int i; | ||
| 1070 | for (i = 0; i < spec->jacks.used; i++) { | ||
| 1071 | if (jacks->nid == nid) { | ||
| 1072 | unsigned int present; | ||
| 1073 | present = snd_hda_jack_detect(codec, nid); | ||
| 1074 | |||
| 1075 | present = (present) ? jacks->type : 0; | ||
| 1076 | |||
| 1077 | snd_jack_report(jacks->jack, present); | ||
| 1078 | } | ||
| 1079 | jacks++; | ||
| 1080 | } | ||
| 1081 | } | ||
| 1082 | } | ||
| 1083 | |||
| 1084 | static int alc_init_jacks(struct hda_codec *codec) | ||
| 1085 | { | ||
| 1086 | struct alc_spec *spec = codec->spec; | ||
| 1087 | int err; | ||
| 1088 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
| 1089 | unsigned int mic_nid = spec->ext_mic.pin; | ||
| 1090 | |||
| 1091 | if (hp_nid) { | ||
| 1092 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | ||
| 1093 | if (err < 0) | ||
| 1094 | return err; | ||
| 1095 | alc_report_jack(codec, hp_nid); | ||
| 1096 | } | ||
| 1097 | |||
| 1098 | if (mic_nid) { | ||
| 1099 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | ||
| 1100 | if (err < 0) | ||
| 1101 | return err; | ||
| 1102 | alc_report_jack(codec, mic_nid); | ||
| 1103 | } | ||
| 1104 | |||
| 1105 | return 0; | ||
| 1106 | } | ||
| 1107 | #else | ||
| 1108 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
| 1109 | { | ||
| 1110 | } | ||
| 1111 | |||
| 1112 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
| 1113 | { | ||
| 1114 | return 0; | ||
| 1115 | } | ||
| 1116 | #endif | ||
| 1117 | |||
| 1118 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | ||
| 1119 | { | ||
| 1120 | struct alc_spec *spec = codec->spec; | ||
| 1121 | unsigned int mute; | ||
| 1122 | hda_nid_t nid; | ||
| 997 | int i; | 1123 | int i; |
| 998 | 1124 | ||
| 999 | if (!nid) | 1125 | spec->jack_present = 0; |
| 1000 | return; | 1126 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
| 1001 | spec->jack_present = snd_hda_jack_detect(codec, nid); | 1127 | nid = spec->autocfg.hp_pins[i]; |
| 1128 | if (!nid) | ||
| 1129 | break; | ||
| 1130 | if (snd_hda_jack_detect(codec, nid)) { | ||
| 1131 | spec->jack_present = 1; | ||
| 1132 | break; | ||
| 1133 | } | ||
| 1134 | alc_report_jack(codec, spec->autocfg.hp_pins[i]); | ||
| 1135 | } | ||
| 1136 | |||
| 1137 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
| 1138 | /* Toggle internal speakers muting */ | ||
| 1002 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | 1139 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
| 1003 | nid = spec->autocfg.speaker_pins[i]; | 1140 | nid = spec->autocfg.speaker_pins[i]; |
| 1004 | if (!nid) | 1141 | if (!nid) |
| 1005 | break; | 1142 | break; |
| 1006 | snd_hda_codec_write(codec, nid, 0, | 1143 | if (pinctl) { |
| 1144 | snd_hda_codec_write(codec, nid, 0, | ||
| 1007 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1145 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 1008 | spec->jack_present ? 0 : PIN_OUT); | 1146 | spec->jack_present ? 0 : PIN_OUT); |
| 1147 | } else { | ||
| 1148 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
| 1149 | HDA_AMP_MUTE, mute); | ||
| 1150 | } | ||
| 1009 | } | 1151 | } |
| 1010 | } | 1152 | } |
| 1011 | 1153 | ||
| 1154 | static void alc_automute_pin(struct hda_codec *codec) | ||
| 1155 | { | ||
| 1156 | alc_automute_speaker(codec, 1); | ||
| 1157 | } | ||
| 1158 | |||
| 1012 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 1159 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, |
| 1013 | hda_nid_t nid) | 1160 | hda_nid_t nid) |
| 1014 | { | 1161 | { |
| @@ -1090,6 +1237,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
| 1090 | AC_VERB_SET_CONNECT_SEL, | 1237 | AC_VERB_SET_CONNECT_SEL, |
| 1091 | alive->mux_idx); | 1238 | alive->mux_idx); |
| 1092 | } | 1239 | } |
| 1240 | alc_report_jack(codec, spec->ext_mic.pin); | ||
| 1093 | 1241 | ||
| 1094 | /* FIXME: analog mixer */ | 1242 | /* FIXME: analog mixer */ |
| 1095 | } | 1243 | } |
| @@ -1236,24 +1384,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
| 1236 | static void alc_init_auto_hp(struct hda_codec *codec) | 1384 | static void alc_init_auto_hp(struct hda_codec *codec) |
| 1237 | { | 1385 | { |
| 1238 | struct alc_spec *spec = codec->spec; | 1386 | struct alc_spec *spec = codec->spec; |
| 1387 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 1388 | int i; | ||
| 1239 | 1389 | ||
| 1240 | if (!spec->autocfg.hp_pins[0]) | 1390 | if (!cfg->hp_pins[0]) { |
| 1241 | return; | 1391 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
| 1392 | return; | ||
| 1393 | } | ||
| 1242 | 1394 | ||
| 1243 | if (!spec->autocfg.speaker_pins[0]) { | 1395 | if (!cfg->speaker_pins[0]) { |
| 1244 | if (spec->autocfg.line_out_pins[0] && | 1396 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) |
| 1245 | spec->autocfg.line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
| 1246 | spec->autocfg.speaker_pins[0] = | ||
| 1247 | spec->autocfg.line_out_pins[0]; | ||
| 1248 | else | ||
| 1249 | return; | 1397 | return; |
| 1398 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
| 1399 | sizeof(cfg->speaker_pins)); | ||
| 1400 | cfg->speaker_outs = cfg->line_outs; | ||
| 1250 | } | 1401 | } |
| 1251 | 1402 | ||
| 1252 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 1403 | if (!cfg->hp_pins[0]) { |
| 1253 | spec->autocfg.hp_pins[0]); | 1404 | memcpy(cfg->hp_pins, cfg->line_out_pins, |
| 1254 | snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0, | 1405 | sizeof(cfg->hp_pins)); |
| 1406 | cfg->hp_outs = cfg->line_outs; | ||
| 1407 | } | ||
| 1408 | |||
| 1409 | for (i = 0; i < cfg->hp_outs; i++) { | ||
| 1410 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | ||
| 1411 | cfg->hp_pins[i]); | ||
| 1412 | snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0, | ||
| 1255 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1413 | AC_VERB_SET_UNSOLICITED_ENABLE, |
| 1256 | AC_USRSP_EN | ALC880_HP_EVENT); | 1414 | AC_USRSP_EN | ALC880_HP_EVENT); |
| 1415 | } | ||
| 1257 | spec->unsol_event = alc_sku_unsol_event; | 1416 | spec->unsol_event = alc_sku_unsol_event; |
| 1258 | } | 1417 | } |
| 1259 | 1418 | ||
| @@ -1265,30 +1424,28 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
| 1265 | int i; | 1424 | int i; |
| 1266 | 1425 | ||
| 1267 | /* there must be only two mic inputs exclusively */ | 1426 | /* there must be only two mic inputs exclusively */ |
| 1268 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) | 1427 | for (i = 0; i < cfg->num_inputs; i++) |
| 1269 | if (cfg->input_pins[i]) | 1428 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
| 1270 | return; | 1429 | return; |
| 1271 | 1430 | ||
| 1272 | fixed = ext = 0; | 1431 | fixed = ext = 0; |
| 1273 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) { | 1432 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1274 | hda_nid_t nid = cfg->input_pins[i]; | 1433 | hda_nid_t nid = cfg->inputs[i].pin; |
| 1275 | unsigned int defcfg; | 1434 | unsigned int defcfg; |
| 1276 | if (!nid) | ||
| 1277 | return; | ||
| 1278 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | 1435 | defcfg = snd_hda_codec_get_pincfg(codec, nid); |
| 1279 | switch (get_defcfg_connect(defcfg)) { | 1436 | switch (snd_hda_get_input_pin_attr(defcfg)) { |
| 1280 | case AC_JACK_PORT_FIXED: | 1437 | case INPUT_PIN_ATTR_INT: |
| 1281 | if (fixed) | 1438 | if (fixed) |
| 1282 | return; /* already occupied */ | 1439 | return; /* already occupied */ |
| 1283 | fixed = nid; | 1440 | fixed = nid; |
| 1284 | break; | 1441 | break; |
| 1285 | case AC_JACK_PORT_COMPLEX: | 1442 | case INPUT_PIN_ATTR_UNUSED: |
| 1443 | return; /* invalid entry */ | ||
| 1444 | default: | ||
| 1286 | if (ext) | 1445 | if (ext) |
| 1287 | return; /* already occupied */ | 1446 | return; /* already occupied */ |
| 1288 | ext = nid; | 1447 | ext = nid; |
| 1289 | break; | 1448 | break; |
| 1290 | default: | ||
| 1291 | return; /* invalid entry */ | ||
| 1292 | } | 1449 | } |
| 1293 | } | 1450 | } |
| 1294 | if (!ext || !fixed) | 1451 | if (!ext || !fixed) |
| @@ -1308,6 +1465,11 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
| 1308 | spec->unsol_event = alc_sku_unsol_event; | 1465 | spec->unsol_event = alc_sku_unsol_event; |
| 1309 | } | 1466 | } |
| 1310 | 1467 | ||
| 1468 | /* Could be any non-zero and even value. When used as fixup, tells | ||
| 1469 | * the driver to ignore any present sku defines. | ||
| 1470 | */ | ||
| 1471 | #define ALC_FIXUP_SKU_IGNORE (2) | ||
| 1472 | |||
| 1311 | static int alc_auto_parse_customize_define(struct hda_codec *codec) | 1473 | static int alc_auto_parse_customize_define(struct hda_codec *codec) |
| 1312 | { | 1474 | { |
| 1313 | unsigned int ass, tmp, i; | 1475 | unsigned int ass, tmp, i; |
| @@ -1316,6 +1478,13 @@ static int alc_auto_parse_customize_define(struct hda_codec *codec) | |||
| 1316 | 1478 | ||
| 1317 | spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ | 1479 | spec->cdefine.enable_pcbeep = 1; /* assume always enabled */ |
| 1318 | 1480 | ||
| 1481 | if (spec->cdefine.fixup) { | ||
| 1482 | ass = spec->cdefine.sku_cfg; | ||
| 1483 | if (ass == ALC_FIXUP_SKU_IGNORE) | ||
| 1484 | return -1; | ||
| 1485 | goto do_sku; | ||
| 1486 | } | ||
| 1487 | |||
| 1319 | ass = codec->subsystem_id & 0xffff; | 1488 | ass = codec->subsystem_id & 0xffff; |
| 1320 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) | 1489 | if (ass != codec->bus->pci->subsystem_device && (ass & 1)) |
| 1321 | goto do_sku; | 1490 | goto do_sku; |
| @@ -1383,6 +1552,13 @@ static int alc_subsystem_id(struct hda_codec *codec, | |||
| 1383 | unsigned nid; | 1552 | unsigned nid; |
| 1384 | struct alc_spec *spec = codec->spec; | 1553 | struct alc_spec *spec = codec->spec; |
| 1385 | 1554 | ||
| 1555 | if (spec->cdefine.fixup) { | ||
| 1556 | ass = spec->cdefine.sku_cfg; | ||
| 1557 | if (ass == ALC_FIXUP_SKU_IGNORE) | ||
| 1558 | return 0; | ||
| 1559 | goto do_sku; | ||
| 1560 | } | ||
| 1561 | |||
| 1386 | ass = codec->subsystem_id & 0xffff; | 1562 | ass = codec->subsystem_id & 0xffff; |
| 1387 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) | 1563 | if ((ass != codec->bus->pci->subsystem_device) && (ass & 1)) |
| 1388 | goto do_sku; | 1564 | goto do_sku; |
| @@ -1502,6 +1678,7 @@ struct alc_pincfg { | |||
| 1502 | }; | 1678 | }; |
| 1503 | 1679 | ||
| 1504 | struct alc_fixup { | 1680 | struct alc_fixup { |
| 1681 | unsigned int sku; | ||
| 1505 | const struct alc_pincfg *pins; | 1682 | const struct alc_pincfg *pins; |
| 1506 | const struct hda_verb *verbs; | 1683 | const struct hda_verb *verbs; |
| 1507 | }; | 1684 | }; |
| @@ -1512,12 +1689,22 @@ static void alc_pick_fixup(struct hda_codec *codec, | |||
| 1512 | int pre_init) | 1689 | int pre_init) |
| 1513 | { | 1690 | { |
| 1514 | const struct alc_pincfg *cfg; | 1691 | const struct alc_pincfg *cfg; |
| 1692 | struct alc_spec *spec; | ||
| 1515 | 1693 | ||
| 1516 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); | 1694 | quirk = snd_pci_quirk_lookup(codec->bus->pci, quirk); |
| 1517 | if (!quirk) | 1695 | if (!quirk) |
| 1518 | return; | 1696 | return; |
| 1519 | fix += quirk->value; | 1697 | fix += quirk->value; |
| 1520 | cfg = fix->pins; | 1698 | cfg = fix->pins; |
| 1699 | if (pre_init && fix->sku) { | ||
| 1700 | #ifdef CONFIG_SND_DEBUG_VERBOSE | ||
| 1701 | snd_printdd(KERN_INFO "hda_codec: %s: Apply sku override for %s\n", | ||
| 1702 | codec->chip_name, quirk->name); | ||
| 1703 | #endif | ||
| 1704 | spec = codec->spec; | ||
| 1705 | spec->cdefine.sku_cfg = fix->sku; | ||
| 1706 | spec->cdefine.fixup = 1; | ||
| 1707 | } | ||
| 1521 | if (pre_init && cfg) { | 1708 | if (pre_init && cfg) { |
| 1522 | #ifdef CONFIG_SND_DEBUG_VERBOSE | 1709 | #ifdef CONFIG_SND_DEBUG_VERBOSE |
| 1523 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", | 1710 | snd_printdd(KERN_INFO "hda_codec: %s: Apply pincfg for %s\n", |
| @@ -1546,6 +1733,15 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
| 1546 | return val; | 1733 | return val; |
| 1547 | } | 1734 | } |
| 1548 | 1735 | ||
| 1736 | static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx, | ||
| 1737 | unsigned int coef_val) | ||
| 1738 | { | ||
| 1739 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, | ||
| 1740 | coef_idx); | ||
| 1741 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, | ||
| 1742 | coef_val); | ||
| 1743 | } | ||
| 1744 | |||
| 1549 | /* set right pin controls for digital I/O */ | 1745 | /* set right pin controls for digital I/O */ |
| 1550 | static void alc_auto_init_digital(struct hda_codec *codec) | 1746 | static void alc_auto_init_digital(struct hda_codec *codec) |
| 1551 | { | 1747 | { |
| @@ -1723,31 +1919,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { | |||
| 1723 | 1919 | ||
| 1724 | static void alc_automute_amp(struct hda_codec *codec) | 1920 | static void alc_automute_amp(struct hda_codec *codec) |
| 1725 | { | 1921 | { |
| 1726 | struct alc_spec *spec = codec->spec; | 1922 | alc_automute_speaker(codec, 0); |
| 1727 | unsigned int mute; | ||
| 1728 | hda_nid_t nid; | ||
| 1729 | int i; | ||
| 1730 | |||
| 1731 | spec->jack_present = 0; | ||
| 1732 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { | ||
| 1733 | nid = spec->autocfg.hp_pins[i]; | ||
| 1734 | if (!nid) | ||
| 1735 | break; | ||
| 1736 | if (snd_hda_jack_detect(codec, nid)) { | ||
| 1737 | spec->jack_present = 1; | ||
| 1738 | break; | ||
| 1739 | } | ||
| 1740 | } | ||
| 1741 | |||
| 1742 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
| 1743 | /* Toggle internal speakers muting */ | ||
| 1744 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | ||
| 1745 | nid = spec->autocfg.speaker_pins[i]; | ||
| 1746 | if (!nid) | ||
| 1747 | break; | ||
| 1748 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
| 1749 | HDA_AMP_MUTE, mute); | ||
| 1750 | } | ||
| 1751 | } | 1923 | } |
| 1752 | 1924 | ||
| 1753 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, | 1925 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, |
| @@ -3602,10 +3774,7 @@ static int alc_init(struct hda_codec *codec) | |||
| 3602 | if (spec->init_hook) | 3774 | if (spec->init_hook) |
| 3603 | spec->init_hook(codec); | 3775 | spec->init_hook(codec); |
| 3604 | 3776 | ||
| 3605 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3777 | hda_call_check_power_status(codec, 0x01); |
| 3606 | if (codec->patch_ops.check_power_status) | ||
| 3607 | codec->patch_ops.check_power_status(codec, 0x01); | ||
| 3608 | #endif | ||
| 3609 | return 0; | 3778 | return 0; |
| 3610 | } | 3779 | } |
| 3611 | 3780 | ||
| @@ -4001,10 +4170,7 @@ static int alc_resume(struct hda_codec *codec) | |||
| 4001 | codec->patch_ops.init(codec); | 4170 | codec->patch_ops.init(codec); |
| 4002 | snd_hda_codec_resume_amp(codec); | 4171 | snd_hda_codec_resume_amp(codec); |
| 4003 | snd_hda_codec_resume_cache(codec); | 4172 | snd_hda_codec_resume_cache(codec); |
| 4004 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4173 | hda_call_check_power_status(codec, 0x01); |
| 4005 | if (codec->patch_ops.check_power_status) | ||
| 4006 | codec->patch_ops.check_power_status(codec, 0x01); | ||
| 4007 | #endif | ||
| 4008 | return 0; | 4174 | return 0; |
| 4009 | } | 4175 | } |
| 4010 | #endif | 4176 | #endif |
| @@ -4729,7 +4895,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = { | |||
| 4729 | 4895 | ||
| 4730 | /* add dynamic controls */ | 4896 | /* add dynamic controls */ |
| 4731 | static int add_control(struct alc_spec *spec, int type, const char *name, | 4897 | static int add_control(struct alc_spec *spec, int type, const char *name, |
| 4732 | unsigned long val) | 4898 | int cidx, unsigned long val) |
| 4733 | { | 4899 | { |
| 4734 | struct snd_kcontrol_new *knew; | 4900 | struct snd_kcontrol_new *knew; |
| 4735 | 4901 | ||
| @@ -4741,6 +4907,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
| 4741 | knew->name = kstrdup(name, GFP_KERNEL); | 4907 | knew->name = kstrdup(name, GFP_KERNEL); |
| 4742 | if (!knew->name) | 4908 | if (!knew->name) |
| 4743 | return -ENOMEM; | 4909 | return -ENOMEM; |
| 4910 | knew->index = cidx; | ||
| 4744 | if (get_amp_nid_(val)) | 4911 | if (get_amp_nid_(val)) |
| 4745 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; | 4912 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
| 4746 | knew->private_value = val; | 4913 | knew->private_value = val; |
| @@ -4749,17 +4916,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
| 4749 | 4916 | ||
| 4750 | static int add_control_with_pfx(struct alc_spec *spec, int type, | 4917 | static int add_control_with_pfx(struct alc_spec *spec, int type, |
| 4751 | const char *pfx, const char *dir, | 4918 | const char *pfx, const char *dir, |
| 4752 | const char *sfx, unsigned long val) | 4919 | const char *sfx, int cidx, unsigned long val) |
| 4753 | { | 4920 | { |
| 4754 | char name[32]; | 4921 | char name[32]; |
| 4755 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); | 4922 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); |
| 4756 | return add_control(spec, type, name, val); | 4923 | return add_control(spec, type, name, cidx, val); |
| 4757 | } | 4924 | } |
| 4758 | 4925 | ||
| 4759 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ | 4926 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ |
| 4760 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val) | 4927 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) |
| 4761 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ | 4928 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ |
| 4762 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val) | 4929 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) |
| 4930 | #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ | ||
| 4931 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) | ||
| 4932 | #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ | ||
| 4933 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) | ||
| 4763 | 4934 | ||
| 4764 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) | 4935 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) |
| 4765 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) | 4936 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) |
| @@ -4912,16 +5083,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
| 4912 | 5083 | ||
| 4913 | /* create input playback/capture controls for the given pin */ | 5084 | /* create input playback/capture controls for the given pin */ |
| 4914 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | 5085 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
| 4915 | const char *ctlname, | 5086 | const char *ctlname, int ctlidx, |
| 4916 | int idx, hda_nid_t mix_nid) | 5087 | int idx, hda_nid_t mix_nid) |
| 4917 | { | 5088 | { |
| 4918 | int err; | 5089 | int err; |
| 4919 | 5090 | ||
| 4920 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | 5091 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx, |
| 4921 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5092 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
| 4922 | if (err < 0) | 5093 | if (err < 0) |
| 4923 | return err; | 5094 | return err; |
| 4924 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | 5095 | err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx, |
| 4925 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5096 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
| 4926 | if (err < 0) | 5097 | if (err < 0) |
| 4927 | return err; | 5098 | return err; |
| @@ -4942,20 +5113,27 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
| 4942 | { | 5113 | { |
| 4943 | struct alc_spec *spec = codec->spec; | 5114 | struct alc_spec *spec = codec->spec; |
| 4944 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5115 | struct hda_input_mux *imux = &spec->private_imux[0]; |
| 4945 | int i, err, idx; | 5116 | int i, err, idx, type, type_idx = 0; |
| 4946 | 5117 | ||
| 4947 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5118 | for (i = 0; i < cfg->num_inputs; i++) { |
| 4948 | hda_nid_t pin; | 5119 | hda_nid_t pin; |
| 5120 | const char *label; | ||
| 4949 | 5121 | ||
| 4950 | pin = cfg->input_pins[i]; | 5122 | pin = cfg->inputs[i].pin; |
| 4951 | if (!alc_is_input_pin(codec, pin)) | 5123 | if (!alc_is_input_pin(codec, pin)) |
| 4952 | continue; | 5124 | continue; |
| 4953 | 5125 | ||
| 5126 | type = cfg->inputs[i].type; | ||
| 5127 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
| 5128 | type_idx++; | ||
| 5129 | else | ||
| 5130 | type_idx = 0; | ||
| 5131 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 4954 | if (mixer) { | 5132 | if (mixer) { |
| 4955 | idx = get_connection_index(codec, mixer, pin); | 5133 | idx = get_connection_index(codec, mixer, pin); |
| 4956 | if (idx >= 0) { | 5134 | if (idx >= 0) { |
| 4957 | err = new_analog_input(spec, pin, | 5135 | err = new_analog_input(spec, pin, |
| 4958 | auto_pin_cfg_labels[i], | 5136 | label, type_idx, |
| 4959 | idx, mixer); | 5137 | idx, mixer); |
| 4960 | if (err < 0) | 5138 | if (err < 0) |
| 4961 | return err; | 5139 | return err; |
| @@ -4967,12 +5145,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
| 4967 | idx = get_connection_index(codec, cap1, pin); | 5145 | idx = get_connection_index(codec, cap1, pin); |
| 4968 | if (idx < 0 && cap2) | 5146 | if (idx < 0 && cap2) |
| 4969 | idx = get_connection_index(codec, cap2, pin); | 5147 | idx = get_connection_index(codec, cap2, pin); |
| 4970 | if (idx >= 0) { | 5148 | if (idx >= 0) |
| 4971 | imux->items[imux->num_items].label = | 5149 | snd_hda_add_imux_item(imux, label, idx, NULL); |
| 4972 | auto_pin_cfg_labels[i]; | ||
| 4973 | imux->items[imux->num_items].index = idx; | ||
| 4974 | imux->num_items++; | ||
| 4975 | } | ||
| 4976 | } | 5150 | } |
| 4977 | return 0; | 5151 | return 0; |
| 4978 | } | 5152 | } |
| @@ -5044,12 +5218,13 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
| 5044 | static void alc880_auto_init_analog_input(struct hda_codec *codec) | 5218 | static void alc880_auto_init_analog_input(struct hda_codec *codec) |
| 5045 | { | 5219 | { |
| 5046 | struct alc_spec *spec = codec->spec; | 5220 | struct alc_spec *spec = codec->spec; |
| 5221 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 5047 | int i; | 5222 | int i; |
| 5048 | 5223 | ||
| 5049 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5224 | for (i = 0; i < cfg->num_inputs; i++) { |
| 5050 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5225 | hda_nid_t nid = cfg->inputs[i].pin; |
| 5051 | if (alc_is_input_pin(codec, nid)) { | 5226 | if (alc_is_input_pin(codec, nid)) { |
| 5052 | alc_set_input_pin(codec, nid, i); | 5227 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 5053 | if (nid != ALC880_PIN_CD_NID && | 5228 | if (nid != ALC880_PIN_CD_NID && |
| 5054 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 5229 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
| 5055 | snd_hda_codec_write(codec, nid, 0, | 5230 | snd_hda_codec_write(codec, nid, 0, |
| @@ -5214,19 +5389,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) | |||
| 5214 | static void fixup_single_adc(struct hda_codec *codec) | 5389 | static void fixup_single_adc(struct hda_codec *codec) |
| 5215 | { | 5390 | { |
| 5216 | struct alc_spec *spec = codec->spec; | 5391 | struct alc_spec *spec = codec->spec; |
| 5217 | hda_nid_t pin = 0; | 5392 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 5218 | int i; | 5393 | int i; |
| 5219 | 5394 | ||
| 5220 | /* search for the input pin; there must be only one */ | 5395 | /* search for the input pin; there must be only one */ |
| 5221 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5396 | if (cfg->num_inputs != 1) |
| 5222 | if (spec->autocfg.input_pins[i]) { | ||
| 5223 | pin = spec->autocfg.input_pins[i]; | ||
| 5224 | break; | ||
| 5225 | } | ||
| 5226 | } | ||
| 5227 | if (!pin) | ||
| 5228 | return; | 5397 | return; |
| 5229 | i = init_capsrc_for_pin(codec, pin); | 5398 | i = init_capsrc_for_pin(codec, cfg->inputs[0].pin); |
| 5230 | if (i >= 0) { | 5399 | if (i >= 0) { |
| 5231 | /* use only this ADC */ | 5400 | /* use only this ADC */ |
| 5232 | if (spec->capsrc_nids) | 5401 | if (spec->capsrc_nids) |
| @@ -5279,6 +5448,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
| 5279 | int num_nids) | 5448 | int num_nids) |
| 5280 | { | 5449 | { |
| 5281 | struct alc_spec *spec = codec->spec; | 5450 | struct alc_spec *spec = codec->spec; |
| 5451 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 5282 | int n; | 5452 | int n; |
| 5283 | hda_nid_t fallback_adc = 0, fallback_cap = 0; | 5453 | hda_nid_t fallback_adc = 0, fallback_cap = 0; |
| 5284 | 5454 | ||
| @@ -5304,10 +5474,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
| 5304 | fallback_adc = adc; | 5474 | fallback_adc = adc; |
| 5305 | fallback_cap = cap; | 5475 | fallback_cap = cap; |
| 5306 | } | 5476 | } |
| 5307 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5477 | for (i = 0; i < cfg->num_inputs; i++) { |
| 5308 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5478 | hda_nid_t nid = cfg->inputs[i].pin; |
| 5309 | if (!nid) | ||
| 5310 | continue; | ||
| 5311 | for (j = 0; j < nconns; j++) { | 5479 | for (j = 0; j < nconns; j++) { |
| 5312 | if (conn[j] == nid) | 5480 | if (conn[j] == nid) |
| 5313 | break; | 5481 | break; |
| @@ -5315,7 +5483,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
| 5315 | if (j >= nconns) | 5483 | if (j >= nconns) |
| 5316 | break; | 5484 | break; |
| 5317 | } | 5485 | } |
| 5318 | if (i >= AUTO_PIN_LAST) { | 5486 | if (i >= cfg->num_inputs) { |
| 5319 | int num_adcs = spec->num_adc_nids; | 5487 | int num_adcs = spec->num_adc_nids; |
| 5320 | spec->private_adc_nids[num_adcs] = adc; | 5488 | spec->private_adc_nids[num_adcs] = adc; |
| 5321 | spec->private_capsrc_nids[num_adcs] = cap; | 5489 | spec->private_capsrc_nids[num_adcs] = cap; |
| @@ -6683,12 +6851,13 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
| 6683 | static void alc260_auto_init_analog_input(struct hda_codec *codec) | 6851 | static void alc260_auto_init_analog_input(struct hda_codec *codec) |
| 6684 | { | 6852 | { |
| 6685 | struct alc_spec *spec = codec->spec; | 6853 | struct alc_spec *spec = codec->spec; |
| 6854 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 6686 | int i; | 6855 | int i; |
| 6687 | 6856 | ||
| 6688 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 6857 | for (i = 0; i < cfg->num_inputs; i++) { |
| 6689 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 6858 | hda_nid_t nid = cfg->inputs[i].pin; |
| 6690 | if (nid >= 0x12) { | 6859 | if (nid >= 0x12) { |
| 6691 | alc_set_input_pin(codec, nid, i); | 6860 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 6692 | if (nid != ALC260_PIN_CD_NID && | 6861 | if (nid != ALC260_PIN_CD_NID && |
| 6693 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 6862 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
| 6694 | snd_hda_codec_write(codec, nid, 0, | 6863 | snd_hda_codec_write(codec, nid, 0, |
| @@ -6810,14 +6979,12 @@ enum { | |||
| 6810 | PINFIX_HP_DC5750, | 6979 | PINFIX_HP_DC5750, |
| 6811 | }; | 6980 | }; |
| 6812 | 6981 | ||
| 6813 | static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { | ||
| 6814 | { 0x11, 0x90130110 }, /* speaker */ | ||
| 6815 | { } | ||
| 6816 | }; | ||
| 6817 | |||
| 6818 | static const struct alc_fixup alc260_fixups[] = { | 6982 | static const struct alc_fixup alc260_fixups[] = { |
| 6819 | [PINFIX_HP_DC5750] = { | 6983 | [PINFIX_HP_DC5750] = { |
| 6820 | .pins = alc260_hp_dc5750_pinfix | 6984 | .pins = (const struct alc_pincfg[]) { |
| 6985 | { 0x11, 0x90130110 }, /* speaker */ | ||
| 6986 | { } | ||
| 6987 | } | ||
| 6821 | }, | 6988 | }, |
| 6822 | }; | 6989 | }; |
| 6823 | 6990 | ||
| @@ -10461,32 +10628,33 @@ static struct alc_config_preset alc882_presets[] = { | |||
| 10461 | enum { | 10628 | enum { |
| 10462 | PINFIX_ABIT_AW9D_MAX, | 10629 | PINFIX_ABIT_AW9D_MAX, |
| 10463 | PINFIX_PB_M5210, | 10630 | PINFIX_PB_M5210, |
| 10464 | }; | 10631 | PINFIX_ACER_ASPIRE_7736, |
| 10465 | |||
| 10466 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | ||
| 10467 | { 0x15, 0x01080104 }, /* side */ | ||
| 10468 | { 0x16, 0x01011012 }, /* rear */ | ||
| 10469 | { 0x17, 0x01016011 }, /* clfe */ | ||
| 10470 | { } | ||
| 10471 | }; | ||
| 10472 | |||
| 10473 | static const struct hda_verb pb_m5210_verbs[] = { | ||
| 10474 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
| 10475 | {} | ||
| 10476 | }; | 10632 | }; |
| 10477 | 10633 | ||
| 10478 | static const struct alc_fixup alc882_fixups[] = { | 10634 | static const struct alc_fixup alc882_fixups[] = { |
| 10479 | [PINFIX_ABIT_AW9D_MAX] = { | 10635 | [PINFIX_ABIT_AW9D_MAX] = { |
| 10480 | .pins = alc882_abit_aw9d_pinfix | 10636 | .pins = (const struct alc_pincfg[]) { |
| 10637 | { 0x15, 0x01080104 }, /* side */ | ||
| 10638 | { 0x16, 0x01011012 }, /* rear */ | ||
| 10639 | { 0x17, 0x01016011 }, /* clfe */ | ||
| 10640 | { } | ||
| 10641 | } | ||
| 10481 | }, | 10642 | }, |
| 10482 | [PINFIX_PB_M5210] = { | 10643 | [PINFIX_PB_M5210] = { |
| 10483 | .verbs = pb_m5210_verbs | 10644 | .verbs = (const struct hda_verb[]) { |
| 10645 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
| 10646 | {} | ||
| 10647 | } | ||
| 10648 | }, | ||
| 10649 | [PINFIX_ACER_ASPIRE_7736] = { | ||
| 10650 | .sku = ALC_FIXUP_SKU_IGNORE, | ||
| 10484 | }, | 10651 | }, |
| 10485 | }; | 10652 | }; |
| 10486 | 10653 | ||
| 10487 | static struct snd_pci_quirk alc882_fixup_tbl[] = { | 10654 | static struct snd_pci_quirk alc882_fixup_tbl[] = { |
| 10488 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), | 10655 | SND_PCI_QUIRK(0x1025, 0x0155, "Packard-Bell M5120", PINFIX_PB_M5210), |
| 10489 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), | 10656 | SND_PCI_QUIRK(0x147b, 0x107a, "Abit AW9D-MAX", PINFIX_ABIT_AW9D_MAX), |
| 10657 | SND_PCI_QUIRK(0x1025, 0x0296, "Acer Aspire 7736z", PINFIX_ACER_ASPIRE_7736), | ||
| 10490 | {} | 10658 | {} |
| 10491 | }; | 10659 | }; |
| 10492 | 10660 | ||
| @@ -10535,16 +10703,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
| 10535 | { | 10703 | { |
| 10536 | struct alc_spec *spec = codec->spec; | 10704 | struct alc_spec *spec = codec->spec; |
| 10537 | hda_nid_t pin, dac; | 10705 | hda_nid_t pin, dac; |
| 10706 | int i; | ||
| 10538 | 10707 | ||
| 10539 | pin = spec->autocfg.hp_pins[0]; | 10708 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
| 10540 | if (pin) { | 10709 | pin = spec->autocfg.hp_pins[i]; |
| 10710 | if (!pin) | ||
| 10711 | break; | ||
| 10541 | dac = spec->multiout.hp_nid; | 10712 | dac = spec->multiout.hp_nid; |
| 10542 | if (!dac) | 10713 | if (!dac) |
| 10543 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10714 | dac = spec->multiout.dac_nids[0]; /* to front */ |
| 10544 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | 10715 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); |
| 10545 | } | 10716 | } |
| 10546 | pin = spec->autocfg.speaker_pins[0]; | 10717 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
| 10547 | if (pin) { | 10718 | pin = spec->autocfg.speaker_pins[i]; |
| 10719 | if (!pin) | ||
| 10720 | break; | ||
| 10548 | dac = spec->multiout.extra_out_nid[0]; | 10721 | dac = spec->multiout.extra_out_nid[0]; |
| 10549 | if (!dac) | 10722 | if (!dac) |
| 10550 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10723 | dac = spec->multiout.dac_nids[0]; /* to front */ |
| @@ -10555,13 +10728,12 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
| 10555 | static void alc882_auto_init_analog_input(struct hda_codec *codec) | 10728 | static void alc882_auto_init_analog_input(struct hda_codec *codec) |
| 10556 | { | 10729 | { |
| 10557 | struct alc_spec *spec = codec->spec; | 10730 | struct alc_spec *spec = codec->spec; |
| 10731 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 10558 | int i; | 10732 | int i; |
| 10559 | 10733 | ||
| 10560 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 10734 | for (i = 0; i < cfg->num_inputs; i++) { |
| 10561 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 10735 | hda_nid_t nid = cfg->inputs[i].pin; |
| 10562 | if (!nid) | 10736 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 10563 | continue; | ||
| 10564 | alc_set_input_pin(codec, nid, i); | ||
| 10565 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) | 10737 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) |
| 10566 | snd_hda_codec_write(codec, nid, 0, | 10738 | snd_hda_codec_write(codec, nid, 0, |
| 10567 | AC_VERB_SET_AMP_GAIN_MUTE, | 10739 | AC_VERB_SET_AMP_GAIN_MUTE, |
| @@ -10623,24 +10795,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
| 10623 | static int alc_auto_add_mic_boost(struct hda_codec *codec) | 10795 | static int alc_auto_add_mic_boost(struct hda_codec *codec) |
| 10624 | { | 10796 | { |
| 10625 | struct alc_spec *spec = codec->spec; | 10797 | struct alc_spec *spec = codec->spec; |
| 10626 | int err; | 10798 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 10799 | int i, err; | ||
| 10627 | hda_nid_t nid; | 10800 | hda_nid_t nid; |
| 10628 | 10801 | ||
| 10629 | nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; | 10802 | for (i = 0; i < cfg->num_inputs; i++) { |
| 10630 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | 10803 | if (cfg->inputs[i].type > AUTO_PIN_MIC) |
| 10631 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 10804 | break; |
| 10632 | "Mic Boost", | 10805 | nid = cfg->inputs[i].pin; |
| 10633 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10806 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { |
| 10634 | if (err < 0) | 10807 | char label[32]; |
| 10635 | return err; | 10808 | snprintf(label, sizeof(label), "%s Boost", |
| 10636 | } | 10809 | hda_get_autocfg_input_label(codec, cfg, i)); |
| 10637 | nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; | 10810 | err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, |
| 10638 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | ||
| 10639 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
| 10640 | "Front Mic Boost", | ||
| 10641 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10811 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
| 10642 | if (err < 0) | 10812 | if (err < 0) |
| 10643 | return err; | 10813 | return err; |
| 10814 | } | ||
| 10644 | } | 10815 | } |
| 10645 | return 0; | 10816 | return 0; |
| 10646 | } | 10817 | } |
| @@ -10726,8 +10897,6 @@ static int patch_alc882(struct hda_codec *codec) | |||
| 10726 | 10897 | ||
| 10727 | codec->spec = spec; | 10898 | codec->spec = spec; |
| 10728 | 10899 | ||
| 10729 | alc_auto_parse_customize_define(codec); | ||
| 10730 | |||
| 10731 | switch (codec->vendor_id) { | 10900 | switch (codec->vendor_id) { |
| 10732 | case 0x10ec0882: | 10901 | case 0x10ec0882: |
| 10733 | case 0x10ec0885: | 10902 | case 0x10ec0885: |
| @@ -10755,6 +10924,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
| 10755 | if (board_config == ALC882_AUTO) | 10924 | if (board_config == ALC882_AUTO) |
| 10756 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); | 10925 | alc_pick_fixup(codec, alc882_fixup_tbl, alc882_fixups, 1); |
| 10757 | 10926 | ||
| 10927 | alc_auto_parse_customize_define(codec); | ||
| 10928 | |||
| 10758 | if (board_config == ALC882_AUTO) { | 10929 | if (board_config == ALC882_AUTO) { |
| 10759 | /* automatic parse from the BIOS config */ | 10930 | /* automatic parse from the BIOS config */ |
| 10760 | err = alc882_parse_auto_config(codec); | 10931 | err = alc882_parse_auto_config(codec); |
| @@ -10835,6 +11006,8 @@ static int patch_alc882(struct hda_codec *codec) | |||
| 10835 | codec->patch_ops = alc_patch_ops; | 11006 | codec->patch_ops = alc_patch_ops; |
| 10836 | if (board_config == ALC882_AUTO) | 11007 | if (board_config == ALC882_AUTO) |
| 10837 | spec->init_hook = alc882_auto_init; | 11008 | spec->init_hook = alc882_auto_init; |
| 11009 | |||
| 11010 | alc_init_jacks(codec); | ||
| 10838 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 11011 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 10839 | if (!spec->loopback.amplist) | 11012 | if (!spec->loopback.amplist) |
| 10840 | spec->loopback.amplist = alc882_loopbacks; | 11013 | spec->loopback.amplist = alc882_loopbacks; |
| @@ -11831,7 +12004,7 @@ static int alc262_check_volbit(hda_nid_t nid) | |||
| 11831 | } | 12004 | } |
| 11832 | 12005 | ||
| 11833 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | 12006 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, |
| 11834 | const char *pfx, int *vbits) | 12007 | const char *pfx, int *vbits, int idx) |
| 11835 | { | 12008 | { |
| 11836 | unsigned long val; | 12009 | unsigned long val; |
| 11837 | int vbit; | 12010 | int vbit; |
| @@ -11846,11 +12019,11 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
| 11846 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); | 12019 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); |
| 11847 | else | 12020 | else |
| 11848 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); | 12021 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); |
| 11849 | return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val); | 12022 | return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val); |
| 11850 | } | 12023 | } |
| 11851 | 12024 | ||
| 11852 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | 12025 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, |
| 11853 | const char *pfx) | 12026 | const char *pfx, int idx) |
| 11854 | { | 12027 | { |
| 11855 | unsigned long val; | 12028 | unsigned long val; |
| 11856 | 12029 | ||
| @@ -11860,7 +12033,7 @@ static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
| 11860 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); | 12033 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); |
| 11861 | else | 12034 | else |
| 11862 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | 12035 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); |
| 11863 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); | 12036 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val); |
| 11864 | } | 12037 | } |
| 11865 | 12038 | ||
| 11866 | /* add playback controls from the parsed DAC table */ | 12039 | /* add playback controls from the parsed DAC table */ |
| @@ -11869,7 +12042,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 11869 | { | 12042 | { |
| 11870 | const char *pfx; | 12043 | const char *pfx; |
| 11871 | int vbits; | 12044 | int vbits; |
| 11872 | int err; | 12045 | int i, err; |
| 11873 | 12046 | ||
| 11874 | spec->multiout.num_dacs = 1; /* only use one dac */ | 12047 | spec->multiout.num_dacs = 1; /* only use one dac */ |
| 11875 | spec->multiout.dac_nids = spec->private_dac_nids; | 12048 | spec->multiout.dac_nids = spec->private_dac_nids; |
| @@ -11879,39 +12052,52 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
| 11879 | pfx = "Master"; | 12052 | pfx = "Master"; |
| 11880 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 12053 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) |
| 11881 | pfx = "Speaker"; | 12054 | pfx = "Speaker"; |
| 12055 | else if (cfg->line_out_type == AUTO_PIN_HP_OUT) | ||
| 12056 | pfx = "Headphone"; | ||
| 11882 | else | 12057 | else |
| 11883 | pfx = "Front"; | 12058 | pfx = "Front"; |
| 11884 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx); | 12059 | for (i = 0; i < 2; i++) { |
| 11885 | if (err < 0) | 12060 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); |
| 11886 | return err; | 12061 | if (err < 0) |
| 11887 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker"); | 12062 | return err; |
| 11888 | if (err < 0) | 12063 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
| 11889 | return err; | 12064 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i], |
| 11890 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone"); | 12065 | "Speaker", i); |
| 11891 | if (err < 0) | 12066 | if (err < 0) |
| 11892 | return err; | 12067 | return err; |
| 12068 | } | ||
| 12069 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
| 12070 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i], | ||
| 12071 | "Headphone", i); | ||
| 12072 | if (err < 0) | ||
| 12073 | return err; | ||
| 12074 | } | ||
| 12075 | } | ||
| 11893 | 12076 | ||
| 11894 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | | 12077 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | |
| 11895 | alc262_check_volbit(cfg->speaker_pins[0]) | | 12078 | alc262_check_volbit(cfg->speaker_pins[0]) | |
| 11896 | alc262_check_volbit(cfg->hp_pins[0]); | 12079 | alc262_check_volbit(cfg->hp_pins[0]); |
| 11897 | if (vbits == 1 || vbits == 2) | 12080 | if (vbits == 1 || vbits == 2) |
| 11898 | pfx = "Master"; /* only one mixer is used */ | 12081 | pfx = "Master"; /* only one mixer is used */ |
| 11899 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
| 11900 | pfx = "Speaker"; | ||
| 11901 | else | ||
| 11902 | pfx = "Front"; | ||
| 11903 | vbits = 0; | 12082 | vbits = 0; |
| 11904 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits); | 12083 | for (i = 0; i < 2; i++) { |
| 11905 | if (err < 0) | 12084 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx, |
| 11906 | return err; | 12085 | &vbits, i); |
| 11907 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker", | 12086 | if (err < 0) |
| 11908 | &vbits); | 12087 | return err; |
| 11909 | if (err < 0) | 12088 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
| 11910 | return err; | 12089 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i], |
| 11911 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone", | 12090 | "Speaker", &vbits, i); |
| 11912 | &vbits); | 12091 | if (err < 0) |
| 11913 | if (err < 0) | 12092 | return err; |
| 11914 | return err; | 12093 | } |
| 12094 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
| 12095 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i], | ||
| 12096 | "Headphone", &vbits, i); | ||
| 12097 | if (err < 0) | ||
| 12098 | return err; | ||
| 12099 | } | ||
| 12100 | } | ||
| 11915 | return 0; | 12101 | return 0; |
| 11916 | } | 12102 | } |
| 11917 | 12103 | ||
| @@ -12199,6 +12385,35 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { | |||
| 12199 | {} | 12385 | {} |
| 12200 | }; | 12386 | }; |
| 12201 | 12387 | ||
| 12388 | /* | ||
| 12389 | * Pin config fixes | ||
| 12390 | */ | ||
| 12391 | enum { | ||
| 12392 | PINFIX_FSC_H270, | ||
| 12393 | }; | ||
| 12394 | |||
| 12395 | static const struct alc_fixup alc262_fixups[] = { | ||
| 12396 | [PINFIX_FSC_H270] = { | ||
| 12397 | .pins = (const struct alc_pincfg[]) { | ||
| 12398 | { 0x14, 0x99130110 }, /* speaker */ | ||
| 12399 | { 0x15, 0x0221142f }, /* front HP */ | ||
| 12400 | { 0x1b, 0x0121141f }, /* rear HP */ | ||
| 12401 | { } | ||
| 12402 | } | ||
| 12403 | }, | ||
| 12404 | [PINFIX_PB_M5210] = { | ||
| 12405 | .verbs = (const struct hda_verb[]) { | ||
| 12406 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
| 12407 | {} | ||
| 12408 | } | ||
| 12409 | }, | ||
| 12410 | }; | ||
| 12411 | |||
| 12412 | static struct snd_pci_quirk alc262_fixup_tbl[] = { | ||
| 12413 | SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270), | ||
| 12414 | {} | ||
| 12415 | }; | ||
| 12416 | |||
| 12202 | 12417 | ||
| 12203 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12418 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 12204 | #define alc262_loopbacks alc880_loopbacks | 12419 | #define alc262_loopbacks alc880_loopbacks |
| @@ -12622,6 +12837,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
| 12622 | board_config = ALC262_AUTO; | 12837 | board_config = ALC262_AUTO; |
| 12623 | } | 12838 | } |
| 12624 | 12839 | ||
| 12840 | if (board_config == ALC262_AUTO) | ||
| 12841 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1); | ||
| 12842 | |||
| 12625 | if (board_config == ALC262_AUTO) { | 12843 | if (board_config == ALC262_AUTO) { |
| 12626 | /* automatic parse from the BIOS config */ | 12844 | /* automatic parse from the BIOS config */ |
| 12627 | err = alc262_parse_auto_config(codec); | 12845 | err = alc262_parse_auto_config(codec); |
| @@ -12690,11 +12908,16 @@ static int patch_alc262(struct hda_codec *codec) | |||
| 12690 | if (!spec->no_analog && has_cdefine_beep(codec)) | 12908 | if (!spec->no_analog && has_cdefine_beep(codec)) |
| 12691 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12909 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
| 12692 | 12910 | ||
| 12911 | if (board_config == ALC262_AUTO) | ||
| 12912 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0); | ||
| 12913 | |||
| 12693 | spec->vmaster_nid = 0x0c; | 12914 | spec->vmaster_nid = 0x0c; |
| 12694 | 12915 | ||
| 12695 | codec->patch_ops = alc_patch_ops; | 12916 | codec->patch_ops = alc_patch_ops; |
| 12696 | if (board_config == ALC262_AUTO) | 12917 | if (board_config == ALC262_AUTO) |
| 12697 | spec->init_hook = alc262_auto_init; | 12918 | spec->init_hook = alc262_auto_init; |
| 12919 | |||
| 12920 | alc_init_jacks(codec); | ||
| 12698 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12921 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 12699 | if (!spec->loopback.amplist) | 12922 | if (!spec->loopback.amplist) |
| 12700 | spec->loopback.amplist = alc262_loopbacks; | 12923 | spec->loopback.amplist = alc262_loopbacks; |
| @@ -13310,8 +13533,10 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec, | |||
| 13310 | static void alc268_auto_init_multi_out(struct hda_codec *codec) | 13533 | static void alc268_auto_init_multi_out(struct hda_codec *codec) |
| 13311 | { | 13534 | { |
| 13312 | struct alc_spec *spec = codec->spec; | 13535 | struct alc_spec *spec = codec->spec; |
| 13313 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | 13536 | int i; |
| 13314 | if (nid) { | 13537 | |
| 13538 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
| 13539 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
| 13315 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 13540 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
| 13316 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); | 13541 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); |
| 13317 | } | 13542 | } |
| @@ -13321,13 +13546,19 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec) | |||
| 13321 | { | 13546 | { |
| 13322 | struct alc_spec *spec = codec->spec; | 13547 | struct alc_spec *spec = codec->spec; |
| 13323 | hda_nid_t pin; | 13548 | hda_nid_t pin; |
| 13549 | int i; | ||
| 13324 | 13550 | ||
| 13325 | pin = spec->autocfg.hp_pins[0]; | 13551 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
| 13326 | if (pin) | 13552 | pin = spec->autocfg.hp_pins[i]; |
| 13327 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); | 13553 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); |
| 13328 | pin = spec->autocfg.speaker_pins[0]; | 13554 | } |
| 13329 | if (pin) | 13555 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { |
| 13556 | pin = spec->autocfg.speaker_pins[i]; | ||
| 13330 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); | 13557 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); |
| 13558 | } | ||
| 13559 | if (spec->autocfg.mono_out_pin) | ||
| 13560 | snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0, | ||
| 13561 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
| 13331 | } | 13562 | } |
| 13332 | 13563 | ||
| 13333 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) | 13564 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) |
| @@ -13766,6 +13997,8 @@ static int patch_alc268(struct hda_codec *codec) | |||
| 13766 | if (board_config == ALC268_AUTO) | 13997 | if (board_config == ALC268_AUTO) |
| 13767 | spec->init_hook = alc268_auto_init; | 13998 | spec->init_hook = alc268_auto_init; |
| 13768 | 13999 | ||
| 14000 | alc_init_jacks(codec); | ||
| 14001 | |||
| 13769 | return 0; | 14002 | return 0; |
| 13770 | } | 14003 | } |
| 13771 | 14004 | ||
| @@ -14132,6 +14365,7 @@ static void alc269_speaker_automute(struct hda_codec *codec) | |||
| 14132 | HDA_AMP_MUTE, bits); | 14365 | HDA_AMP_MUTE, bits); |
| 14133 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, | 14366 | snd_hda_codec_amp_stereo(codec, 0x0c, HDA_INPUT, 1, |
| 14134 | HDA_AMP_MUTE, bits); | 14367 | HDA_AMP_MUTE, bits); |
| 14368 | alc_report_jack(codec, nid); | ||
| 14135 | } | 14369 | } |
| 14136 | 14370 | ||
| 14137 | /* unsolicited event for HP jack sensing */ | 14371 | /* unsolicited event for HP jack sensing */ |
| @@ -14386,6 +14620,13 @@ static int alc275_setup_dual_adc(struct hda_codec *codec) | |||
| 14386 | return 0; | 14620 | return 0; |
| 14387 | } | 14621 | } |
| 14388 | 14622 | ||
| 14623 | /* different alc269-variants */ | ||
| 14624 | enum { | ||
| 14625 | ALC269_TYPE_NORMAL, | ||
| 14626 | ALC269_TYPE_ALC259, | ||
| 14627 | ALC269_TYPE_ALC271X, | ||
| 14628 | }; | ||
| 14629 | |||
| 14389 | /* | 14630 | /* |
| 14390 | * BIOS auto configuration | 14631 | * BIOS auto configuration |
| 14391 | */ | 14632 | */ |
| @@ -14403,7 +14644,11 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
| 14403 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); | 14644 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); |
| 14404 | if (err < 0) | 14645 | if (err < 0) |
| 14405 | return err; | 14646 | return err; |
| 14406 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | 14647 | if (spec->codec_variant == ALC269_TYPE_NORMAL) |
| 14648 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | ||
| 14649 | else | ||
| 14650 | err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0, | ||
| 14651 | 0x22, 0); | ||
| 14407 | if (err < 0) | 14652 | if (err < 0) |
| 14408 | return err; | 14653 | return err; |
| 14409 | 14654 | ||
| @@ -14414,7 +14659,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
| 14414 | if (spec->kctls.list) | 14659 | if (spec->kctls.list) |
| 14415 | add_mixer(spec, spec->kctls.list); | 14660 | add_mixer(spec, spec->kctls.list); |
| 14416 | 14661 | ||
| 14417 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { | 14662 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
| 14418 | add_verb(spec, alc269vb_init_verbs); | 14663 | add_verb(spec, alc269vb_init_verbs); |
| 14419 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | 14664 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); |
| 14420 | } else { | 14665 | } else { |
| @@ -14461,19 +14706,71 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
| 14461 | alc_inithook(codec); | 14706 | alc_inithook(codec); |
| 14462 | } | 14707 | } |
| 14463 | 14708 | ||
| 14709 | #ifdef SND_HDA_NEEDS_RESUME | ||
| 14710 | static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) | ||
| 14711 | { | ||
| 14712 | int val = alc_read_coef_idx(codec, 0x04); | ||
| 14713 | if (power_up) | ||
| 14714 | val |= 1 << 11; | ||
| 14715 | else | ||
| 14716 | val &= ~(1 << 11); | ||
| 14717 | alc_write_coef_idx(codec, 0x04, val); | ||
| 14718 | } | ||
| 14719 | |||
| 14720 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 14721 | static int alc269_suspend(struct hda_codec *codec, pm_message_t state) | ||
| 14722 | { | ||
| 14723 | struct alc_spec *spec = codec->spec; | ||
| 14724 | |||
| 14725 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) | ||
| 14726 | alc269_toggle_power_output(codec, 0); | ||
| 14727 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
| 14728 | alc269_toggle_power_output(codec, 0); | ||
| 14729 | msleep(150); | ||
| 14730 | } | ||
| 14731 | |||
| 14732 | alc_shutup(codec); | ||
| 14733 | if (spec && spec->power_hook) | ||
| 14734 | spec->power_hook(codec); | ||
| 14735 | return 0; | ||
| 14736 | } | ||
| 14737 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
| 14738 | |||
| 14739 | static int alc269_resume(struct hda_codec *codec) | ||
| 14740 | { | ||
| 14741 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
| 14742 | alc269_toggle_power_output(codec, 0); | ||
| 14743 | msleep(150); | ||
| 14744 | } | ||
| 14745 | |||
| 14746 | codec->patch_ops.init(codec); | ||
| 14747 | |||
| 14748 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
| 14749 | alc269_toggle_power_output(codec, 1); | ||
| 14750 | msleep(200); | ||
| 14751 | } | ||
| 14752 | |||
| 14753 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) | ||
| 14754 | alc269_toggle_power_output(codec, 1); | ||
| 14755 | |||
| 14756 | snd_hda_codec_resume_amp(codec); | ||
| 14757 | snd_hda_codec_resume_cache(codec); | ||
| 14758 | hda_call_check_power_status(codec, 0x01); | ||
| 14759 | return 0; | ||
| 14760 | } | ||
| 14761 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
| 14762 | |||
| 14464 | enum { | 14763 | enum { |
| 14465 | ALC269_FIXUP_SONY_VAIO, | 14764 | ALC269_FIXUP_SONY_VAIO, |
| 14466 | ALC269_FIXUP_DELL_M101Z, | 14765 | ALC269_FIXUP_DELL_M101Z, |
| 14467 | }; | 14766 | }; |
| 14468 | 14767 | ||
| 14469 | static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { | ||
| 14470 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
| 14471 | {} | ||
| 14472 | }; | ||
| 14473 | |||
| 14474 | static const struct alc_fixup alc269_fixups[] = { | 14768 | static const struct alc_fixup alc269_fixups[] = { |
| 14475 | [ALC269_FIXUP_SONY_VAIO] = { | 14769 | [ALC269_FIXUP_SONY_VAIO] = { |
| 14476 | .verbs = alc269_sony_vaio_fixup_verbs | 14770 | .verbs = (const struct hda_verb[]) { |
| 14771 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
| 14772 | {} | ||
| 14773 | } | ||
| 14477 | }, | 14774 | }, |
| 14478 | [ALC269_FIXUP_DELL_M101Z] = { | 14775 | [ALC269_FIXUP_DELL_M101Z] = { |
| 14479 | .verbs = (const struct hda_verb[]) { | 14776 | .verbs = (const struct hda_verb[]) { |
| @@ -14486,8 +14783,7 @@ static const struct alc_fixup alc269_fixups[] = { | |||
| 14486 | }; | 14783 | }; |
| 14487 | 14784 | ||
| 14488 | static struct snd_pci_quirk alc269_fixup_tbl[] = { | 14785 | static struct snd_pci_quirk alc269_fixup_tbl[] = { |
| 14489 | SND_PCI_QUIRK(0x104d, 0x9071, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | 14786 | SND_PCI_QUIRK_VENDOR(0x104d, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), |
| 14490 | SND_PCI_QUIRK(0x104d, 0x9077, "Sony VAIO", ALC269_FIXUP_SONY_VAIO), | ||
| 14491 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), | 14787 | SND_PCI_QUIRK(0x1028, 0x0470, "Dell M101z", ALC269_FIXUP_DELL_M101Z), |
| 14492 | {} | 14788 | {} |
| 14493 | }; | 14789 | }; |
| @@ -14689,12 +14985,46 @@ static struct alc_config_preset alc269_presets[] = { | |||
| 14689 | }, | 14985 | }, |
| 14690 | }; | 14986 | }; |
| 14691 | 14987 | ||
| 14988 | static int alc269_fill_coef(struct hda_codec *codec) | ||
| 14989 | { | ||
| 14990 | int val; | ||
| 14991 | |||
| 14992 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) { | ||
| 14993 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
| 14994 | alc_write_coef_idx(codec, 0xe, 0x8817); | ||
| 14995 | } | ||
| 14996 | |||
| 14997 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) { | ||
| 14998 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
| 14999 | alc_write_coef_idx(codec, 0xe, 0x8814); | ||
| 15000 | } | ||
| 15001 | |||
| 15002 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
| 15003 | val = alc_read_coef_idx(codec, 0x04); | ||
| 15004 | /* Power up output pin */ | ||
| 15005 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | ||
| 15006 | } | ||
| 15007 | |||
| 15008 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
| 15009 | val = alc_read_coef_idx(codec, 0xd); | ||
| 15010 | if ((val & 0x0c00) >> 10 != 0x1) { | ||
| 15011 | /* Capless ramp up clock control */ | ||
| 15012 | alc_write_coef_idx(codec, 0xd, val | 1<<10); | ||
| 15013 | } | ||
| 15014 | val = alc_read_coef_idx(codec, 0x17); | ||
| 15015 | if ((val & 0x01c0) >> 6 != 0x4) { | ||
| 15016 | /* Class D power on reset */ | ||
| 15017 | alc_write_coef_idx(codec, 0x17, val | 1<<7); | ||
| 15018 | } | ||
| 15019 | } | ||
| 15020 | return 0; | ||
| 15021 | } | ||
| 15022 | |||
| 14692 | static int patch_alc269(struct hda_codec *codec) | 15023 | static int patch_alc269(struct hda_codec *codec) |
| 14693 | { | 15024 | { |
| 14694 | struct alc_spec *spec; | 15025 | struct alc_spec *spec; |
| 14695 | int board_config; | 15026 | int board_config; |
| 14696 | int err; | 15027 | int err; |
| 14697 | int is_alc269vb = 0; | ||
| 14698 | 15028 | ||
| 14699 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 15029 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
| 14700 | if (spec == NULL) | 15030 | if (spec == NULL) |
| @@ -14706,14 +15036,18 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 14706 | 15036 | ||
| 14707 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 15037 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
| 14708 | if (codec->bus->pci->subsystem_vendor == 0x1025 && | 15038 | if (codec->bus->pci->subsystem_vendor == 0x1025 && |
| 14709 | spec->cdefine.platform_type == 1) | 15039 | spec->cdefine.platform_type == 1) { |
| 14710 | alc_codec_rename(codec, "ALC271X"); | 15040 | alc_codec_rename(codec, "ALC271X"); |
| 14711 | else | 15041 | spec->codec_variant = ALC269_TYPE_ALC271X; |
| 15042 | } else { | ||
| 14712 | alc_codec_rename(codec, "ALC259"); | 15043 | alc_codec_rename(codec, "ALC259"); |
| 14713 | is_alc269vb = 1; | 15044 | spec->codec_variant = ALC269_TYPE_ALC259; |
| 15045 | } | ||
| 14714 | } else | 15046 | } else |
| 14715 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 15047 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
| 14716 | 15048 | ||
| 15049 | alc269_fill_coef(codec); | ||
| 15050 | |||
| 14717 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 15051 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
| 14718 | alc269_models, | 15052 | alc269_models, |
| 14719 | alc269_cfg_tbl); | 15053 | alc269_cfg_tbl); |
| @@ -14770,7 +15104,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 14770 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 15104 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
| 14771 | 15105 | ||
| 14772 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ | 15106 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ |
| 14773 | if (!is_alc269vb) { | 15107 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
| 14774 | spec->adc_nids = alc269_adc_nids; | 15108 | spec->adc_nids = alc269_adc_nids; |
| 14775 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 15109 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
| 14776 | spec->capsrc_nids = alc269_capsrc_nids; | 15110 | spec->capsrc_nids = alc269_capsrc_nids; |
| @@ -14792,8 +15126,16 @@ static int patch_alc269(struct hda_codec *codec) | |||
| 14792 | spec->vmaster_nid = 0x02; | 15126 | spec->vmaster_nid = 0x02; |
| 14793 | 15127 | ||
| 14794 | codec->patch_ops = alc_patch_ops; | 15128 | codec->patch_ops = alc_patch_ops; |
| 15129 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 15130 | codec->patch_ops.suspend = alc269_suspend; | ||
| 15131 | #endif | ||
| 15132 | #ifdef SND_HDA_NEEDS_RESUME | ||
| 15133 | codec->patch_ops.resume = alc269_resume; | ||
| 15134 | #endif | ||
| 14795 | if (board_config == ALC269_AUTO) | 15135 | if (board_config == ALC269_AUTO) |
| 14796 | spec->init_hook = alc269_auto_init; | 15136 | spec->init_hook = alc269_auto_init; |
| 15137 | |||
| 15138 | alc_init_jacks(codec); | ||
| 14797 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15139 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 14798 | if (!spec->loopback.amplist) | 15140 | if (!spec->loopback.amplist) |
| 14799 | spec->loopback.amplist = alc269_loopbacks; | 15141 | spec->loopback.amplist = alc269_loopbacks; |
| @@ -15606,12 +15948,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
| 15606 | static void alc861_auto_init_analog_input(struct hda_codec *codec) | 15948 | static void alc861_auto_init_analog_input(struct hda_codec *codec) |
| 15607 | { | 15949 | { |
| 15608 | struct alc_spec *spec = codec->spec; | 15950 | struct alc_spec *spec = codec->spec; |
| 15951 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 15609 | int i; | 15952 | int i; |
| 15610 | 15953 | ||
| 15611 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 15954 | for (i = 0; i < cfg->num_inputs; i++) { |
| 15612 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 15955 | hda_nid_t nid = cfg->inputs[i].pin; |
| 15613 | if (nid >= 0x0c && nid <= 0x11) | 15956 | if (nid >= 0x0c && nid <= 0x11) |
| 15614 | alc_set_input_pin(codec, nid, i); | 15957 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 15615 | } | 15958 | } |
| 15616 | } | 15959 | } |
| 15617 | 15960 | ||
| @@ -15840,15 +16183,13 @@ enum { | |||
| 15840 | PINFIX_FSC_AMILO_PI1505, | 16183 | PINFIX_FSC_AMILO_PI1505, |
| 15841 | }; | 16184 | }; |
| 15842 | 16185 | ||
| 15843 | static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = { | ||
| 15844 | { 0x0b, 0x0221101f }, /* HP */ | ||
| 15845 | { 0x0f, 0x90170310 }, /* speaker */ | ||
| 15846 | { } | ||
| 15847 | }; | ||
| 15848 | |||
| 15849 | static const struct alc_fixup alc861_fixups[] = { | 16186 | static const struct alc_fixup alc861_fixups[] = { |
| 15850 | [PINFIX_FSC_AMILO_PI1505] = { | 16187 | [PINFIX_FSC_AMILO_PI1505] = { |
| 15851 | .pins = alc861_fsc_amilo_pi1505_pinfix | 16188 | .pins = (const struct alc_pincfg[]) { |
| 16189 | { 0x0b, 0x0221101f }, /* HP */ | ||
| 16190 | { 0x0f, 0x90170310 }, /* speaker */ | ||
| 16191 | { } | ||
| 16192 | } | ||
| 15852 | }, | 16193 | }, |
| 15853 | }; | 16194 | }; |
| 15854 | 16195 | ||
| @@ -16600,12 +16941,13 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec) | |||
| 16600 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | 16941 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) |
| 16601 | { | 16942 | { |
| 16602 | struct alc_spec *spec = codec->spec; | 16943 | struct alc_spec *spec = codec->spec; |
| 16944 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 16603 | int i; | 16945 | int i; |
| 16604 | 16946 | ||
| 16605 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16947 | for (i = 0; i < cfg->num_inputs; i++) { |
| 16606 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 16948 | hda_nid_t nid = cfg->inputs[i].pin; |
| 16607 | if (alc_is_input_pin(codec, nid)) { | 16949 | if (alc_is_input_pin(codec, nid)) { |
| 16608 | alc_set_input_pin(codec, nid, i); | 16950 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 16609 | if (nid != ALC861VD_PIN_CD_NID && | 16951 | if (nid != ALC861VD_PIN_CD_NID && |
| 16610 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 16952 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
| 16611 | snd_hda_codec_write(codec, nid, 0, | 16953 | snd_hda_codec_write(codec, nid, 0, |
| @@ -16815,16 +17157,14 @@ enum { | |||
| 16815 | }; | 17157 | }; |
| 16816 | 17158 | ||
| 16817 | /* reset GPIO1 */ | 17159 | /* reset GPIO1 */ |
| 16818 | static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = { | ||
| 16819 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
| 16820 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
| 16821 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
| 16822 | { } | ||
| 16823 | }; | ||
| 16824 | |||
| 16825 | static const struct alc_fixup alc861vd_fixups[] = { | 17160 | static const struct alc_fixup alc861vd_fixups[] = { |
| 16826 | [ALC660VD_FIX_ASUS_GPIO1] = { | 17161 | [ALC660VD_FIX_ASUS_GPIO1] = { |
| 16827 | .verbs = alc660vd_fix_asus_gpio1_verbs, | 17162 | .verbs = (const struct hda_verb[]) { |
| 17163 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
| 17164 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
| 17165 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
| 17166 | { } | ||
| 17167 | } | ||
| 16828 | }, | 17168 | }, |
| 16829 | }; | 17169 | }; |
| 16830 | 17170 | ||
| @@ -18838,12 +19178,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
| 18838 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | 19178 | static void alc662_auto_init_analog_input(struct hda_codec *codec) |
| 18839 | { | 19179 | { |
| 18840 | struct alc_spec *spec = codec->spec; | 19180 | struct alc_spec *spec = codec->spec; |
| 19181 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 18841 | int i; | 19182 | int i; |
| 18842 | 19183 | ||
| 18843 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 19184 | for (i = 0; i < cfg->num_inputs; i++) { |
| 18844 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 19185 | hda_nid_t nid = cfg->inputs[i].pin; |
| 18845 | if (alc_is_input_pin(codec, nid)) { | 19186 | if (alc_is_input_pin(codec, nid)) { |
| 18846 | alc_set_input_pin(codec, nid, i); | 19187 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
| 18847 | if (nid != ALC662_PIN_CD_NID && | 19188 | if (nid != ALC662_PIN_CD_NID && |
| 18848 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 19189 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
| 18849 | snd_hda_codec_write(codec, nid, 0, | 19190 | snd_hda_codec_write(codec, nid, 0, |
| @@ -18935,10 +19276,40 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
| 18935 | alc_inithook(codec); | 19276 | alc_inithook(codec); |
| 18936 | } | 19277 | } |
| 18937 | 19278 | ||
| 19279 | enum { | ||
| 19280 | ALC662_FIXUP_ASPIRE, | ||
| 19281 | ALC662_FIXUP_IDEAPAD, | ||
| 19282 | }; | ||
| 19283 | |||
| 19284 | static const struct alc_fixup alc662_fixups[] = { | ||
| 19285 | [ALC662_FIXUP_ASPIRE] = { | ||
| 19286 | .pins = (const struct alc_pincfg[]) { | ||
| 19287 | { 0x15, 0x99130112 }, /* subwoofer */ | ||
| 19288 | { } | ||
| 19289 | } | ||
| 19290 | }, | ||
| 19291 | [ALC662_FIXUP_IDEAPAD] = { | ||
| 19292 | .pins = (const struct alc_pincfg[]) { | ||
| 19293 | { 0x17, 0x99130112 }, /* subwoofer */ | ||
| 19294 | { } | ||
| 19295 | } | ||
| 19296 | }, | ||
| 19297 | }; | ||
| 19298 | |||
| 19299 | static struct snd_pci_quirk alc662_fixup_tbl[] = { | ||
| 19300 | SND_PCI_QUIRK(0x1025, 0x038b, "Acer Aspire 8943G", ALC662_FIXUP_ASPIRE), | ||
| 19301 | SND_PCI_QUIRK(0x17aa, 0x38af, "Lenovo Ideapad Y550P", ALC662_FIXUP_IDEAPAD), | ||
| 19302 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), | ||
| 19303 | {} | ||
| 19304 | }; | ||
| 19305 | |||
| 19306 | |||
| 19307 | |||
| 18938 | static int patch_alc662(struct hda_codec *codec) | 19308 | static int patch_alc662(struct hda_codec *codec) |
| 18939 | { | 19309 | { |
| 18940 | struct alc_spec *spec; | 19310 | struct alc_spec *spec; |
| 18941 | int err, board_config; | 19311 | int err, board_config; |
| 19312 | int coef; | ||
| 18942 | 19313 | ||
| 18943 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 19314 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
| 18944 | if (!spec) | 19315 | if (!spec) |
| @@ -18950,12 +19321,15 @@ static int patch_alc662(struct hda_codec *codec) | |||
| 18950 | 19321 | ||
| 18951 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 19322 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
| 18952 | 19323 | ||
| 18953 | if (alc_read_coef_idx(codec, 0) == 0x8020) | 19324 | coef = alc_read_coef_idx(codec, 0); |
| 19325 | if (coef == 0x8020 || coef == 0x8011) | ||
| 18954 | alc_codec_rename(codec, "ALC661"); | 19326 | alc_codec_rename(codec, "ALC661"); |
| 18955 | else if ((alc_read_coef_idx(codec, 0) & (1 << 14)) && | 19327 | else if (coef & (1 << 14) && |
| 18956 | codec->bus->pci->subsystem_vendor == 0x1025 && | 19328 | codec->bus->pci->subsystem_vendor == 0x1025 && |
| 18957 | spec->cdefine.platform_type == 1) | 19329 | spec->cdefine.platform_type == 1) |
| 18958 | alc_codec_rename(codec, "ALC272X"); | 19330 | alc_codec_rename(codec, "ALC272X"); |
| 19331 | else if (coef == 0x4011) | ||
| 19332 | alc_codec_rename(codec, "ALC656"); | ||
| 18959 | 19333 | ||
| 18960 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, | 19334 | board_config = snd_hda_check_board_config(codec, ALC662_MODEL_LAST, |
| 18961 | alc662_models, | 19335 | alc662_models, |
| @@ -18967,6 +19341,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
| 18967 | } | 19341 | } |
| 18968 | 19342 | ||
| 18969 | if (board_config == ALC662_AUTO) { | 19343 | if (board_config == ALC662_AUTO) { |
| 19344 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1); | ||
| 18970 | /* automatic parse from the BIOS config */ | 19345 | /* automatic parse from the BIOS config */ |
| 18971 | err = alc662_parse_auto_config(codec); | 19346 | err = alc662_parse_auto_config(codec); |
| 18972 | if (err < 0) { | 19347 | if (err < 0) { |
| @@ -19025,8 +19400,13 @@ static int patch_alc662(struct hda_codec *codec) | |||
| 19025 | spec->vmaster_nid = 0x02; | 19400 | spec->vmaster_nid = 0x02; |
| 19026 | 19401 | ||
| 19027 | codec->patch_ops = alc_patch_ops; | 19402 | codec->patch_ops = alc_patch_ops; |
| 19028 | if (board_config == ALC662_AUTO) | 19403 | if (board_config == ALC662_AUTO) { |
| 19029 | spec->init_hook = alc662_auto_init; | 19404 | spec->init_hook = alc662_auto_init; |
| 19405 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0); | ||
| 19406 | } | ||
| 19407 | |||
| 19408 | alc_init_jacks(codec); | ||
| 19409 | |||
| 19030 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 19410 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 19031 | if (!spec->loopback.amplist) | 19411 | if (!spec->loopback.amplist) |
| 19032 | spec->loopback.amplist = alc662_loopbacks; | 19412 | spec->loopback.amplist = alc662_loopbacks; |
| @@ -19070,6 +19450,39 @@ static hda_nid_t alc680_adc_nids[3] = { | |||
| 19070 | /* | 19450 | /* |
| 19071 | * Analog capture ADC cgange | 19451 | * Analog capture ADC cgange |
| 19072 | */ | 19452 | */ |
| 19453 | static void alc680_rec_autoswitch(struct hda_codec *codec) | ||
| 19454 | { | ||
| 19455 | struct alc_spec *spec = codec->spec; | ||
| 19456 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 19457 | int pin_found = 0; | ||
| 19458 | int type_found = AUTO_PIN_LAST; | ||
| 19459 | hda_nid_t nid; | ||
| 19460 | int i; | ||
| 19461 | |||
| 19462 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 19463 | nid = cfg->inputs[i].pin; | ||
| 19464 | if (!(snd_hda_query_pin_caps(codec, nid) & | ||
| 19465 | AC_PINCAP_PRES_DETECT)) | ||
| 19466 | continue; | ||
| 19467 | if (snd_hda_jack_detect(codec, nid)) { | ||
| 19468 | if (cfg->inputs[i].type < type_found) { | ||
| 19469 | type_found = cfg->inputs[i].type; | ||
| 19470 | pin_found = nid; | ||
| 19471 | } | ||
| 19472 | } | ||
| 19473 | } | ||
| 19474 | |||
| 19475 | nid = 0x07; | ||
| 19476 | if (pin_found) | ||
| 19477 | snd_hda_get_connections(codec, pin_found, &nid, 1); | ||
| 19478 | |||
| 19479 | if (nid != spec->cur_adc) | ||
| 19480 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
| 19481 | spec->cur_adc = nid; | ||
| 19482 | snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0, | ||
| 19483 | spec->cur_adc_format); | ||
| 19484 | } | ||
| 19485 | |||
| 19073 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 19486 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, |
| 19074 | struct hda_codec *codec, | 19487 | struct hda_codec *codec, |
| 19075 | unsigned int stream_tag, | 19488 | unsigned int stream_tag, |
| @@ -19077,24 +19490,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
| 19077 | struct snd_pcm_substream *substream) | 19490 | struct snd_pcm_substream *substream) |
| 19078 | { | 19491 | { |
| 19079 | struct alc_spec *spec = codec->spec; | 19492 | struct alc_spec *spec = codec->spec; |
| 19080 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 19081 | unsigned int pre_mic, pre_line; | ||
| 19082 | |||
| 19083 | pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
| 19084 | pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); | ||
| 19085 | 19493 | ||
| 19494 | spec->cur_adc = 0x07; | ||
| 19086 | spec->cur_adc_stream_tag = stream_tag; | 19495 | spec->cur_adc_stream_tag = stream_tag; |
| 19087 | spec->cur_adc_format = format; | 19496 | spec->cur_adc_format = format; |
| 19088 | 19497 | ||
| 19089 | if (pre_mic || pre_line) { | 19498 | alc680_rec_autoswitch(codec); |
| 19090 | if (pre_mic) | ||
| 19091 | snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, | ||
| 19092 | format); | ||
| 19093 | else | ||
| 19094 | snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, | ||
| 19095 | format); | ||
| 19096 | } else | ||
| 19097 | snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); | ||
| 19098 | return 0; | 19499 | return 0; |
| 19099 | } | 19500 | } |
| 19100 | 19501 | ||
| @@ -19180,6 +19581,7 @@ static struct hda_verb alc680_init_verbs[] = { | |||
| 19180 | 19581 | ||
| 19181 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 19582 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
| 19182 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | 19583 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, |
| 19584 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | ||
| 19183 | 19585 | ||
| 19184 | { } | 19586 | { } |
| 19185 | }; | 19587 | }; |
| @@ -19192,25 +19594,11 @@ static void alc680_base_setup(struct hda_codec *codec) | |||
| 19192 | spec->autocfg.hp_pins[0] = 0x16; | 19594 | spec->autocfg.hp_pins[0] = 0x16; |
| 19193 | spec->autocfg.speaker_pins[0] = 0x14; | 19595 | spec->autocfg.speaker_pins[0] = 0x14; |
| 19194 | spec->autocfg.speaker_pins[1] = 0x15; | 19596 | spec->autocfg.speaker_pins[1] = 0x15; |
| 19195 | spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; | 19597 | spec->autocfg.num_inputs = 2; |
| 19196 | spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; | 19598 | spec->autocfg.inputs[0].pin = 0x18; |
| 19197 | } | 19599 | spec->autocfg.inputs[0].type = AUTO_PIN_MIC; |
| 19198 | 19600 | spec->autocfg.inputs[1].pin = 0x19; | |
| 19199 | static void alc680_rec_autoswitch(struct hda_codec *codec) | 19601 | spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN; |
| 19200 | { | ||
| 19201 | struct alc_spec *spec = codec->spec; | ||
| 19202 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 19203 | unsigned int present; | ||
| 19204 | hda_nid_t new_adc; | ||
| 19205 | |||
| 19206 | present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
| 19207 | |||
| 19208 | new_adc = present ? 0x8 : 0x7; | ||
| 19209 | __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); | ||
| 19210 | snd_hda_codec_setup_stream(codec, new_adc, | ||
| 19211 | spec->cur_adc_stream_tag, 0, | ||
| 19212 | spec->cur_adc_format); | ||
| 19213 | |||
| 19214 | } | 19602 | } |
| 19215 | 19603 | ||
| 19216 | static void alc680_unsol_event(struct hda_codec *codec, | 19604 | static void alc680_unsol_event(struct hda_codec *codec, |
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c index c16c5ba0fda0..82ebeb9544fe 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
| @@ -32,6 +32,7 @@ | |||
| 32 | #include <sound/core.h> | 32 | #include <sound/core.h> |
| 33 | #include <sound/asoundef.h> | 33 | #include <sound/asoundef.h> |
| 34 | #include <sound/jack.h> | 34 | #include <sound/jack.h> |
| 35 | #include <sound/tlv.h> | ||
| 35 | #include "hda_codec.h" | 36 | #include "hda_codec.h" |
| 36 | #include "hda_local.h" | 37 | #include "hda_local.h" |
| 37 | #include "hda_beep.h" | 38 | #include "hda_beep.h" |
| @@ -263,6 +264,7 @@ struct sigmatel_spec { | |||
| 263 | 264 | ||
| 264 | struct sigmatel_mic_route ext_mic; | 265 | struct sigmatel_mic_route ext_mic; |
| 265 | struct sigmatel_mic_route int_mic; | 266 | struct sigmatel_mic_route int_mic; |
| 267 | struct sigmatel_mic_route dock_mic; | ||
| 266 | 268 | ||
| 267 | const char **spdif_labels; | 269 | const char **spdif_labels; |
| 268 | 270 | ||
| @@ -382,6 +384,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = { | |||
| 382 | 0x03, 0x0c, 0x20, 0x40, | 384 | 0x03, 0x0c, 0x20, 0x40, |
| 383 | }; | 385 | }; |
| 384 | 386 | ||
| 387 | #define STAC92HD83XXX_NUM_DMICS 2 | ||
| 388 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | ||
| 389 | 0x11, 0x20, 0 | ||
| 390 | }; | ||
| 391 | |||
| 385 | #define STAC92HD83XXX_NUM_CAPS 2 | 392 | #define STAC92HD83XXX_NUM_CAPS 2 |
| 386 | static unsigned long stac92hd83xxx_capvols[] = { | 393 | static unsigned long stac92hd83xxx_capvols[] = { |
| 387 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), | 394 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), |
| @@ -986,7 +993,7 @@ static struct hda_verb stac9205_core_init[] = { | |||
| 986 | } | 993 | } |
| 987 | 994 | ||
| 988 | static struct snd_kcontrol_new stac9200_mixer[] = { | 995 | static struct snd_kcontrol_new stac9200_mixer[] = { |
| 989 | HDA_CODEC_VOLUME("Master Playback Volume", 0xb, 0, HDA_OUTPUT), | 996 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xb, 0, HDA_OUTPUT), |
| 990 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), | 997 | HDA_CODEC_MUTE("Master Playback Switch", 0xb, 0, HDA_OUTPUT), |
| 991 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), | 998 | HDA_CODEC_VOLUME("Capture Volume", 0x0a, 0, HDA_OUTPUT), |
| 992 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), | 999 | HDA_CODEC_MUTE("Capture Switch", 0x0a, 0, HDA_OUTPUT), |
| @@ -1014,7 +1021,7 @@ static struct snd_kcontrol_new stac92hd71bxx_loopback[] = { | |||
| 1014 | }; | 1021 | }; |
| 1015 | 1022 | ||
| 1016 | static struct snd_kcontrol_new stac925x_mixer[] = { | 1023 | static struct snd_kcontrol_new stac925x_mixer[] = { |
| 1017 | HDA_CODEC_VOLUME("Master Playback Volume", 0x0e, 0, HDA_OUTPUT), | 1024 | HDA_CODEC_VOLUME_MIN_MUTE("Master Playback Volume", 0xe, 0, HDA_OUTPUT), |
| 1018 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), | 1025 | HDA_CODEC_MUTE("Master Playback Switch", 0x0e, 0, HDA_OUTPUT), |
| 1019 | { } /* end */ | 1026 | { } /* end */ |
| 1020 | }; | 1027 | }; |
| @@ -1105,9 +1112,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
| 1105 | struct hda_input_mux *smux = &spec->private_smux; | 1112 | struct hda_input_mux *smux = &spec->private_smux; |
| 1106 | /* check for mute support on SPDIF out */ | 1113 | /* check for mute support on SPDIF out */ |
| 1107 | if (wcaps & AC_WCAP_OUT_AMP) { | 1114 | if (wcaps & AC_WCAP_OUT_AMP) { |
| 1108 | smux->items[smux->num_items].label = "Off"; | 1115 | snd_hda_add_imux_item(smux, "Off", 0, NULL); |
| 1109 | smux->items[smux->num_items].index = 0; | ||
| 1110 | smux->num_items++; | ||
| 1111 | spec->spdif_mute = 1; | 1116 | spec->spdif_mute = 1; |
| 1112 | } | 1117 | } |
| 1113 | stac_smux_mixer.count = spec->num_smuxes; | 1118 | stac_smux_mixer.count = spec->num_smuxes; |
| @@ -1140,6 +1145,8 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
| 1140 | HDA_OUTPUT, vmaster_tlv); | 1145 | HDA_OUTPUT, vmaster_tlv); |
| 1141 | /* correct volume offset */ | 1146 | /* correct volume offset */ |
| 1142 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; | 1147 | vmaster_tlv[2] += vmaster_tlv[3] * spec->volume_offset; |
| 1148 | /* minimum value is actually mute */ | ||
| 1149 | vmaster_tlv[3] |= TLV_DB_SCALE_MUTE; | ||
| 1143 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", | 1150 | err = snd_hda_add_vmaster(codec, "Master Playback Volume", |
| 1144 | vmaster_tlv, slave_vols); | 1151 | vmaster_tlv, slave_vols); |
| 1145 | if (err < 0) | 1152 | if (err < 0) |
| @@ -1180,14 +1187,11 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
| 1180 | if (err < 0) | 1187 | if (err < 0) |
| 1181 | return err; | 1188 | return err; |
| 1182 | } | 1189 | } |
| 1183 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1190 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1184 | nid = cfg->input_pins[i]; | 1191 | nid = cfg->inputs[i].pin; |
| 1185 | if (nid) { | 1192 | err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE); |
| 1186 | err = stac92xx_add_jack(codec, nid, | 1193 | if (err < 0) |
| 1187 | SND_JACK_MICROPHONE); | 1194 | return err; |
| 1188 | if (err < 0) | ||
| 1189 | return err; | ||
| 1190 | } | ||
| 1191 | } | 1195 | } |
| 1192 | 1196 | ||
| 1193 | return 0; | 1197 | return 0; |
| @@ -2779,7 +2783,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
| 2779 | struct sigmatel_spec *spec = codec->spec; | 2783 | struct sigmatel_spec *spec = codec->spec; |
| 2780 | char name[22]; | 2784 | char name[22]; |
| 2781 | 2785 | ||
| 2782 | if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) { | 2786 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
| 2783 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD | 2787 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD |
| 2784 | && nid == spec->line_switch) | 2788 | && nid == spec->line_switch) |
| 2785 | control = STAC_CTL_WIDGET_IO_SWITCH; | 2789 | control = STAC_CTL_WIDGET_IO_SWITCH; |
| @@ -2791,7 +2795,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
| 2791 | } | 2795 | } |
| 2792 | 2796 | ||
| 2793 | if (control) { | 2797 | if (control) { |
| 2794 | strcpy(name, auto_pin_cfg_labels[idx]); | 2798 | strcpy(name, hda_get_input_pin_label(codec, nid, 1)); |
| 2795 | return stac92xx_add_control(codec->spec, control, | 2799 | return stac92xx_add_control(codec->spec, control, |
| 2796 | strcat(name, " Jack Mode"), nid); | 2800 | strcat(name, " Jack Mode"), nid); |
| 2797 | } | 2801 | } |
| @@ -2823,41 +2827,49 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |||
| 2823 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2827 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 2824 | hda_nid_t nid; | 2828 | hda_nid_t nid; |
| 2825 | unsigned int pincap; | 2829 | unsigned int pincap; |
| 2830 | int i; | ||
| 2826 | 2831 | ||
| 2827 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2832 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
| 2828 | return 0; | 2833 | return 0; |
| 2829 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 2834 | for (i = 0; i < cfg->num_inputs; i++) { |
| 2830 | pincap = snd_hda_query_pin_caps(codec, nid); | 2835 | if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) { |
| 2831 | if (pincap & AC_PINCAP_OUT) | 2836 | nid = cfg->inputs[i].pin; |
| 2832 | return nid; | 2837 | pincap = snd_hda_query_pin_caps(codec, nid); |
| 2838 | if (pincap & AC_PINCAP_OUT) | ||
| 2839 | return nid; | ||
| 2840 | } | ||
| 2841 | } | ||
| 2833 | return 0; | 2842 | return 0; |
| 2834 | } | 2843 | } |
| 2835 | 2844 | ||
| 2845 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); | ||
| 2846 | |||
| 2836 | /* check whether the mic-input can be used as line-out */ | 2847 | /* check whether the mic-input can be used as line-out */ |
| 2837 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | 2848 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) |
| 2838 | { | 2849 | { |
| 2839 | struct sigmatel_spec *spec = codec->spec; | 2850 | struct sigmatel_spec *spec = codec->spec; |
| 2840 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2851 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 2841 | unsigned int def_conf, pincap; | 2852 | unsigned int def_conf, pincap; |
| 2842 | unsigned int mic_pin; | 2853 | int i; |
| 2843 | 2854 | ||
| 2855 | *dac = 0; | ||
| 2844 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2856 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
| 2845 | return 0; | 2857 | return 0; |
| 2846 | mic_pin = AUTO_PIN_MIC; | 2858 | for (i = 0; i < cfg->num_inputs; i++) { |
| 2847 | for (;;) { | 2859 | hda_nid_t nid = cfg->inputs[i].pin; |
| 2848 | hda_nid_t nid = cfg->input_pins[mic_pin]; | 2860 | if (cfg->inputs[i].type != AUTO_PIN_MIC) |
| 2861 | continue; | ||
| 2849 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 2862 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
| 2850 | /* some laptops have an internal analog microphone | 2863 | /* some laptops have an internal analog microphone |
| 2851 | * which can't be used as a output */ | 2864 | * which can't be used as a output */ |
| 2852 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 2865 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
| 2853 | pincap = snd_hda_query_pin_caps(codec, nid); | 2866 | pincap = snd_hda_query_pin_caps(codec, nid); |
| 2854 | if (pincap & AC_PINCAP_OUT) | 2867 | if (pincap & AC_PINCAP_OUT) { |
| 2855 | return nid; | 2868 | *dac = get_unassigned_dac(codec, nid); |
| 2869 | if (*dac) | ||
| 2870 | return nid; | ||
| 2871 | } | ||
| 2856 | } | 2872 | } |
| 2857 | if (mic_pin == AUTO_PIN_MIC) | ||
| 2858 | mic_pin = AUTO_PIN_FRONT_MIC; | ||
| 2859 | else | ||
| 2860 | break; | ||
| 2861 | } | 2873 | } |
| 2862 | return 0; | 2874 | return 0; |
| 2863 | } | 2875 | } |
| @@ -3004,17 +3016,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
| 3004 | } | 3016 | } |
| 3005 | } | 3017 | } |
| 3006 | /* add mic as output */ | 3018 | /* add mic as output */ |
| 3007 | nid = check_mic_out_switch(codec); | 3019 | nid = check_mic_out_switch(codec, &dac); |
| 3008 | if (nid) { | 3020 | if (nid && dac) { |
| 3009 | dac = get_unassigned_dac(codec, nid); | 3021 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", |
| 3010 | if (dac) { | 3022 | nid, cfg->line_outs); |
| 3011 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | 3023 | cfg->line_out_pins[cfg->line_outs] = nid; |
| 3012 | nid, cfg->line_outs); | 3024 | cfg->line_outs++; |
| 3013 | cfg->line_out_pins[cfg->line_outs] = nid; | 3025 | spec->mic_switch = nid; |
| 3014 | cfg->line_outs++; | 3026 | add_spec_dacs(spec, dac); |
| 3015 | spec->mic_switch = nid; | ||
| 3016 | add_spec_dacs(spec, dac); | ||
| 3017 | } | ||
| 3018 | } | 3027 | } |
| 3019 | 3028 | ||
| 3020 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 3029 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
| @@ -3204,13 +3213,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
| 3204 | return err; | 3213 | return err; |
| 3205 | } | 3214 | } |
| 3206 | 3215 | ||
| 3207 | for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { | 3216 | for (idx = 0; idx < cfg->num_inputs; idx++) { |
| 3208 | nid = cfg->input_pins[idx]; | 3217 | if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN) |
| 3209 | if (nid) { | 3218 | break; |
| 3210 | err = stac92xx_add_jack_mode_control(codec, nid, idx); | 3219 | nid = cfg->inputs[idx].pin; |
| 3211 | if (err < 0) | 3220 | err = stac92xx_add_jack_mode_control(codec, nid, idx); |
| 3212 | return err; | 3221 | if (err < 0) |
| 3213 | } | 3222 | return err; |
| 3214 | } | 3223 | } |
| 3215 | 3224 | ||
| 3216 | return 0; | 3225 | return 0; |
| @@ -3256,12 +3265,9 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | |||
| 3256 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | 3265 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) |
| 3257 | return -EINVAL; | 3266 | return -EINVAL; |
| 3258 | 3267 | ||
| 3259 | for (i = 0; i < num_cons; i++) { | 3268 | for (i = 0; i < num_cons; i++) |
| 3260 | mono_mux->items[mono_mux->num_items].label = | 3269 | snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i, |
| 3261 | stac92xx_mono_labels[i]; | 3270 | NULL); |
| 3262 | mono_mux->items[mono_mux->num_items].index = i; | ||
| 3263 | mono_mux->num_items++; | ||
| 3264 | } | ||
| 3265 | 3271 | ||
| 3266 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | 3272 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, |
| 3267 | "Mono Mux", spec->mono_nid); | 3273 | "Mono Mux", spec->mono_nid); |
| @@ -3386,11 +3392,8 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | |||
| 3386 | if (!labels) | 3392 | if (!labels) |
| 3387 | labels = stac92xx_spdif_labels; | 3393 | labels = stac92xx_spdif_labels; |
| 3388 | 3394 | ||
| 3389 | for (i = 0; i < num_cons; i++) { | 3395 | for (i = 0; i < num_cons; i++) |
| 3390 | spdif_mux->items[spdif_mux->num_items].label = labels[i]; | 3396 | snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL); |
| 3391 | spdif_mux->items[spdif_mux->num_items].index = i; | ||
| 3392 | spdif_mux->num_items++; | ||
| 3393 | } | ||
| 3394 | 3397 | ||
| 3395 | return 0; | 3398 | return 0; |
| 3396 | } | 3399 | } |
| @@ -3417,7 +3420,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
| 3417 | /* create a volume assigned to the given pin (only if supported) */ | 3420 | /* create a volume assigned to the given pin (only if supported) */ |
| 3418 | /* return 1 if the volume control is created */ | 3421 | /* return 1 if the volume control is created */ |
| 3419 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | 3422 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, |
| 3420 | const char *label, int direction) | 3423 | const char *label, int idx, int direction) |
| 3421 | { | 3424 | { |
| 3422 | unsigned int caps, nums; | 3425 | unsigned int caps, nums; |
| 3423 | char name[32]; | 3426 | char name[32]; |
| @@ -3434,8 +3437,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | |||
| 3434 | if (!nums) | 3437 | if (!nums) |
| 3435 | return 0; | 3438 | return 0; |
| 3436 | snprintf(name, sizeof(name), "%s Capture Volume", label); | 3439 | snprintf(name, sizeof(name), "%s Capture Volume", label); |
| 3437 | err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, | 3440 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, |
| 3438 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); | 3441 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); |
| 3439 | if (err < 0) | 3442 | if (err < 0) |
| 3440 | return err; | 3443 | return err; |
| 3441 | return 1; | 3444 | return 1; |
| @@ -3448,27 +3451,14 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
| 3448 | struct sigmatel_spec *spec = codec->spec; | 3451 | struct sigmatel_spec *spec = codec->spec; |
| 3449 | struct hda_input_mux *imux = &spec->private_imux; | 3452 | struct hda_input_mux *imux = &spec->private_imux; |
| 3450 | struct hda_input_mux *dimux = &spec->private_dimux; | 3453 | struct hda_input_mux *dimux = &spec->private_dimux; |
| 3451 | int err, i, active_mics; | 3454 | int err, i; |
| 3452 | unsigned int def_conf; | 3455 | unsigned int def_conf; |
| 3453 | 3456 | ||
| 3454 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | 3457 | snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL); |
| 3455 | dimux->items[dimux->num_items].index = 0; | ||
| 3456 | dimux->num_items++; | ||
| 3457 | |||
| 3458 | active_mics = 0; | ||
| 3459 | for (i = 0; i < spec->num_dmics; i++) { | ||
| 3460 | /* check the validity: sometimes it's a dead vendor-spec node */ | ||
| 3461 | if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i])) | ||
| 3462 | != AC_WID_PIN) | ||
| 3463 | continue; | ||
| 3464 | def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); | ||
| 3465 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) | ||
| 3466 | active_mics++; | ||
| 3467 | } | ||
| 3468 | 3458 | ||
| 3469 | for (i = 0; i < spec->num_dmics; i++) { | 3459 | for (i = 0; i < spec->num_dmics; i++) { |
| 3470 | hda_nid_t nid; | 3460 | hda_nid_t nid; |
| 3471 | int index; | 3461 | int index, type_idx; |
| 3472 | const char *label; | 3462 | const char *label; |
| 3473 | 3463 | ||
| 3474 | nid = spec->dmic_nids[i]; | 3464 | nid = spec->dmic_nids[i]; |
| @@ -3482,28 +3472,23 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
| 3482 | if (index < 0) | 3472 | if (index < 0) |
| 3483 | continue; | 3473 | continue; |
| 3484 | 3474 | ||
| 3485 | if (active_mics == 1) | 3475 | label = hda_get_input_pin_label(codec, nid, 1); |
| 3486 | label = "Digital Mic"; | 3476 | snd_hda_add_imux_item(dimux, label, index, &type_idx); |
| 3487 | else | ||
| 3488 | label = stac92xx_dmic_labels[dimux->num_items]; | ||
| 3489 | 3477 | ||
| 3490 | err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); | 3478 | err = create_elem_capture_vol(codec, nid, label, type_idx, |
| 3479 | HDA_INPUT); | ||
| 3491 | if (err < 0) | 3480 | if (err < 0) |
| 3492 | return err; | 3481 | return err; |
| 3493 | if (!err) { | 3482 | if (!err) { |
| 3494 | err = create_elem_capture_vol(codec, nid, label, | 3483 | err = create_elem_capture_vol(codec, nid, label, |
| 3495 | HDA_OUTPUT); | 3484 | type_idx, HDA_OUTPUT); |
| 3496 | if (err < 0) | 3485 | if (err < 0) |
| 3497 | return err; | 3486 | return err; |
| 3498 | } | 3487 | } |
| 3499 | 3488 | ||
| 3500 | dimux->items[dimux->num_items].label = label; | ||
| 3501 | dimux->items[dimux->num_items].index = index; | ||
| 3502 | dimux->num_items++; | ||
| 3503 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { | 3489 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { |
| 3504 | imux->items[imux->num_items].label = label; | 3490 | snd_hda_add_imux_item(imux, label, index, NULL); |
| 3505 | imux->items[imux->num_items].index = index; | 3491 | spec->num_analog_muxes++; |
| 3506 | imux->num_items++; | ||
| 3507 | } | 3492 | } |
| 3508 | } | 3493 | } |
| 3509 | 3494 | ||
| @@ -3511,20 +3496,27 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
| 3511 | } | 3496 | } |
| 3512 | 3497 | ||
| 3513 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, | 3498 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, |
| 3514 | hda_nid_t *fixed, hda_nid_t *ext) | 3499 | hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock) |
| 3515 | { | 3500 | { |
| 3516 | unsigned int cfg; | 3501 | unsigned int cfg; |
| 3517 | 3502 | ||
| 3518 | if (!nid) | 3503 | if (!nid) |
| 3519 | return 0; | 3504 | return 0; |
| 3520 | cfg = snd_hda_codec_get_pincfg(codec, nid); | 3505 | cfg = snd_hda_codec_get_pincfg(codec, nid); |
| 3521 | switch (get_defcfg_connect(cfg)) { | 3506 | switch (snd_hda_get_input_pin_attr(cfg)) { |
| 3522 | case AC_JACK_PORT_FIXED: | 3507 | case INPUT_PIN_ATTR_INT: |
| 3523 | if (*fixed) | 3508 | if (*fixed) |
| 3524 | return 1; /* already occupied */ | 3509 | return 1; /* already occupied */ |
| 3525 | *fixed = nid; | 3510 | *fixed = nid; |
| 3526 | break; | 3511 | break; |
| 3527 | case AC_JACK_PORT_COMPLEX: | 3512 | case INPUT_PIN_ATTR_UNUSED: |
| 3513 | break; | ||
| 3514 | case INPUT_PIN_ATTR_DOCK: | ||
| 3515 | if (*dock) | ||
| 3516 | return 1; /* already occupied */ | ||
| 3517 | *dock = nid; | ||
| 3518 | break; | ||
| 3519 | default: | ||
| 3528 | if (*ext) | 3520 | if (*ext) |
| 3529 | return 1; /* already occupied */ | 3521 | return 1; /* already occupied */ |
| 3530 | *ext = nid; | 3522 | *ext = nid; |
| @@ -3542,10 +3534,13 @@ static int set_mic_route(struct hda_codec *codec, | |||
| 3542 | int i; | 3534 | int i; |
| 3543 | 3535 | ||
| 3544 | mic->pin = pin; | 3536 | mic->pin = pin; |
| 3545 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3537 | if (pin == 0) |
| 3546 | if (pin == cfg->input_pins[i]) | 3538 | return 0; |
| 3539 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 3540 | if (pin == cfg->inputs[i].pin) | ||
| 3547 | break; | 3541 | break; |
| 3548 | if (i <= AUTO_PIN_FRONT_MIC) { | 3542 | } |
| 3543 | if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) { | ||
| 3549 | /* analog pin */ | 3544 | /* analog pin */ |
| 3550 | i = get_connection_index(codec, spec->mux_nids[0], pin); | 3545 | i = get_connection_index(codec, spec->mux_nids[0], pin); |
| 3551 | if (i < 0) | 3546 | if (i < 0) |
| @@ -3576,26 +3571,29 @@ static int stac_check_auto_mic(struct hda_codec *codec) | |||
| 3576 | { | 3571 | { |
| 3577 | struct sigmatel_spec *spec = codec->spec; | 3572 | struct sigmatel_spec *spec = codec->spec; |
| 3578 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3573 | struct auto_pin_cfg *cfg = &spec->autocfg; |
| 3579 | hda_nid_t fixed, ext; | 3574 | hda_nid_t fixed, ext, dock; |
| 3580 | int i; | 3575 | int i; |
| 3581 | 3576 | ||
| 3582 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { | 3577 | for (i = 0; i < cfg->num_inputs; i++) { |
| 3583 | if (cfg->input_pins[i]) | 3578 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
| 3584 | return 0; /* must be exclusively mics */ | 3579 | return 0; /* must be exclusively mics */ |
| 3585 | } | 3580 | } |
| 3586 | fixed = ext = 0; | 3581 | fixed = ext = dock = 0; |
| 3587 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3582 | for (i = 0; i < cfg->num_inputs; i++) |
| 3588 | if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) | 3583 | if (check_mic_pin(codec, cfg->inputs[i].pin, |
| 3584 | &fixed, &ext, &dock)) | ||
| 3589 | return 0; | 3585 | return 0; |
| 3590 | for (i = 0; i < spec->num_dmics; i++) | 3586 | for (i = 0; i < spec->num_dmics; i++) |
| 3591 | if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) | 3587 | if (check_mic_pin(codec, spec->dmic_nids[i], |
| 3588 | &fixed, &ext, &dock)) | ||
| 3592 | return 0; | 3589 | return 0; |
| 3593 | if (!fixed || !ext) | 3590 | if (!fixed && !ext && !dock) |
| 3594 | return 0; | 3591 | return 0; /* no input to switch */ |
| 3595 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) | 3592 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) |
| 3596 | return 0; /* no unsol support */ | 3593 | return 0; /* no unsol support */ |
| 3597 | if (set_mic_route(codec, &spec->ext_mic, ext) || | 3594 | if (set_mic_route(codec, &spec->ext_mic, ext) || |
| 3598 | set_mic_route(codec, &spec->int_mic, fixed)) | 3595 | set_mic_route(codec, &spec->int_mic, fixed) || |
| 3596 | set_mic_route(codec, &spec->dock_mic, dock)) | ||
| 3599 | return 0; /* something is wrong */ | 3597 | return 0; /* something is wrong */ |
| 3600 | return 1; | 3598 | return 1; |
| 3601 | } | 3599 | } |
| @@ -3606,13 +3604,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
| 3606 | struct sigmatel_spec *spec = codec->spec; | 3604 | struct sigmatel_spec *spec = codec->spec; |
| 3607 | struct hda_input_mux *imux = &spec->private_imux; | 3605 | struct hda_input_mux *imux = &spec->private_imux; |
| 3608 | int i, j; | 3606 | int i, j; |
| 3607 | const char *label; | ||
| 3609 | 3608 | ||
| 3610 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3609 | for (i = 0; i < cfg->num_inputs; i++) { |
| 3611 | hda_nid_t nid = cfg->input_pins[i]; | 3610 | hda_nid_t nid = cfg->inputs[i].pin; |
| 3612 | int index, err; | 3611 | int index, err, type_idx; |
| 3613 | 3612 | ||
| 3614 | if (!nid) | ||
| 3615 | continue; | ||
| 3616 | index = -1; | 3613 | index = -1; |
| 3617 | for (j = 0; j < spec->num_muxes; j++) { | 3614 | for (j = 0; j < spec->num_muxes; j++) { |
| 3618 | index = get_connection_index(codec, spec->mux_nids[j], | 3615 | index = get_connection_index(codec, spec->mux_nids[j], |
| @@ -3623,15 +3620,14 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
| 3623 | if (index < 0) | 3620 | if (index < 0) |
| 3624 | continue; | 3621 | continue; |
| 3625 | 3622 | ||
| 3623 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 3624 | snd_hda_add_imux_item(imux, label, index, &type_idx); | ||
| 3625 | |||
| 3626 | err = create_elem_capture_vol(codec, nid, | 3626 | err = create_elem_capture_vol(codec, nid, |
| 3627 | auto_pin_cfg_labels[i], | 3627 | label, type_idx, |
| 3628 | HDA_INPUT); | 3628 | HDA_INPUT); |
| 3629 | if (err < 0) | 3629 | if (err < 0) |
| 3630 | return err; | 3630 | return err; |
| 3631 | |||
| 3632 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
| 3633 | imux->items[imux->num_items].index = index; | ||
| 3634 | imux->num_items++; | ||
| 3635 | } | 3631 | } |
| 3636 | spec->num_analog_muxes = imux->num_items; | 3632 | spec->num_analog_muxes = imux->num_items; |
| 3637 | 3633 | ||
| @@ -4305,38 +4301,38 @@ static int stac92xx_init(struct hda_codec *codec) | |||
| 4305 | AC_VERB_SET_CONNECT_SEL, 0); | 4301 | AC_VERB_SET_CONNECT_SEL, 0); |
| 4306 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) | 4302 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) |
| 4307 | stac_issue_unsol_event(codec, spec->ext_mic.pin); | 4303 | stac_issue_unsol_event(codec, spec->ext_mic.pin); |
| 4308 | } | 4304 | if (enable_pin_detect(codec, spec->dock_mic.pin, |
| 4309 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4305 | STAC_MIC_EVENT)) |
| 4310 | hda_nid_t nid = cfg->input_pins[i]; | 4306 | stac_issue_unsol_event(codec, spec->dock_mic.pin); |
| 4311 | if (nid) { | 4307 | } |
| 4312 | unsigned int pinctl, conf; | 4308 | for (i = 0; i < cfg->num_inputs; i++) { |
| 4313 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { | 4309 | hda_nid_t nid = cfg->inputs[i].pin; |
| 4314 | /* for mic pins, force to initialize */ | 4310 | int type = cfg->inputs[i].type; |
| 4315 | pinctl = stac92xx_get_default_vref(codec, nid); | 4311 | unsigned int pinctl, conf; |
| 4312 | if (type == AUTO_PIN_MIC) { | ||
| 4313 | /* for mic pins, force to initialize */ | ||
| 4314 | pinctl = stac92xx_get_default_vref(codec, nid); | ||
| 4315 | pinctl |= AC_PINCTL_IN_EN; | ||
| 4316 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
| 4317 | } else { | ||
| 4318 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
| 4319 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
| 4320 | /* if PINCTL already set then skip */ | ||
| 4321 | /* Also, if both INPUT and OUTPUT are set, | ||
| 4322 | * it must be a BIOS bug; need to override, too | ||
| 4323 | */ | ||
| 4324 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
| 4325 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
| 4326 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
| 4316 | pinctl |= AC_PINCTL_IN_EN; | 4327 | pinctl |= AC_PINCTL_IN_EN; |
| 4317 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 4328 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
| 4318 | } else { | ||
| 4319 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
| 4320 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
| 4321 | /* if PINCTL already set then skip */ | ||
| 4322 | /* Also, if both INPUT and OUTPUT are set, | ||
| 4323 | * it must be a BIOS bug; need to override, too | ||
| 4324 | */ | ||
| 4325 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
| 4326 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
| 4327 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
| 4328 | pinctl |= AC_PINCTL_IN_EN; | ||
| 4329 | stac92xx_auto_set_pinctl(codec, nid, | ||
| 4330 | pinctl); | ||
| 4331 | } | ||
| 4332 | } | ||
| 4333 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
| 4334 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
| 4335 | if (enable_pin_detect(codec, nid, | ||
| 4336 | STAC_INSERT_EVENT)) | ||
| 4337 | stac_issue_unsol_event(codec, nid); | ||
| 4338 | } | 4329 | } |
| 4339 | } | 4330 | } |
| 4331 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
| 4332 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
| 4333 | if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) | ||
| 4334 | stac_issue_unsol_event(codec, nid); | ||
| 4335 | } | ||
| 4340 | } | 4336 | } |
| 4341 | for (i = 0; i < spec->num_dmics; i++) | 4337 | for (i = 0; i < spec->num_dmics; i++) |
| 4342 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 4338 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
| @@ -4383,11 +4379,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
| 4383 | stac_issue_unsol_event(codec, nid); | 4379 | stac_issue_unsol_event(codec, nid); |
| 4384 | } | 4380 | } |
| 4385 | 4381 | ||
| 4386 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 4387 | /* sync mute LED */ | 4382 | /* sync mute LED */ |
| 4388 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4383 | if (spec->gpio_led) |
| 4389 | codec->patch_ops.check_power_status(codec, 0x01); | 4384 | hda_call_check_power_status(codec, 0x01); |
| 4390 | #endif | ||
| 4391 | if (spec->dac_list) | 4385 | if (spec->dac_list) |
| 4392 | stac92xx_power_down(codec); | 4386 | stac92xx_power_down(codec); |
| 4393 | return 0; | 4387 | return 0; |
| @@ -4688,6 +4682,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | |||
| 4688 | } | 4682 | } |
| 4689 | } | 4683 | } |
| 4690 | 4684 | ||
| 4685 | /* get the pin connection (fixed, none, etc) */ | ||
| 4686 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
| 4687 | { | ||
| 4688 | struct sigmatel_spec *spec = codec->spec; | ||
| 4689 | unsigned int cfg; | ||
| 4690 | |||
| 4691 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
| 4692 | return get_defcfg_connect(cfg); | ||
| 4693 | } | ||
| 4694 | |||
| 4695 | static int stac92xx_connected_ports(struct hda_codec *codec, | ||
| 4696 | hda_nid_t *nids, int num_nids) | ||
| 4697 | { | ||
| 4698 | struct sigmatel_spec *spec = codec->spec; | ||
| 4699 | int idx, num; | ||
| 4700 | unsigned int def_conf; | ||
| 4701 | |||
| 4702 | for (num = 0; num < num_nids; num++) { | ||
| 4703 | for (idx = 0; idx < spec->num_pins; idx++) | ||
| 4704 | if (spec->pin_nids[idx] == nids[num]) | ||
| 4705 | break; | ||
| 4706 | if (idx >= spec->num_pins) | ||
| 4707 | break; | ||
| 4708 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
| 4709 | if (def_conf == AC_JACK_PORT_NONE) | ||
| 4710 | break; | ||
| 4711 | } | ||
| 4712 | return num; | ||
| 4713 | } | ||
| 4714 | |||
| 4691 | static void stac92xx_mic_detect(struct hda_codec *codec) | 4715 | static void stac92xx_mic_detect(struct hda_codec *codec) |
| 4692 | { | 4716 | { |
| 4693 | struct sigmatel_spec *spec = codec->spec; | 4717 | struct sigmatel_spec *spec = codec->spec; |
| @@ -4695,6 +4719,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
| 4695 | 4719 | ||
| 4696 | if (get_pin_presence(codec, spec->ext_mic.pin)) | 4720 | if (get_pin_presence(codec, spec->ext_mic.pin)) |
| 4697 | mic = &spec->ext_mic; | 4721 | mic = &spec->ext_mic; |
| 4722 | else if (get_pin_presence(codec, spec->dock_mic.pin)) | ||
| 4723 | mic = &spec->dock_mic; | ||
| 4698 | else | 4724 | else |
| 4699 | mic = &spec->int_mic; | 4725 | mic = &spec->int_mic; |
| 4700 | if (mic->dmux_idx >= 0) | 4726 | if (mic->dmux_idx >= 0) |
| @@ -4937,11 +4963,9 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
| 4937 | stac_issue_unsol_event(codec, | 4963 | stac_issue_unsol_event(codec, |
| 4938 | spec->autocfg.line_out_pins[0]); | 4964 | spec->autocfg.line_out_pins[0]); |
| 4939 | } | 4965 | } |
| 4940 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
| 4941 | /* sync mute LED */ | 4966 | /* sync mute LED */ |
| 4942 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4967 | if (spec->gpio_led) |
| 4943 | codec->patch_ops.check_power_status(codec, 0x01); | 4968 | hda_call_check_power_status(codec, 0x01); |
| 4944 | #endif | ||
| 4945 | return 0; | 4969 | return 0; |
| 4946 | } | 4970 | } |
| 4947 | 4971 | ||
| @@ -5313,11 +5337,16 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
| 5313 | if (spec == NULL) | 5337 | if (spec == NULL) |
| 5314 | return -ENOMEM; | 5338 | return -ENOMEM; |
| 5315 | 5339 | ||
| 5340 | /* reset pin power-down; Windows may leave these bits after reboot */ | ||
| 5341 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7EC, 0); | ||
| 5342 | snd_hda_codec_write_cache(codec, codec->afg, 0, 0x7ED, 0); | ||
| 5316 | codec->no_trigger_sense = 1; | 5343 | codec->no_trigger_sense = 1; |
| 5317 | codec->spec = spec; | 5344 | codec->spec = spec; |
| 5318 | spec->linear_tone_beep = 1; | 5345 | spec->linear_tone_beep = 1; |
| 5319 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5346 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
| 5320 | spec->digbeep_nid = 0x21; | 5347 | spec->digbeep_nid = 0x21; |
| 5348 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | ||
| 5349 | spec->dmux_nids = stac92hd83xxx_mux_nids; | ||
| 5321 | spec->mux_nids = stac92hd83xxx_mux_nids; | 5350 | spec->mux_nids = stac92hd83xxx_mux_nids; |
| 5322 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); | 5351 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); |
| 5323 | spec->adc_nids = stac92hd83xxx_adc_nids; | 5352 | spec->adc_nids = stac92hd83xxx_adc_nids; |
| @@ -5363,9 +5392,13 @@ again: | |||
| 5363 | case 0x111d76d4: | 5392 | case 0x111d76d4: |
| 5364 | case 0x111d7605: | 5393 | case 0x111d7605: |
| 5365 | case 0x111d76d5: | 5394 | case 0x111d76d5: |
| 5395 | case 0x111d76e7: | ||
| 5366 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) | 5396 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) |
| 5367 | break; | 5397 | break; |
| 5368 | spec->num_pwrs = 0; | 5398 | spec->num_pwrs = 0; |
| 5399 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
| 5400 | stac92hd83xxx_dmic_nids, | ||
| 5401 | STAC92HD83XXX_NUM_DMICS); | ||
| 5369 | break; | 5402 | break; |
| 5370 | } | 5403 | } |
| 5371 | 5404 | ||
| @@ -5424,36 +5457,6 @@ again: | |||
| 5424 | return 0; | 5457 | return 0; |
| 5425 | } | 5458 | } |
| 5426 | 5459 | ||
| 5427 | /* get the pin connection (fixed, none, etc) */ | ||
| 5428 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
| 5429 | { | ||
| 5430 | struct sigmatel_spec *spec = codec->spec; | ||
| 5431 | unsigned int cfg; | ||
| 5432 | |||
| 5433 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
| 5434 | return get_defcfg_connect(cfg); | ||
| 5435 | } | ||
| 5436 | |||
| 5437 | static int stac92hd71bxx_connected_ports(struct hda_codec *codec, | ||
| 5438 | hda_nid_t *nids, int num_nids) | ||
| 5439 | { | ||
| 5440 | struct sigmatel_spec *spec = codec->spec; | ||
| 5441 | int idx, num; | ||
| 5442 | unsigned int def_conf; | ||
| 5443 | |||
| 5444 | for (num = 0; num < num_nids; num++) { | ||
| 5445 | for (idx = 0; idx < spec->num_pins; idx++) | ||
| 5446 | if (spec->pin_nids[idx] == nids[num]) | ||
| 5447 | break; | ||
| 5448 | if (idx >= spec->num_pins) | ||
| 5449 | break; | ||
| 5450 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
| 5451 | if (def_conf == AC_JACK_PORT_NONE) | ||
| 5452 | break; | ||
| 5453 | } | ||
| 5454 | return num; | ||
| 5455 | } | ||
| 5456 | |||
| 5457 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | 5460 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, |
| 5458 | hda_nid_t dig0pin) | 5461 | hda_nid_t dig0pin) |
| 5459 | { | 5462 | { |
| @@ -5592,7 +5595,7 @@ again: | |||
| 5592 | case 0x111d76b5: | 5595 | case 0x111d76b5: |
| 5593 | spec->init = stac92hd71bxx_core_init; | 5596 | spec->init = stac92hd71bxx_core_init; |
| 5594 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5597 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
| 5595 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5598 | spec->num_dmics = stac92xx_connected_ports(codec, |
| 5596 | stac92hd71bxx_dmic_nids, | 5599 | stac92hd71bxx_dmic_nids, |
| 5597 | STAC92HD71BXX_NUM_DMICS); | 5600 | STAC92HD71BXX_NUM_DMICS); |
| 5598 | break; | 5601 | break; |
| @@ -5624,7 +5627,7 @@ again: | |||
| 5624 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 5627 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
| 5625 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 5628 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
| 5626 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; | 5629 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; |
| 5627 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5630 | spec->num_dmics = stac92xx_connected_ports(codec, |
| 5628 | stac92hd71bxx_dmic_nids, | 5631 | stac92hd71bxx_dmic_nids, |
| 5629 | STAC92HD71BXX_NUM_DMICS - 1); | 5632 | STAC92HD71BXX_NUM_DMICS - 1); |
| 5630 | break; | 5633 | break; |
| @@ -5638,7 +5641,7 @@ again: | |||
| 5638 | default: | 5641 | default: |
| 5639 | spec->init = stac92hd71bxx_core_init; | 5642 | spec->init = stac92hd71bxx_core_init; |
| 5640 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5643 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
| 5641 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5644 | spec->num_dmics = stac92xx_connected_ports(codec, |
| 5642 | stac92hd71bxx_dmic_nids, | 5645 | stac92hd71bxx_dmic_nids, |
| 5643 | STAC92HD71BXX_NUM_DMICS); | 5646 | STAC92HD71BXX_NUM_DMICS); |
| 5644 | break; | 5647 | break; |
| @@ -6320,6 +6323,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
| 6320 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, | 6323 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, |
| 6321 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, | 6324 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, |
| 6322 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, | 6325 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, |
| 6326 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, | ||
| 6327 | { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, | ||
| 6323 | {} /* terminator */ | 6328 | {} /* terminator */ |
| 6324 | }; | 6329 | }; |
| 6325 | 6330 | ||
diff --git a/sound/pci/hda/patch_via.c b/sound/pci/hda/patch_via.c index ae3acb2b42d1..d1c3f8defc48 100644 --- a/sound/pci/hda/patch_via.c +++ b/sound/pci/hda/patch_via.c | |||
| @@ -444,8 +444,8 @@ static hda_nid_t vt1812_adc_nids[2] = { | |||
| 444 | 444 | ||
| 445 | 445 | ||
| 446 | /* add dynamic controls */ | 446 | /* add dynamic controls */ |
| 447 | static int via_add_control(struct via_spec *spec, int type, const char *name, | 447 | static int __via_add_control(struct via_spec *spec, int type, const char *name, |
| 448 | unsigned long val) | 448 | int idx, unsigned long val) |
| 449 | { | 449 | { |
| 450 | struct snd_kcontrol_new *knew; | 450 | struct snd_kcontrol_new *knew; |
| 451 | 451 | ||
| @@ -463,6 +463,9 @@ static int via_add_control(struct via_spec *spec, int type, const char *name, | |||
| 463 | return 0; | 463 | return 0; |
| 464 | } | 464 | } |
| 465 | 465 | ||
| 466 | #define via_add_control(spec, type, name, val) \ | ||
| 467 | __via_add_control(spec, type, name, 0, val) | ||
| 468 | |||
| 466 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, | 469 | static struct snd_kcontrol_new *via_clone_control(struct via_spec *spec, |
| 467 | struct snd_kcontrol_new *tmpl) | 470 | struct snd_kcontrol_new *tmpl) |
| 468 | { | 471 | { |
| @@ -494,18 +497,18 @@ static void via_free_kctls(struct hda_codec *codec) | |||
| 494 | 497 | ||
| 495 | /* create input playback/capture controls for the given pin */ | 498 | /* create input playback/capture controls for the given pin */ |
| 496 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, | 499 | static int via_new_analog_input(struct via_spec *spec, const char *ctlname, |
| 497 | int idx, int mix_nid) | 500 | int type_idx, int idx, int mix_nid) |
| 498 | { | 501 | { |
| 499 | char name[32]; | 502 | char name[32]; |
| 500 | int err; | 503 | int err; |
| 501 | 504 | ||
| 502 | sprintf(name, "%s Playback Volume", ctlname); | 505 | sprintf(name, "%s Playback Volume", ctlname); |
| 503 | err = via_add_control(spec, VIA_CTL_WIDGET_VOL, name, | 506 | err = __via_add_control(spec, VIA_CTL_WIDGET_VOL, name, type_idx, |
| 504 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 507 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
| 505 | if (err < 0) | 508 | if (err < 0) |
| 506 | return err; | 509 | return err; |
| 507 | sprintf(name, "%s Playback Switch", ctlname); | 510 | sprintf(name, "%s Playback Switch", ctlname); |
| 508 | err = via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, | 511 | err = __via_add_control(spec, VIA_CTL_WIDGET_ANALOG_MUTE, name, type_idx, |
| 509 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 512 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
| 510 | if (err < 0) | 513 | if (err < 0) |
| 511 | return err; | 514 | return err; |
| @@ -557,17 +560,15 @@ static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin); | |||
| 557 | static void via_auto_init_analog_input(struct hda_codec *codec) | 560 | static void via_auto_init_analog_input(struct hda_codec *codec) |
| 558 | { | 561 | { |
| 559 | struct via_spec *spec = codec->spec; | 562 | struct via_spec *spec = codec->spec; |
| 563 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 560 | unsigned int ctl; | 564 | unsigned int ctl; |
| 561 | int i; | 565 | int i; |
| 562 | 566 | ||
| 563 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 567 | for (i = 0; i < cfg->num_inputs; i++) { |
| 564 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 568 | hda_nid_t nid = cfg->inputs[i].pin; |
| 565 | if (!nid) | ||
| 566 | continue; | ||
| 567 | |||
| 568 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) | 569 | if (spec->smart51_enabled && is_smart51_pins(spec, nid)) |
| 569 | ctl = PIN_OUT; | 570 | ctl = PIN_OUT; |
| 570 | else if (i <= AUTO_PIN_FRONT_MIC) | 571 | else if (i == AUTO_PIN_MIC) |
| 571 | ctl = PIN_VREF50; | 572 | ctl = PIN_VREF50; |
| 572 | else | 573 | else |
| 573 | ctl = PIN_IN; | 574 | ctl = PIN_IN; |
| @@ -1322,15 +1323,14 @@ static void mute_aa_path(struct hda_codec *codec, int mute) | |||
| 1322 | } | 1323 | } |
| 1323 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) | 1324 | static int is_smart51_pins(struct via_spec *spec, hda_nid_t pin) |
| 1324 | { | 1325 | { |
| 1325 | int res = 0; | 1326 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
| 1326 | int index; | 1327 | int i; |
| 1327 | for (index = AUTO_PIN_MIC; index < AUTO_PIN_FRONT_LINE; index++) { | 1328 | |
| 1328 | if (pin == spec->autocfg.input_pins[index]) { | 1329 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1329 | res = 1; | 1330 | if (pin == cfg->inputs[i].pin) |
| 1330 | break; | 1331 | return cfg->inputs[i].type <= AUTO_PIN_LINE_IN; |
| 1331 | } | ||
| 1332 | } | 1332 | } |
| 1333 | return res; | 1333 | return 0; |
| 1334 | } | 1334 | } |
| 1335 | 1335 | ||
| 1336 | static int via_smart51_info(struct snd_kcontrol *kcontrol, | 1336 | static int via_smart51_info(struct snd_kcontrol *kcontrol, |
| @@ -1348,25 +1348,21 @@ static int via_smart51_get(struct snd_kcontrol *kcontrol, | |||
| 1348 | { | 1348 | { |
| 1349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1349 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 1350 | struct via_spec *spec = codec->spec; | 1350 | struct via_spec *spec = codec->spec; |
| 1351 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 1351 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
| 1352 | int on = 1; | 1352 | int on = 1; |
| 1353 | int i; | 1353 | int i; |
| 1354 | 1354 | ||
| 1355 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1355 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1356 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 1356 | hda_nid_t nid = cfg->inputs[i].pin; |
| 1357 | if (nid) { | 1357 | int ctl = snd_hda_codec_read(codec, nid, 0, |
| 1358 | int ctl = | 1358 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
| 1359 | snd_hda_codec_read(codec, nid, 0, | 1359 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
| 1360 | AC_VERB_GET_PIN_WIDGET_CONTROL, | 1360 | continue; |
| 1361 | 0); | 1361 | if (cfg->inputs[i].type == AUTO_PIN_MIC && |
| 1362 | if (i == AUTO_PIN_FRONT_MIC | 1362 | spec->hp_independent_mode && spec->codec_type != VT1718S) |
| 1363 | && spec->hp_independent_mode | 1363 | continue; /* ignore FMic for independent HP */ |
| 1364 | && spec->codec_type != VT1718S) | 1364 | if ((ctl & AC_PINCTL_IN_EN) && !(ctl & AC_PINCTL_OUT_EN)) |
| 1365 | continue; /* ignore FMic for independent HP */ | 1365 | on = 0; |
| 1366 | if (ctl & AC_PINCTL_IN_EN | ||
| 1367 | && !(ctl & AC_PINCTL_OUT_EN)) | ||
| 1368 | on = 0; | ||
| 1369 | } | ||
| 1370 | } | 1366 | } |
| 1371 | *ucontrol->value.integer.value = on; | 1367 | *ucontrol->value.integer.value = on; |
| 1372 | return 0; | 1368 | return 0; |
| @@ -1377,36 +1373,38 @@ static int via_smart51_put(struct snd_kcontrol *kcontrol, | |||
| 1377 | { | 1373 | { |
| 1378 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 1374 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
| 1379 | struct via_spec *spec = codec->spec; | 1375 | struct via_spec *spec = codec->spec; |
| 1376 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
| 1380 | int out_in = *ucontrol->value.integer.value | 1377 | int out_in = *ucontrol->value.integer.value |
| 1381 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; | 1378 | ? AC_PINCTL_OUT_EN : AC_PINCTL_IN_EN; |
| 1382 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | ||
| 1383 | int i; | 1379 | int i; |
| 1384 | 1380 | ||
| 1385 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1381 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1386 | hda_nid_t nid = spec->autocfg.input_pins[index[i]]; | 1382 | hda_nid_t nid = cfg->inputs[i].pin; |
| 1387 | if (i == AUTO_PIN_FRONT_MIC | 1383 | unsigned int parm; |
| 1388 | && spec->hp_independent_mode | 1384 | |
| 1389 | && spec->codec_type != VT1718S) | 1385 | if (cfg->inputs[i].type > AUTO_PIN_LINE_IN) |
| 1386 | continue; | ||
| 1387 | if (cfg->inputs[i].type == AUTO_PIN_MIC && | ||
| 1388 | spec->hp_independent_mode && spec->codec_type != VT1718S) | ||
| 1390 | continue; /* don't retask FMic for independent HP */ | 1389 | continue; /* don't retask FMic for independent HP */ |
| 1391 | if (nid) { | 1390 | |
| 1392 | unsigned int parm = snd_hda_codec_read( | 1391 | parm = snd_hda_codec_read(codec, nid, 0, |
| 1393 | codec, nid, 0, | 1392 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); |
| 1394 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | 1393 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); |
| 1395 | parm &= ~(AC_PINCTL_IN_EN | AC_PINCTL_OUT_EN); | 1394 | parm |= out_in; |
| 1396 | parm |= out_in; | 1395 | snd_hda_codec_write(codec, nid, 0, |
| 1397 | snd_hda_codec_write(codec, nid, 0, | 1396 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
| 1398 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1397 | parm); |
| 1399 | parm); | 1398 | if (out_in == AC_PINCTL_OUT_EN) { |
| 1400 | if (out_in == AC_PINCTL_OUT_EN) { | 1399 | mute_aa_path(codec, 1); |
| 1401 | mute_aa_path(codec, 1); | 1400 | notify_aa_path_ctls(codec); |
| 1402 | notify_aa_path_ctls(codec); | 1401 | } |
| 1403 | } | 1402 | if (spec->codec_type == VT1718S) { |
| 1404 | if (spec->codec_type == VT1718S) | 1403 | snd_hda_codec_amp_stereo( |
| 1405 | snd_hda_codec_amp_stereo( | ||
| 1406 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, | 1404 | codec, nid, HDA_OUTPUT, 0, HDA_AMP_MUTE, |
| 1407 | HDA_AMP_UNMUTE); | 1405 | HDA_AMP_UNMUTE); |
| 1408 | } | 1406 | } |
| 1409 | if (i == AUTO_PIN_FRONT_MIC) { | 1407 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
| 1410 | if (spec->codec_type == VT1708S | 1408 | if (spec->codec_type == VT1708S |
| 1411 | || spec->codec_type == VT1716S) { | 1409 | || spec->codec_type == VT1716S) { |
| 1412 | /* input = index 1 (AOW3) */ | 1410 | /* input = index 1 (AOW3) */ |
| @@ -1442,7 +1440,7 @@ static struct snd_kcontrol_new via_smart51_mixer[2] = { | |||
| 1442 | static int via_smart51_build(struct via_spec *spec) | 1440 | static int via_smart51_build(struct via_spec *spec) |
| 1443 | { | 1441 | { |
| 1444 | struct snd_kcontrol_new *knew; | 1442 | struct snd_kcontrol_new *knew; |
| 1445 | int index[] = { AUTO_PIN_MIC, AUTO_PIN_FRONT_MIC, AUTO_PIN_LINE }; | 1443 | const struct auto_pin_cfg *cfg = &spec->autocfg; |
| 1446 | hda_nid_t nid; | 1444 | hda_nid_t nid; |
| 1447 | int i; | 1445 | int i; |
| 1448 | 1446 | ||
| @@ -1450,13 +1448,14 @@ static int via_smart51_build(struct via_spec *spec) | |||
| 1450 | if (knew == NULL) | 1448 | if (knew == NULL) |
| 1451 | return -ENOMEM; | 1449 | return -ENOMEM; |
| 1452 | 1450 | ||
| 1453 | for (i = 0; i < ARRAY_SIZE(index); i++) { | 1451 | for (i = 0; i < cfg->num_inputs; i++) { |
| 1454 | nid = spec->autocfg.input_pins[index[i]]; | 1452 | nid = cfg->inputs[i].pin; |
| 1455 | if (nid) { | 1453 | if (cfg->inputs[i].type <= AUTO_PIN_LINE_IN) { |
| 1456 | knew = via_clone_control(spec, &via_smart51_mixer[1]); | 1454 | knew = via_clone_control(spec, &via_smart51_mixer[1]); |
| 1457 | if (knew == NULL) | 1455 | if (knew == NULL) |
| 1458 | return -ENOMEM; | 1456 | return -ENOMEM; |
| 1459 | knew->subdevice = nid; | 1457 | knew->subdevice = nid; |
| 1458 | break; | ||
| 1460 | } | 1459 | } |
| 1461 | } | 1460 | } |
| 1462 | 1461 | ||
| @@ -2375,13 +2374,8 @@ static void create_hp_imux(struct via_spec *spec) | |||
| 2375 | static const char *texts[] = { "OFF", "ON", NULL}; | 2374 | static const char *texts[] = { "OFF", "ON", NULL}; |
| 2376 | 2375 | ||
| 2377 | /* for hp mode select */ | 2376 | /* for hp mode select */ |
| 2378 | i = 0; | 2377 | for (i = 0; texts[i]; i++) |
| 2379 | while (texts[i] != NULL) { | 2378 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
| 2380 | imux->items[imux->num_items].label = texts[i]; | ||
| 2381 | imux->items[imux->num_items].index = i; | ||
| 2382 | imux->num_items++; | ||
| 2383 | i++; | ||
| 2384 | } | ||
| 2385 | 2379 | ||
| 2386 | spec->hp_mux = &spec->private_imux[1]; | 2380 | spec->hp_mux = &spec->private_imux[1]; |
| 2387 | } | 2381 | } |
| @@ -2413,51 +2407,53 @@ static int vt1708_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 2413 | } | 2407 | } |
| 2414 | 2408 | ||
| 2415 | /* create playback/capture controls for input pins */ | 2409 | /* create playback/capture controls for input pins */ |
| 2416 | static int vt1708_auto_create_analog_input_ctls(struct via_spec *spec, | 2410 | static int vt_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 2417 | const struct auto_pin_cfg *cfg) | 2411 | const struct auto_pin_cfg *cfg, |
| 2412 | hda_nid_t cap_nid, | ||
| 2413 | hda_nid_t pin_idxs[], int num_idxs) | ||
| 2418 | { | 2414 | { |
| 2419 | static char *labels[] = { | 2415 | struct via_spec *spec = codec->spec; |
| 2420 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
| 2421 | }; | ||
| 2422 | struct hda_input_mux *imux = &spec->private_imux[0]; | 2416 | struct hda_input_mux *imux = &spec->private_imux[0]; |
| 2423 | int i, err, idx = 0; | 2417 | int i, err, idx, type, type_idx = 0; |
| 2424 | 2418 | ||
| 2425 | /* for internal loopback recording select */ | 2419 | /* for internal loopback recording select */ |
| 2426 | imux->items[imux->num_items].label = "Stereo Mixer"; | 2420 | for (idx = 0; idx < num_idxs; idx++) { |
| 2427 | imux->items[imux->num_items].index = idx; | 2421 | if (pin_idxs[idx] == 0xff) { |
| 2428 | imux->num_items++; | 2422 | snd_hda_add_imux_item(imux, "Stereo Mixer", idx, NULL); |
| 2429 | |||
| 2430 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 2431 | if (!cfg->input_pins[i]) | ||
| 2432 | continue; | ||
| 2433 | |||
| 2434 | switch (cfg->input_pins[i]) { | ||
| 2435 | case 0x1d: /* Mic */ | ||
| 2436 | idx = 2; | ||
| 2437 | break; | ||
| 2438 | |||
| 2439 | case 0x1e: /* Line In */ | ||
| 2440 | idx = 3; | ||
| 2441 | break; | ||
| 2442 | |||
| 2443 | case 0x21: /* Front Mic */ | ||
| 2444 | idx = 4; | ||
| 2445 | break; | ||
| 2446 | |||
| 2447 | case 0x24: /* CD */ | ||
| 2448 | idx = 1; | ||
| 2449 | break; | 2423 | break; |
| 2450 | } | 2424 | } |
| 2451 | err = via_new_analog_input(spec, labels[i], idx, 0x17); | 2425 | } |
| 2426 | |||
| 2427 | for (i = 0; i < cfg->num_inputs; i++) { | ||
| 2428 | const char *label; | ||
| 2429 | type = cfg->inputs[i].type; | ||
| 2430 | for (idx = 0; idx < num_idxs; idx++) | ||
| 2431 | if (pin_idxs[idx] == cfg->inputs[i].pin) | ||
| 2432 | break; | ||
| 2433 | if (idx >= num_idxs) | ||
| 2434 | continue; | ||
| 2435 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
| 2436 | type_idx++; | ||
| 2437 | else | ||
| 2438 | type_idx = 0; | ||
| 2439 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
| 2440 | err = via_new_analog_input(spec, label, type_idx, idx, cap_nid); | ||
| 2452 | if (err < 0) | 2441 | if (err < 0) |
| 2453 | return err; | 2442 | return err; |
| 2454 | imux->items[imux->num_items].label = labels[i]; | 2443 | snd_hda_add_imux_item(imux, label, idx, NULL); |
| 2455 | imux->items[imux->num_items].index = idx; | ||
| 2456 | imux->num_items++; | ||
| 2457 | } | 2444 | } |
| 2458 | return 0; | 2445 | return 0; |
| 2459 | } | 2446 | } |
| 2460 | 2447 | ||
| 2448 | /* create playback/capture controls for input pins */ | ||
| 2449 | static int vt1708_auto_create_analog_input_ctls(struct hda_codec *codec, | ||
| 2450 | const struct auto_pin_cfg *cfg) | ||
| 2451 | { | ||
| 2452 | static hda_nid_t pin_idxs[] = { 0xff, 0x24, 0x1d, 0x1e, 0x21 }; | ||
| 2453 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x17, pin_idxs, | ||
| 2454 | ARRAY_SIZE(pin_idxs)); | ||
| 2455 | } | ||
| 2456 | |||
| 2461 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2457 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
| 2462 | static struct hda_amp_list vt1708_loopbacks[] = { | 2458 | static struct hda_amp_list vt1708_loopbacks[] = { |
| 2463 | { 0x17, HDA_INPUT, 1 }, | 2459 | { 0x17, HDA_INPUT, 1 }, |
| @@ -2554,7 +2550,7 @@ static int vt1708_parse_auto_config(struct hda_codec *codec) | |||
| 2554 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 2550 | err = vt1708_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 2555 | if (err < 0) | 2551 | if (err < 0) |
| 2556 | return err; | 2552 | return err; |
| 2557 | err = vt1708_auto_create_analog_input_ctls(spec, &spec->autocfg); | 2553 | err = vt1708_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 2558 | if (err < 0) | 2554 | if (err < 0) |
| 2559 | return err; | 2555 | return err; |
| 2560 | /* add jack detect on/off control */ | 2556 | /* add jack detect on/off control */ |
| @@ -3021,49 +3017,12 @@ static int vt1709_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 3021 | } | 3017 | } |
| 3022 | 3018 | ||
| 3023 | /* create playback/capture controls for input pins */ | 3019 | /* create playback/capture controls for input pins */ |
| 3024 | static int vt1709_auto_create_analog_input_ctls(struct via_spec *spec, | 3020 | static int vt1709_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 3025 | const struct auto_pin_cfg *cfg) | 3021 | const struct auto_pin_cfg *cfg) |
| 3026 | { | 3022 | { |
| 3027 | static char *labels[] = { | 3023 | static hda_nid_t pin_idxs[] = { 0xff, 0x23, 0x1d, 0x1e, 0x21 }; |
| 3028 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3024 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x18, pin_idxs, |
| 3029 | }; | 3025 | ARRAY_SIZE(pin_idxs)); |
| 3030 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 3031 | int i, err, idx = 0; | ||
| 3032 | |||
| 3033 | /* for internal loopback recording select */ | ||
| 3034 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 3035 | imux->items[imux->num_items].index = idx; | ||
| 3036 | imux->num_items++; | ||
| 3037 | |||
| 3038 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 3039 | if (!cfg->input_pins[i]) | ||
| 3040 | continue; | ||
| 3041 | |||
| 3042 | switch (cfg->input_pins[i]) { | ||
| 3043 | case 0x1d: /* Mic */ | ||
| 3044 | idx = 2; | ||
| 3045 | break; | ||
| 3046 | |||
| 3047 | case 0x1e: /* Line In */ | ||
| 3048 | idx = 3; | ||
| 3049 | break; | ||
| 3050 | |||
| 3051 | case 0x21: /* Front Mic */ | ||
| 3052 | idx = 4; | ||
| 3053 | break; | ||
| 3054 | |||
| 3055 | case 0x23: /* CD */ | ||
| 3056 | idx = 1; | ||
| 3057 | break; | ||
| 3058 | } | ||
| 3059 | err = via_new_analog_input(spec, labels[i], idx, 0x18); | ||
| 3060 | if (err < 0) | ||
| 3061 | return err; | ||
| 3062 | imux->items[imux->num_items].label = labels[i]; | ||
| 3063 | imux->items[imux->num_items].index = idx; | ||
| 3064 | imux->num_items++; | ||
| 3065 | } | ||
| 3066 | return 0; | ||
| 3067 | } | 3026 | } |
| 3068 | 3027 | ||
| 3069 | static int vt1709_parse_auto_config(struct hda_codec *codec) | 3028 | static int vt1709_parse_auto_config(struct hda_codec *codec) |
| @@ -3086,7 +3045,7 @@ static int vt1709_parse_auto_config(struct hda_codec *codec) | |||
| 3086 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3045 | err = vt1709_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 3087 | if (err < 0) | 3046 | if (err < 0) |
| 3088 | return err; | 3047 | return err; |
| 3089 | err = vt1709_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3048 | err = vt1709_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 3090 | if (err < 0) | 3049 | if (err < 0) |
| 3091 | return err; | 3050 | return err; |
| 3092 | 3051 | ||
| @@ -3588,49 +3547,12 @@ static int vt1708B_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 3588 | } | 3547 | } |
| 3589 | 3548 | ||
| 3590 | /* create playback/capture controls for input pins */ | 3549 | /* create playback/capture controls for input pins */ |
| 3591 | static int vt1708B_auto_create_analog_input_ctls(struct via_spec *spec, | 3550 | static int vt1708B_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 3592 | const struct auto_pin_cfg *cfg) | 3551 | const struct auto_pin_cfg *cfg) |
| 3593 | { | 3552 | { |
| 3594 | static char *labels[] = { | 3553 | static hda_nid_t pin_idxs[] = { 0xff, 0x1f, 0x1a, 0x1b, 0x1e }; |
| 3595 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3554 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
| 3596 | }; | 3555 | ARRAY_SIZE(pin_idxs)); |
| 3597 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 3598 | int i, err, idx = 0; | ||
| 3599 | |||
| 3600 | /* for internal loopback recording select */ | ||
| 3601 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 3602 | imux->items[imux->num_items].index = idx; | ||
| 3603 | imux->num_items++; | ||
| 3604 | |||
| 3605 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 3606 | if (!cfg->input_pins[i]) | ||
| 3607 | continue; | ||
| 3608 | |||
| 3609 | switch (cfg->input_pins[i]) { | ||
| 3610 | case 0x1a: /* Mic */ | ||
| 3611 | idx = 2; | ||
| 3612 | break; | ||
| 3613 | |||
| 3614 | case 0x1b: /* Line In */ | ||
| 3615 | idx = 3; | ||
| 3616 | break; | ||
| 3617 | |||
| 3618 | case 0x1e: /* Front Mic */ | ||
| 3619 | idx = 4; | ||
| 3620 | break; | ||
| 3621 | |||
| 3622 | case 0x1f: /* CD */ | ||
| 3623 | idx = 1; | ||
| 3624 | break; | ||
| 3625 | } | ||
| 3626 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
| 3627 | if (err < 0) | ||
| 3628 | return err; | ||
| 3629 | imux->items[imux->num_items].label = labels[i]; | ||
| 3630 | imux->items[imux->num_items].index = idx; | ||
| 3631 | imux->num_items++; | ||
| 3632 | } | ||
| 3633 | return 0; | ||
| 3634 | } | 3556 | } |
| 3635 | 3557 | ||
| 3636 | static int vt1708B_parse_auto_config(struct hda_codec *codec) | 3558 | static int vt1708B_parse_auto_config(struct hda_codec *codec) |
| @@ -3653,7 +3575,7 @@ static int vt1708B_parse_auto_config(struct hda_codec *codec) | |||
| 3653 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 3575 | err = vt1708B_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 3654 | if (err < 0) | 3576 | if (err < 0) |
| 3655 | return err; | 3577 | return err; |
| 3656 | err = vt1708B_auto_create_analog_input_ctls(spec, &spec->autocfg); | 3578 | err = vt1708B_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 3657 | if (err < 0) | 3579 | if (err < 0) |
| 3658 | return err; | 3580 | return err; |
| 3659 | 3581 | ||
| @@ -4061,49 +3983,12 @@ static int vt1708S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 4061 | } | 3983 | } |
| 4062 | 3984 | ||
| 4063 | /* create playback/capture controls for input pins */ | 3985 | /* create playback/capture controls for input pins */ |
| 4064 | static int vt1708S_auto_create_analog_input_ctls(struct via_spec *spec, | 3986 | static int vt1708S_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 4065 | const struct auto_pin_cfg *cfg) | 3987 | const struct auto_pin_cfg *cfg) |
| 4066 | { | 3988 | { |
| 4067 | static char *labels[] = { | 3989 | static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
| 4068 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 3990 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
| 4069 | }; | 3991 | ARRAY_SIZE(pin_idxs)); |
| 4070 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 4071 | int i, err, idx = 0; | ||
| 4072 | |||
| 4073 | /* for internal loopback recording select */ | ||
| 4074 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 4075 | imux->items[imux->num_items].index = 5; | ||
| 4076 | imux->num_items++; | ||
| 4077 | |||
| 4078 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 4079 | if (!cfg->input_pins[i]) | ||
| 4080 | continue; | ||
| 4081 | |||
| 4082 | switch (cfg->input_pins[i]) { | ||
| 4083 | case 0x1a: /* Mic */ | ||
| 4084 | idx = 2; | ||
| 4085 | break; | ||
| 4086 | |||
| 4087 | case 0x1b: /* Line In */ | ||
| 4088 | idx = 3; | ||
| 4089 | break; | ||
| 4090 | |||
| 4091 | case 0x1e: /* Front Mic */ | ||
| 4092 | idx = 4; | ||
| 4093 | break; | ||
| 4094 | |||
| 4095 | case 0x1f: /* CD */ | ||
| 4096 | idx = 1; | ||
| 4097 | break; | ||
| 4098 | } | ||
| 4099 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
| 4100 | if (err < 0) | ||
| 4101 | return err; | ||
| 4102 | imux->items[imux->num_items].label = labels[i]; | ||
| 4103 | imux->items[imux->num_items].index = idx-1; | ||
| 4104 | imux->num_items++; | ||
| 4105 | } | ||
| 4106 | return 0; | ||
| 4107 | } | 3992 | } |
| 4108 | 3993 | ||
| 4109 | /* fill out digital output widgets; one for master and one for slave outputs */ | 3994 | /* fill out digital output widgets; one for master and one for slave outputs */ |
| @@ -4151,7 +4036,7 @@ static int vt1708S_parse_auto_config(struct hda_codec *codec) | |||
| 4151 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 4036 | err = vt1708S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 4152 | if (err < 0) | 4037 | if (err < 0) |
| 4153 | return err; | 4038 | return err; |
| 4154 | err = vt1708S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4039 | err = vt1708S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 4155 | if (err < 0) | 4040 | if (err < 0) |
| 4156 | return err; | 4041 | return err; |
| 4157 | 4042 | ||
| @@ -4441,58 +4326,20 @@ static int vt1702_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 4441 | imux = &spec->private_imux[1]; | 4326 | imux = &spec->private_imux[1]; |
| 4442 | 4327 | ||
| 4443 | /* for hp mode select */ | 4328 | /* for hp mode select */ |
| 4444 | i = 0; | 4329 | for (i = 0; texts[i]; i++) |
| 4445 | while (texts[i] != NULL) { | 4330 | snd_hda_add_imux_item(imux, texts[i], i, NULL); |
| 4446 | imux->items[imux->num_items].label = texts[i]; | ||
| 4447 | imux->items[imux->num_items].index = i; | ||
| 4448 | imux->num_items++; | ||
| 4449 | i++; | ||
| 4450 | } | ||
| 4451 | 4331 | ||
| 4452 | spec->hp_mux = &spec->private_imux[1]; | 4332 | spec->hp_mux = &spec->private_imux[1]; |
| 4453 | return 0; | 4333 | return 0; |
| 4454 | } | 4334 | } |
| 4455 | 4335 | ||
| 4456 | /* create playback/capture controls for input pins */ | 4336 | /* create playback/capture controls for input pins */ |
| 4457 | static int vt1702_auto_create_analog_input_ctls(struct via_spec *spec, | 4337 | static int vt1702_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 4458 | const struct auto_pin_cfg *cfg) | 4338 | const struct auto_pin_cfg *cfg) |
| 4459 | { | 4339 | { |
| 4460 | static char *labels[] = { | 4340 | static hda_nid_t pin_idxs[] = { 0x14, 0x15, 0x18, 0xff }; |
| 4461 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4341 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x1a, pin_idxs, |
| 4462 | }; | 4342 | ARRAY_SIZE(pin_idxs)); |
| 4463 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 4464 | int i, err, idx = 0; | ||
| 4465 | |||
| 4466 | /* for internal loopback recording select */ | ||
| 4467 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 4468 | imux->items[imux->num_items].index = 3; | ||
| 4469 | imux->num_items++; | ||
| 4470 | |||
| 4471 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 4472 | if (!cfg->input_pins[i]) | ||
| 4473 | continue; | ||
| 4474 | |||
| 4475 | switch (cfg->input_pins[i]) { | ||
| 4476 | case 0x14: /* Mic */ | ||
| 4477 | idx = 1; | ||
| 4478 | break; | ||
| 4479 | |||
| 4480 | case 0x15: /* Line In */ | ||
| 4481 | idx = 2; | ||
| 4482 | break; | ||
| 4483 | |||
| 4484 | case 0x18: /* Front Mic */ | ||
| 4485 | idx = 3; | ||
| 4486 | break; | ||
| 4487 | } | ||
| 4488 | err = via_new_analog_input(spec, labels[i], idx, 0x1A); | ||
| 4489 | if (err < 0) | ||
| 4490 | return err; | ||
| 4491 | imux->items[imux->num_items].label = labels[i]; | ||
| 4492 | imux->items[imux->num_items].index = idx-1; | ||
| 4493 | imux->num_items++; | ||
| 4494 | } | ||
| 4495 | return 0; | ||
| 4496 | } | 4343 | } |
| 4497 | 4344 | ||
| 4498 | static int vt1702_parse_auto_config(struct hda_codec *codec) | 4345 | static int vt1702_parse_auto_config(struct hda_codec *codec) |
| @@ -4521,7 +4368,7 @@ static int vt1702_parse_auto_config(struct hda_codec *codec) | |||
| 4521 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | | 4368 | (0x17 << AC_AMPCAP_NUM_STEPS_SHIFT) | |
| 4522 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | | 4369 | (0x5 << AC_AMPCAP_STEP_SIZE_SHIFT) | |
| 4523 | (1 << AC_AMPCAP_MUTE_SHIFT)); | 4370 | (1 << AC_AMPCAP_MUTE_SHIFT)); |
| 4524 | err = vt1702_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4371 | err = vt1702_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 4525 | if (err < 0) | 4372 | if (err < 0) |
| 4526 | return err; | 4373 | return err; |
| 4527 | 4374 | ||
| @@ -4872,49 +4719,12 @@ static int vt1718S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 4872 | } | 4719 | } |
| 4873 | 4720 | ||
| 4874 | /* create playback/capture controls for input pins */ | 4721 | /* create playback/capture controls for input pins */ |
| 4875 | static int vt1718S_auto_create_analog_input_ctls(struct via_spec *spec, | 4722 | static int vt1718S_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 4876 | const struct auto_pin_cfg *cfg) | 4723 | const struct auto_pin_cfg *cfg) |
| 4877 | { | 4724 | { |
| 4878 | static char *labels[] = { | 4725 | static hda_nid_t pin_idxs[] = { 0x2c, 0x2b, 0x2a, 0x29, 0, 0xff }; |
| 4879 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 4726 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
| 4880 | }; | 4727 | ARRAY_SIZE(pin_idxs)); |
| 4881 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 4882 | int i, err, idx = 0; | ||
| 4883 | |||
| 4884 | /* for internal loopback recording select */ | ||
| 4885 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 4886 | imux->items[imux->num_items].index = 5; | ||
| 4887 | imux->num_items++; | ||
| 4888 | |||
| 4889 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 4890 | if (!cfg->input_pins[i]) | ||
| 4891 | continue; | ||
| 4892 | |||
| 4893 | switch (cfg->input_pins[i]) { | ||
| 4894 | case 0x2b: /* Mic */ | ||
| 4895 | idx = 1; | ||
| 4896 | break; | ||
| 4897 | |||
| 4898 | case 0x2a: /* Line In */ | ||
| 4899 | idx = 2; | ||
| 4900 | break; | ||
| 4901 | |||
| 4902 | case 0x29: /* Front Mic */ | ||
| 4903 | idx = 3; | ||
| 4904 | break; | ||
| 4905 | |||
| 4906 | case 0x2c: /* CD */ | ||
| 4907 | idx = 0; | ||
| 4908 | break; | ||
| 4909 | } | ||
| 4910 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
| 4911 | if (err < 0) | ||
| 4912 | return err; | ||
| 4913 | imux->items[imux->num_items].label = labels[i]; | ||
| 4914 | imux->items[imux->num_items].index = idx; | ||
| 4915 | imux->num_items++; | ||
| 4916 | } | ||
| 4917 | return 0; | ||
| 4918 | } | 4728 | } |
| 4919 | 4729 | ||
| 4920 | static int vt1718S_parse_auto_config(struct hda_codec *codec) | 4730 | static int vt1718S_parse_auto_config(struct hda_codec *codec) |
| @@ -4938,7 +4748,7 @@ static int vt1718S_parse_auto_config(struct hda_codec *codec) | |||
| 4938 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 4748 | err = vt1718S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 4939 | if (err < 0) | 4749 | if (err < 0) |
| 4940 | return err; | 4750 | return err; |
| 4941 | err = vt1718S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 4751 | err = vt1718S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 4942 | if (err < 0) | 4752 | if (err < 0) |
| 4943 | return err; | 4753 | return err; |
| 4944 | 4754 | ||
| @@ -5371,49 +5181,12 @@ static int vt1716S_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 5371 | } | 5181 | } |
| 5372 | 5182 | ||
| 5373 | /* create playback/capture controls for input pins */ | 5183 | /* create playback/capture controls for input pins */ |
| 5374 | static int vt1716S_auto_create_analog_input_ctls(struct via_spec *spec, | 5184 | static int vt1716S_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 5375 | const struct auto_pin_cfg *cfg) | 5185 | const struct auto_pin_cfg *cfg) |
| 5376 | { | 5186 | { |
| 5377 | static char *labels[] = { | 5187 | static hda_nid_t pin_idxs[] = { 0x1f, 0x1a, 0x1b, 0x1e, 0, 0xff }; |
| 5378 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | 5188 | return vt_auto_create_analog_input_ctls(codec, cfg, 0x16, pin_idxs, |
| 5379 | }; | 5189 | ARRAY_SIZE(pin_idxs)); |
| 5380 | struct hda_input_mux *imux = &spec->private_imux[0]; | ||
| 5381 | int i, err, idx = 0; | ||
| 5382 | |||
| 5383 | /* for internal loopback recording select */ | ||
| 5384 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 5385 | imux->items[imux->num_items].index = 5; | ||
| 5386 | imux->num_items++; | ||
| 5387 | |||
| 5388 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 5389 | if (!cfg->input_pins[i]) | ||
| 5390 | continue; | ||
| 5391 | |||
| 5392 | switch (cfg->input_pins[i]) { | ||
| 5393 | case 0x1a: /* Mic */ | ||
| 5394 | idx = 2; | ||
| 5395 | break; | ||
| 5396 | |||
| 5397 | case 0x1b: /* Line In */ | ||
| 5398 | idx = 3; | ||
| 5399 | break; | ||
| 5400 | |||
| 5401 | case 0x1e: /* Front Mic */ | ||
| 5402 | idx = 4; | ||
| 5403 | break; | ||
| 5404 | |||
| 5405 | case 0x1f: /* CD */ | ||
| 5406 | idx = 1; | ||
| 5407 | break; | ||
| 5408 | } | ||
| 5409 | err = via_new_analog_input(spec, labels[i], idx, 0x16); | ||
| 5410 | if (err < 0) | ||
| 5411 | return err; | ||
| 5412 | imux->items[imux->num_items].label = labels[i]; | ||
| 5413 | imux->items[imux->num_items].index = idx-1; | ||
| 5414 | imux->num_items++; | ||
| 5415 | } | ||
| 5416 | return 0; | ||
| 5417 | } | 5190 | } |
| 5418 | 5191 | ||
| 5419 | static int vt1716S_parse_auto_config(struct hda_codec *codec) | 5192 | static int vt1716S_parse_auto_config(struct hda_codec *codec) |
| @@ -5436,7 +5209,7 @@ static int vt1716S_parse_auto_config(struct hda_codec *codec) | |||
| 5436 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5209 | err = vt1716S_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 5437 | if (err < 0) | 5210 | if (err < 0) |
| 5438 | return err; | 5211 | return err; |
| 5439 | err = vt1716S_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5212 | err = vt1716S_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 5440 | if (err < 0) | 5213 | if (err < 0) |
| 5441 | return err; | 5214 | return err; |
| 5442 | 5215 | ||
| @@ -5717,54 +5490,25 @@ static int vt2002P_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 5717 | } | 5490 | } |
| 5718 | 5491 | ||
| 5719 | /* create playback/capture controls for input pins */ | 5492 | /* create playback/capture controls for input pins */ |
| 5720 | static int vt2002P_auto_create_analog_input_ctls(struct via_spec *spec, | 5493 | static int vt2002P_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 5721 | const struct auto_pin_cfg *cfg) | 5494 | const struct auto_pin_cfg *cfg) |
| 5722 | { | 5495 | { |
| 5723 | static char *labels[] = { | 5496 | struct via_spec *spec = codec->spec; |
| 5724 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
| 5725 | }; | ||
| 5726 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5497 | struct hda_input_mux *imux = &spec->private_imux[0]; |
| 5727 | int i, err, idx = 0; | 5498 | static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0xff }; |
| 5728 | 5499 | int err; | |
| 5729 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 5730 | if (!cfg->input_pins[i]) | ||
| 5731 | continue; | ||
| 5732 | |||
| 5733 | switch (cfg->input_pins[i]) { | ||
| 5734 | case 0x2b: /* Mic */ | ||
| 5735 | idx = 0; | ||
| 5736 | break; | ||
| 5737 | |||
| 5738 | case 0x2a: /* Line In */ | ||
| 5739 | idx = 1; | ||
| 5740 | break; | ||
| 5741 | |||
| 5742 | case 0x29: /* Front Mic */ | ||
| 5743 | idx = 2; | ||
| 5744 | break; | ||
| 5745 | } | ||
| 5746 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
| 5747 | if (err < 0) | ||
| 5748 | return err; | ||
| 5749 | imux->items[imux->num_items].label = labels[i]; | ||
| 5750 | imux->items[imux->num_items].index = idx; | ||
| 5751 | imux->num_items++; | ||
| 5752 | } | ||
| 5753 | 5500 | ||
| 5501 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, | ||
| 5502 | ARRAY_SIZE(pin_idxs)); | ||
| 5503 | if (err < 0) | ||
| 5504 | return err; | ||
| 5754 | /* build volume/mute control of loopback */ | 5505 | /* build volume/mute control of loopback */ |
| 5755 | err = via_new_analog_input(spec, "Stereo Mixer", 3, 0x21); | 5506 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 3, 0x21); |
| 5756 | if (err < 0) | 5507 | if (err < 0) |
| 5757 | return err; | 5508 | return err; |
| 5758 | 5509 | ||
| 5759 | /* for internal loopback recording select */ | ||
| 5760 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 5761 | imux->items[imux->num_items].index = 3; | ||
| 5762 | imux->num_items++; | ||
| 5763 | |||
| 5764 | /* for digital mic select */ | 5510 | /* for digital mic select */ |
| 5765 | imux->items[imux->num_items].label = "Digital Mic"; | 5511 | snd_hda_add_imux_item(imux, "Digital Mic", 4, NULL); |
| 5766 | imux->items[imux->num_items].index = 4; | ||
| 5767 | imux->num_items++; | ||
| 5768 | 5512 | ||
| 5769 | return 0; | 5513 | return 0; |
| 5770 | } | 5514 | } |
| @@ -5792,7 +5536,7 @@ static int vt2002P_parse_auto_config(struct hda_codec *codec) | |||
| 5792 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5536 | err = vt2002P_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 5793 | if (err < 0) | 5537 | if (err < 0) |
| 5794 | return err; | 5538 | return err; |
| 5795 | err = vt2002P_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5539 | err = vt2002P_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 5796 | if (err < 0) | 5540 | if (err < 0) |
| 5797 | return err; | 5541 | return err; |
| 5798 | 5542 | ||
| @@ -6067,53 +5811,26 @@ static int vt1812_auto_create_hp_ctls(struct via_spec *spec, hda_nid_t pin) | |||
| 6067 | } | 5811 | } |
| 6068 | 5812 | ||
| 6069 | /* create playback/capture controls for input pins */ | 5813 | /* create playback/capture controls for input pins */ |
| 6070 | static int vt1812_auto_create_analog_input_ctls(struct via_spec *spec, | 5814 | static int vt1812_auto_create_analog_input_ctls(struct hda_codec *codec, |
| 6071 | const struct auto_pin_cfg *cfg) | 5815 | const struct auto_pin_cfg *cfg) |
| 6072 | { | 5816 | { |
| 6073 | static char *labels[] = { | 5817 | struct via_spec *spec = codec->spec; |
| 6074 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux", NULL | ||
| 6075 | }; | ||
| 6076 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5818 | struct hda_input_mux *imux = &spec->private_imux[0]; |
| 6077 | int i, err, idx = 0; | 5819 | static hda_nid_t pin_idxs[] = { 0x2b, 0x2a, 0x29, 0, 0, 0xff }; |
| 6078 | 5820 | int err; | |
| 6079 | for (i = 0; i < AUTO_PIN_LAST; i++) { | ||
| 6080 | if (!cfg->input_pins[i]) | ||
| 6081 | continue; | ||
| 6082 | |||
| 6083 | switch (cfg->input_pins[i]) { | ||
| 6084 | case 0x2b: /* Mic */ | ||
| 6085 | idx = 0; | ||
| 6086 | break; | ||
| 6087 | 5821 | ||
| 6088 | case 0x2a: /* Line In */ | 5822 | err = vt_auto_create_analog_input_ctls(codec, cfg, 0x21, pin_idxs, |
| 6089 | idx = 1; | 5823 | ARRAY_SIZE(pin_idxs)); |
| 6090 | break; | 5824 | if (err < 0) |
| 5825 | return err; | ||
| 6091 | 5826 | ||
| 6092 | case 0x29: /* Front Mic */ | ||
| 6093 | idx = 2; | ||
| 6094 | break; | ||
| 6095 | } | ||
| 6096 | err = via_new_analog_input(spec, labels[i], idx, 0x21); | ||
| 6097 | if (err < 0) | ||
| 6098 | return err; | ||
| 6099 | imux->items[imux->num_items].label = labels[i]; | ||
| 6100 | imux->items[imux->num_items].index = idx; | ||
| 6101 | imux->num_items++; | ||
| 6102 | } | ||
| 6103 | /* build volume/mute control of loopback */ | 5827 | /* build volume/mute control of loopback */ |
| 6104 | err = via_new_analog_input(spec, "Stereo Mixer", 5, 0x21); | 5828 | err = via_new_analog_input(spec, "Stereo Mixer", 0, 5, 0x21); |
| 6105 | if (err < 0) | 5829 | if (err < 0) |
| 6106 | return err; | 5830 | return err; |
| 6107 | 5831 | ||
| 6108 | /* for internal loopback recording select */ | ||
| 6109 | imux->items[imux->num_items].label = "Stereo Mixer"; | ||
| 6110 | imux->items[imux->num_items].index = 5; | ||
| 6111 | imux->num_items++; | ||
| 6112 | |||
| 6113 | /* for digital mic select */ | 5832 | /* for digital mic select */ |
| 6114 | imux->items[imux->num_items].label = "Digital Mic"; | 5833 | snd_hda_add_imux_item(imux, "Digital Mic", 6, NULL); |
| 6115 | imux->items[imux->num_items].index = 6; | ||
| 6116 | imux->num_items++; | ||
| 6117 | 5834 | ||
| 6118 | return 0; | 5835 | return 0; |
| 6119 | } | 5836 | } |
| @@ -6141,7 +5858,7 @@ static int vt1812_parse_auto_config(struct hda_codec *codec) | |||
| 6141 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); | 5858 | err = vt1812_auto_create_hp_ctls(spec, spec->autocfg.hp_pins[0]); |
| 6142 | if (err < 0) | 5859 | if (err < 0) |
| 6143 | return err; | 5860 | return err; |
| 6144 | err = vt1812_auto_create_analog_input_ctls(spec, &spec->autocfg); | 5861 | err = vt1812_auto_create_analog_input_ctls(codec, &spec->autocfg); |
| 6145 | if (err < 0) | 5862 | if (err < 0) |
| 6146 | return err; | 5863 | return err; |
| 6147 | 5864 | ||
