diff options
Diffstat (limited to 'sound')
-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 | 260 | ||||
-rw-r--r-- | sound/pci/hda/hda_codec.h | 12 | ||||
-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 | 18 | ||||
-rw-r--r-- | sound/pci/hda/hda_local.h | 37 | ||||
-rw-r--r-- | sound/pci/hda/patch_analog.c | 41 | ||||
-rw-r--r-- | sound/pci/hda/patch_atihdmi.c | 224 | ||||
-rw-r--r-- | sound/pci/hda/patch_ca0110.c | 8 | ||||
-rw-r--r-- | sound/pci/hda/patch_cirrus.c | 44 | ||||
-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 | 834 | ||||
-rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 371 | ||||
-rw-r--r-- | sound/pci/hda/patch_via.c | 587 |
19 files changed, 2629 insertions, 2185 deletions
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..053f827d2c2c 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -2228,10 +2228,7 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2228 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, | 2228 | change |= snd_hda_codec_amp_update(codec, nid, 1, dir, idx, |
2229 | HDA_AMP_MUTE, | 2229 | HDA_AMP_MUTE, |
2230 | *valp ? 0 : HDA_AMP_MUTE); | 2230 | *valp ? 0 : HDA_AMP_MUTE); |
2231 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 2231 | 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); | 2232 | snd_hda_power_down(codec); |
2236 | return change; | 2233 | return change; |
2237 | } | 2234 | } |
@@ -4372,6 +4369,34 @@ static void sort_pins_by_sequence(hda_nid_t *pins, short *sequences, | |||
4372 | } | 4369 | } |
4373 | 4370 | ||
4374 | 4371 | ||
4372 | /* add the found input-pin to the cfg->inputs[] table */ | ||
4373 | static void add_auto_cfg_input_pin(struct auto_pin_cfg *cfg, hda_nid_t nid, | ||
4374 | int type) | ||
4375 | { | ||
4376 | if (cfg->num_inputs < AUTO_CFG_MAX_INS) { | ||
4377 | cfg->inputs[cfg->num_inputs].pin = nid; | ||
4378 | cfg->inputs[cfg->num_inputs].type = type; | ||
4379 | cfg->num_inputs++; | ||
4380 | } | ||
4381 | } | ||
4382 | |||
4383 | /* sort inputs in the order of AUTO_PIN_* type */ | ||
4384 | static void sort_autocfg_input_pins(struct auto_pin_cfg *cfg) | ||
4385 | { | ||
4386 | int i, j; | ||
4387 | |||
4388 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4389 | for (j = i + 1; j < cfg->num_inputs; j++) { | ||
4390 | if (cfg->inputs[i].type > cfg->inputs[j].type) { | ||
4391 | struct auto_pin_cfg_item tmp; | ||
4392 | tmp = cfg->inputs[i]; | ||
4393 | cfg->inputs[i] = cfg->inputs[j]; | ||
4394 | cfg->inputs[j] = tmp; | ||
4395 | } | ||
4396 | } | ||
4397 | } | ||
4398 | } | ||
4399 | |||
4375 | /* | 4400 | /* |
4376 | * Parse all pin widgets and store the useful pin nids to cfg | 4401 | * Parse all pin widgets and store the useful pin nids to cfg |
4377 | * | 4402 | * |
@@ -4385,7 +4410,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 | 4410 | * output, i.e. to line_out_pins[0]. So, line_outs is always positive |
4386 | * if any analog output exists. | 4411 | * if any analog output exists. |
4387 | * | 4412 | * |
4388 | * The analog input pins are assigned to input_pins array. | 4413 | * 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, | 4414 | * The digital input/output pins are assigned to dig_in_pin and dig_out_pin, |
4390 | * respectively. | 4415 | * respectively. |
4391 | */ | 4416 | */ |
@@ -4398,6 +4423,7 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4398 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; | 4423 | short sequences_line_out[ARRAY_SIZE(cfg->line_out_pins)]; |
4399 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; | 4424 | short sequences_speaker[ARRAY_SIZE(cfg->speaker_pins)]; |
4400 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; | 4425 | short sequences_hp[ARRAY_SIZE(cfg->hp_pins)]; |
4426 | int i; | ||
4401 | 4427 | ||
4402 | memset(cfg, 0, sizeof(*cfg)); | 4428 | memset(cfg, 0, sizeof(*cfg)); |
4403 | 4429 | ||
@@ -4468,33 +4494,17 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4468 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; | 4494 | sequences_hp[cfg->hp_outs] = (assoc << 4) | seq; |
4469 | cfg->hp_outs++; | 4495 | cfg->hp_outs++; |
4470 | break; | 4496 | break; |
4471 | case AC_JACK_MIC_IN: { | 4497 | case AC_JACK_MIC_IN: |
4472 | int preferred, alt; | 4498 | 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; | 4499 | break; |
4486 | } | ||
4487 | case AC_JACK_LINE_IN: | 4500 | case AC_JACK_LINE_IN: |
4488 | if (loc == AC_JACK_LOC_FRONT) | 4501 | 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; | 4502 | break; |
4493 | case AC_JACK_CD: | 4503 | case AC_JACK_CD: |
4494 | cfg->input_pins[AUTO_PIN_CD] = nid; | 4504 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_CD); |
4495 | break; | 4505 | break; |
4496 | case AC_JACK_AUX: | 4506 | case AC_JACK_AUX: |
4497 | cfg->input_pins[AUTO_PIN_AUX] = nid; | 4507 | add_auto_cfg_input_pin(cfg, nid, AUTO_PIN_AUX); |
4498 | break; | 4508 | break; |
4499 | case AC_JACK_SPDIF_OUT: | 4509 | case AC_JACK_SPDIF_OUT: |
4500 | case AC_JACK_DIG_OTHER_OUT: | 4510 | case AC_JACK_DIG_OTHER_OUT: |
@@ -4539,6 +4549,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4539 | memmove(sequences_hp + i, sequences_hp + i + 1, | 4549 | memmove(sequences_hp + i, sequences_hp + i + 1, |
4540 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); | 4550 | sizeof(sequences_hp[0]) * (cfg->hp_outs - i)); |
4541 | } | 4551 | } |
4552 | memset(cfg->hp_pins + cfg->hp_outs, 0, | ||
4553 | sizeof(hda_nid_t) * (AUTO_CFG_MAX_OUTS - cfg->hp_outs)); | ||
4542 | } | 4554 | } |
4543 | 4555 | ||
4544 | /* sort by sequence */ | 4556 | /* sort by sequence */ |
@@ -4549,21 +4561,6 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4549 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, | 4561 | sort_pins_by_sequence(cfg->hp_pins, sequences_hp, |
4550 | cfg->hp_outs); | 4562 | cfg->hp_outs); |
4551 | 4563 | ||
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 | /* | 4564 | /* |
4568 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin | 4565 | * FIX-UP: if no line-outs are detected, try to use speaker or HP pin |
4569 | * as a primary output | 4566 | * as a primary output |
@@ -4602,6 +4599,8 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4602 | break; | 4599 | break; |
4603 | } | 4600 | } |
4604 | 4601 | ||
4602 | sort_autocfg_input_pins(cfg); | ||
4603 | |||
4605 | /* | 4604 | /* |
4606 | * debug prints of the parsed results | 4605 | * debug prints of the parsed results |
4607 | */ | 4606 | */ |
@@ -4621,14 +4620,13 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4621 | if (cfg->dig_outs) | 4620 | if (cfg->dig_outs) |
4622 | snd_printd(" dig-out=0x%x/0x%x\n", | 4621 | snd_printd(" dig-out=0x%x/0x%x\n", |
4623 | cfg->dig_out_pins[0], cfg->dig_out_pins[1]); | 4622 | 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," | 4623 | snd_printd(" inputs:"); |
4625 | " cd=0x%x, aux=0x%x\n", | 4624 | for (i = 0; i < cfg->num_inputs; i++) { |
4626 | cfg->input_pins[AUTO_PIN_MIC], | 4625 | snd_printdd(" %s=0x%x", |
4627 | cfg->input_pins[AUTO_PIN_FRONT_MIC], | 4626 | hda_get_autocfg_input_label(codec, cfg, i), |
4628 | cfg->input_pins[AUTO_PIN_LINE], | 4627 | cfg->inputs[i].pin); |
4629 | cfg->input_pins[AUTO_PIN_FRONT_LINE], | 4628 | } |
4630 | cfg->input_pins[AUTO_PIN_CD], | 4629 | snd_printd("\n"); |
4631 | cfg->input_pins[AUTO_PIN_AUX]); | ||
4632 | if (cfg->dig_in_pin) | 4630 | if (cfg->dig_in_pin) |
4633 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); | 4631 | snd_printd(" dig-in=0x%x\n", cfg->dig_in_pin); |
4634 | 4632 | ||
@@ -4636,11 +4634,165 @@ int snd_hda_parse_pin_def_config(struct hda_codec *codec, | |||
4636 | } | 4634 | } |
4637 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); | 4635 | EXPORT_SYMBOL_HDA(snd_hda_parse_pin_def_config); |
4638 | 4636 | ||
4639 | /* labels for input pins */ | 4637 | int snd_hda_get_input_pin_attr(unsigned int def_conf) |
4640 | const char *auto_pin_cfg_labels[AUTO_PIN_LAST] = { | 4638 | { |
4641 | "Mic", "Front Mic", "Line", "Front Line", "CD", "Aux" | 4639 | unsigned int loc = get_defcfg_location(def_conf); |
4642 | }; | 4640 | unsigned int conn = get_defcfg_connect(def_conf); |
4643 | EXPORT_SYMBOL_HDA(auto_pin_cfg_labels); | 4641 | if (conn == AC_JACK_PORT_NONE) |
4642 | return INPUT_PIN_ATTR_UNUSED; | ||
4643 | /* Windows may claim the internal mic to be BOTH, too */ | ||
4644 | if (conn == AC_JACK_PORT_FIXED || conn == AC_JACK_PORT_BOTH) | ||
4645 | return INPUT_PIN_ATTR_INT; | ||
4646 | if ((loc & 0x30) == AC_JACK_LOC_INTERNAL) | ||
4647 | return INPUT_PIN_ATTR_INT; | ||
4648 | if ((loc & 0x30) == AC_JACK_LOC_SEPARATE) | ||
4649 | return INPUT_PIN_ATTR_DOCK; | ||
4650 | if (loc == AC_JACK_LOC_REAR) | ||
4651 | return INPUT_PIN_ATTR_REAR; | ||
4652 | if (loc == AC_JACK_LOC_FRONT) | ||
4653 | return INPUT_PIN_ATTR_FRONT; | ||
4654 | return INPUT_PIN_ATTR_NORMAL; | ||
4655 | } | ||
4656 | EXPORT_SYMBOL_HDA(snd_hda_get_input_pin_attr); | ||
4657 | |||
4658 | /** | ||
4659 | * hda_get_input_pin_label - Give a label for the given input pin | ||
4660 | * | ||
4661 | * When check_location is true, the function checks the pin location | ||
4662 | * for mic and line-in pins, and set an appropriate prefix like "Front", | ||
4663 | * "Rear", "Internal". | ||
4664 | */ | ||
4665 | |||
4666 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
4667 | int check_location) | ||
4668 | { | ||
4669 | unsigned int def_conf; | ||
4670 | static const char *mic_names[] = { | ||
4671 | "Internal Mic", "Dock Mic", "Mic", "Front Mic", "Rear Mic", | ||
4672 | }; | ||
4673 | int attr; | ||
4674 | |||
4675 | def_conf = snd_hda_codec_get_pincfg(codec, pin); | ||
4676 | |||
4677 | switch (get_defcfg_device(def_conf)) { | ||
4678 | case AC_JACK_MIC_IN: | ||
4679 | if (!check_location) | ||
4680 | return "Mic"; | ||
4681 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4682 | if (!attr) | ||
4683 | return "None"; | ||
4684 | return mic_names[attr - 1]; | ||
4685 | case AC_JACK_LINE_IN: | ||
4686 | if (!check_location) | ||
4687 | return "Line"; | ||
4688 | attr = snd_hda_get_input_pin_attr(def_conf); | ||
4689 | if (!attr) | ||
4690 | return "None"; | ||
4691 | if (attr == INPUT_PIN_ATTR_DOCK) | ||
4692 | return "Dock Line"; | ||
4693 | return "Line"; | ||
4694 | case AC_JACK_AUX: | ||
4695 | return "Aux"; | ||
4696 | case AC_JACK_CD: | ||
4697 | return "CD"; | ||
4698 | case AC_JACK_SPDIF_IN: | ||
4699 | return "SPDIF In"; | ||
4700 | case AC_JACK_DIG_OTHER_IN: | ||
4701 | return "Digital In"; | ||
4702 | default: | ||
4703 | return "Misc"; | ||
4704 | } | ||
4705 | } | ||
4706 | EXPORT_SYMBOL_HDA(hda_get_input_pin_label); | ||
4707 | |||
4708 | /* Check whether the location prefix needs to be added to the label. | ||
4709 | * If all mic-jacks are in the same location (e.g. rear panel), we don't | ||
4710 | * have to put "Front" prefix to each label. In such a case, returns false. | ||
4711 | */ | ||
4712 | static int check_mic_location_need(struct hda_codec *codec, | ||
4713 | const struct auto_pin_cfg *cfg, | ||
4714 | int input) | ||
4715 | { | ||
4716 | unsigned int defc; | ||
4717 | int i, attr, attr2; | ||
4718 | |||
4719 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[input].pin); | ||
4720 | attr = snd_hda_get_input_pin_attr(defc); | ||
4721 | /* for internal or docking mics, we need locations */ | ||
4722 | if (attr <= INPUT_PIN_ATTR_NORMAL) | ||
4723 | return 1; | ||
4724 | |||
4725 | attr = 0; | ||
4726 | for (i = 0; i < cfg->num_inputs; i++) { | ||
4727 | defc = snd_hda_codec_get_pincfg(codec, cfg->inputs[i].pin); | ||
4728 | attr2 = snd_hda_get_input_pin_attr(defc); | ||
4729 | if (attr2 >= INPUT_PIN_ATTR_NORMAL) { | ||
4730 | if (attr && attr != attr2) | ||
4731 | return 1; /* different locations found */ | ||
4732 | attr = attr2; | ||
4733 | } | ||
4734 | } | ||
4735 | return 0; | ||
4736 | } | ||
4737 | |||
4738 | /** | ||
4739 | * hda_get_autocfg_input_label - Get a label for the given input | ||
4740 | * | ||
4741 | * Get a label for the given input pin defined by the autocfg item. | ||
4742 | * Unlike hda_get_input_pin_label(), this function checks all inputs | ||
4743 | * defined in autocfg and avoids the redundant mic/line prefix as much as | ||
4744 | * possible. | ||
4745 | */ | ||
4746 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
4747 | const struct auto_pin_cfg *cfg, | ||
4748 | int input) | ||
4749 | { | ||
4750 | int type = cfg->inputs[input].type; | ||
4751 | int has_multiple_pins = 0; | ||
4752 | |||
4753 | if ((input > 0 && cfg->inputs[input - 1].type == type) || | ||
4754 | (input < cfg->num_inputs - 1 && cfg->inputs[input + 1].type == type)) | ||
4755 | has_multiple_pins = 1; | ||
4756 | if (has_multiple_pins && type == AUTO_PIN_MIC) | ||
4757 | has_multiple_pins &= check_mic_location_need(codec, cfg, input); | ||
4758 | return hda_get_input_pin_label(codec, cfg->inputs[input].pin, | ||
4759 | has_multiple_pins); | ||
4760 | } | ||
4761 | EXPORT_SYMBOL_HDA(hda_get_autocfg_input_label); | ||
4762 | |||
4763 | /** | ||
4764 | * snd_hda_add_imux_item - Add an item to input_mux | ||
4765 | * | ||
4766 | * When the same label is used already in the existing items, the number | ||
4767 | * suffix is appended to the label. This label index number is stored | ||
4768 | * to type_idx when non-NULL pointer is given. | ||
4769 | */ | ||
4770 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
4771 | int index, int *type_idx) | ||
4772 | { | ||
4773 | int i, label_idx = 0; | ||
4774 | if (imux->num_items >= HDA_MAX_NUM_INPUTS) { | ||
4775 | snd_printd(KERN_ERR "hda_codec: Too many imux items!\n"); | ||
4776 | return -EINVAL; | ||
4777 | } | ||
4778 | for (i = 0; i < imux->num_items; i++) { | ||
4779 | if (!strncmp(label, imux->items[i].label, strlen(label))) | ||
4780 | label_idx++; | ||
4781 | } | ||
4782 | if (type_idx) | ||
4783 | *type_idx = label_idx; | ||
4784 | if (label_idx > 0) | ||
4785 | snprintf(imux->items[imux->num_items].label, | ||
4786 | sizeof(imux->items[imux->num_items].label), | ||
4787 | "%s %d", label, label_idx); | ||
4788 | else | ||
4789 | strlcpy(imux->items[imux->num_items].label, label, | ||
4790 | sizeof(imux->items[imux->num_items].label)); | ||
4791 | imux->items[imux->num_items].index = index; | ||
4792 | imux->num_items++; | ||
4793 | return 0; | ||
4794 | } | ||
4795 | EXPORT_SYMBOL_HDA(snd_hda_add_imux_item); | ||
4644 | 4796 | ||
4645 | 4797 | ||
4646 | #ifdef CONFIG_PM | 4798 | #ifdef CONFIG_PM |
diff --git a/sound/pci/hda/hda_codec.h b/sound/pci/hda/hda_codec.h index 62c702240108..ebf8eb02e3c2 100644 --- a/sound/pci/hda/hda_codec.h +++ b/sound/pci/hda/hda_codec.h | |||
@@ -989,6 +989,18 @@ int snd_hda_suspend(struct hda_bus *bus); | |||
989 | int snd_hda_resume(struct hda_bus *bus); | 989 | int snd_hda_resume(struct hda_bus *bus); |
990 | #endif | 990 | #endif |
991 | 991 | ||
992 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
993 | static inline | ||
994 | int hda_call_check_power_status(struct hda_codec *codec, hda_nid_t nid) | ||
995 | { | ||
996 | if (codec->patch_ops.check_power_status) | ||
997 | return codec->patch_ops.check_power_status(codec, nid); | ||
998 | return 0; | ||
999 | } | ||
1000 | #else | ||
1001 | #define hda_call_check_power_status(codec, nid) 0 | ||
1002 | #endif | ||
1003 | |||
992 | /* | 1004 | /* |
993 | * get widget information | 1005 | * get widget information |
994 | */ | 1006 | */ |
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..5f6f9039a41a 100644 --- a/sound/pci/hda/hda_intel.c +++ b/sound/pci/hda/hda_intel.c | |||
@@ -2735,25 +2735,17 @@ static void __devexit azx_remove(struct pci_dev *pci) | |||
2735 | 2735 | ||
2736 | /* PCI IDs */ | 2736 | /* PCI IDs */ |
2737 | static DEFINE_PCI_DEVICE_TABLE(azx_ids) = { | 2737 | 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 */ | 2738 | /* CPT */ |
2752 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, | 2739 | { PCI_DEVICE(0x8086, 0x1c20), .driver_data = AZX_DRIVER_PCH }, |
2753 | /* PBG */ | 2740 | /* PBG */ |
2754 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, | 2741 | { PCI_DEVICE(0x8086, 0x1d20), .driver_data = AZX_DRIVER_PCH }, |
2755 | /* SCH */ | 2742 | /* SCH */ |
2756 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, | 2743 | { PCI_DEVICE(0x8086, 0x811b), .driver_data = AZX_DRIVER_SCH }, |
2744 | /* Generic Intel */ | ||
2745 | { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_ANY_ID), | ||
2746 | .class = PCI_CLASS_MULTIMEDIA_HD_AUDIO << 8, | ||
2747 | .class_mask = 0xffffff, | ||
2748 | .driver_data = AZX_DRIVER_ICH }, | ||
2757 | /* ATI SB 450/600 */ | 2749 | /* ATI SB 450/600 */ |
2758 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, | 2750 | { PCI_DEVICE(0x1002, 0x437b), .driver_data = AZX_DRIVER_ATI }, |
2759 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, | 2751 | { PCI_DEVICE(0x1002, 0x4383), .driver_data = AZX_DRIVER_ATI }, |
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h index 28ab4aead48f..d7dfa547e2d8 100644 --- a/sound/pci/hda/hda_local.h +++ b/sound/pci/hda/hda_local.h | |||
@@ -215,7 +215,7 @@ int snd_hda_create_spdif_in_ctls(struct hda_codec *codec, hda_nid_t nid); | |||
215 | */ | 215 | */ |
216 | #define HDA_MAX_NUM_INPUTS 16 | 216 | #define HDA_MAX_NUM_INPUTS 16 |
217 | struct hda_input_mux_item { | 217 | struct hda_input_mux_item { |
218 | const char *label; | 218 | char label[32]; |
219 | unsigned int index; | 219 | unsigned int index; |
220 | }; | 220 | }; |
221 | struct hda_input_mux { | 221 | struct hda_input_mux { |
@@ -366,9 +366,7 @@ struct hda_bus_unsolicited { | |||
366 | 366 | ||
367 | enum { | 367 | enum { |
368 | AUTO_PIN_MIC, | 368 | AUTO_PIN_MIC, |
369 | AUTO_PIN_FRONT_MIC, | 369 | AUTO_PIN_LINE_IN, |
370 | AUTO_PIN_LINE, | ||
371 | AUTO_PIN_FRONT_LINE, | ||
372 | AUTO_PIN_CD, | 370 | AUTO_PIN_CD, |
373 | AUTO_PIN_AUX, | 371 | AUTO_PIN_AUX, |
374 | AUTO_PIN_LAST | 372 | AUTO_PIN_LAST |
@@ -380,9 +378,33 @@ enum { | |||
380 | AUTO_PIN_HP_OUT | 378 | AUTO_PIN_HP_OUT |
381 | }; | 379 | }; |
382 | 380 | ||
383 | extern const char *auto_pin_cfg_labels[AUTO_PIN_LAST]; | ||
384 | |||
385 | #define AUTO_CFG_MAX_OUTS 5 | 381 | #define AUTO_CFG_MAX_OUTS 5 |
382 | #define AUTO_CFG_MAX_INS 8 | ||
383 | |||
384 | struct auto_pin_cfg_item { | ||
385 | hda_nid_t pin; | ||
386 | int type; | ||
387 | }; | ||
388 | |||
389 | struct auto_pin_cfg; | ||
390 | const char *hda_get_input_pin_label(struct hda_codec *codec, hda_nid_t pin, | ||
391 | int check_location); | ||
392 | const char *hda_get_autocfg_input_label(struct hda_codec *codec, | ||
393 | const struct auto_pin_cfg *cfg, | ||
394 | int input); | ||
395 | int snd_hda_add_imux_item(struct hda_input_mux *imux, const char *label, | ||
396 | int index, int *type_index_ret); | ||
397 | |||
398 | enum { | ||
399 | INPUT_PIN_ATTR_UNUSED, /* pin not connected */ | ||
400 | INPUT_PIN_ATTR_INT, /* internal mic/line-in */ | ||
401 | INPUT_PIN_ATTR_DOCK, /* docking mic/line-in */ | ||
402 | INPUT_PIN_ATTR_NORMAL, /* mic/line-in jack */ | ||
403 | INPUT_PIN_ATTR_FRONT, /* mic/line-in jack in front */ | ||
404 | INPUT_PIN_ATTR_REAR, /* mic/line-in jack in rear */ | ||
405 | }; | ||
406 | |||
407 | int snd_hda_get_input_pin_attr(unsigned int def_conf); | ||
386 | 408 | ||
387 | struct auto_pin_cfg { | 409 | struct auto_pin_cfg { |
388 | int line_outs; | 410 | int line_outs; |
@@ -393,7 +415,8 @@ struct auto_pin_cfg { | |||
393 | int hp_outs; | 415 | int hp_outs; |
394 | int line_out_type; /* AUTO_PIN_XXX_OUT */ | 416 | int line_out_type; /* AUTO_PIN_XXX_OUT */ |
395 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; | 417 | hda_nid_t hp_pins[AUTO_CFG_MAX_OUTS]; |
396 | hda_nid_t input_pins[AUTO_PIN_LAST]; | 418 | int num_inputs; |
419 | struct auto_pin_cfg_item inputs[AUTO_CFG_MAX_INS]; | ||
397 | int dig_outs; | 420 | int dig_outs; |
398 | hda_nid_t dig_out_pins[2]; | 421 | hda_nid_t dig_out_pins[2]; |
399 | hda_nid_t dig_in_pin; | 422 | hda_nid_t dig_in_pin; |
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c index 10bbbaf6ebc3..507523d5ed42 100644 --- a/sound/pci/hda/patch_analog.c +++ b/sound/pci/hda/patch_analog.c | |||
@@ -2880,7 +2880,7 @@ static int ad1988_auto_create_extra_out(struct hda_codec *codec, hda_nid_t pin, | |||
2880 | 2880 | ||
2881 | /* create input playback/capture controls for the given pin */ | 2881 | /* create input playback/capture controls for the given pin */ |
2882 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | 2882 | static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, |
2883 | const char *ctlname, int boost) | 2883 | const char *ctlname, int ctlidx, int boost) |
2884 | { | 2884 | { |
2885 | char name[32]; | 2885 | char name[32]; |
2886 | int err, idx; | 2886 | int err, idx; |
@@ -2909,25 +2909,27 @@ static int new_analog_input(struct ad198x_spec *spec, hda_nid_t pin, | |||
2909 | } | 2909 | } |
2910 | 2910 | ||
2911 | /* create playback/capture controls for input pins */ | 2911 | /* create playback/capture controls for input pins */ |
2912 | static int ad1988_auto_create_analog_input_ctls(struct ad198x_spec *spec, | 2912 | static int ad1988_auto_create_analog_input_ctls(struct hda_codec *codec, |
2913 | const struct auto_pin_cfg *cfg) | 2913 | const struct auto_pin_cfg *cfg) |
2914 | { | 2914 | { |
2915 | struct ad198x_spec *spec = codec->spec; | ||
2915 | struct hda_input_mux *imux = &spec->private_imux; | 2916 | struct hda_input_mux *imux = &spec->private_imux; |
2916 | int i, err; | 2917 | int i, err, type, type_idx; |
2917 | 2918 | ||
2918 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 2919 | for (i = 0; i < cfg->num_inputs; i++) { |
2919 | err = new_analog_input(spec, cfg->input_pins[i], | 2920 | const char *label; |
2920 | auto_pin_cfg_labels[i], | 2921 | type = cfg->inputs[i].type; |
2921 | i <= AUTO_PIN_FRONT_MIC); | 2922 | label = hda_get_autocfg_input_label(codec, cfg, i); |
2923 | snd_hda_add_imux_item(imux, label, | ||
2924 | ad1988_pin_to_adc_idx(cfg->inputs[i].pin), | ||
2925 | &type_idx); | ||
2926 | err = new_analog_input(spec, cfg->inputs[i].pin, | ||
2927 | label, type_idx, | ||
2928 | type == AUTO_PIN_MIC); | ||
2922 | if (err < 0) | 2929 | if (err < 0) |
2923 | return err; | 2930 | 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 | } | 2931 | } |
2928 | imux->items[imux->num_items].label = "Mix"; | 2932 | snd_hda_add_imux_item(imux, "Mix", 9, NULL); |
2929 | imux->items[imux->num_items].index = 9; | ||
2930 | imux->num_items++; | ||
2931 | 2933 | ||
2932 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, | 2934 | if ((err = add_control(spec, AD_CTL_WIDGET_VOL, |
2933 | "Analog Mix Playback Volume", | 2935 | "Analog Mix Playback Volume", |
@@ -2994,12 +2996,11 @@ static void ad1988_auto_init_extra_out(struct hda_codec *codec) | |||
2994 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) | 2996 | static void ad1988_auto_init_analog_input(struct hda_codec *codec) |
2995 | { | 2997 | { |
2996 | struct ad198x_spec *spec = codec->spec; | 2998 | struct ad198x_spec *spec = codec->spec; |
2999 | const struct auto_pin_cfg *cfg = &spec->autocfg; | ||
2997 | int i, idx; | 3000 | int i, idx; |
2998 | 3001 | ||
2999 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3002 | for (i = 0; i < cfg->num_inputs; i++) { |
3000 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 3003 | hda_nid_t nid = cfg->inputs[i].pin; |
3001 | if (! nid) | ||
3002 | continue; | ||
3003 | switch (nid) { | 3004 | switch (nid) { |
3004 | case 0x15: /* port-C */ | 3005 | case 0x15: /* port-C */ |
3005 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); | 3006 | snd_hda_codec_write(codec, 0x33, 0, AC_VERB_SET_CONNECT_SEL, 0x0); |
@@ -3009,7 +3010,7 @@ static void ad1988_auto_init_analog_input(struct hda_codec *codec) | |||
3009 | break; | 3010 | break; |
3010 | } | 3011 | } |
3011 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, | 3012 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, |
3012 | i <= AUTO_PIN_FRONT_MIC ? PIN_VREF80 : PIN_IN); | 3013 | i == AUTO_PIN_MIC ? PIN_VREF80 : PIN_IN); |
3013 | if (nid != AD1988_PIN_CD_NID) | 3014 | if (nid != AD1988_PIN_CD_NID) |
3014 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, | 3015 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_AMP_GAIN_MUTE, |
3015 | AMP_OUT_MUTE); | 3016 | AMP_OUT_MUTE); |
@@ -3040,7 +3041,7 @@ static int ad1988_parse_auto_config(struct hda_codec *codec) | |||
3040 | "Speaker")) < 0 || | 3041 | "Speaker")) < 0 || |
3041 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], | 3042 | (err = ad1988_auto_create_extra_out(codec, spec->autocfg.hp_pins[0], |
3042 | "Headphone")) < 0 || | 3043 | "Headphone")) < 0 || |
3043 | (err = ad1988_auto_create_analog_input_ctls(spec, &spec->autocfg)) < 0) | 3044 | (err = ad1988_auto_create_analog_input_ctls(codec, &spec->autocfg)) < 0) |
3044 | return err; | 3045 | return err; |
3045 | 3046 | ||
3046 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; | 3047 | spec->multiout.max_channels = spec->multiout.num_dacs * 2; |
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..cca11fdd3d79 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 | } |
diff --git a/sound/pci/hda/patch_cirrus.c b/sound/pci/hda/patch_cirrus.c index 488fd9ade1ba..483c3f2d8d39 100644 --- a/sound/pci/hda/patch_cirrus.c +++ b/sound/pci/hda/patch_cirrus.c | |||
@@ -329,12 +329,12 @@ static int is_ext_mic(struct hda_codec *codec, unsigned int idx) | |||
329 | { | 329 | { |
330 | struct cs_spec *spec = codec->spec; | 330 | struct cs_spec *spec = codec->spec; |
331 | struct auto_pin_cfg *cfg = &spec->autocfg; | 331 | struct auto_pin_cfg *cfg = &spec->autocfg; |
332 | hda_nid_t pin = cfg->input_pins[idx]; | 332 | hda_nid_t pin = cfg->inputs[idx].pin; |
333 | unsigned int val = snd_hda_query_pin_caps(codec, pin); | 333 | unsigned int val = snd_hda_query_pin_caps(codec, pin); |
334 | if (!(val & AC_PINCAP_PRES_DETECT)) | 334 | if (!(val & AC_PINCAP_PRES_DETECT)) |
335 | return 0; | 335 | return 0; |
336 | val = snd_hda_codec_get_pincfg(codec, pin); | 336 | val = snd_hda_codec_get_pincfg(codec, pin); |
337 | return (get_defcfg_connect(val) == AC_JACK_PORT_COMPLEX); | 337 | return (snd_hda_get_input_pin_attr(val) != INPUT_PIN_ATTR_INT); |
338 | } | 338 | } |
339 | 339 | ||
340 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, | 340 | static hda_nid_t get_adc(struct hda_codec *codec, hda_nid_t pin, |
@@ -424,10 +424,8 @@ static int parse_input(struct hda_codec *codec) | |||
424 | struct auto_pin_cfg *cfg = &spec->autocfg; | 424 | struct auto_pin_cfg *cfg = &spec->autocfg; |
425 | int i; | 425 | int i; |
426 | 426 | ||
427 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 427 | for (i = 0; i < cfg->num_inputs; i++) { |
428 | hda_nid_t pin = cfg->input_pins[i]; | 428 | hda_nid_t pin = cfg->inputs[i].pin; |
429 | if (!pin) | ||
430 | continue; | ||
431 | spec->input_idx[spec->num_inputs] = i; | 429 | spec->input_idx[spec->num_inputs] = i; |
432 | spec->capsrc_idx[i] = spec->num_inputs++; | 430 | spec->capsrc_idx[i] = spec->num_inputs++; |
433 | spec->cur_input = i; | 431 | spec->cur_input = i; |
@@ -438,16 +436,17 @@ static int parse_input(struct hda_codec *codec) | |||
438 | 436 | ||
439 | /* check whether the automatic mic switch is available */ | 437 | /* check whether the automatic mic switch is available */ |
440 | if (spec->num_inputs == 2 && | 438 | if (spec->num_inputs == 2 && |
441 | spec->adc_nid[AUTO_PIN_MIC] && spec->adc_nid[AUTO_PIN_FRONT_MIC]) { | 439 | cfg->inputs[0].type == AUTO_PIN_MIC && |
442 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_FRONT_MIC])) { | 440 | cfg->inputs[1].type == AUTO_PIN_MIC) { |
443 | if (!is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 441 | if (is_ext_mic(codec, cfg->inputs[0].pin)) { |
442 | if (!is_ext_mic(codec, cfg->inputs[1].pin)) { | ||
444 | spec->mic_detect = 1; | 443 | spec->mic_detect = 1; |
445 | spec->automic_idx = AUTO_PIN_FRONT_MIC; | 444 | spec->automic_idx = 0; |
446 | } | 445 | } |
447 | } else { | 446 | } else { |
448 | if (is_ext_mic(codec, cfg->input_pins[AUTO_PIN_MIC])) { | 447 | if (is_ext_mic(codec, cfg->inputs[1].pin)) { |
449 | spec->mic_detect = 1; | 448 | spec->mic_detect = 1; |
450 | spec->automic_idx = AUTO_PIN_MIC; | 449 | spec->automic_idx = 1; |
451 | } | 450 | } |
452 | } | 451 | } |
453 | } | 452 | } |
@@ -674,6 +673,7 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
674 | { | 673 | { |
675 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | 674 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); |
676 | struct cs_spec *spec = codec->spec; | 675 | struct cs_spec *spec = codec->spec; |
676 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
677 | unsigned int idx; | 677 | unsigned int idx; |
678 | 678 | ||
679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; | 679 | uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED; |
@@ -682,7 +682,8 @@ static int cs_capture_source_info(struct snd_kcontrol *kcontrol, | |||
682 | if (uinfo->value.enumerated.item >= spec->num_inputs) | 682 | if (uinfo->value.enumerated.item >= spec->num_inputs) |
683 | uinfo->value.enumerated.item = spec->num_inputs - 1; | 683 | uinfo->value.enumerated.item = spec->num_inputs - 1; |
684 | idx = spec->input_idx[uinfo->value.enumerated.item]; | 684 | idx = spec->input_idx[uinfo->value.enumerated.item]; |
685 | strcpy(uinfo->value.enumerated.name, auto_pin_cfg_labels[idx]); | 685 | strcpy(uinfo->value.enumerated.name, |
686 | hda_get_input_pin_label(codec, cfg->inputs[idx].pin, 1)); | ||
686 | return 0; | 687 | return 0; |
687 | } | 688 | } |
688 | 689 | ||
@@ -853,15 +854,12 @@ static void cs_automic(struct hda_codec *codec) | |||
853 | hda_nid_t nid; | 854 | hda_nid_t nid; |
854 | unsigned int present; | 855 | unsigned int present; |
855 | 856 | ||
856 | nid = cfg->input_pins[spec->automic_idx]; | 857 | nid = cfg->inputs[spec->automic_idx].pin; |
857 | present = snd_hda_jack_detect(codec, nid); | 858 | present = snd_hda_jack_detect(codec, nid); |
858 | if (present) | 859 | if (present) |
859 | change_cur_input(codec, spec->automic_idx, 0); | 860 | change_cur_input(codec, spec->automic_idx, 0); |
860 | else { | 861 | else |
861 | unsigned int imic = (spec->automic_idx == AUTO_PIN_MIC) ? | 862 | 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 | } | 863 | } |
866 | 864 | ||
867 | /* | 865 | /* |
@@ -918,14 +916,14 @@ static void init_input(struct hda_codec *codec) | |||
918 | unsigned int coef; | 916 | unsigned int coef; |
919 | int i; | 917 | int i; |
920 | 918 | ||
921 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 919 | for (i = 0; i < cfg->num_inputs; i++) { |
922 | unsigned int ctl; | 920 | unsigned int ctl; |
923 | hda_nid_t pin = cfg->input_pins[i]; | 921 | hda_nid_t pin = cfg->inputs[i].pin; |
924 | if (!pin || !spec->adc_nid[i]) | 922 | if (!spec->adc_nid[i]) |
925 | continue; | 923 | continue; |
926 | /* set appropriate pin control and mute first */ | 924 | /* set appropriate pin control and mute first */ |
927 | ctl = PIN_IN; | 925 | ctl = PIN_IN; |
928 | if (i <= AUTO_PIN_FRONT_MIC) { | 926 | if (cfg->inputs[i].type == AUTO_PIN_MIC) { |
929 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); | 927 | unsigned int caps = snd_hda_query_pin_caps(codec, pin); |
930 | caps >>= AC_PINCAP_VREF_SHIFT; | 928 | caps >>= AC_PINCAP_VREF_SHIFT; |
931 | if (caps & AC_PINCAP_VREF_80) | 929 | if (caps & AC_PINCAP_VREF_80) |
diff --git a/sound/pci/hda/patch_conexant.c b/sound/pci/hda/patch_conexant.c index 972e7c453b3d..a6c68cb06ddb 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(0x1025, 0x040a, "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 a1312a6c8af2..f2a30447f26f 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 { |
@@ -357,6 +364,9 @@ struct alc_spec { | |||
357 | /* PCM information */ | 364 | /* PCM information */ |
358 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ | 365 | struct hda_pcm pcm_rec[3]; /* used in alc_build_pcms() */ |
359 | 366 | ||
367 | /* jack detection */ | ||
368 | struct snd_array jacks; | ||
369 | |||
360 | /* dynamic controls, init_verbs and input_mux */ | 370 | /* dynamic controls, init_verbs and input_mux */ |
361 | struct auto_pin_cfg autocfg; | 371 | struct auto_pin_cfg autocfg; |
362 | struct alc_customize_define cdefine; | 372 | struct alc_customize_define cdefine; |
@@ -383,6 +393,7 @@ struct alc_spec { | |||
383 | unsigned int no_analog :1; /* digital I/O only */ | 393 | unsigned int no_analog :1; /* digital I/O only */ |
384 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ | 394 | unsigned int dual_adc_switch:1; /* switch ADCs (for ALC275) */ |
385 | int init_amp; | 395 | int init_amp; |
396 | int codec_variant; /* flag for other variants */ | ||
386 | 397 | ||
387 | /* for virtual master */ | 398 | /* for virtual master */ |
388 | hda_nid_t vmaster_nid; | 399 | hda_nid_t vmaster_nid; |
@@ -846,7 +857,7 @@ static void alc_set_input_pin(struct hda_codec *codec, hda_nid_t nid, | |||
846 | { | 857 | { |
847 | unsigned int val = PIN_IN; | 858 | unsigned int val = PIN_IN; |
848 | 859 | ||
849 | if (auto_pin_type <= AUTO_PIN_FRONT_MIC) { | 860 | if (auto_pin_type == AUTO_PIN_MIC) { |
850 | unsigned int pincap; | 861 | unsigned int pincap; |
851 | unsigned int oldval; | 862 | unsigned int oldval; |
852 | oldval = snd_hda_codec_read(codec, nid, 0, | 863 | oldval = snd_hda_codec_read(codec, nid, 0, |
@@ -866,6 +877,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); | 877 | snd_hda_codec_write(codec, nid, 0, AC_VERB_SET_PIN_WIDGET_CONTROL, val); |
867 | } | 878 | } |
868 | 879 | ||
880 | static void alc_fixup_autocfg_pin_nums(struct hda_codec *codec) | ||
881 | { | ||
882 | struct alc_spec *spec = codec->spec; | ||
883 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
884 | |||
885 | if (!cfg->line_outs) { | ||
886 | while (cfg->line_outs < AUTO_CFG_MAX_OUTS && | ||
887 | cfg->line_out_pins[cfg->line_outs]) | ||
888 | cfg->line_outs++; | ||
889 | } | ||
890 | if (!cfg->speaker_outs) { | ||
891 | while (cfg->speaker_outs < AUTO_CFG_MAX_OUTS && | ||
892 | cfg->speaker_pins[cfg->speaker_outs]) | ||
893 | cfg->speaker_outs++; | ||
894 | } | ||
895 | if (!cfg->hp_outs) { | ||
896 | while (cfg->hp_outs < AUTO_CFG_MAX_OUTS && | ||
897 | cfg->hp_pins[cfg->hp_outs]) | ||
898 | cfg->hp_outs++; | ||
899 | } | ||
900 | } | ||
901 | |||
869 | /* | 902 | /* |
870 | */ | 903 | */ |
871 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) | 904 | static void add_mixer(struct alc_spec *spec, struct snd_kcontrol_new *mix) |
@@ -934,6 +967,8 @@ static void setup_preset(struct hda_codec *codec, | |||
934 | 967 | ||
935 | if (preset->setup) | 968 | if (preset->setup) |
936 | preset->setup(codec); | 969 | preset->setup(codec); |
970 | |||
971 | alc_fixup_autocfg_pin_nums(codec); | ||
937 | } | 972 | } |
938 | 973 | ||
939 | /* Enable GPIO mask and set output */ | 974 | /* Enable GPIO mask and set output */ |
@@ -990,25 +1025,136 @@ static void alc_fix_pll_init(struct hda_codec *codec, hda_nid_t nid, | |||
990 | alc_fix_pll(codec); | 1025 | alc_fix_pll(codec); |
991 | } | 1026 | } |
992 | 1027 | ||
993 | static void alc_automute_pin(struct hda_codec *codec) | 1028 | #ifdef CONFIG_SND_HDA_INPUT_JACK |
1029 | static void alc_free_jack_priv(struct snd_jack *jack) | ||
1030 | { | ||
1031 | struct alc_jack *jacks = jack->private_data; | ||
1032 | jacks->nid = 0; | ||
1033 | jacks->jack = NULL; | ||
1034 | } | ||
1035 | |||
1036 | static int alc_add_jack(struct hda_codec *codec, | ||
1037 | hda_nid_t nid, int type) | ||
1038 | { | ||
1039 | struct alc_spec *spec; | ||
1040 | struct alc_jack *jack; | ||
1041 | const char *name; | ||
1042 | int err; | ||
1043 | |||
1044 | spec = codec->spec; | ||
1045 | snd_array_init(&spec->jacks, sizeof(*jack), 32); | ||
1046 | jack = snd_array_new(&spec->jacks); | ||
1047 | if (!jack) | ||
1048 | return -ENOMEM; | ||
1049 | |||
1050 | jack->nid = nid; | ||
1051 | jack->type = type; | ||
1052 | name = (type == SND_JACK_HEADPHONE) ? "Headphone" : "Mic" ; | ||
1053 | |||
1054 | err = snd_jack_new(codec->bus->card, name, type, &jack->jack); | ||
1055 | if (err < 0) | ||
1056 | return err; | ||
1057 | jack->jack->private_data = jack; | ||
1058 | jack->jack->private_free = alc_free_jack_priv; | ||
1059 | return 0; | ||
1060 | } | ||
1061 | |||
1062 | static void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
994 | { | 1063 | { |
995 | struct alc_spec *spec = codec->spec; | 1064 | struct alc_spec *spec = codec->spec; |
996 | unsigned int nid = spec->autocfg.hp_pins[0]; | 1065 | struct alc_jack *jacks = spec->jacks.list; |
1066 | |||
1067 | if (jacks) { | ||
1068 | int i; | ||
1069 | for (i = 0; i < spec->jacks.used; i++) { | ||
1070 | if (jacks->nid == nid) { | ||
1071 | unsigned int present; | ||
1072 | present = snd_hda_jack_detect(codec, nid); | ||
1073 | |||
1074 | present = (present) ? jacks->type : 0; | ||
1075 | |||
1076 | snd_jack_report(jacks->jack, present); | ||
1077 | } | ||
1078 | jacks++; | ||
1079 | } | ||
1080 | } | ||
1081 | } | ||
1082 | |||
1083 | static int alc_init_jacks(struct hda_codec *codec) | ||
1084 | { | ||
1085 | struct alc_spec *spec = codec->spec; | ||
1086 | int err; | ||
1087 | unsigned int hp_nid = spec->autocfg.hp_pins[0]; | ||
1088 | unsigned int mic_nid = spec->ext_mic.pin; | ||
1089 | |||
1090 | if (hp_nid) { | ||
1091 | err = alc_add_jack(codec, hp_nid, SND_JACK_HEADPHONE); | ||
1092 | if (err < 0) | ||
1093 | return err; | ||
1094 | alc_report_jack(codec, hp_nid); | ||
1095 | } | ||
1096 | |||
1097 | if (mic_nid) { | ||
1098 | err = alc_add_jack(codec, mic_nid, SND_JACK_MICROPHONE); | ||
1099 | if (err < 0) | ||
1100 | return err; | ||
1101 | alc_report_jack(codec, mic_nid); | ||
1102 | } | ||
1103 | |||
1104 | return 0; | ||
1105 | } | ||
1106 | #else | ||
1107 | static inline void alc_report_jack(struct hda_codec *codec, hda_nid_t nid) | ||
1108 | { | ||
1109 | } | ||
1110 | |||
1111 | static inline int alc_init_jacks(struct hda_codec *codec) | ||
1112 | { | ||
1113 | return 0; | ||
1114 | } | ||
1115 | #endif | ||
1116 | |||
1117 | static void alc_automute_speaker(struct hda_codec *codec, int pinctl) | ||
1118 | { | ||
1119 | struct alc_spec *spec = codec->spec; | ||
1120 | unsigned int mute; | ||
1121 | hda_nid_t nid; | ||
997 | int i; | 1122 | int i; |
998 | 1123 | ||
999 | if (!nid) | 1124 | spec->jack_present = 0; |
1000 | return; | 1125 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
1001 | spec->jack_present = snd_hda_jack_detect(codec, nid); | 1126 | nid = spec->autocfg.hp_pins[i]; |
1127 | if (!nid) | ||
1128 | break; | ||
1129 | if (snd_hda_jack_detect(codec, nid)) { | ||
1130 | spec->jack_present = 1; | ||
1131 | break; | ||
1132 | } | ||
1133 | alc_report_jack(codec, spec->autocfg.hp_pins[i]); | ||
1134 | } | ||
1135 | |||
1136 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1137 | /* Toggle internal speakers muting */ | ||
1002 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | 1138 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
1003 | nid = spec->autocfg.speaker_pins[i]; | 1139 | nid = spec->autocfg.speaker_pins[i]; |
1004 | if (!nid) | 1140 | if (!nid) |
1005 | break; | 1141 | break; |
1006 | snd_hda_codec_write(codec, nid, 0, | 1142 | if (pinctl) { |
1143 | snd_hda_codec_write(codec, nid, 0, | ||
1007 | AC_VERB_SET_PIN_WIDGET_CONTROL, | 1144 | AC_VERB_SET_PIN_WIDGET_CONTROL, |
1008 | spec->jack_present ? 0 : PIN_OUT); | 1145 | spec->jack_present ? 0 : PIN_OUT); |
1146 | } else { | ||
1147 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1148 | HDA_AMP_MUTE, mute); | ||
1149 | } | ||
1009 | } | 1150 | } |
1010 | } | 1151 | } |
1011 | 1152 | ||
1153 | static void alc_automute_pin(struct hda_codec *codec) | ||
1154 | { | ||
1155 | alc_automute_speaker(codec, 1); | ||
1156 | } | ||
1157 | |||
1012 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | 1158 | static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, |
1013 | hda_nid_t nid) | 1159 | hda_nid_t nid) |
1014 | { | 1160 | { |
@@ -1090,6 +1236,7 @@ static void alc_mic_automute(struct hda_codec *codec) | |||
1090 | AC_VERB_SET_CONNECT_SEL, | 1236 | AC_VERB_SET_CONNECT_SEL, |
1091 | alive->mux_idx); | 1237 | alive->mux_idx); |
1092 | } | 1238 | } |
1239 | alc_report_jack(codec, spec->ext_mic.pin); | ||
1093 | 1240 | ||
1094 | /* FIXME: analog mixer */ | 1241 | /* FIXME: analog mixer */ |
1095 | } | 1242 | } |
@@ -1236,24 +1383,35 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type) | |||
1236 | static void alc_init_auto_hp(struct hda_codec *codec) | 1383 | static void alc_init_auto_hp(struct hda_codec *codec) |
1237 | { | 1384 | { |
1238 | struct alc_spec *spec = codec->spec; | 1385 | struct alc_spec *spec = codec->spec; |
1386 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
1387 | int i; | ||
1239 | 1388 | ||
1240 | if (!spec->autocfg.hp_pins[0]) | 1389 | if (!cfg->hp_pins[0]) { |
1241 | return; | 1390 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) |
1391 | return; | ||
1392 | } | ||
1242 | 1393 | ||
1243 | if (!spec->autocfg.speaker_pins[0]) { | 1394 | if (!cfg->speaker_pins[0]) { |
1244 | if (spec->autocfg.line_out_pins[0] && | 1395 | 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; | 1396 | return; |
1397 | memcpy(cfg->speaker_pins, cfg->line_out_pins, | ||
1398 | sizeof(cfg->speaker_pins)); | ||
1399 | cfg->speaker_outs = cfg->line_outs; | ||
1250 | } | 1400 | } |
1251 | 1401 | ||
1252 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | 1402 | if (!cfg->hp_pins[0]) { |
1253 | spec->autocfg.hp_pins[0]); | 1403 | memcpy(cfg->hp_pins, cfg->line_out_pins, |
1254 | snd_hda_codec_write_cache(codec, spec->autocfg.hp_pins[0], 0, | 1404 | sizeof(cfg->hp_pins)); |
1405 | cfg->hp_outs = cfg->line_outs; | ||
1406 | } | ||
1407 | |||
1408 | for (i = 0; i < cfg->hp_outs; i++) { | ||
1409 | snd_printdd("realtek: Enable HP auto-muting on NID 0x%x\n", | ||
1410 | cfg->hp_pins[i]); | ||
1411 | snd_hda_codec_write_cache(codec, cfg->hp_pins[i], 0, | ||
1255 | AC_VERB_SET_UNSOLICITED_ENABLE, | 1412 | AC_VERB_SET_UNSOLICITED_ENABLE, |
1256 | AC_USRSP_EN | ALC880_HP_EVENT); | 1413 | AC_USRSP_EN | ALC880_HP_EVENT); |
1414 | } | ||
1257 | spec->unsol_event = alc_sku_unsol_event; | 1415 | spec->unsol_event = alc_sku_unsol_event; |
1258 | } | 1416 | } |
1259 | 1417 | ||
@@ -1265,30 +1423,28 @@ static void alc_init_auto_mic(struct hda_codec *codec) | |||
1265 | int i; | 1423 | int i; |
1266 | 1424 | ||
1267 | /* there must be only two mic inputs exclusively */ | 1425 | /* there must be only two mic inputs exclusively */ |
1268 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) | 1426 | for (i = 0; i < cfg->num_inputs; i++) |
1269 | if (cfg->input_pins[i]) | 1427 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
1270 | return; | 1428 | return; |
1271 | 1429 | ||
1272 | fixed = ext = 0; | 1430 | fixed = ext = 0; |
1273 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) { | 1431 | for (i = 0; i < cfg->num_inputs; i++) { |
1274 | hda_nid_t nid = cfg->input_pins[i]; | 1432 | hda_nid_t nid = cfg->inputs[i].pin; |
1275 | unsigned int defcfg; | 1433 | unsigned int defcfg; |
1276 | if (!nid) | ||
1277 | return; | ||
1278 | defcfg = snd_hda_codec_get_pincfg(codec, nid); | 1434 | defcfg = snd_hda_codec_get_pincfg(codec, nid); |
1279 | switch (get_defcfg_connect(defcfg)) { | 1435 | switch (snd_hda_get_input_pin_attr(defcfg)) { |
1280 | case AC_JACK_PORT_FIXED: | 1436 | case INPUT_PIN_ATTR_INT: |
1281 | if (fixed) | 1437 | if (fixed) |
1282 | return; /* already occupied */ | 1438 | return; /* already occupied */ |
1283 | fixed = nid; | 1439 | fixed = nid; |
1284 | break; | 1440 | break; |
1285 | case AC_JACK_PORT_COMPLEX: | 1441 | case INPUT_PIN_ATTR_UNUSED: |
1442 | return; /* invalid entry */ | ||
1443 | default: | ||
1286 | if (ext) | 1444 | if (ext) |
1287 | return; /* already occupied */ | 1445 | return; /* already occupied */ |
1288 | ext = nid; | 1446 | ext = nid; |
1289 | break; | 1447 | break; |
1290 | default: | ||
1291 | return; /* invalid entry */ | ||
1292 | } | 1448 | } |
1293 | } | 1449 | } |
1294 | if (!ext || !fixed) | 1450 | if (!ext || !fixed) |
@@ -1546,6 +1702,15 @@ static int alc_read_coef_idx(struct hda_codec *codec, | |||
1546 | return val; | 1702 | return val; |
1547 | } | 1703 | } |
1548 | 1704 | ||
1705 | static void alc_write_coef_idx(struct hda_codec *codec, unsigned int coef_idx, | ||
1706 | unsigned int coef_val) | ||
1707 | { | ||
1708 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_COEF_INDEX, | ||
1709 | coef_idx); | ||
1710 | snd_hda_codec_write(codec, 0x20, 0, AC_VERB_SET_PROC_COEF, | ||
1711 | coef_val); | ||
1712 | } | ||
1713 | |||
1549 | /* set right pin controls for digital I/O */ | 1714 | /* set right pin controls for digital I/O */ |
1550 | static void alc_auto_init_digital(struct hda_codec *codec) | 1715 | static void alc_auto_init_digital(struct hda_codec *codec) |
1551 | { | 1716 | { |
@@ -1713,31 +1878,7 @@ static struct hda_verb alc888_fujitsu_xa3530_verbs[] = { | |||
1713 | 1878 | ||
1714 | static void alc_automute_amp(struct hda_codec *codec) | 1879 | static void alc_automute_amp(struct hda_codec *codec) |
1715 | { | 1880 | { |
1716 | struct alc_spec *spec = codec->spec; | 1881 | alc_automute_speaker(codec, 0); |
1717 | unsigned int mute; | ||
1718 | hda_nid_t nid; | ||
1719 | int i; | ||
1720 | |||
1721 | spec->jack_present = 0; | ||
1722 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { | ||
1723 | nid = spec->autocfg.hp_pins[i]; | ||
1724 | if (!nid) | ||
1725 | break; | ||
1726 | if (snd_hda_jack_detect(codec, nid)) { | ||
1727 | spec->jack_present = 1; | ||
1728 | break; | ||
1729 | } | ||
1730 | } | ||
1731 | |||
1732 | mute = spec->jack_present ? HDA_AMP_MUTE : 0; | ||
1733 | /* Toggle internal speakers muting */ | ||
1734 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { | ||
1735 | nid = spec->autocfg.speaker_pins[i]; | ||
1736 | if (!nid) | ||
1737 | break; | ||
1738 | snd_hda_codec_amp_stereo(codec, nid, HDA_OUTPUT, 0, | ||
1739 | HDA_AMP_MUTE, mute); | ||
1740 | } | ||
1741 | } | 1882 | } |
1742 | 1883 | ||
1743 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, | 1884 | static void alc_automute_amp_unsol_event(struct hda_codec *codec, |
@@ -3592,10 +3733,7 @@ static int alc_init(struct hda_codec *codec) | |||
3592 | if (spec->init_hook) | 3733 | if (spec->init_hook) |
3593 | spec->init_hook(codec); | 3734 | spec->init_hook(codec); |
3594 | 3735 | ||
3595 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 3736 | hda_call_check_power_status(codec, 0x01); |
3596 | if (codec->patch_ops.check_power_status) | ||
3597 | codec->patch_ops.check_power_status(codec, 0x01); | ||
3598 | #endif | ||
3599 | return 0; | 3737 | return 0; |
3600 | } | 3738 | } |
3601 | 3739 | ||
@@ -3991,10 +4129,7 @@ static int alc_resume(struct hda_codec *codec) | |||
3991 | codec->patch_ops.init(codec); | 4129 | codec->patch_ops.init(codec); |
3992 | snd_hda_codec_resume_amp(codec); | 4130 | snd_hda_codec_resume_amp(codec); |
3993 | snd_hda_codec_resume_cache(codec); | 4131 | snd_hda_codec_resume_cache(codec); |
3994 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 4132 | hda_call_check_power_status(codec, 0x01); |
3995 | if (codec->patch_ops.check_power_status) | ||
3996 | codec->patch_ops.check_power_status(codec, 0x01); | ||
3997 | #endif | ||
3998 | return 0; | 4133 | return 0; |
3999 | } | 4134 | } |
4000 | #endif | 4135 | #endif |
@@ -4719,7 +4854,7 @@ static struct snd_kcontrol_new alc880_control_templates[] = { | |||
4719 | 4854 | ||
4720 | /* add dynamic controls */ | 4855 | /* add dynamic controls */ |
4721 | static int add_control(struct alc_spec *spec, int type, const char *name, | 4856 | static int add_control(struct alc_spec *spec, int type, const char *name, |
4722 | unsigned long val) | 4857 | int cidx, unsigned long val) |
4723 | { | 4858 | { |
4724 | struct snd_kcontrol_new *knew; | 4859 | struct snd_kcontrol_new *knew; |
4725 | 4860 | ||
@@ -4731,6 +4866,7 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4731 | knew->name = kstrdup(name, GFP_KERNEL); | 4866 | knew->name = kstrdup(name, GFP_KERNEL); |
4732 | if (!knew->name) | 4867 | if (!knew->name) |
4733 | return -ENOMEM; | 4868 | return -ENOMEM; |
4869 | knew->index = cidx; | ||
4734 | if (get_amp_nid_(val)) | 4870 | if (get_amp_nid_(val)) |
4735 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; | 4871 | knew->subdevice = HDA_SUBDEV_AMP_FLAG; |
4736 | knew->private_value = val; | 4872 | knew->private_value = val; |
@@ -4739,17 +4875,21 @@ static int add_control(struct alc_spec *spec, int type, const char *name, | |||
4739 | 4875 | ||
4740 | static int add_control_with_pfx(struct alc_spec *spec, int type, | 4876 | static int add_control_with_pfx(struct alc_spec *spec, int type, |
4741 | const char *pfx, const char *dir, | 4877 | const char *pfx, const char *dir, |
4742 | const char *sfx, unsigned long val) | 4878 | const char *sfx, int cidx, unsigned long val) |
4743 | { | 4879 | { |
4744 | char name[32]; | 4880 | char name[32]; |
4745 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); | 4881 | snprintf(name, sizeof(name), "%s %s %s", pfx, dir, sfx); |
4746 | return add_control(spec, type, name, val); | 4882 | return add_control(spec, type, name, cidx, val); |
4747 | } | 4883 | } |
4748 | 4884 | ||
4749 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ | 4885 | #define add_pb_vol_ctrl(spec, type, pfx, val) \ |
4750 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", val) | 4886 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", 0, val) |
4751 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ | 4887 | #define add_pb_sw_ctrl(spec, type, pfx, val) \ |
4752 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", val) | 4888 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", 0, val) |
4889 | #define __add_pb_vol_ctrl(spec, type, pfx, cidx, val) \ | ||
4890 | add_control_with_pfx(spec, type, pfx, "Playback", "Volume", cidx, val) | ||
4891 | #define __add_pb_sw_ctrl(spec, type, pfx, cidx, val) \ | ||
4892 | add_control_with_pfx(spec, type, pfx, "Playback", "Switch", cidx, val) | ||
4753 | 4893 | ||
4754 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) | 4894 | #define alc880_is_fixed_pin(nid) ((nid) >= 0x14 && (nid) <= 0x17) |
4755 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) | 4895 | #define alc880_fixed_pin_idx(nid) ((nid) - 0x14) |
@@ -4902,16 +5042,16 @@ static int alc880_auto_create_extra_out(struct alc_spec *spec, hda_nid_t pin, | |||
4902 | 5042 | ||
4903 | /* create input playback/capture controls for the given pin */ | 5043 | /* create input playback/capture controls for the given pin */ |
4904 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, | 5044 | static int new_analog_input(struct alc_spec *spec, hda_nid_t pin, |
4905 | const char *ctlname, | 5045 | const char *ctlname, int ctlidx, |
4906 | int idx, hda_nid_t mix_nid) | 5046 | int idx, hda_nid_t mix_nid) |
4907 | { | 5047 | { |
4908 | int err; | 5048 | int err; |
4909 | 5049 | ||
4910 | err = add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, | 5050 | err = __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, ctlname, ctlidx, |
4911 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5051 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
4912 | if (err < 0) | 5052 | if (err < 0) |
4913 | return err; | 5053 | return err; |
4914 | err = add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, | 5054 | err = __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, ctlname, ctlidx, |
4915 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); | 5055 | HDA_COMPOSE_AMP_VAL(mix_nid, 3, idx, HDA_INPUT)); |
4916 | if (err < 0) | 5056 | if (err < 0) |
4917 | return err; | 5057 | return err; |
@@ -4932,20 +5072,27 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
4932 | { | 5072 | { |
4933 | struct alc_spec *spec = codec->spec; | 5073 | struct alc_spec *spec = codec->spec; |
4934 | struct hda_input_mux *imux = &spec->private_imux[0]; | 5074 | struct hda_input_mux *imux = &spec->private_imux[0]; |
4935 | int i, err, idx; | 5075 | int i, err, idx, type, type_idx = 0; |
4936 | 5076 | ||
4937 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5077 | for (i = 0; i < cfg->num_inputs; i++) { |
4938 | hda_nid_t pin; | 5078 | hda_nid_t pin; |
5079 | const char *label; | ||
4939 | 5080 | ||
4940 | pin = cfg->input_pins[i]; | 5081 | pin = cfg->inputs[i].pin; |
4941 | if (!alc_is_input_pin(codec, pin)) | 5082 | if (!alc_is_input_pin(codec, pin)) |
4942 | continue; | 5083 | continue; |
4943 | 5084 | ||
5085 | type = cfg->inputs[i].type; | ||
5086 | if (i > 0 && type == cfg->inputs[i - 1].type) | ||
5087 | type_idx++; | ||
5088 | else | ||
5089 | type_idx = 0; | ||
5090 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
4944 | if (mixer) { | 5091 | if (mixer) { |
4945 | idx = get_connection_index(codec, mixer, pin); | 5092 | idx = get_connection_index(codec, mixer, pin); |
4946 | if (idx >= 0) { | 5093 | if (idx >= 0) { |
4947 | err = new_analog_input(spec, pin, | 5094 | err = new_analog_input(spec, pin, |
4948 | auto_pin_cfg_labels[i], | 5095 | label, type_idx, |
4949 | idx, mixer); | 5096 | idx, mixer); |
4950 | if (err < 0) | 5097 | if (err < 0) |
4951 | return err; | 5098 | return err; |
@@ -4957,12 +5104,8 @@ static int alc_auto_create_input_ctls(struct hda_codec *codec, | |||
4957 | idx = get_connection_index(codec, cap1, pin); | 5104 | idx = get_connection_index(codec, cap1, pin); |
4958 | if (idx < 0 && cap2) | 5105 | if (idx < 0 && cap2) |
4959 | idx = get_connection_index(codec, cap2, pin); | 5106 | idx = get_connection_index(codec, cap2, pin); |
4960 | if (idx >= 0) { | 5107 | if (idx >= 0) |
4961 | imux->items[imux->num_items].label = | 5108 | snd_hda_add_imux_item(imux, label, idx, NULL); |
4962 | auto_pin_cfg_labels[i]; | ||
4963 | imux->items[imux->num_items].index = idx; | ||
4964 | imux->num_items++; | ||
4965 | } | ||
4966 | } | 5109 | } |
4967 | return 0; | 5110 | return 0; |
4968 | } | 5111 | } |
@@ -5034,12 +5177,13 @@ static void alc880_auto_init_extra_out(struct hda_codec *codec) | |||
5034 | static void alc880_auto_init_analog_input(struct hda_codec *codec) | 5177 | static void alc880_auto_init_analog_input(struct hda_codec *codec) |
5035 | { | 5178 | { |
5036 | struct alc_spec *spec = codec->spec; | 5179 | struct alc_spec *spec = codec->spec; |
5180 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5037 | int i; | 5181 | int i; |
5038 | 5182 | ||
5039 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5183 | for (i = 0; i < cfg->num_inputs; i++) { |
5040 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5184 | hda_nid_t nid = cfg->inputs[i].pin; |
5041 | if (alc_is_input_pin(codec, nid)) { | 5185 | if (alc_is_input_pin(codec, nid)) { |
5042 | alc_set_input_pin(codec, nid, i); | 5186 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
5043 | if (nid != ALC880_PIN_CD_NID && | 5187 | if (nid != ALC880_PIN_CD_NID && |
5044 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 5188 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
5045 | snd_hda_codec_write(codec, nid, 0, | 5189 | snd_hda_codec_write(codec, nid, 0, |
@@ -5204,19 +5348,13 @@ static int init_capsrc_for_pin(struct hda_codec *codec, hda_nid_t pin) | |||
5204 | static void fixup_single_adc(struct hda_codec *codec) | 5348 | static void fixup_single_adc(struct hda_codec *codec) |
5205 | { | 5349 | { |
5206 | struct alc_spec *spec = codec->spec; | 5350 | struct alc_spec *spec = codec->spec; |
5207 | hda_nid_t pin = 0; | 5351 | struct auto_pin_cfg *cfg = &spec->autocfg; |
5208 | int i; | 5352 | int i; |
5209 | 5353 | ||
5210 | /* search for the input pin; there must be only one */ | 5354 | /* search for the input pin; there must be only one */ |
5211 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5355 | if (cfg->num_inputs != 1) |
5212 | if (spec->autocfg.input_pins[i]) { | ||
5213 | pin = spec->autocfg.input_pins[i]; | ||
5214 | break; | ||
5215 | } | ||
5216 | } | ||
5217 | if (!pin) | ||
5218 | return; | 5356 | return; |
5219 | i = init_capsrc_for_pin(codec, pin); | 5357 | i = init_capsrc_for_pin(codec, cfg->inputs[0].pin); |
5220 | if (i >= 0) { | 5358 | if (i >= 0) { |
5221 | /* use only this ADC */ | 5359 | /* use only this ADC */ |
5222 | if (spec->capsrc_nids) | 5360 | if (spec->capsrc_nids) |
@@ -5269,6 +5407,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5269 | int num_nids) | 5407 | int num_nids) |
5270 | { | 5408 | { |
5271 | struct alc_spec *spec = codec->spec; | 5409 | struct alc_spec *spec = codec->spec; |
5410 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
5272 | int n; | 5411 | int n; |
5273 | hda_nid_t fallback_adc = 0, fallback_cap = 0; | 5412 | hda_nid_t fallback_adc = 0, fallback_cap = 0; |
5274 | 5413 | ||
@@ -5294,10 +5433,8 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5294 | fallback_adc = adc; | 5433 | fallback_adc = adc; |
5295 | fallback_cap = cap; | 5434 | fallback_cap = cap; |
5296 | } | 5435 | } |
5297 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 5436 | for (i = 0; i < cfg->num_inputs; i++) { |
5298 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 5437 | hda_nid_t nid = cfg->inputs[i].pin; |
5299 | if (!nid) | ||
5300 | continue; | ||
5301 | for (j = 0; j < nconns; j++) { | 5438 | for (j = 0; j < nconns; j++) { |
5302 | if (conn[j] == nid) | 5439 | if (conn[j] == nid) |
5303 | break; | 5440 | break; |
@@ -5305,7 +5442,7 @@ static void fillup_priv_adc_nids(struct hda_codec *codec, hda_nid_t *nids, | |||
5305 | if (j >= nconns) | 5442 | if (j >= nconns) |
5306 | break; | 5443 | break; |
5307 | } | 5444 | } |
5308 | if (i >= AUTO_PIN_LAST) { | 5445 | if (i >= cfg->num_inputs) { |
5309 | int num_adcs = spec->num_adc_nids; | 5446 | int num_adcs = spec->num_adc_nids; |
5310 | spec->private_adc_nids[num_adcs] = adc; | 5447 | spec->private_adc_nids[num_adcs] = adc; |
5311 | spec->private_capsrc_nids[num_adcs] = cap; | 5448 | spec->private_capsrc_nids[num_adcs] = cap; |
@@ -6673,12 +6810,13 @@ static void alc260_auto_init_multi_out(struct hda_codec *codec) | |||
6673 | static void alc260_auto_init_analog_input(struct hda_codec *codec) | 6810 | static void alc260_auto_init_analog_input(struct hda_codec *codec) |
6674 | { | 6811 | { |
6675 | struct alc_spec *spec = codec->spec; | 6812 | struct alc_spec *spec = codec->spec; |
6813 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
6676 | int i; | 6814 | int i; |
6677 | 6815 | ||
6678 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 6816 | for (i = 0; i < cfg->num_inputs; i++) { |
6679 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 6817 | hda_nid_t nid = cfg->inputs[i].pin; |
6680 | if (nid >= 0x12) { | 6818 | if (nid >= 0x12) { |
6681 | alc_set_input_pin(codec, nid, i); | 6819 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
6682 | if (nid != ALC260_PIN_CD_NID && | 6820 | if (nid != ALC260_PIN_CD_NID && |
6683 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 6821 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
6684 | snd_hda_codec_write(codec, nid, 0, | 6822 | snd_hda_codec_write(codec, nid, 0, |
@@ -6800,14 +6938,12 @@ enum { | |||
6800 | PINFIX_HP_DC5750, | 6938 | PINFIX_HP_DC5750, |
6801 | }; | 6939 | }; |
6802 | 6940 | ||
6803 | static struct alc_pincfg alc260_hp_dc5750_pinfix[] = { | ||
6804 | { 0x11, 0x90130110 }, /* speaker */ | ||
6805 | { } | ||
6806 | }; | ||
6807 | |||
6808 | static const struct alc_fixup alc260_fixups[] = { | 6941 | static const struct alc_fixup alc260_fixups[] = { |
6809 | [PINFIX_HP_DC5750] = { | 6942 | [PINFIX_HP_DC5750] = { |
6810 | .pins = alc260_hp_dc5750_pinfix | 6943 | .pins = (const struct alc_pincfg[]) { |
6944 | { 0x11, 0x90130110 }, /* speaker */ | ||
6945 | { } | ||
6946 | } | ||
6811 | }, | 6947 | }, |
6812 | }; | 6948 | }; |
6813 | 6949 | ||
@@ -10453,24 +10589,20 @@ enum { | |||
10453 | PINFIX_PB_M5210, | 10589 | PINFIX_PB_M5210, |
10454 | }; | 10590 | }; |
10455 | 10591 | ||
10456 | static struct alc_pincfg alc882_abit_aw9d_pinfix[] = { | ||
10457 | { 0x15, 0x01080104 }, /* side */ | ||
10458 | { 0x16, 0x01011012 }, /* rear */ | ||
10459 | { 0x17, 0x01016011 }, /* clfe */ | ||
10460 | { } | ||
10461 | }; | ||
10462 | |||
10463 | static const struct hda_verb pb_m5210_verbs[] = { | ||
10464 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10465 | {} | ||
10466 | }; | ||
10467 | |||
10468 | static const struct alc_fixup alc882_fixups[] = { | 10592 | static const struct alc_fixup alc882_fixups[] = { |
10469 | [PINFIX_ABIT_AW9D_MAX] = { | 10593 | [PINFIX_ABIT_AW9D_MAX] = { |
10470 | .pins = alc882_abit_aw9d_pinfix | 10594 | .pins = (const struct alc_pincfg[]) { |
10595 | { 0x15, 0x01080104 }, /* side */ | ||
10596 | { 0x16, 0x01011012 }, /* rear */ | ||
10597 | { 0x17, 0x01016011 }, /* clfe */ | ||
10598 | { } | ||
10599 | } | ||
10471 | }, | 10600 | }, |
10472 | [PINFIX_PB_M5210] = { | 10601 | [PINFIX_PB_M5210] = { |
10473 | .verbs = pb_m5210_verbs | 10602 | .verbs = (const struct hda_verb[]) { |
10603 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
10604 | {} | ||
10605 | } | ||
10474 | }, | 10606 | }, |
10475 | }; | 10607 | }; |
10476 | 10608 | ||
@@ -10525,16 +10657,21 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
10525 | { | 10657 | { |
10526 | struct alc_spec *spec = codec->spec; | 10658 | struct alc_spec *spec = codec->spec; |
10527 | hda_nid_t pin, dac; | 10659 | hda_nid_t pin, dac; |
10660 | int i; | ||
10528 | 10661 | ||
10529 | pin = spec->autocfg.hp_pins[0]; | 10662 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.hp_pins); i++) { |
10530 | if (pin) { | 10663 | pin = spec->autocfg.hp_pins[i]; |
10664 | if (!pin) | ||
10665 | break; | ||
10531 | dac = spec->multiout.hp_nid; | 10666 | dac = spec->multiout.hp_nid; |
10532 | if (!dac) | 10667 | if (!dac) |
10533 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10668 | dac = spec->multiout.dac_nids[0]; /* to front */ |
10534 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); | 10669 | alc882_auto_set_output_and_unmute(codec, pin, PIN_HP, dac); |
10535 | } | 10670 | } |
10536 | pin = spec->autocfg.speaker_pins[0]; | 10671 | for (i = 0; i < ARRAY_SIZE(spec->autocfg.speaker_pins); i++) { |
10537 | if (pin) { | 10672 | pin = spec->autocfg.speaker_pins[i]; |
10673 | if (!pin) | ||
10674 | break; | ||
10538 | dac = spec->multiout.extra_out_nid[0]; | 10675 | dac = spec->multiout.extra_out_nid[0]; |
10539 | if (!dac) | 10676 | if (!dac) |
10540 | dac = spec->multiout.dac_nids[0]; /* to front */ | 10677 | dac = spec->multiout.dac_nids[0]; /* to front */ |
@@ -10545,13 +10682,12 @@ static void alc882_auto_init_hp_out(struct hda_codec *codec) | |||
10545 | static void alc882_auto_init_analog_input(struct hda_codec *codec) | 10682 | static void alc882_auto_init_analog_input(struct hda_codec *codec) |
10546 | { | 10683 | { |
10547 | struct alc_spec *spec = codec->spec; | 10684 | struct alc_spec *spec = codec->spec; |
10685 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
10548 | int i; | 10686 | int i; |
10549 | 10687 | ||
10550 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 10688 | for (i = 0; i < cfg->num_inputs; i++) { |
10551 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 10689 | hda_nid_t nid = cfg->inputs[i].pin; |
10552 | if (!nid) | 10690 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
10553 | continue; | ||
10554 | alc_set_input_pin(codec, nid, i); | ||
10555 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) | 10691 | if (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP) |
10556 | snd_hda_codec_write(codec, nid, 0, | 10692 | snd_hda_codec_write(codec, nid, 0, |
10557 | AC_VERB_SET_AMP_GAIN_MUTE, | 10693 | AC_VERB_SET_AMP_GAIN_MUTE, |
@@ -10613,24 +10749,23 @@ static void alc882_auto_init_input_src(struct hda_codec *codec) | |||
10613 | static int alc_auto_add_mic_boost(struct hda_codec *codec) | 10749 | static int alc_auto_add_mic_boost(struct hda_codec *codec) |
10614 | { | 10750 | { |
10615 | struct alc_spec *spec = codec->spec; | 10751 | struct alc_spec *spec = codec->spec; |
10616 | int err; | 10752 | struct auto_pin_cfg *cfg = &spec->autocfg; |
10753 | int i, err; | ||
10617 | hda_nid_t nid; | 10754 | hda_nid_t nid; |
10618 | 10755 | ||
10619 | nid = spec->autocfg.input_pins[AUTO_PIN_MIC]; | 10756 | for (i = 0; i < cfg->num_inputs; i++) { |
10620 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | 10757 | if (cfg->inputs[i].type > AUTO_PIN_MIC) |
10621 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | 10758 | break; |
10622 | "Mic Boost", | 10759 | nid = cfg->inputs[i].pin; |
10623 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10760 | if (get_wcaps(codec, nid) & AC_WCAP_IN_AMP) { |
10624 | if (err < 0) | 10761 | char label[32]; |
10625 | return err; | 10762 | snprintf(label, sizeof(label), "%s Boost", |
10626 | } | 10763 | hda_get_autocfg_input_label(codec, cfg, i)); |
10627 | nid = spec->autocfg.input_pins[AUTO_PIN_FRONT_MIC]; | 10764 | err = add_control(spec, ALC_CTL_WIDGET_VOL, label, 0, |
10628 | if (nid && (get_wcaps(codec, nid) & AC_WCAP_IN_AMP)) { | ||
10629 | err = add_control(spec, ALC_CTL_WIDGET_VOL, | ||
10630 | "Front Mic Boost", | ||
10631 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); | 10765 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_INPUT)); |
10632 | if (err < 0) | 10766 | if (err < 0) |
10633 | return err; | 10767 | return err; |
10768 | } | ||
10634 | } | 10769 | } |
10635 | return 0; | 10770 | return 0; |
10636 | } | 10771 | } |
@@ -11821,7 +11956,7 @@ static int alc262_check_volbit(hda_nid_t nid) | |||
11821 | } | 11956 | } |
11822 | 11957 | ||
11823 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | 11958 | static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, |
11824 | const char *pfx, int *vbits) | 11959 | const char *pfx, int *vbits, int idx) |
11825 | { | 11960 | { |
11826 | unsigned long val; | 11961 | unsigned long val; |
11827 | int vbit; | 11962 | int vbit; |
@@ -11836,11 +11971,11 @@ static int alc262_add_out_vol_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
11836 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); | 11971 | val = HDA_COMPOSE_AMP_VAL(0x0e, 2, 0, HDA_OUTPUT); |
11837 | else | 11972 | else |
11838 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); | 11973 | val = HDA_COMPOSE_AMP_VAL(0x0c, 3, 0, HDA_OUTPUT); |
11839 | return add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, val); | 11974 | return __add_pb_vol_ctrl(spec, ALC_CTL_WIDGET_VOL, pfx, idx, val); |
11840 | } | 11975 | } |
11841 | 11976 | ||
11842 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | 11977 | static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, |
11843 | const char *pfx) | 11978 | const char *pfx, int idx) |
11844 | { | 11979 | { |
11845 | unsigned long val; | 11980 | unsigned long val; |
11846 | 11981 | ||
@@ -11850,7 +11985,7 @@ static int alc262_add_out_sw_ctl(struct alc_spec *spec, hda_nid_t nid, | |||
11850 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); | 11985 | val = HDA_COMPOSE_AMP_VAL(nid, 2, 0, HDA_OUTPUT); |
11851 | else | 11986 | else |
11852 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); | 11987 | val = HDA_COMPOSE_AMP_VAL(nid, 3, 0, HDA_OUTPUT); |
11853 | return add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, val); | 11988 | return __add_pb_sw_ctrl(spec, ALC_CTL_WIDGET_MUTE, pfx, idx, val); |
11854 | } | 11989 | } |
11855 | 11990 | ||
11856 | /* add playback controls from the parsed DAC table */ | 11991 | /* add playback controls from the parsed DAC table */ |
@@ -11859,7 +11994,7 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11859 | { | 11994 | { |
11860 | const char *pfx; | 11995 | const char *pfx; |
11861 | int vbits; | 11996 | int vbits; |
11862 | int err; | 11997 | int i, err; |
11863 | 11998 | ||
11864 | spec->multiout.num_dacs = 1; /* only use one dac */ | 11999 | spec->multiout.num_dacs = 1; /* only use one dac */ |
11865 | spec->multiout.dac_nids = spec->private_dac_nids; | 12000 | spec->multiout.dac_nids = spec->private_dac_nids; |
@@ -11869,39 +12004,52 @@ static int alc262_auto_create_multi_out_ctls(struct alc_spec *spec, | |||
11869 | pfx = "Master"; | 12004 | pfx = "Master"; |
11870 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | 12005 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) |
11871 | pfx = "Speaker"; | 12006 | pfx = "Speaker"; |
12007 | else if (cfg->line_out_type == AUTO_PIN_HP_OUT) | ||
12008 | pfx = "Headphone"; | ||
11872 | else | 12009 | else |
11873 | pfx = "Front"; | 12010 | pfx = "Front"; |
11874 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[0], pfx); | 12011 | for (i = 0; i < 2; i++) { |
11875 | if (err < 0) | 12012 | err = alc262_add_out_sw_ctl(spec, cfg->line_out_pins[i], pfx, i); |
11876 | return err; | 12013 | if (err < 0) |
11877 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[0], "Speaker"); | 12014 | return err; |
11878 | if (err < 0) | 12015 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
11879 | return err; | 12016 | err = alc262_add_out_sw_ctl(spec, cfg->speaker_pins[i], |
11880 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[0], "Headphone"); | 12017 | "Speaker", i); |
11881 | if (err < 0) | 12018 | if (err < 0) |
11882 | return err; | 12019 | return err; |
12020 | } | ||
12021 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
12022 | err = alc262_add_out_sw_ctl(spec, cfg->hp_pins[i], | ||
12023 | "Headphone", i); | ||
12024 | if (err < 0) | ||
12025 | return err; | ||
12026 | } | ||
12027 | } | ||
11883 | 12028 | ||
11884 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | | 12029 | vbits = alc262_check_volbit(cfg->line_out_pins[0]) | |
11885 | alc262_check_volbit(cfg->speaker_pins[0]) | | 12030 | alc262_check_volbit(cfg->speaker_pins[0]) | |
11886 | alc262_check_volbit(cfg->hp_pins[0]); | 12031 | alc262_check_volbit(cfg->hp_pins[0]); |
11887 | if (vbits == 1 || vbits == 2) | 12032 | if (vbits == 1 || vbits == 2) |
11888 | pfx = "Master"; /* only one mixer is used */ | 12033 | pfx = "Master"; /* only one mixer is used */ |
11889 | else if (cfg->line_out_type == AUTO_PIN_SPEAKER_OUT) | ||
11890 | pfx = "Speaker"; | ||
11891 | else | ||
11892 | pfx = "Front"; | ||
11893 | vbits = 0; | 12034 | vbits = 0; |
11894 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[0], pfx, &vbits); | 12035 | for (i = 0; i < 2; i++) { |
11895 | if (err < 0) | 12036 | err = alc262_add_out_vol_ctl(spec, cfg->line_out_pins[i], pfx, |
11896 | return err; | 12037 | &vbits, i); |
11897 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[0], "Speaker", | 12038 | if (err < 0) |
11898 | &vbits); | 12039 | return err; |
11899 | if (err < 0) | 12040 | if (cfg->line_out_type != AUTO_PIN_SPEAKER_OUT) { |
11900 | return err; | 12041 | err = alc262_add_out_vol_ctl(spec, cfg->speaker_pins[i], |
11901 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[0], "Headphone", | 12042 | "Speaker", &vbits, i); |
11902 | &vbits); | 12043 | if (err < 0) |
11903 | if (err < 0) | 12044 | return err; |
11904 | return err; | 12045 | } |
12046 | if (cfg->line_out_type != AUTO_PIN_HP_OUT) { | ||
12047 | err = alc262_add_out_vol_ctl(spec, cfg->hp_pins[i], | ||
12048 | "Headphone", &vbits, i); | ||
12049 | if (err < 0) | ||
12050 | return err; | ||
12051 | } | ||
12052 | } | ||
11905 | return 0; | 12053 | return 0; |
11906 | } | 12054 | } |
11907 | 12055 | ||
@@ -12189,6 +12337,35 @@ static struct hda_verb alc262_toshiba_rx1_unsol_verbs[] = { | |||
12189 | {} | 12337 | {} |
12190 | }; | 12338 | }; |
12191 | 12339 | ||
12340 | /* | ||
12341 | * Pin config fixes | ||
12342 | */ | ||
12343 | enum { | ||
12344 | PINFIX_FSC_H270, | ||
12345 | }; | ||
12346 | |||
12347 | static const struct alc_fixup alc262_fixups[] = { | ||
12348 | [PINFIX_FSC_H270] = { | ||
12349 | .pins = (const struct alc_pincfg[]) { | ||
12350 | { 0x14, 0x99130110 }, /* speaker */ | ||
12351 | { 0x15, 0x0221142f }, /* front HP */ | ||
12352 | { 0x1b, 0x0121141f }, /* rear HP */ | ||
12353 | { } | ||
12354 | } | ||
12355 | }, | ||
12356 | [PINFIX_PB_M5210] = { | ||
12357 | .verbs = (const struct hda_verb[]) { | ||
12358 | { 0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREF50 }, | ||
12359 | {} | ||
12360 | } | ||
12361 | }, | ||
12362 | }; | ||
12363 | |||
12364 | static struct snd_pci_quirk alc262_fixup_tbl[] = { | ||
12365 | SND_PCI_QUIRK(0x1734, 0x1147, "FSC Celsius H270", PINFIX_FSC_H270), | ||
12366 | {} | ||
12367 | }; | ||
12368 | |||
12192 | 12369 | ||
12193 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 12370 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
12194 | #define alc262_loopbacks alc880_loopbacks | 12371 | #define alc262_loopbacks alc880_loopbacks |
@@ -12612,6 +12789,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
12612 | board_config = ALC262_AUTO; | 12789 | board_config = ALC262_AUTO; |
12613 | } | 12790 | } |
12614 | 12791 | ||
12792 | if (board_config == ALC262_AUTO) | ||
12793 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 1); | ||
12794 | |||
12615 | if (board_config == ALC262_AUTO) { | 12795 | if (board_config == ALC262_AUTO) { |
12616 | /* automatic parse from the BIOS config */ | 12796 | /* automatic parse from the BIOS config */ |
12617 | err = alc262_parse_auto_config(codec); | 12797 | err = alc262_parse_auto_config(codec); |
@@ -12680,6 +12860,9 @@ static int patch_alc262(struct hda_codec *codec) | |||
12680 | if (!spec->no_analog && has_cdefine_beep(codec)) | 12860 | if (!spec->no_analog && has_cdefine_beep(codec)) |
12681 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); | 12861 | set_beep_amp(spec, 0x0b, 0x05, HDA_INPUT); |
12682 | 12862 | ||
12863 | if (board_config == ALC262_AUTO) | ||
12864 | alc_pick_fixup(codec, alc262_fixup_tbl, alc262_fixups, 0); | ||
12865 | |||
12683 | spec->vmaster_nid = 0x0c; | 12866 | spec->vmaster_nid = 0x0c; |
12684 | 12867 | ||
12685 | codec->patch_ops = alc_patch_ops; | 12868 | codec->patch_ops = alc_patch_ops; |
@@ -13300,8 +13483,10 @@ static void alc268_auto_set_output_and_unmute(struct hda_codec *codec, | |||
13300 | static void alc268_auto_init_multi_out(struct hda_codec *codec) | 13483 | static void alc268_auto_init_multi_out(struct hda_codec *codec) |
13301 | { | 13484 | { |
13302 | struct alc_spec *spec = codec->spec; | 13485 | struct alc_spec *spec = codec->spec; |
13303 | hda_nid_t nid = spec->autocfg.line_out_pins[0]; | 13486 | int i; |
13304 | if (nid) { | 13487 | |
13488 | for (i = 0; i < spec->autocfg.line_outs; i++) { | ||
13489 | hda_nid_t nid = spec->autocfg.line_out_pins[i]; | ||
13305 | int pin_type = get_pin_type(spec->autocfg.line_out_type); | 13490 | int pin_type = get_pin_type(spec->autocfg.line_out_type); |
13306 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); | 13491 | alc268_auto_set_output_and_unmute(codec, nid, pin_type); |
13307 | } | 13492 | } |
@@ -13311,13 +13496,19 @@ static void alc268_auto_init_hp_out(struct hda_codec *codec) | |||
13311 | { | 13496 | { |
13312 | struct alc_spec *spec = codec->spec; | 13497 | struct alc_spec *spec = codec->spec; |
13313 | hda_nid_t pin; | 13498 | hda_nid_t pin; |
13499 | int i; | ||
13314 | 13500 | ||
13315 | pin = spec->autocfg.hp_pins[0]; | 13501 | for (i = 0; i < spec->autocfg.hp_outs; i++) { |
13316 | if (pin) | 13502 | pin = spec->autocfg.hp_pins[i]; |
13317 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); | 13503 | alc268_auto_set_output_and_unmute(codec, pin, PIN_HP); |
13318 | pin = spec->autocfg.speaker_pins[0]; | 13504 | } |
13319 | if (pin) | 13505 | for (i = 0; i < spec->autocfg.speaker_outs; i++) { |
13506 | pin = spec->autocfg.speaker_pins[i]; | ||
13320 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); | 13507 | alc268_auto_set_output_and_unmute(codec, pin, PIN_OUT); |
13508 | } | ||
13509 | if (spec->autocfg.mono_out_pin) | ||
13510 | snd_hda_codec_write(codec, spec->autocfg.mono_out_pin, 0, | ||
13511 | AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_OUT); | ||
13321 | } | 13512 | } |
13322 | 13513 | ||
13323 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) | 13514 | static void alc268_auto_init_mono_speaker_out(struct hda_codec *codec) |
@@ -14376,6 +14567,13 @@ static int alc275_setup_dual_adc(struct hda_codec *codec) | |||
14376 | return 0; | 14567 | return 0; |
14377 | } | 14568 | } |
14378 | 14569 | ||
14570 | /* different alc269-variants */ | ||
14571 | enum { | ||
14572 | ALC269_TYPE_NORMAL, | ||
14573 | ALC269_TYPE_ALC259, | ||
14574 | ALC269_TYPE_ALC271X, | ||
14575 | }; | ||
14576 | |||
14379 | /* | 14577 | /* |
14380 | * BIOS auto configuration | 14578 | * BIOS auto configuration |
14381 | */ | 14579 | */ |
@@ -14393,7 +14591,11 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14393 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); | 14591 | err = alc269_auto_create_multi_out_ctls(spec, &spec->autocfg); |
14394 | if (err < 0) | 14592 | if (err < 0) |
14395 | return err; | 14593 | return err; |
14396 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | 14594 | if (spec->codec_variant == ALC269_TYPE_NORMAL) |
14595 | err = alc269_auto_create_input_ctls(codec, &spec->autocfg); | ||
14596 | else | ||
14597 | err = alc_auto_create_input_ctls(codec, &spec->autocfg, 0, | ||
14598 | 0x22, 0); | ||
14397 | if (err < 0) | 14599 | if (err < 0) |
14398 | return err; | 14600 | return err; |
14399 | 14601 | ||
@@ -14404,7 +14606,7 @@ static int alc269_parse_auto_config(struct hda_codec *codec) | |||
14404 | if (spec->kctls.list) | 14606 | if (spec->kctls.list) |
14405 | add_mixer(spec, spec->kctls.list); | 14607 | add_mixer(spec, spec->kctls.list); |
14406 | 14608 | ||
14407 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010) { | 14609 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
14408 | add_verb(spec, alc269vb_init_verbs); | 14610 | add_verb(spec, alc269vb_init_verbs); |
14409 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); | 14611 | alc_ssid_check(codec, 0, 0x1b, 0x14, 0x21); |
14410 | } else { | 14612 | } else { |
@@ -14447,23 +14649,76 @@ static void alc269_auto_init(struct hda_codec *codec) | |||
14447 | alc269_auto_init_hp_out(codec); | 14649 | alc269_auto_init_hp_out(codec); |
14448 | alc269_auto_init_analog_input(codec); | 14650 | alc269_auto_init_analog_input(codec); |
14449 | alc_auto_init_digital(codec); | 14651 | alc_auto_init_digital(codec); |
14652 | alc_init_jacks(codec); | ||
14450 | if (spec->unsol_event) | 14653 | if (spec->unsol_event) |
14451 | alc_inithook(codec); | 14654 | alc_inithook(codec); |
14452 | } | 14655 | } |
14453 | 14656 | ||
14657 | #ifdef SND_HDA_NEEDS_RESUME | ||
14658 | static void alc269_toggle_power_output(struct hda_codec *codec, int power_up) | ||
14659 | { | ||
14660 | int val = alc_read_coef_idx(codec, 0x04); | ||
14661 | if (power_up) | ||
14662 | val |= 1 << 11; | ||
14663 | else | ||
14664 | val &= ~(1 << 11); | ||
14665 | alc_write_coef_idx(codec, 0x04, val); | ||
14666 | } | ||
14667 | |||
14668 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
14669 | static int alc269_suspend(struct hda_codec *codec, pm_message_t state) | ||
14670 | { | ||
14671 | struct alc_spec *spec = codec->spec; | ||
14672 | |||
14673 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) | ||
14674 | alc269_toggle_power_output(codec, 0); | ||
14675 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
14676 | alc269_toggle_power_output(codec, 0); | ||
14677 | msleep(150); | ||
14678 | } | ||
14679 | |||
14680 | alc_shutup(codec); | ||
14681 | if (spec && spec->power_hook) | ||
14682 | spec->power_hook(codec); | ||
14683 | return 0; | ||
14684 | } | ||
14685 | #endif /* CONFIG_SND_HDA_POWER_SAVE */ | ||
14686 | |||
14687 | static int alc269_resume(struct hda_codec *codec) | ||
14688 | { | ||
14689 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
14690 | alc269_toggle_power_output(codec, 0); | ||
14691 | msleep(150); | ||
14692 | } | ||
14693 | |||
14694 | codec->patch_ops.init(codec); | ||
14695 | |||
14696 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
14697 | alc269_toggle_power_output(codec, 1); | ||
14698 | msleep(200); | ||
14699 | } | ||
14700 | |||
14701 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) | ||
14702 | alc269_toggle_power_output(codec, 1); | ||
14703 | |||
14704 | snd_hda_codec_resume_amp(codec); | ||
14705 | snd_hda_codec_resume_cache(codec); | ||
14706 | hda_call_check_power_status(codec, 0x01); | ||
14707 | return 0; | ||
14708 | } | ||
14709 | #endif /* SND_HDA_NEEDS_RESUME */ | ||
14710 | |||
14454 | enum { | 14711 | enum { |
14455 | ALC269_FIXUP_SONY_VAIO, | 14712 | ALC269_FIXUP_SONY_VAIO, |
14456 | ALC269_FIXUP_DELL_M101Z, | 14713 | ALC269_FIXUP_DELL_M101Z, |
14457 | }; | 14714 | }; |
14458 | 14715 | ||
14459 | static const struct hda_verb alc269_sony_vaio_fixup_verbs[] = { | ||
14460 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
14461 | {} | ||
14462 | }; | ||
14463 | |||
14464 | static const struct alc_fixup alc269_fixups[] = { | 14716 | static const struct alc_fixup alc269_fixups[] = { |
14465 | [ALC269_FIXUP_SONY_VAIO] = { | 14717 | [ALC269_FIXUP_SONY_VAIO] = { |
14466 | .verbs = alc269_sony_vaio_fixup_verbs | 14718 | .verbs = (const struct hda_verb[]) { |
14719 | {0x19, AC_VERB_SET_PIN_WIDGET_CONTROL, PIN_VREFGRD}, | ||
14720 | {} | ||
14721 | } | ||
14467 | }, | 14722 | }, |
14468 | [ALC269_FIXUP_DELL_M101Z] = { | 14723 | [ALC269_FIXUP_DELL_M101Z] = { |
14469 | .verbs = (const struct hda_verb[]) { | 14724 | .verbs = (const struct hda_verb[]) { |
@@ -14679,12 +14934,46 @@ static struct alc_config_preset alc269_presets[] = { | |||
14679 | }, | 14934 | }, |
14680 | }; | 14935 | }; |
14681 | 14936 | ||
14937 | static int alc269_fill_coef(struct hda_codec *codec) | ||
14938 | { | ||
14939 | int val; | ||
14940 | |||
14941 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) < 0x015) { | ||
14942 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
14943 | alc_write_coef_idx(codec, 0xe, 0x8817); | ||
14944 | } | ||
14945 | |||
14946 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x016) { | ||
14947 | alc_write_coef_idx(codec, 0xf, 0x960b); | ||
14948 | alc_write_coef_idx(codec, 0xe, 0x8814); | ||
14949 | } | ||
14950 | |||
14951 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x017) { | ||
14952 | val = alc_read_coef_idx(codec, 0x04); | ||
14953 | /* Power up output pin */ | ||
14954 | alc_write_coef_idx(codec, 0x04, val | (1<<11)); | ||
14955 | } | ||
14956 | |||
14957 | if ((alc_read_coef_idx(codec, 0) & 0x00ff) == 0x018) { | ||
14958 | val = alc_read_coef_idx(codec, 0xd); | ||
14959 | if ((val & 0x0c00) >> 10 != 0x1) { | ||
14960 | /* Capless ramp up clock control */ | ||
14961 | alc_write_coef_idx(codec, 0xd, val | 1<<10); | ||
14962 | } | ||
14963 | val = alc_read_coef_idx(codec, 0x17); | ||
14964 | if ((val & 0x01c0) >> 6 != 0x4) { | ||
14965 | /* Class D power on reset */ | ||
14966 | alc_write_coef_idx(codec, 0x17, val | 1<<7); | ||
14967 | } | ||
14968 | } | ||
14969 | return 0; | ||
14970 | } | ||
14971 | |||
14682 | static int patch_alc269(struct hda_codec *codec) | 14972 | static int patch_alc269(struct hda_codec *codec) |
14683 | { | 14973 | { |
14684 | struct alc_spec *spec; | 14974 | struct alc_spec *spec; |
14685 | int board_config; | 14975 | int board_config; |
14686 | int err; | 14976 | int err; |
14687 | int is_alc269vb = 0; | ||
14688 | 14977 | ||
14689 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); | 14978 | spec = kzalloc(sizeof(*spec), GFP_KERNEL); |
14690 | if (spec == NULL) | 14979 | if (spec == NULL) |
@@ -14696,14 +14985,18 @@ static int patch_alc269(struct hda_codec *codec) | |||
14696 | 14985 | ||
14697 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ | 14986 | if ((alc_read_coef_idx(codec, 0) & 0x00f0) == 0x0010){ |
14698 | if (codec->bus->pci->subsystem_vendor == 0x1025 && | 14987 | if (codec->bus->pci->subsystem_vendor == 0x1025 && |
14699 | spec->cdefine.platform_type == 1) | 14988 | spec->cdefine.platform_type == 1) { |
14700 | alc_codec_rename(codec, "ALC271X"); | 14989 | alc_codec_rename(codec, "ALC271X"); |
14701 | else | 14990 | spec->codec_variant = ALC269_TYPE_ALC271X; |
14991 | } else { | ||
14702 | alc_codec_rename(codec, "ALC259"); | 14992 | alc_codec_rename(codec, "ALC259"); |
14703 | is_alc269vb = 1; | 14993 | spec->codec_variant = ALC269_TYPE_ALC259; |
14994 | } | ||
14704 | } else | 14995 | } else |
14705 | alc_fix_pll_init(codec, 0x20, 0x04, 15); | 14996 | alc_fix_pll_init(codec, 0x20, 0x04, 15); |
14706 | 14997 | ||
14998 | alc269_fill_coef(codec); | ||
14999 | |||
14707 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, | 15000 | board_config = snd_hda_check_board_config(codec, ALC269_MODEL_LAST, |
14708 | alc269_models, | 15001 | alc269_models, |
14709 | alc269_cfg_tbl); | 15002 | alc269_cfg_tbl); |
@@ -14760,7 +15053,7 @@ static int patch_alc269(struct hda_codec *codec) | |||
14760 | spec->stream_digital_capture = &alc269_pcm_digital_capture; | 15053 | spec->stream_digital_capture = &alc269_pcm_digital_capture; |
14761 | 15054 | ||
14762 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ | 15055 | if (!spec->adc_nids) { /* wasn't filled automatically? use default */ |
14763 | if (!is_alc269vb) { | 15056 | if (spec->codec_variant != ALC269_TYPE_NORMAL) { |
14764 | spec->adc_nids = alc269_adc_nids; | 15057 | spec->adc_nids = alc269_adc_nids; |
14765 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); | 15058 | spec->num_adc_nids = ARRAY_SIZE(alc269_adc_nids); |
14766 | spec->capsrc_nids = alc269_capsrc_nids; | 15059 | spec->capsrc_nids = alc269_capsrc_nids; |
@@ -14782,6 +15075,12 @@ static int patch_alc269(struct hda_codec *codec) | |||
14782 | spec->vmaster_nid = 0x02; | 15075 | spec->vmaster_nid = 0x02; |
14783 | 15076 | ||
14784 | codec->patch_ops = alc_patch_ops; | 15077 | codec->patch_ops = alc_patch_ops; |
15078 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
15079 | codec->patch_ops.suspend = alc269_suspend; | ||
15080 | #endif | ||
15081 | #ifdef SND_HDA_NEEDS_RESUME | ||
15082 | codec->patch_ops.resume = alc269_resume; | ||
15083 | #endif | ||
14785 | if (board_config == ALC269_AUTO) | 15084 | if (board_config == ALC269_AUTO) |
14786 | spec->init_hook = alc269_auto_init; | 15085 | spec->init_hook = alc269_auto_init; |
14787 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 15086 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
@@ -15596,12 +15895,13 @@ static void alc861_auto_init_hp_out(struct hda_codec *codec) | |||
15596 | static void alc861_auto_init_analog_input(struct hda_codec *codec) | 15895 | static void alc861_auto_init_analog_input(struct hda_codec *codec) |
15597 | { | 15896 | { |
15598 | struct alc_spec *spec = codec->spec; | 15897 | struct alc_spec *spec = codec->spec; |
15898 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
15599 | int i; | 15899 | int i; |
15600 | 15900 | ||
15601 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 15901 | for (i = 0; i < cfg->num_inputs; i++) { |
15602 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 15902 | hda_nid_t nid = cfg->inputs[i].pin; |
15603 | if (nid >= 0x0c && nid <= 0x11) | 15903 | if (nid >= 0x0c && nid <= 0x11) |
15604 | alc_set_input_pin(codec, nid, i); | 15904 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
15605 | } | 15905 | } |
15606 | } | 15906 | } |
15607 | 15907 | ||
@@ -15830,15 +16130,13 @@ enum { | |||
15830 | PINFIX_FSC_AMILO_PI1505, | 16130 | PINFIX_FSC_AMILO_PI1505, |
15831 | }; | 16131 | }; |
15832 | 16132 | ||
15833 | static struct alc_pincfg alc861_fsc_amilo_pi1505_pinfix[] = { | ||
15834 | { 0x0b, 0x0221101f }, /* HP */ | ||
15835 | { 0x0f, 0x90170310 }, /* speaker */ | ||
15836 | { } | ||
15837 | }; | ||
15838 | |||
15839 | static const struct alc_fixup alc861_fixups[] = { | 16133 | static const struct alc_fixup alc861_fixups[] = { |
15840 | [PINFIX_FSC_AMILO_PI1505] = { | 16134 | [PINFIX_FSC_AMILO_PI1505] = { |
15841 | .pins = alc861_fsc_amilo_pi1505_pinfix | 16135 | .pins = (const struct alc_pincfg[]) { |
16136 | { 0x0b, 0x0221101f }, /* HP */ | ||
16137 | { 0x0f, 0x90170310 }, /* speaker */ | ||
16138 | { } | ||
16139 | } | ||
15842 | }, | 16140 | }, |
15843 | }; | 16141 | }; |
15844 | 16142 | ||
@@ -16590,12 +16888,13 @@ static void alc861vd_auto_init_hp_out(struct hda_codec *codec) | |||
16590 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) | 16888 | static void alc861vd_auto_init_analog_input(struct hda_codec *codec) |
16591 | { | 16889 | { |
16592 | struct alc_spec *spec = codec->spec; | 16890 | struct alc_spec *spec = codec->spec; |
16891 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
16593 | int i; | 16892 | int i; |
16594 | 16893 | ||
16595 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 16894 | for (i = 0; i < cfg->num_inputs; i++) { |
16596 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 16895 | hda_nid_t nid = cfg->inputs[i].pin; |
16597 | if (alc_is_input_pin(codec, nid)) { | 16896 | if (alc_is_input_pin(codec, nid)) { |
16598 | alc_set_input_pin(codec, nid, i); | 16897 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
16599 | if (nid != ALC861VD_PIN_CD_NID && | 16898 | if (nid != ALC861VD_PIN_CD_NID && |
16600 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 16899 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
16601 | snd_hda_codec_write(codec, nid, 0, | 16900 | snd_hda_codec_write(codec, nid, 0, |
@@ -16805,16 +17104,14 @@ enum { | |||
16805 | }; | 17104 | }; |
16806 | 17105 | ||
16807 | /* reset GPIO1 */ | 17106 | /* reset GPIO1 */ |
16808 | static const struct hda_verb alc660vd_fix_asus_gpio1_verbs[] = { | ||
16809 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
16810 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
16811 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
16812 | { } | ||
16813 | }; | ||
16814 | |||
16815 | static const struct alc_fixup alc861vd_fixups[] = { | 17107 | static const struct alc_fixup alc861vd_fixups[] = { |
16816 | [ALC660VD_FIX_ASUS_GPIO1] = { | 17108 | [ALC660VD_FIX_ASUS_GPIO1] = { |
16817 | .verbs = alc660vd_fix_asus_gpio1_verbs, | 17109 | .verbs = (const struct hda_verb[]) { |
17110 | {0x01, AC_VERB_SET_GPIO_MASK, 0x03}, | ||
17111 | {0x01, AC_VERB_SET_GPIO_DIRECTION, 0x01}, | ||
17112 | {0x01, AC_VERB_SET_GPIO_DATA, 0x01}, | ||
17113 | { } | ||
17114 | } | ||
16818 | }, | 17115 | }, |
16819 | }; | 17116 | }; |
16820 | 17117 | ||
@@ -18828,12 +19125,13 @@ static void alc662_auto_init_hp_out(struct hda_codec *codec) | |||
18828 | static void alc662_auto_init_analog_input(struct hda_codec *codec) | 19125 | static void alc662_auto_init_analog_input(struct hda_codec *codec) |
18829 | { | 19126 | { |
18830 | struct alc_spec *spec = codec->spec; | 19127 | struct alc_spec *spec = codec->spec; |
19128 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
18831 | int i; | 19129 | int i; |
18832 | 19130 | ||
18833 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 19131 | for (i = 0; i < cfg->num_inputs; i++) { |
18834 | hda_nid_t nid = spec->autocfg.input_pins[i]; | 19132 | hda_nid_t nid = cfg->inputs[i].pin; |
18835 | if (alc_is_input_pin(codec, nid)) { | 19133 | if (alc_is_input_pin(codec, nid)) { |
18836 | alc_set_input_pin(codec, nid, i); | 19134 | alc_set_input_pin(codec, nid, cfg->inputs[i].type); |
18837 | if (nid != ALC662_PIN_CD_NID && | 19135 | if (nid != ALC662_PIN_CD_NID && |
18838 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) | 19136 | (get_wcaps(codec, nid) & AC_WCAP_OUT_AMP)) |
18839 | snd_hda_codec_write(codec, nid, 0, | 19137 | snd_hda_codec_write(codec, nid, 0, |
@@ -18925,6 +19223,26 @@ static void alc662_auto_init(struct hda_codec *codec) | |||
18925 | alc_inithook(codec); | 19223 | alc_inithook(codec); |
18926 | } | 19224 | } |
18927 | 19225 | ||
19226 | enum { | ||
19227 | ALC662_FIXUP_IDEAPAD, | ||
19228 | }; | ||
19229 | |||
19230 | static const struct alc_fixup alc662_fixups[] = { | ||
19231 | [ALC662_FIXUP_IDEAPAD] = { | ||
19232 | .pins = (const struct alc_pincfg[]) { | ||
19233 | { 0x17, 0x99130112 }, /* subwoofer */ | ||
19234 | { } | ||
19235 | } | ||
19236 | }, | ||
19237 | }; | ||
19238 | |||
19239 | static struct snd_pci_quirk alc662_fixup_tbl[] = { | ||
19240 | SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Ideapad Y550", ALC662_FIXUP_IDEAPAD), | ||
19241 | {} | ||
19242 | }; | ||
19243 | |||
19244 | |||
19245 | |||
18928 | static int patch_alc662(struct hda_codec *codec) | 19246 | static int patch_alc662(struct hda_codec *codec) |
18929 | { | 19247 | { |
18930 | struct alc_spec *spec; | 19248 | struct alc_spec *spec; |
@@ -18957,6 +19275,7 @@ static int patch_alc662(struct hda_codec *codec) | |||
18957 | } | 19275 | } |
18958 | 19276 | ||
18959 | if (board_config == ALC662_AUTO) { | 19277 | if (board_config == ALC662_AUTO) { |
19278 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 1); | ||
18960 | /* automatic parse from the BIOS config */ | 19279 | /* automatic parse from the BIOS config */ |
18961 | err = alc662_parse_auto_config(codec); | 19280 | err = alc662_parse_auto_config(codec); |
18962 | if (err < 0) { | 19281 | if (err < 0) { |
@@ -19015,8 +19334,11 @@ static int patch_alc662(struct hda_codec *codec) | |||
19015 | spec->vmaster_nid = 0x02; | 19334 | spec->vmaster_nid = 0x02; |
19016 | 19335 | ||
19017 | codec->patch_ops = alc_patch_ops; | 19336 | codec->patch_ops = alc_patch_ops; |
19018 | if (board_config == ALC662_AUTO) | 19337 | if (board_config == ALC662_AUTO) { |
19019 | spec->init_hook = alc662_auto_init; | 19338 | spec->init_hook = alc662_auto_init; |
19339 | alc_pick_fixup(codec, alc662_fixup_tbl, alc662_fixups, 0); | ||
19340 | } | ||
19341 | |||
19020 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 19342 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
19021 | if (!spec->loopback.amplist) | 19343 | if (!spec->loopback.amplist) |
19022 | spec->loopback.amplist = alc662_loopbacks; | 19344 | spec->loopback.amplist = alc662_loopbacks; |
@@ -19060,6 +19382,39 @@ static hda_nid_t alc680_adc_nids[3] = { | |||
19060 | /* | 19382 | /* |
19061 | * Analog capture ADC cgange | 19383 | * Analog capture ADC cgange |
19062 | */ | 19384 | */ |
19385 | static void alc680_rec_autoswitch(struct hda_codec *codec) | ||
19386 | { | ||
19387 | struct alc_spec *spec = codec->spec; | ||
19388 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19389 | int pin_found = 0; | ||
19390 | int type_found = AUTO_PIN_LAST; | ||
19391 | hda_nid_t nid; | ||
19392 | int i; | ||
19393 | |||
19394 | for (i = 0; i < cfg->num_inputs; i++) { | ||
19395 | nid = cfg->inputs[i].pin; | ||
19396 | if (!(snd_hda_query_pin_caps(codec, nid) & | ||
19397 | AC_PINCAP_PRES_DETECT)) | ||
19398 | continue; | ||
19399 | if (snd_hda_jack_detect(codec, nid)) { | ||
19400 | if (cfg->inputs[i].type < type_found) { | ||
19401 | type_found = cfg->inputs[i].type; | ||
19402 | pin_found = nid; | ||
19403 | } | ||
19404 | } | ||
19405 | } | ||
19406 | |||
19407 | nid = 0x07; | ||
19408 | if (pin_found) | ||
19409 | snd_hda_get_connections(codec, pin_found, &nid, 1); | ||
19410 | |||
19411 | if (nid != spec->cur_adc) | ||
19412 | __snd_hda_codec_cleanup_stream(codec, spec->cur_adc, 1); | ||
19413 | spec->cur_adc = nid; | ||
19414 | snd_hda_codec_setup_stream(codec, nid, spec->cur_adc_stream_tag, 0, | ||
19415 | spec->cur_adc_format); | ||
19416 | } | ||
19417 | |||
19063 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 19418 | static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, |
19064 | struct hda_codec *codec, | 19419 | struct hda_codec *codec, |
19065 | unsigned int stream_tag, | 19420 | unsigned int stream_tag, |
@@ -19067,24 +19422,12 @@ static int alc680_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | |||
19067 | struct snd_pcm_substream *substream) | 19422 | struct snd_pcm_substream *substream) |
19068 | { | 19423 | { |
19069 | struct alc_spec *spec = codec->spec; | 19424 | struct alc_spec *spec = codec->spec; |
19070 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19071 | unsigned int pre_mic, pre_line; | ||
19072 | |||
19073 | pre_mic = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19074 | pre_line = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_LINE]); | ||
19075 | 19425 | ||
19426 | spec->cur_adc = 0x07; | ||
19076 | spec->cur_adc_stream_tag = stream_tag; | 19427 | spec->cur_adc_stream_tag = stream_tag; |
19077 | spec->cur_adc_format = format; | 19428 | spec->cur_adc_format = format; |
19078 | 19429 | ||
19079 | if (pre_mic || pre_line) { | 19430 | alc680_rec_autoswitch(codec); |
19080 | if (pre_mic) | ||
19081 | snd_hda_codec_setup_stream(codec, 0x08, stream_tag, 0, | ||
19082 | format); | ||
19083 | else | ||
19084 | snd_hda_codec_setup_stream(codec, 0x09, stream_tag, 0, | ||
19085 | format); | ||
19086 | } else | ||
19087 | snd_hda_codec_setup_stream(codec, 0x07, stream_tag, 0, format); | ||
19088 | return 0; | 19431 | return 0; |
19089 | } | 19432 | } |
19090 | 19433 | ||
@@ -19170,6 +19513,7 @@ static struct hda_verb alc680_init_verbs[] = { | |||
19170 | 19513 | ||
19171 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, | 19514 | {0x16, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_HP_EVENT | AC_USRSP_EN}, |
19172 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | 19515 | {0x18, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, |
19516 | {0x19, AC_VERB_SET_UNSOLICITED_ENABLE, ALC880_MIC_EVENT | AC_USRSP_EN}, | ||
19173 | 19517 | ||
19174 | { } | 19518 | { } |
19175 | }; | 19519 | }; |
@@ -19182,25 +19526,11 @@ static void alc680_base_setup(struct hda_codec *codec) | |||
19182 | spec->autocfg.hp_pins[0] = 0x16; | 19526 | spec->autocfg.hp_pins[0] = 0x16; |
19183 | spec->autocfg.speaker_pins[0] = 0x14; | 19527 | spec->autocfg.speaker_pins[0] = 0x14; |
19184 | spec->autocfg.speaker_pins[1] = 0x15; | 19528 | spec->autocfg.speaker_pins[1] = 0x15; |
19185 | spec->autocfg.input_pins[AUTO_PIN_MIC] = 0x18; | 19529 | spec->autocfg.num_inputs = 2; |
19186 | spec->autocfg.input_pins[AUTO_PIN_LINE] = 0x19; | 19530 | spec->autocfg.inputs[0].pin = 0x18; |
19187 | } | 19531 | spec->autocfg.inputs[0].type = AUTO_PIN_MIC; |
19188 | 19532 | spec->autocfg.inputs[1].pin = 0x19; | |
19189 | static void alc680_rec_autoswitch(struct hda_codec *codec) | 19533 | spec->autocfg.inputs[1].type = AUTO_PIN_LINE_IN; |
19190 | { | ||
19191 | struct alc_spec *spec = codec->spec; | ||
19192 | struct auto_pin_cfg *cfg = &spec->autocfg; | ||
19193 | unsigned int present; | ||
19194 | hda_nid_t new_adc; | ||
19195 | |||
19196 | present = snd_hda_jack_detect(codec, cfg->input_pins[AUTO_PIN_MIC]); | ||
19197 | |||
19198 | new_adc = present ? 0x8 : 0x7; | ||
19199 | __snd_hda_codec_cleanup_stream(codec, !present ? 0x8 : 0x7, 1); | ||
19200 | snd_hda_codec_setup_stream(codec, new_adc, | ||
19201 | spec->cur_adc_stream_tag, 0, | ||
19202 | spec->cur_adc_format); | ||
19203 | |||
19204 | } | 19534 | } |
19205 | 19535 | ||
19206 | static void alc680_unsol_event(struct hda_codec *codec, | 19536 | 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 95148e58026c..a90327b0cc3e 100644 --- a/sound/pci/hda/patch_sigmatel.c +++ b/sound/pci/hda/patch_sigmatel.c | |||
@@ -263,6 +263,7 @@ struct sigmatel_spec { | |||
263 | 263 | ||
264 | struct sigmatel_mic_route ext_mic; | 264 | struct sigmatel_mic_route ext_mic; |
265 | struct sigmatel_mic_route int_mic; | 265 | struct sigmatel_mic_route int_mic; |
266 | struct sigmatel_mic_route dock_mic; | ||
266 | 267 | ||
267 | const char **spdif_labels; | 268 | const char **spdif_labels; |
268 | 269 | ||
@@ -382,6 +383,11 @@ static unsigned int stac92hd83xxx_pwr_mapping[4] = { | |||
382 | 0x03, 0x0c, 0x20, 0x40, | 383 | 0x03, 0x0c, 0x20, 0x40, |
383 | }; | 384 | }; |
384 | 385 | ||
386 | #define STAC92HD83XXX_NUM_DMICS 2 | ||
387 | static hda_nid_t stac92hd83xxx_dmic_nids[STAC92HD83XXX_NUM_DMICS + 1] = { | ||
388 | 0x11, 0x20, 0 | ||
389 | }; | ||
390 | |||
385 | #define STAC92HD83XXX_NUM_CAPS 2 | 391 | #define STAC92HD83XXX_NUM_CAPS 2 |
386 | static unsigned long stac92hd83xxx_capvols[] = { | 392 | static unsigned long stac92hd83xxx_capvols[] = { |
387 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), | 393 | HDA_COMPOSE_AMP_VAL(0x17, 3, 0, HDA_OUTPUT), |
@@ -1105,9 +1111,7 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1105 | struct hda_input_mux *smux = &spec->private_smux; | 1111 | struct hda_input_mux *smux = &spec->private_smux; |
1106 | /* check for mute support on SPDIF out */ | 1112 | /* check for mute support on SPDIF out */ |
1107 | if (wcaps & AC_WCAP_OUT_AMP) { | 1113 | if (wcaps & AC_WCAP_OUT_AMP) { |
1108 | smux->items[smux->num_items].label = "Off"; | 1114 | 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; | 1115 | spec->spdif_mute = 1; |
1112 | } | 1116 | } |
1113 | stac_smux_mixer.count = spec->num_smuxes; | 1117 | stac_smux_mixer.count = spec->num_smuxes; |
@@ -1180,14 +1184,11 @@ static int stac92xx_build_controls(struct hda_codec *codec) | |||
1180 | if (err < 0) | 1184 | if (err < 0) |
1181 | return err; | 1185 | return err; |
1182 | } | 1186 | } |
1183 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 1187 | for (i = 0; i < cfg->num_inputs; i++) { |
1184 | nid = cfg->input_pins[i]; | 1188 | nid = cfg->inputs[i].pin; |
1185 | if (nid) { | 1189 | err = stac92xx_add_jack(codec, nid, SND_JACK_MICROPHONE); |
1186 | err = stac92xx_add_jack(codec, nid, | 1190 | if (err < 0) |
1187 | SND_JACK_MICROPHONE); | 1191 | return err; |
1188 | if (err < 0) | ||
1189 | return err; | ||
1190 | } | ||
1191 | } | 1192 | } |
1192 | 1193 | ||
1193 | return 0; | 1194 | return 0; |
@@ -2777,7 +2778,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
2777 | struct sigmatel_spec *spec = codec->spec; | 2778 | struct sigmatel_spec *spec = codec->spec; |
2778 | char name[22]; | 2779 | char name[22]; |
2779 | 2780 | ||
2780 | if (!((get_defcfg_connect(def_conf)) & AC_JACK_PORT_FIXED)) { | 2781 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
2781 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD | 2782 | if (stac92xx_get_default_vref(codec, nid) == AC_PINCTL_VREF_GRD |
2782 | && nid == spec->line_switch) | 2783 | && nid == spec->line_switch) |
2783 | control = STAC_CTL_WIDGET_IO_SWITCH; | 2784 | control = STAC_CTL_WIDGET_IO_SWITCH; |
@@ -2789,7 +2790,7 @@ static inline int stac92xx_add_jack_mode_control(struct hda_codec *codec, | |||
2789 | } | 2790 | } |
2790 | 2791 | ||
2791 | if (control) { | 2792 | if (control) { |
2792 | strcpy(name, auto_pin_cfg_labels[idx]); | 2793 | strcpy(name, hda_get_input_pin_label(codec, nid, 1)); |
2793 | return stac92xx_add_control(codec->spec, control, | 2794 | return stac92xx_add_control(codec->spec, control, |
2794 | strcat(name, " Jack Mode"), nid); | 2795 | strcat(name, " Jack Mode"), nid); |
2795 | } | 2796 | } |
@@ -2821,41 +2822,49 @@ static hda_nid_t check_line_out_switch(struct hda_codec *codec) | |||
2821 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2822 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2822 | hda_nid_t nid; | 2823 | hda_nid_t nid; |
2823 | unsigned int pincap; | 2824 | unsigned int pincap; |
2825 | int i; | ||
2824 | 2826 | ||
2825 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2827 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2826 | return 0; | 2828 | return 0; |
2827 | nid = cfg->input_pins[AUTO_PIN_LINE]; | 2829 | for (i = 0; i < cfg->num_inputs; i++) { |
2828 | pincap = snd_hda_query_pin_caps(codec, nid); | 2830 | if (cfg->inputs[i].type == AUTO_PIN_LINE_IN) { |
2829 | if (pincap & AC_PINCAP_OUT) | 2831 | nid = cfg->inputs[i].pin; |
2830 | return nid; | 2832 | pincap = snd_hda_query_pin_caps(codec, nid); |
2833 | if (pincap & AC_PINCAP_OUT) | ||
2834 | return nid; | ||
2835 | } | ||
2836 | } | ||
2831 | return 0; | 2837 | return 0; |
2832 | } | 2838 | } |
2833 | 2839 | ||
2840 | static hda_nid_t get_unassigned_dac(struct hda_codec *codec, hda_nid_t nid); | ||
2841 | |||
2834 | /* check whether the mic-input can be used as line-out */ | 2842 | /* check whether the mic-input can be used as line-out */ |
2835 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec) | 2843 | static hda_nid_t check_mic_out_switch(struct hda_codec *codec, hda_nid_t *dac) |
2836 | { | 2844 | { |
2837 | struct sigmatel_spec *spec = codec->spec; | 2845 | struct sigmatel_spec *spec = codec->spec; |
2838 | struct auto_pin_cfg *cfg = &spec->autocfg; | 2846 | struct auto_pin_cfg *cfg = &spec->autocfg; |
2839 | unsigned int def_conf, pincap; | 2847 | unsigned int def_conf, pincap; |
2840 | unsigned int mic_pin; | 2848 | int i; |
2841 | 2849 | ||
2850 | *dac = 0; | ||
2842 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) | 2851 | if (cfg->line_out_type != AUTO_PIN_LINE_OUT) |
2843 | return 0; | 2852 | return 0; |
2844 | mic_pin = AUTO_PIN_MIC; | 2853 | for (i = 0; i < cfg->num_inputs; i++) { |
2845 | for (;;) { | 2854 | hda_nid_t nid = cfg->inputs[i].pin; |
2846 | hda_nid_t nid = cfg->input_pins[mic_pin]; | 2855 | if (cfg->inputs[i].type != AUTO_PIN_MIC) |
2856 | continue; | ||
2847 | def_conf = snd_hda_codec_get_pincfg(codec, nid); | 2857 | def_conf = snd_hda_codec_get_pincfg(codec, nid); |
2848 | /* some laptops have an internal analog microphone | 2858 | /* some laptops have an internal analog microphone |
2849 | * which can't be used as a output */ | 2859 | * which can't be used as a output */ |
2850 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_FIXED) { | 2860 | if (snd_hda_get_input_pin_attr(def_conf) != INPUT_PIN_ATTR_INT) { |
2851 | pincap = snd_hda_query_pin_caps(codec, nid); | 2861 | pincap = snd_hda_query_pin_caps(codec, nid); |
2852 | if (pincap & AC_PINCAP_OUT) | 2862 | if (pincap & AC_PINCAP_OUT) { |
2853 | return nid; | 2863 | *dac = get_unassigned_dac(codec, nid); |
2864 | if (*dac) | ||
2865 | return nid; | ||
2866 | } | ||
2854 | } | 2867 | } |
2855 | if (mic_pin == AUTO_PIN_MIC) | ||
2856 | mic_pin = AUTO_PIN_FRONT_MIC; | ||
2857 | else | ||
2858 | break; | ||
2859 | } | 2868 | } |
2860 | return 0; | 2869 | return 0; |
2861 | } | 2870 | } |
@@ -3002,17 +3011,14 @@ static int stac92xx_auto_fill_dac_nids(struct hda_codec *codec) | |||
3002 | } | 3011 | } |
3003 | } | 3012 | } |
3004 | /* add mic as output */ | 3013 | /* add mic as output */ |
3005 | nid = check_mic_out_switch(codec); | 3014 | nid = check_mic_out_switch(codec, &dac); |
3006 | if (nid) { | 3015 | if (nid && dac) { |
3007 | dac = get_unassigned_dac(codec, nid); | 3016 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", |
3008 | if (dac) { | 3017 | nid, cfg->line_outs); |
3009 | snd_printdd("STAC: Add mic-in 0x%x as output %d\n", | 3018 | cfg->line_out_pins[cfg->line_outs] = nid; |
3010 | nid, cfg->line_outs); | 3019 | cfg->line_outs++; |
3011 | cfg->line_out_pins[cfg->line_outs] = nid; | 3020 | spec->mic_switch = nid; |
3012 | cfg->line_outs++; | 3021 | add_spec_dacs(spec, dac); |
3013 | spec->mic_switch = nid; | ||
3014 | add_spec_dacs(spec, dac); | ||
3015 | } | ||
3016 | } | 3022 | } |
3017 | 3023 | ||
3018 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", | 3024 | snd_printd("stac92xx: dac_nids=%d (0x%x/0x%x/0x%x/0x%x/0x%x)\n", |
@@ -3202,13 +3208,13 @@ static int stac92xx_auto_create_multi_out_ctls(struct hda_codec *codec, | |||
3202 | return err; | 3208 | return err; |
3203 | } | 3209 | } |
3204 | 3210 | ||
3205 | for (idx = AUTO_PIN_MIC; idx <= AUTO_PIN_FRONT_LINE; idx++) { | 3211 | for (idx = 0; idx < cfg->num_inputs; idx++) { |
3206 | nid = cfg->input_pins[idx]; | 3212 | if (cfg->inputs[idx].type > AUTO_PIN_LINE_IN) |
3207 | if (nid) { | 3213 | break; |
3208 | err = stac92xx_add_jack_mode_control(codec, nid, idx); | 3214 | nid = cfg->inputs[idx].pin; |
3209 | if (err < 0) | 3215 | err = stac92xx_add_jack_mode_control(codec, nid, idx); |
3210 | return err; | 3216 | if (err < 0) |
3211 | } | 3217 | return err; |
3212 | } | 3218 | } |
3213 | 3219 | ||
3214 | return 0; | 3220 | return 0; |
@@ -3254,12 +3260,9 @@ static int stac92xx_auto_create_mono_output_ctls(struct hda_codec *codec) | |||
3254 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) | 3260 | if (num_cons <= 0 || num_cons > ARRAY_SIZE(stac92xx_mono_labels)) |
3255 | return -EINVAL; | 3261 | return -EINVAL; |
3256 | 3262 | ||
3257 | for (i = 0; i < num_cons; i++) { | 3263 | for (i = 0; i < num_cons; i++) |
3258 | mono_mux->items[mono_mux->num_items].label = | 3264 | snd_hda_add_imux_item(mono_mux, stac92xx_mono_labels[i], i, |
3259 | stac92xx_mono_labels[i]; | 3265 | NULL); |
3260 | mono_mux->items[mono_mux->num_items].index = i; | ||
3261 | mono_mux->num_items++; | ||
3262 | } | ||
3263 | 3266 | ||
3264 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, | 3267 | return stac92xx_add_control(spec, STAC_CTL_WIDGET_MONO_MUX, |
3265 | "Mono Mux", spec->mono_nid); | 3268 | "Mono Mux", spec->mono_nid); |
@@ -3384,11 +3387,8 @@ static int stac92xx_auto_create_spdif_mux_ctls(struct hda_codec *codec) | |||
3384 | if (!labels) | 3387 | if (!labels) |
3385 | labels = stac92xx_spdif_labels; | 3388 | labels = stac92xx_spdif_labels; |
3386 | 3389 | ||
3387 | for (i = 0; i < num_cons; i++) { | 3390 | for (i = 0; i < num_cons; i++) |
3388 | spdif_mux->items[spdif_mux->num_items].label = labels[i]; | 3391 | snd_hda_add_imux_item(spdif_mux, labels[i], i, NULL); |
3389 | spdif_mux->items[spdif_mux->num_items].index = i; | ||
3390 | spdif_mux->num_items++; | ||
3391 | } | ||
3392 | 3392 | ||
3393 | return 0; | 3393 | return 0; |
3394 | } | 3394 | } |
@@ -3415,7 +3415,7 @@ static int get_connection_index(struct hda_codec *codec, hda_nid_t mux, | |||
3415 | /* create a volume assigned to the given pin (only if supported) */ | 3415 | /* create a volume assigned to the given pin (only if supported) */ |
3416 | /* return 1 if the volume control is created */ | 3416 | /* return 1 if the volume control is created */ |
3417 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | 3417 | static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, |
3418 | const char *label, int direction) | 3418 | const char *label, int idx, int direction) |
3419 | { | 3419 | { |
3420 | unsigned int caps, nums; | 3420 | unsigned int caps, nums; |
3421 | char name[32]; | 3421 | char name[32]; |
@@ -3432,8 +3432,8 @@ static int create_elem_capture_vol(struct hda_codec *codec, hda_nid_t nid, | |||
3432 | if (!nums) | 3432 | if (!nums) |
3433 | return 0; | 3433 | return 0; |
3434 | snprintf(name, sizeof(name), "%s Capture Volume", label); | 3434 | snprintf(name, sizeof(name), "%s Capture Volume", label); |
3435 | err = stac92xx_add_control(codec->spec, STAC_CTL_WIDGET_VOL, name, | 3435 | err = stac92xx_add_control_idx(codec->spec, STAC_CTL_WIDGET_VOL, idx, name, |
3436 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); | 3436 | HDA_COMPOSE_AMP_VAL(nid, 3, 0, direction)); |
3437 | if (err < 0) | 3437 | if (err < 0) |
3438 | return err; | 3438 | return err; |
3439 | return 1; | 3439 | return 1; |
@@ -3446,27 +3446,14 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3446 | struct sigmatel_spec *spec = codec->spec; | 3446 | struct sigmatel_spec *spec = codec->spec; |
3447 | struct hda_input_mux *imux = &spec->private_imux; | 3447 | struct hda_input_mux *imux = &spec->private_imux; |
3448 | struct hda_input_mux *dimux = &spec->private_dimux; | 3448 | struct hda_input_mux *dimux = &spec->private_dimux; |
3449 | int err, i, active_mics; | 3449 | int err, i; |
3450 | unsigned int def_conf; | 3450 | unsigned int def_conf; |
3451 | 3451 | ||
3452 | dimux->items[dimux->num_items].label = stac92xx_dmic_labels[0]; | 3452 | snd_hda_add_imux_item(dimux, stac92xx_dmic_labels[0], 0, NULL); |
3453 | dimux->items[dimux->num_items].index = 0; | ||
3454 | dimux->num_items++; | ||
3455 | |||
3456 | active_mics = 0; | ||
3457 | for (i = 0; i < spec->num_dmics; i++) { | ||
3458 | /* check the validity: sometimes it's a dead vendor-spec node */ | ||
3459 | if (get_wcaps_type(get_wcaps(codec, spec->dmic_nids[i])) | ||
3460 | != AC_WID_PIN) | ||
3461 | continue; | ||
3462 | def_conf = snd_hda_codec_get_pincfg(codec, spec->dmic_nids[i]); | ||
3463 | if (get_defcfg_connect(def_conf) != AC_JACK_PORT_NONE) | ||
3464 | active_mics++; | ||
3465 | } | ||
3466 | 3453 | ||
3467 | for (i = 0; i < spec->num_dmics; i++) { | 3454 | for (i = 0; i < spec->num_dmics; i++) { |
3468 | hda_nid_t nid; | 3455 | hda_nid_t nid; |
3469 | int index; | 3456 | int index, type_idx; |
3470 | const char *label; | 3457 | const char *label; |
3471 | 3458 | ||
3472 | nid = spec->dmic_nids[i]; | 3459 | nid = spec->dmic_nids[i]; |
@@ -3480,49 +3467,49 @@ static int stac92xx_auto_create_dmic_input_ctls(struct hda_codec *codec, | |||
3480 | if (index < 0) | 3467 | if (index < 0) |
3481 | continue; | 3468 | continue; |
3482 | 3469 | ||
3483 | if (active_mics == 1) | 3470 | label = hda_get_input_pin_label(codec, nid, 1); |
3484 | label = "Digital Mic"; | 3471 | snd_hda_add_imux_item(dimux, label, index, &type_idx); |
3485 | else | ||
3486 | label = stac92xx_dmic_labels[dimux->num_items]; | ||
3487 | 3472 | ||
3488 | err = create_elem_capture_vol(codec, nid, label, HDA_INPUT); | 3473 | err = create_elem_capture_vol(codec, nid, label, type_idx, |
3474 | HDA_INPUT); | ||
3489 | if (err < 0) | 3475 | if (err < 0) |
3490 | return err; | 3476 | return err; |
3491 | if (!err) { | 3477 | if (!err) { |
3492 | err = create_elem_capture_vol(codec, nid, label, | 3478 | err = create_elem_capture_vol(codec, nid, label, |
3493 | HDA_OUTPUT); | 3479 | type_idx, HDA_OUTPUT); |
3494 | if (err < 0) | 3480 | if (err < 0) |
3495 | return err; | 3481 | return err; |
3496 | } | 3482 | } |
3497 | 3483 | ||
3498 | dimux->items[dimux->num_items].label = label; | 3484 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) |
3499 | dimux->items[dimux->num_items].index = index; | 3485 | snd_hda_add_imux_item(imux, label, index, NULL); |
3500 | dimux->num_items++; | ||
3501 | if (snd_hda_get_bool_hint(codec, "separate_dmux") != 1) { | ||
3502 | imux->items[imux->num_items].label = label; | ||
3503 | imux->items[imux->num_items].index = index; | ||
3504 | imux->num_items++; | ||
3505 | } | ||
3506 | } | 3486 | } |
3507 | 3487 | ||
3508 | return 0; | 3488 | return 0; |
3509 | } | 3489 | } |
3510 | 3490 | ||
3511 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, | 3491 | static int check_mic_pin(struct hda_codec *codec, hda_nid_t nid, |
3512 | hda_nid_t *fixed, hda_nid_t *ext) | 3492 | hda_nid_t *fixed, hda_nid_t *ext, hda_nid_t *dock) |
3513 | { | 3493 | { |
3514 | unsigned int cfg; | 3494 | unsigned int cfg; |
3515 | 3495 | ||
3516 | if (!nid) | 3496 | if (!nid) |
3517 | return 0; | 3497 | return 0; |
3518 | cfg = snd_hda_codec_get_pincfg(codec, nid); | 3498 | cfg = snd_hda_codec_get_pincfg(codec, nid); |
3519 | switch (get_defcfg_connect(cfg)) { | 3499 | switch (snd_hda_get_input_pin_attr(cfg)) { |
3520 | case AC_JACK_PORT_FIXED: | 3500 | case INPUT_PIN_ATTR_INT: |
3521 | if (*fixed) | 3501 | if (*fixed) |
3522 | return 1; /* already occupied */ | 3502 | return 1; /* already occupied */ |
3523 | *fixed = nid; | 3503 | *fixed = nid; |
3524 | break; | 3504 | break; |
3525 | case AC_JACK_PORT_COMPLEX: | 3505 | case INPUT_PIN_ATTR_UNUSED: |
3506 | break; | ||
3507 | case INPUT_PIN_ATTR_DOCK: | ||
3508 | if (*dock) | ||
3509 | return 1; /* already occupied */ | ||
3510 | *dock = nid; | ||
3511 | break; | ||
3512 | default: | ||
3526 | if (*ext) | 3513 | if (*ext) |
3527 | return 1; /* already occupied */ | 3514 | return 1; /* already occupied */ |
3528 | *ext = nid; | 3515 | *ext = nid; |
@@ -3540,10 +3527,13 @@ static int set_mic_route(struct hda_codec *codec, | |||
3540 | int i; | 3527 | int i; |
3541 | 3528 | ||
3542 | mic->pin = pin; | 3529 | mic->pin = pin; |
3543 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3530 | if (pin == 0) |
3544 | if (pin == cfg->input_pins[i]) | 3531 | return 0; |
3532 | for (i = 0; i < cfg->num_inputs; i++) { | ||
3533 | if (pin == cfg->inputs[i].pin) | ||
3545 | break; | 3534 | break; |
3546 | if (i <= AUTO_PIN_FRONT_MIC) { | 3535 | } |
3536 | if (i < cfg->num_inputs && cfg->inputs[i].type == AUTO_PIN_MIC) { | ||
3547 | /* analog pin */ | 3537 | /* analog pin */ |
3548 | i = get_connection_index(codec, spec->mux_nids[0], pin); | 3538 | i = get_connection_index(codec, spec->mux_nids[0], pin); |
3549 | if (i < 0) | 3539 | if (i < 0) |
@@ -3574,26 +3564,29 @@ static int stac_check_auto_mic(struct hda_codec *codec) | |||
3574 | { | 3564 | { |
3575 | struct sigmatel_spec *spec = codec->spec; | 3565 | struct sigmatel_spec *spec = codec->spec; |
3576 | struct auto_pin_cfg *cfg = &spec->autocfg; | 3566 | struct auto_pin_cfg *cfg = &spec->autocfg; |
3577 | hda_nid_t fixed, ext; | 3567 | hda_nid_t fixed, ext, dock; |
3578 | int i; | 3568 | int i; |
3579 | 3569 | ||
3580 | for (i = AUTO_PIN_LINE; i < AUTO_PIN_LAST; i++) { | 3570 | for (i = 0; i < cfg->num_inputs; i++) { |
3581 | if (cfg->input_pins[i]) | 3571 | if (cfg->inputs[i].type >= AUTO_PIN_LINE_IN) |
3582 | return 0; /* must be exclusively mics */ | 3572 | return 0; /* must be exclusively mics */ |
3583 | } | 3573 | } |
3584 | fixed = ext = 0; | 3574 | fixed = ext = dock = 0; |
3585 | for (i = AUTO_PIN_MIC; i <= AUTO_PIN_FRONT_MIC; i++) | 3575 | for (i = 0; i < cfg->num_inputs; i++) |
3586 | if (check_mic_pin(codec, cfg->input_pins[i], &fixed, &ext)) | 3576 | if (check_mic_pin(codec, cfg->inputs[i].pin, |
3577 | &fixed, &ext, &dock)) | ||
3587 | return 0; | 3578 | return 0; |
3588 | for (i = 0; i < spec->num_dmics; i++) | 3579 | for (i = 0; i < spec->num_dmics; i++) |
3589 | if (check_mic_pin(codec, spec->dmic_nids[i], &fixed, &ext)) | 3580 | if (check_mic_pin(codec, spec->dmic_nids[i], |
3581 | &fixed, &ext, &dock)) | ||
3590 | return 0; | 3582 | return 0; |
3591 | if (!fixed || !ext) | 3583 | if (!fixed && !ext && !dock) |
3592 | return 0; | 3584 | return 0; /* no input to switch */ |
3593 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) | 3585 | if (!(get_wcaps(codec, ext) & AC_WCAP_UNSOL_CAP)) |
3594 | return 0; /* no unsol support */ | 3586 | return 0; /* no unsol support */ |
3595 | if (set_mic_route(codec, &spec->ext_mic, ext) || | 3587 | if (set_mic_route(codec, &spec->ext_mic, ext) || |
3596 | set_mic_route(codec, &spec->int_mic, fixed)) | 3588 | set_mic_route(codec, &spec->int_mic, fixed) || |
3589 | set_mic_route(codec, &spec->dock_mic, dock)) | ||
3597 | return 0; /* something is wrong */ | 3590 | return 0; /* something is wrong */ |
3598 | return 1; | 3591 | return 1; |
3599 | } | 3592 | } |
@@ -3604,13 +3597,12 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
3604 | struct sigmatel_spec *spec = codec->spec; | 3597 | struct sigmatel_spec *spec = codec->spec; |
3605 | struct hda_input_mux *imux = &spec->private_imux; | 3598 | struct hda_input_mux *imux = &spec->private_imux; |
3606 | int i, j; | 3599 | int i, j; |
3600 | const char *label; | ||
3607 | 3601 | ||
3608 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 3602 | for (i = 0; i < cfg->num_inputs; i++) { |
3609 | hda_nid_t nid = cfg->input_pins[i]; | 3603 | hda_nid_t nid = cfg->inputs[i].pin; |
3610 | int index, err; | 3604 | int index, err, type_idx; |
3611 | 3605 | ||
3612 | if (!nid) | ||
3613 | continue; | ||
3614 | index = -1; | 3606 | index = -1; |
3615 | for (j = 0; j < spec->num_muxes; j++) { | 3607 | for (j = 0; j < spec->num_muxes; j++) { |
3616 | index = get_connection_index(codec, spec->mux_nids[j], | 3608 | index = get_connection_index(codec, spec->mux_nids[j], |
@@ -3621,15 +3613,14 @@ static int stac92xx_auto_create_analog_input_ctls(struct hda_codec *codec, const | |||
3621 | if (index < 0) | 3613 | if (index < 0) |
3622 | continue; | 3614 | continue; |
3623 | 3615 | ||
3616 | label = hda_get_autocfg_input_label(codec, cfg, i); | ||
3617 | snd_hda_add_imux_item(imux, label, index, &type_idx); | ||
3618 | |||
3624 | err = create_elem_capture_vol(codec, nid, | 3619 | err = create_elem_capture_vol(codec, nid, |
3625 | auto_pin_cfg_labels[i], | 3620 | label, type_idx, |
3626 | HDA_INPUT); | 3621 | HDA_INPUT); |
3627 | if (err < 0) | 3622 | if (err < 0) |
3628 | return err; | 3623 | return err; |
3629 | |||
3630 | imux->items[imux->num_items].label = auto_pin_cfg_labels[i]; | ||
3631 | imux->items[imux->num_items].index = index; | ||
3632 | imux->num_items++; | ||
3633 | } | 3624 | } |
3634 | spec->num_analog_muxes = imux->num_items; | 3625 | spec->num_analog_muxes = imux->num_items; |
3635 | 3626 | ||
@@ -4303,38 +4294,38 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4303 | AC_VERB_SET_CONNECT_SEL, 0); | 4294 | AC_VERB_SET_CONNECT_SEL, 0); |
4304 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) | 4295 | if (enable_pin_detect(codec, spec->ext_mic.pin, STAC_MIC_EVENT)) |
4305 | stac_issue_unsol_event(codec, spec->ext_mic.pin); | 4296 | stac_issue_unsol_event(codec, spec->ext_mic.pin); |
4306 | } | 4297 | if (enable_pin_detect(codec, spec->dock_mic.pin, |
4307 | for (i = 0; i < AUTO_PIN_LAST; i++) { | 4298 | STAC_MIC_EVENT)) |
4308 | hda_nid_t nid = cfg->input_pins[i]; | 4299 | stac_issue_unsol_event(codec, spec->dock_mic.pin); |
4309 | if (nid) { | 4300 | } |
4310 | unsigned int pinctl, conf; | 4301 | for (i = 0; i < cfg->num_inputs; i++) { |
4311 | if (i == AUTO_PIN_MIC || i == AUTO_PIN_FRONT_MIC) { | 4302 | hda_nid_t nid = cfg->inputs[i].pin; |
4312 | /* for mic pins, force to initialize */ | 4303 | int type = cfg->inputs[i].type; |
4313 | pinctl = stac92xx_get_default_vref(codec, nid); | 4304 | unsigned int pinctl, conf; |
4305 | if (type == AUTO_PIN_MIC) { | ||
4306 | /* for mic pins, force to initialize */ | ||
4307 | pinctl = stac92xx_get_default_vref(codec, nid); | ||
4308 | pinctl |= AC_PINCTL_IN_EN; | ||
4309 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | ||
4310 | } else { | ||
4311 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
4312 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4313 | /* if PINCTL already set then skip */ | ||
4314 | /* Also, if both INPUT and OUTPUT are set, | ||
4315 | * it must be a BIOS bug; need to override, too | ||
4316 | */ | ||
4317 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
4318 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
4319 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
4314 | pinctl |= AC_PINCTL_IN_EN; | 4320 | pinctl |= AC_PINCTL_IN_EN; |
4315 | stac92xx_auto_set_pinctl(codec, nid, pinctl); | 4321 | stac92xx_auto_set_pinctl(codec, nid, pinctl); |
4316 | } else { | ||
4317 | pinctl = snd_hda_codec_read(codec, nid, 0, | ||
4318 | AC_VERB_GET_PIN_WIDGET_CONTROL, 0); | ||
4319 | /* if PINCTL already set then skip */ | ||
4320 | /* Also, if both INPUT and OUTPUT are set, | ||
4321 | * it must be a BIOS bug; need to override, too | ||
4322 | */ | ||
4323 | if (!(pinctl & AC_PINCTL_IN_EN) || | ||
4324 | (pinctl & AC_PINCTL_OUT_EN)) { | ||
4325 | pinctl &= ~AC_PINCTL_OUT_EN; | ||
4326 | pinctl |= AC_PINCTL_IN_EN; | ||
4327 | stac92xx_auto_set_pinctl(codec, nid, | ||
4328 | pinctl); | ||
4329 | } | ||
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, | ||
4334 | STAC_INSERT_EVENT)) | ||
4335 | stac_issue_unsol_event(codec, nid); | ||
4336 | } | 4322 | } |
4337 | } | 4323 | } |
4324 | conf = snd_hda_codec_get_pincfg(codec, nid); | ||
4325 | if (get_defcfg_connect(conf) != AC_JACK_PORT_FIXED) { | ||
4326 | if (enable_pin_detect(codec, nid, STAC_INSERT_EVENT)) | ||
4327 | stac_issue_unsol_event(codec, nid); | ||
4328 | } | ||
4338 | } | 4329 | } |
4339 | for (i = 0; i < spec->num_dmics; i++) | 4330 | for (i = 0; i < spec->num_dmics; i++) |
4340 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], | 4331 | stac92xx_auto_set_pinctl(codec, spec->dmic_nids[i], |
@@ -4381,11 +4372,9 @@ static int stac92xx_init(struct hda_codec *codec) | |||
4381 | stac_issue_unsol_event(codec, nid); | 4372 | stac_issue_unsol_event(codec, nid); |
4382 | } | 4373 | } |
4383 | 4374 | ||
4384 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4385 | /* sync mute LED */ | 4375 | /* sync mute LED */ |
4386 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4376 | if (spec->gpio_led) |
4387 | codec->patch_ops.check_power_status(codec, 0x01); | 4377 | hda_call_check_power_status(codec, 0x01); |
4388 | #endif | ||
4389 | if (spec->dac_list) | 4378 | if (spec->dac_list) |
4390 | stac92xx_power_down(codec); | 4379 | stac92xx_power_down(codec); |
4391 | return 0; | 4380 | return 0; |
@@ -4686,6 +4675,36 @@ static void stac92xx_report_jack(struct hda_codec *codec, hda_nid_t nid) | |||
4686 | } | 4675 | } |
4687 | } | 4676 | } |
4688 | 4677 | ||
4678 | /* get the pin connection (fixed, none, etc) */ | ||
4679 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
4680 | { | ||
4681 | struct sigmatel_spec *spec = codec->spec; | ||
4682 | unsigned int cfg; | ||
4683 | |||
4684 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
4685 | return get_defcfg_connect(cfg); | ||
4686 | } | ||
4687 | |||
4688 | static int stac92xx_connected_ports(struct hda_codec *codec, | ||
4689 | hda_nid_t *nids, int num_nids) | ||
4690 | { | ||
4691 | struct sigmatel_spec *spec = codec->spec; | ||
4692 | int idx, num; | ||
4693 | unsigned int def_conf; | ||
4694 | |||
4695 | for (num = 0; num < num_nids; num++) { | ||
4696 | for (idx = 0; idx < spec->num_pins; idx++) | ||
4697 | if (spec->pin_nids[idx] == nids[num]) | ||
4698 | break; | ||
4699 | if (idx >= spec->num_pins) | ||
4700 | break; | ||
4701 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
4702 | if (def_conf == AC_JACK_PORT_NONE) | ||
4703 | break; | ||
4704 | } | ||
4705 | return num; | ||
4706 | } | ||
4707 | |||
4689 | static void stac92xx_mic_detect(struct hda_codec *codec) | 4708 | static void stac92xx_mic_detect(struct hda_codec *codec) |
4690 | { | 4709 | { |
4691 | struct sigmatel_spec *spec = codec->spec; | 4710 | struct sigmatel_spec *spec = codec->spec; |
@@ -4693,6 +4712,8 @@ static void stac92xx_mic_detect(struct hda_codec *codec) | |||
4693 | 4712 | ||
4694 | if (get_pin_presence(codec, spec->ext_mic.pin)) | 4713 | if (get_pin_presence(codec, spec->ext_mic.pin)) |
4695 | mic = &spec->ext_mic; | 4714 | mic = &spec->ext_mic; |
4715 | else if (get_pin_presence(codec, spec->dock_mic.pin)) | ||
4716 | mic = &spec->dock_mic; | ||
4696 | else | 4717 | else |
4697 | mic = &spec->int_mic; | 4718 | mic = &spec->int_mic; |
4698 | if (mic->dmux_idx >= 0) | 4719 | if (mic->dmux_idx >= 0) |
@@ -4935,11 +4956,9 @@ static int stac92xx_resume(struct hda_codec *codec) | |||
4935 | stac_issue_unsol_event(codec, | 4956 | stac_issue_unsol_event(codec, |
4936 | spec->autocfg.line_out_pins[0]); | 4957 | spec->autocfg.line_out_pins[0]); |
4937 | } | 4958 | } |
4938 | #ifdef CONFIG_SND_HDA_POWER_SAVE | ||
4939 | /* sync mute LED */ | 4959 | /* sync mute LED */ |
4940 | if (spec->gpio_led && codec->patch_ops.check_power_status) | 4960 | if (spec->gpio_led) |
4941 | codec->patch_ops.check_power_status(codec, 0x01); | 4961 | hda_call_check_power_status(codec, 0x01); |
4942 | #endif | ||
4943 | return 0; | 4962 | return 0; |
4944 | } | 4963 | } |
4945 | 4964 | ||
@@ -5316,6 +5335,8 @@ static int patch_stac92hd83xxx(struct hda_codec *codec) | |||
5316 | spec->linear_tone_beep = 1; | 5335 | spec->linear_tone_beep = 1; |
5317 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; | 5336 | codec->slave_dig_outs = stac92hd83xxx_slave_dig_outs; |
5318 | spec->digbeep_nid = 0x21; | 5337 | spec->digbeep_nid = 0x21; |
5338 | spec->dmic_nids = stac92hd83xxx_dmic_nids; | ||
5339 | spec->dmux_nids = stac92hd83xxx_mux_nids; | ||
5319 | spec->mux_nids = stac92hd83xxx_mux_nids; | 5340 | spec->mux_nids = stac92hd83xxx_mux_nids; |
5320 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); | 5341 | spec->num_muxes = ARRAY_SIZE(stac92hd83xxx_mux_nids); |
5321 | spec->adc_nids = stac92hd83xxx_adc_nids; | 5342 | spec->adc_nids = stac92hd83xxx_adc_nids; |
@@ -5361,9 +5382,13 @@ again: | |||
5361 | case 0x111d76d4: | 5382 | case 0x111d76d4: |
5362 | case 0x111d7605: | 5383 | case 0x111d7605: |
5363 | case 0x111d76d5: | 5384 | case 0x111d76d5: |
5385 | case 0x111d76e7: | ||
5364 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) | 5386 | if (spec->board_config == STAC_92HD83XXX_PWR_REF) |
5365 | break; | 5387 | break; |
5366 | spec->num_pwrs = 0; | 5388 | spec->num_pwrs = 0; |
5389 | spec->num_dmics = stac92xx_connected_ports(codec, | ||
5390 | stac92hd83xxx_dmic_nids, | ||
5391 | STAC92HD83XXX_NUM_DMICS); | ||
5367 | break; | 5392 | break; |
5368 | } | 5393 | } |
5369 | 5394 | ||
@@ -5422,36 +5447,6 @@ again: | |||
5422 | return 0; | 5447 | return 0; |
5423 | } | 5448 | } |
5424 | 5449 | ||
5425 | /* get the pin connection (fixed, none, etc) */ | ||
5426 | static unsigned int stac_get_defcfg_connect(struct hda_codec *codec, int idx) | ||
5427 | { | ||
5428 | struct sigmatel_spec *spec = codec->spec; | ||
5429 | unsigned int cfg; | ||
5430 | |||
5431 | cfg = snd_hda_codec_get_pincfg(codec, spec->pin_nids[idx]); | ||
5432 | return get_defcfg_connect(cfg); | ||
5433 | } | ||
5434 | |||
5435 | static int stac92hd71bxx_connected_ports(struct hda_codec *codec, | ||
5436 | hda_nid_t *nids, int num_nids) | ||
5437 | { | ||
5438 | struct sigmatel_spec *spec = codec->spec; | ||
5439 | int idx, num; | ||
5440 | unsigned int def_conf; | ||
5441 | |||
5442 | for (num = 0; num < num_nids; num++) { | ||
5443 | for (idx = 0; idx < spec->num_pins; idx++) | ||
5444 | if (spec->pin_nids[idx] == nids[num]) | ||
5445 | break; | ||
5446 | if (idx >= spec->num_pins) | ||
5447 | break; | ||
5448 | def_conf = stac_get_defcfg_connect(codec, idx); | ||
5449 | if (def_conf == AC_JACK_PORT_NONE) | ||
5450 | break; | ||
5451 | } | ||
5452 | return num; | ||
5453 | } | ||
5454 | |||
5455 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, | 5450 | static int stac92hd71bxx_connected_smuxes(struct hda_codec *codec, |
5456 | hda_nid_t dig0pin) | 5451 | hda_nid_t dig0pin) |
5457 | { | 5452 | { |
@@ -5590,7 +5585,7 @@ again: | |||
5590 | case 0x111d76b5: | 5585 | case 0x111d76b5: |
5591 | spec->init = stac92hd71bxx_core_init; | 5586 | spec->init = stac92hd71bxx_core_init; |
5592 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5587 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5593 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5588 | spec->num_dmics = stac92xx_connected_ports(codec, |
5594 | stac92hd71bxx_dmic_nids, | 5589 | stac92hd71bxx_dmic_nids, |
5595 | STAC92HD71BXX_NUM_DMICS); | 5590 | STAC92HD71BXX_NUM_DMICS); |
5596 | break; | 5591 | break; |
@@ -5622,7 +5617,7 @@ again: | |||
5622 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); | 5617 | snd_hda_codec_set_pincfg(codec, 0x0f, 0x40f000f0); |
5623 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); | 5618 | snd_hda_codec_set_pincfg(codec, 0x19, 0x40f000f3); |
5624 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; | 5619 | stac92hd71bxx_dmic_nids[STAC92HD71BXX_NUM_DMICS - 1] = 0; |
5625 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5620 | spec->num_dmics = stac92xx_connected_ports(codec, |
5626 | stac92hd71bxx_dmic_nids, | 5621 | stac92hd71bxx_dmic_nids, |
5627 | STAC92HD71BXX_NUM_DMICS - 1); | 5622 | STAC92HD71BXX_NUM_DMICS - 1); |
5628 | break; | 5623 | break; |
@@ -5636,7 +5631,7 @@ again: | |||
5636 | default: | 5631 | default: |
5637 | spec->init = stac92hd71bxx_core_init; | 5632 | spec->init = stac92hd71bxx_core_init; |
5638 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; | 5633 | codec->slave_dig_outs = stac92hd71bxx_slave_dig_outs; |
5639 | spec->num_dmics = stac92hd71bxx_connected_ports(codec, | 5634 | spec->num_dmics = stac92xx_connected_ports(codec, |
5640 | stac92hd71bxx_dmic_nids, | 5635 | stac92hd71bxx_dmic_nids, |
5641 | STAC92HD71BXX_NUM_DMICS); | 5636 | STAC92HD71BXX_NUM_DMICS); |
5642 | break; | 5637 | break; |
@@ -6318,6 +6313,8 @@ static struct hda_codec_preset snd_hda_preset_sigmatel[] = { | |||
6318 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, | 6313 | { .id = 0x111d76cc, .name = "92HD89F3", .patch = patch_stac92hd73xx }, |
6319 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, | 6314 | { .id = 0x111d76cd, .name = "92HD89F2", .patch = patch_stac92hd73xx }, |
6320 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, | 6315 | { .id = 0x111d76ce, .name = "92HD89F1", .patch = patch_stac92hd73xx }, |
6316 | { .id = 0x111d76e0, .name = "92HD91BXX", .patch = patch_stac92hd83xxx}, | ||
6317 | { .id = 0x111d76e7, .name = "92HD90BXX", .patch = patch_stac92hd83xxx}, | ||
6321 | {} /* terminator */ | 6318 | {} /* terminator */ |
6322 | }; | 6319 | }; |
6323 | 6320 | ||
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 | ||