aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sound/pci/hda/hda_codec.c48
-rw-r--r--sound/pci/hda/hda_local.h17
-rw-r--r--sound/pci/hda/patch_analog.c2
-rw-r--r--sound/pci/hda/patch_cmedia.c62
-rw-r--r--sound/pci/hda/patch_realtek.c67
5 files changed, 99 insertions, 97 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c
index e7fb182f90ed..14a6f5463277 100644
--- a/sound/pci/hda/hda_codec.c
+++ b/sound/pci/hda/hda_codec.c
@@ -1662,6 +1662,54 @@ int snd_hda_add_new_ctls(struct hda_codec *codec, snd_kcontrol_new_t *knew)
1662} 1662}
1663 1663
1664 1664
1665 /*
1666 * Channel mode helper
1667 */
1668int snd_hda_ch_mode_info(struct hda_codec *codec, snd_ctl_elem_info_t *uinfo,
1669 const struct hda_channel_mode *chmode, int num_chmodes)
1670{
1671 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
1672 uinfo->count = 1;
1673 uinfo->value.enumerated.items = num_chmodes;
1674 if (uinfo->value.enumerated.item >= num_chmodes)
1675 uinfo->value.enumerated.item = num_chmodes - 1;
1676 sprintf(uinfo->value.enumerated.name, "%dch",
1677 chmode[uinfo->value.enumerated.item].channels);
1678 return 0;
1679}
1680
1681int snd_hda_ch_mode_get(struct hda_codec *codec, snd_ctl_elem_value_t *ucontrol,
1682 const struct hda_channel_mode *chmode, int num_chmodes,
1683 int max_channels)
1684{
1685 int i;
1686
1687 for (i = 0; i < num_chmodes; i++) {
1688 if (max_channels == chmode[i].channels) {
1689 ucontrol->value.enumerated.item[0] = i;
1690 break;
1691 }
1692 }
1693 return 0;
1694}
1695
1696int snd_hda_ch_mode_put(struct hda_codec *codec, snd_ctl_elem_value_t *ucontrol,
1697 const struct hda_channel_mode *chmode, int num_chmodes,
1698 int *max_channelsp)
1699{
1700 unsigned int mode;
1701
1702 mode = ucontrol->value.enumerated.item[0];
1703 snd_assert(mode < num_chmodes, return -EINVAL);
1704 if (*max_channelsp && ! codec->in_resume)
1705 return 0;
1706 /* change the current channel setting */
1707 *max_channelsp = chmode[mode].channels;
1708 if (chmode[mode].sequence)
1709 snd_hda_sequence_write(codec, chmode[mode].sequence);
1710 return 1;
1711}
1712
1665/* 1713/*
1666 * input MUX helper 1714 * input MUX helper
1667 */ 1715 */
diff --git a/sound/pci/hda/hda_local.h b/sound/pci/hda/hda_local.h
index f51a56f813c8..05a88fb1d652 100644
--- a/sound/pci/hda/hda_local.h
+++ b/sound/pci/hda/hda_local.h
@@ -102,6 +102,23 @@ int snd_hda_input_mux_put(struct hda_codec *codec, const struct hda_input_mux *i
102 snd_ctl_elem_value_t *ucontrol, hda_nid_t nid, 102 snd_ctl_elem_value_t *ucontrol, hda_nid_t nid,
103 unsigned int *cur_val); 103 unsigned int *cur_val);
104 104
105 /*
106 * Channel mode helper
107 */
108struct hda_channel_mode {
109 int channels;
110 const struct hda_verb *sequence;
111};
112
113int snd_hda_ch_mode_info(struct hda_codec *codec, snd_ctl_elem_info_t *uinfo,
114 const struct hda_channel_mode *chmode, int num_chmodes);
115int snd_hda_ch_mode_get(struct hda_codec *codec, snd_ctl_elem_value_t *ucontrol,
116 const struct hda_channel_mode *chmode, int num_chmodes,
117 int max_channels);
118int snd_hda_ch_mode_put(struct hda_codec *codec, snd_ctl_elem_value_t *ucontrol,
119 const struct hda_channel_mode *chmode, int num_chmodes,
120 int *max_channelsp);
121
105/* 122/*
106 * Multi-channel / digital-out PCM helper 123 * Multi-channel / digital-out PCM helper
107 */ 124 */
diff --git a/sound/pci/hda/patch_analog.c b/sound/pci/hda/patch_analog.c
index d7d636decef8..4687736aa0d7 100644
--- a/sound/pci/hda/patch_analog.c
+++ b/sound/pci/hda/patch_analog.c
@@ -52,7 +52,7 @@ struct ad198x_spec {
52 unsigned int cur_mux[3]; 52 unsigned int cur_mux[3];
53 53
54 /* channel model */ 54 /* channel model */
55 const struct alc_channel_mode *channel_mode; 55 const struct hda_channel_mode *channel_mode;
56 int num_channel_mode; 56 int num_channel_mode;
57 57
58 /* PCM information */ 58 /* PCM information */
diff --git a/sound/pci/hda/patch_cmedia.c b/sound/pci/hda/patch_cmedia.c
index 523c362ec44d..6e0fd92a2be3 100644
--- a/sound/pci/hda/patch_cmedia.c
+++ b/sound/pci/hda/patch_cmedia.c
@@ -44,7 +44,6 @@ enum {
44 44
45struct cmi_spec { 45struct cmi_spec {
46 int board_config; 46 int board_config;
47 unsigned int surr_switch: 1; /* switchable line,mic */
48 unsigned int no_line_in: 1; /* no line-in (5-jack) */ 47 unsigned int no_line_in: 1; /* no line-in (5-jack) */
49 unsigned int front_panel: 1; /* has front-panel 2-jack */ 48 unsigned int front_panel: 1; /* has front-panel 2-jack */
50 49
@@ -62,9 +61,8 @@ struct cmi_spec {
62 unsigned int cur_mux[2]; 61 unsigned int cur_mux[2];
63 62
64 /* channel mode */ 63 /* channel mode */
65 unsigned int num_ch_modes; 64 int num_channel_modes;
66 unsigned int cur_ch_mode; 65 const struct hda_channel_mode *channel_modes;
67 const struct cmi_channel_mode *channel_modes;
68 66
69 struct hda_pcm pcm_rec[2]; /* PCM information */ 67 struct hda_pcm pcm_rec[2]; /* PCM information */
70 68
@@ -158,12 +156,7 @@ static struct hda_verb cmi9880_ch8_init[] = {
158 {} 156 {}
159}; 157};
160 158
161struct cmi_channel_mode { 159static struct hda_channel_mode cmi9880_channel_modes[3] = {
162 unsigned int channels;
163 const struct hda_verb *sequence;
164};
165
166static struct cmi_channel_mode cmi9880_channel_modes[3] = {
167 { 2, cmi9880_ch2_init }, 160 { 2, cmi9880_ch2_init },
168 { 6, cmi9880_ch6_init }, 161 { 6, cmi9880_ch6_init },
169 { 8, cmi9880_ch8_init }, 162 { 8, cmi9880_ch8_init },
@@ -173,43 +166,24 @@ static int cmi_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo
173{ 166{
174 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 167 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
175 struct cmi_spec *spec = codec->spec; 168 struct cmi_spec *spec = codec->spec;
176 169 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_modes,
177 snd_assert(spec->channel_modes, return -EINVAL); 170 spec->num_channel_modes);
178 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
179 uinfo->count = 1;
180 uinfo->value.enumerated.items = spec->num_ch_modes;
181 if (uinfo->value.enumerated.item >= uinfo->value.enumerated.items)
182 uinfo->value.enumerated.item = uinfo->value.enumerated.items - 1;
183 sprintf(uinfo->value.enumerated.name, "%dch",
184 spec->channel_modes[uinfo->value.enumerated.item].channels);
185 return 0;
186} 171}
187 172
188static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 173static int cmi_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
189{ 174{
190 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 175 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
191 struct cmi_spec *spec = codec->spec; 176 struct cmi_spec *spec = codec->spec;
192 177 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_modes,
193 ucontrol->value.enumerated.item[0] = spec->cur_ch_mode; 178 spec->num_channel_modes, spec->multiout.max_channels);
194 return 0;
195} 179}
196 180
197static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 181static int cmi_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
198{ 182{
199 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 183 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
200 struct cmi_spec *spec = codec->spec; 184 struct cmi_spec *spec = codec->spec;
201 185 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_modes,
202 snd_assert(spec->channel_modes, return -EINVAL); 186 spec->num_channel_modes, &spec->multiout.max_channels);
203 if (ucontrol->value.enumerated.item[0] >= spec->num_ch_modes)
204 ucontrol->value.enumerated.item[0] = spec->num_ch_modes;
205 if (ucontrol->value.enumerated.item[0] == spec->cur_ch_mode &&
206 ! codec->in_resume)
207 return 0;
208
209 spec->cur_ch_mode = ucontrol->value.enumerated.item[0];
210 snd_hda_sequence_write(codec, spec->channel_modes[spec->cur_ch_mode].sequence);
211 spec->multiout.max_channels = spec->channel_modes[spec->cur_ch_mode].channels;
212 return 1;
213} 187}
214 188
215/* 189/*
@@ -361,7 +335,7 @@ static int cmi9880_build_controls(struct hda_codec *codec)
361 err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer); 335 err = snd_hda_add_new_ctls(codec, cmi9880_basic_mixer);
362 if (err < 0) 336 if (err < 0)
363 return err; 337 return err;
364 if (spec->surr_switch) { 338 if (spec->channel_modes) {
365 err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer); 339 err = snd_hda_add_new_ctls(codec, cmi9880_ch_mode_mixer);
366 if (err < 0) 340 if (err < 0)
367 return err; 341 return err;
@@ -475,7 +449,7 @@ static int cmi9880_resume(struct hda_codec *codec)
475 449
476 cmi9880_init(codec); 450 cmi9880_init(codec);
477 snd_hda_resume_ctls(codec, cmi9880_basic_mixer); 451 snd_hda_resume_ctls(codec, cmi9880_basic_mixer);
478 if (spec->surr_switch) 452 if (spec->channel_modes)
479 snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer); 453 snd_hda_resume_ctls(codec, cmi9880_ch_mode_mixer);
480 if (spec->multiout.dig_out_nid) 454 if (spec->multiout.dig_out_nid)
481 snd_hda_resume_spdif_out(codec); 455 snd_hda_resume_spdif_out(codec);
@@ -685,14 +659,13 @@ static int patch_cmi9880(struct hda_codec *codec)
685 switch (spec->board_config) { 659 switch (spec->board_config) {
686 case CMI_MINIMAL: 660 case CMI_MINIMAL:
687 case CMI_MIN_FP: 661 case CMI_MIN_FP:
688 spec->surr_switch = 1; 662 spec->channel_modes = cmi9880_channel_modes;
689 if (spec->board_config == CMI_MINIMAL) 663 if (spec->board_config == CMI_MINIMAL)
690 spec->num_ch_modes = 2; 664 spec->num_channel_modes = 2;
691 else { 665 else {
692 spec->front_panel = 1; 666 spec->front_panel = 1;
693 spec->num_ch_modes = 3; 667 spec->num_channel_modes = 3;
694 } 668 }
695 spec->channel_modes = cmi9880_channel_modes;
696 spec->multiout.max_channels = cmi9880_channel_modes[0].channels; 669 spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
697 spec->input_mux = &cmi9880_basic_mux; 670 spec->input_mux = &cmi9880_basic_mux;
698 break; 671 break;
@@ -727,19 +700,18 @@ static int patch_cmi9880(struct hda_codec *codec)
727 get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) { 700 get_defcfg_connect(port_f) == AC_JACK_PORT_NONE) {
728 port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); 701 port_g = snd_hda_codec_read(codec, 0x1f, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
729 port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0); 702 port_h = snd_hda_codec_read(codec, 0x20, 0, AC_VERB_GET_CONFIG_DEFAULT, 0);
730 spec->surr_switch = 1; 703 spec->channel_modes = cmi9880_channel_modes;
731 /* no front panel */ 704 /* no front panel */
732 if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE || 705 if (get_defcfg_connect(port_g) == AC_JACK_PORT_NONE ||
733 get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) { 706 get_defcfg_connect(port_h) == AC_JACK_PORT_NONE) {
734 /* no optional rear panel */ 707 /* no optional rear panel */
735 spec->board_config = CMI_MINIMAL; 708 spec->board_config = CMI_MINIMAL;
736 spec->front_panel = 0; 709 spec->front_panel = 0;
737 spec->num_ch_modes = 2; 710 spec->num_channel_modes = 2;
738 } else { 711 } else {
739 spec->board_config = CMI_MIN_FP; 712 spec->board_config = CMI_MIN_FP;
740 spec->num_ch_modes = 3; 713 spec->num_channel_modes = 3;
741 } 714 }
742 spec->channel_modes = cmi9880_channel_modes;
743 spec->input_mux = &cmi9880_basic_mux; 715 spec->input_mux = &cmi9880_basic_mux;
744 spec->multiout.max_channels = cmi9880_channel_modes[0].channels; 716 spec->multiout.max_channels = cmi9880_channel_modes[0].channels;
745 } else { 717 } else {
diff --git a/sound/pci/hda/patch_realtek.c b/sound/pci/hda/patch_realtek.c
index cffb83fdcff7..a213c19ab06c 100644
--- a/sound/pci/hda/patch_realtek.c
+++ b/sound/pci/hda/patch_realtek.c
@@ -109,7 +109,7 @@ struct alc_spec {
109 unsigned int cur_mux[3]; 109 unsigned int cur_mux[3];
110 110
111 /* channel model */ 111 /* channel model */
112 const struct alc_channel_mode *channel_mode; 112 const struct hda_channel_mode *channel_mode;
113 int num_channel_mode; 113 int num_channel_mode;
114 114
115 /* PCM information */ 115 /* PCM information */
@@ -157,63 +157,28 @@ static int alc_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucon
157/* 157/*
158 * channel mode setting 158 * channel mode setting
159 */ 159 */
160struct alc_channel_mode {
161 int channels;
162 const struct hda_verb *sequence;
163};
164
165static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo) 160static int alc880_ch_mode_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t *uinfo)
166{ 161{
167 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 162 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
168 struct alc_spec *spec = codec->spec; 163 struct alc_spec *spec = codec->spec;
169 int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; 164 return snd_hda_ch_mode_info(codec, uinfo, spec->channel_mode,
170 165 spec->num_channel_mode);
171 snd_assert(spec->channel_mode, return -ENXIO);
172 uinfo->type = SNDRV_CTL_ELEM_TYPE_ENUMERATED;
173 uinfo->count = 1;
174 uinfo->value.enumerated.items = items;
175 if (uinfo->value.enumerated.item >= items)
176 uinfo->value.enumerated.item = items - 1;
177 sprintf(uinfo->value.enumerated.name, "%dch",
178 spec->channel_mode[uinfo->value.enumerated.item].channels);
179 return 0;
180} 166}
181 167
182static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 168static int alc880_ch_mode_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
183{ 169{
184 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 170 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
185 struct alc_spec *spec = codec->spec; 171 struct alc_spec *spec = codec->spec;
186 int items = kcontrol->private_value ? (int)kcontrol->private_value : 2; 172 return snd_hda_ch_mode_get(codec, ucontrol, spec->channel_mode,
187 int i; 173 spec->num_channel_mode, spec->multiout.max_channels);
188
189 snd_assert(spec->channel_mode, return -ENXIO);
190 for (i = 0; i < items; i++) {
191 if (spec->multiout.max_channels == spec->channel_mode[i].channels) {
192 ucontrol->value.enumerated.item[0] = i;
193 break;
194 }
195 }
196 return 0;
197} 174}
198 175
199static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 176static int alc880_ch_mode_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
200{ 177{
201 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 178 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
202 struct alc_spec *spec = codec->spec; 179 struct alc_spec *spec = codec->spec;
203 int mode; 180 return snd_hda_ch_mode_put(codec, ucontrol, spec->channel_mode,
204 181 spec->num_channel_mode, &spec->multiout.max_channels);
205 snd_assert(spec->channel_mode, return -ENXIO);
206 mode = ucontrol->value.enumerated.item[0] ? 1 : 0;
207 if (spec->multiout.max_channels == spec->channel_mode[mode].channels &&
208 ! codec->in_resume)
209 return 0;
210
211 /* change the current channel setting */
212 spec->multiout.max_channels = spec->channel_mode[mode].channels;
213 if (spec->channel_mode[mode].sequence)
214 snd_hda_sequence_write(codec, spec->channel_mode[mode].sequence);
215
216 return 1;
217} 182}
218 183
219 184
@@ -328,7 +293,7 @@ static struct hda_verb alc880_threestack_ch6_init[] = {
328 { } /* end */ 293 { } /* end */
329}; 294};
330 295
331static struct alc_channel_mode alc880_threestack_modes[2] = { 296static struct hda_channel_mode alc880_threestack_modes[2] = {
332 { 2, alc880_threestack_ch2_init }, 297 { 2, alc880_threestack_ch2_init },
333 { 6, alc880_threestack_ch6_init }, 298 { 6, alc880_threestack_ch6_init },
334}; 299};
@@ -443,7 +408,7 @@ static struct hda_verb alc880_fivestack_ch8_init[] = {
443 { } /* end */ 408 { } /* end */
444}; 409};
445 410
446static struct alc_channel_mode alc880_fivestack_modes[2] = { 411static struct hda_channel_mode alc880_fivestack_modes[2] = {
447 { 6, alc880_fivestack_ch6_init }, 412 { 6, alc880_fivestack_ch6_init },
448 { 8, alc880_fivestack_ch8_init }, 413 { 8, alc880_fivestack_ch8_init },
449}; 414};
@@ -473,7 +438,7 @@ static struct hda_input_mux alc880_6stack_capture_source = {
473}; 438};
474 439
475/* fixed 8-channels */ 440/* fixed 8-channels */
476static struct alc_channel_mode alc880_sixstack_modes[1] = { 441static struct hda_channel_mode alc880_sixstack_modes[1] = {
477 { 8, NULL }, 442 { 8, NULL },
478}; 443};
479 444
@@ -540,7 +505,7 @@ static hda_nid_t alc880_w810_dac_nids[3] = {
540}; 505};
541 506
542/* fixed 6 channels */ 507/* fixed 6 channels */
543static struct alc_channel_mode alc880_w810_modes[1] = { 508static struct hda_channel_mode alc880_w810_modes[1] = {
544 { 6, NULL } 509 { 6, NULL }
545}; 510};
546 511
@@ -572,7 +537,7 @@ static hda_nid_t alc880_z71v_dac_nids[1] = {
572#define ALC880_Z71V_HP_DAC 0x03 537#define ALC880_Z71V_HP_DAC 0x03
573 538
574/* fixed 2 channels */ 539/* fixed 2 channels */
575static struct alc_channel_mode alc880_2_jack_modes[1] = { 540static struct hda_channel_mode alc880_2_jack_modes[1] = {
576 { 2, NULL } 541 { 2, NULL }
577}; 542};
578 543
@@ -1227,7 +1192,7 @@ static struct hda_input_mux alc880_test_capture_source = {
1227 }, 1192 },
1228}; 1193};
1229 1194
1230static struct alc_channel_mode alc880_test_modes[4] = { 1195static struct hda_channel_mode alc880_test_modes[4] = {
1231 { 2, NULL }, 1196 { 2, NULL },
1232 { 4, NULL }, 1197 { 4, NULL },
1233 { 6, NULL }, 1198 { 6, NULL },
@@ -1585,7 +1550,7 @@ struct alc_config_preset {
1585 unsigned int num_adc_nids; 1550 unsigned int num_adc_nids;
1586 hda_nid_t *adc_nids; 1551 hda_nid_t *adc_nids;
1587 unsigned int num_channel_mode; 1552 unsigned int num_channel_mode;
1588 const struct alc_channel_mode *channel_mode; 1553 const struct hda_channel_mode *channel_mode;
1589 const struct hda_input_mux *input_mux; 1554 const struct hda_input_mux *input_mux;
1590}; 1555};
1591 1556
@@ -2202,7 +2167,7 @@ static struct hda_input_mux alc260_fujitsu_capture_source = {
2202 * element which allows changing the channel mode, so the verb list is 2167 * element which allows changing the channel mode, so the verb list is
2203 * never used. 2168 * never used.
2204 */ 2169 */
2205static struct alc_channel_mode alc260_modes[1] = { 2170static struct hda_channel_mode alc260_modes[1] = {
2206 { 2, NULL }, 2171 { 2, NULL },
2207}; 2172};
2208 2173
@@ -2506,7 +2471,7 @@ static int patch_alc260(struct hda_codec *codec)
2506 * driver yet). 2471 * driver yet).
2507 */ 2472 */
2508 2473
2509static struct alc_channel_mode alc882_ch_modes[1] = { 2474static struct hda_channel_mode alc882_ch_modes[1] = {
2510 { 8, NULL } 2475 { 8, NULL }
2511}; 2476};
2512 2477