aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci
diff options
context:
space:
mode:
authorMatt <matt@embeddedalley.com>2005-06-14 04:19:34 -0400
committerJaroslav Kysela <perex@suse.cz>2005-06-22 06:29:05 -0400
commitdabbed6f729d806092851150ca3dd9efe2b64b58 (patch)
treec6b6acdacb9f4cf67b3eeadf55225226a9171098 /sound/pci
parentee3b4c60f452f8e24fe30ae73cb97da1beda0ca2 (diff)
[ALSA] SigmaTel HDA SPDIF and input mux updates
HDA Codec driver Adds SPDIF in/out support to the SigmaTel HDA codecs. Now builds the input mux control element names from the defcfg regs. Signed-off-by: Matt <matt@embeddedalley.com> Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci')
-rw-r--r--sound/pci/hda/patch_sigmatel.c184
1 files changed, 145 insertions, 39 deletions
diff --git a/sound/pci/hda/patch_sigmatel.c b/sound/pci/hda/patch_sigmatel.c
index 1534e20af63d..013be2ea513a 100644
--- a/sound/pci/hda/patch_sigmatel.c
+++ b/sound/pci/hda/patch_sigmatel.c
@@ -42,9 +42,11 @@ struct sigmatel_spec {
42 42
43 /* capture */ 43 /* capture */
44 hda_nid_t *adc_nids; 44 hda_nid_t *adc_nids;
45 hda_nid_t *mux_nids;
46 unsigned int num_adcs; 45 unsigned int num_adcs;
46 hda_nid_t *mux_nids;
47 unsigned int num_muxes;
47 hda_nid_t capture_nid; 48 hda_nid_t capture_nid;
49 hda_nid_t dig_in_nid;
48 50
49 /* power management*/ 51 /* power management*/
50 hda_nid_t *pstate_nids; 52 hda_nid_t *pstate_nids;
@@ -62,7 +64,8 @@ struct sigmatel_spec {
62 snd_kcontrol_new_t *mixer; 64 snd_kcontrol_new_t *mixer;
63 65
64 /* capture source */ 66 /* capture source */
65 const struct hda_input_mux *input_mux; 67 struct hda_input_mux input_mux;
68 char input_labels[HDA_MAX_NUM_INPUTS][16];
66 unsigned int cur_mux[2]; 69 unsigned int cur_mux[2];
67 70
68 /* channel mode */ 71 /* channel mode */
@@ -105,8 +108,8 @@ static hda_nid_t stac922x_dac_nids[4] = {
105 0x02, 0x03, 0x04, 0x05, 108 0x02, 0x03, 0x04, 0x05,
106}; 109};
107 110
108static hda_nid_t stac922x_pstate_nids[7] = { 111static hda_nid_t stac922x_pstate_nids[8] = {
109 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 112 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x11,
110}; 113};
111 114
112static hda_nid_t stac922x_pin_nids[10] = { 115static hda_nid_t stac922x_pin_nids[10] = {
@@ -118,7 +121,7 @@ static int stac92xx_mux_enum_info(snd_kcontrol_t *kcontrol, snd_ctl_elem_info_t
118{ 121{
119 struct hda_codec *codec = snd_kcontrol_chip(kcontrol); 122 struct hda_codec *codec = snd_kcontrol_chip(kcontrol);
120 struct sigmatel_spec *spec = codec->spec; 123 struct sigmatel_spec *spec = codec->spec;
121 return snd_hda_input_mux_info(spec->input_mux, uinfo); 124 return snd_hda_input_mux_info(&spec->input_mux, uinfo);
122} 125}
123 126
124static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) 127static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol)
@@ -137,7 +140,7 @@ static int stac92xx_mux_enum_put(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t
137 struct sigmatel_spec *spec = codec->spec; 140 struct sigmatel_spec *spec = codec->spec;
138 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id); 141 unsigned int adc_idx = snd_ctl_get_ioffidx(kcontrol, &ucontrol->id);
139 142
140 return snd_hda_input_mux_put(codec, spec->input_mux, ucontrol, 143 return snd_hda_input_mux_put(codec, &spec->input_mux, ucontrol,
141 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]); 144 spec->mux_nids[adc_idx], &spec->cur_mux[adc_idx]);
142} 145}
143 146
@@ -192,30 +195,6 @@ static snd_kcontrol_new_t stac922x_mixer[] = {
192 { } /* end */ 195 { } /* end */
193}; 196};
194 197
195static struct hda_input_mux stac9200_input_mux = {
196 .num_items = 5,
197 .items = {
198 { "Port B", 0x0 },
199 { "Port C", 0x1 },
200 { "Port D", 0x2 },
201 { "Port A", 0x3 },
202 { "CD", 0x4 },
203 }
204};
205
206static struct hda_input_mux stac922x_input_mux = {
207 .num_items = 7,
208 .items = {
209 { "Port E", 0x0 },
210 { "CD", 0x1 },
211 { "Port F", 0x2 },
212 { "Port B", 0x3 },
213 { "Port C", 0x4 },
214 { "Port D", 0x5 },
215 { "Port A", 0x6 },
216 }
217};
218
219static int stac92xx_build_controls(struct hda_codec *codec) 198static int stac92xx_build_controls(struct hda_codec *codec)
220{ 199{
221 struct sigmatel_spec *spec = codec->spec; 200 struct sigmatel_spec *spec = codec->spec;
@@ -224,19 +203,28 @@ static int stac92xx_build_controls(struct hda_codec *codec)
224 err = snd_hda_add_new_ctls(codec, spec->mixer); 203 err = snd_hda_add_new_ctls(codec, spec->mixer);
225 if (err < 0) 204 if (err < 0)
226 return err; 205 return err;
227 206 if (spec->multiout.dig_out_nid) {
228 return 0; 207 err = snd_hda_create_spdif_out_ctls(codec, spec->multiout.dig_out_nid);
208 if (err < 0)
209 return err;
210 }
211 if (spec->dig_in_nid) {
212 err = snd_hda_create_spdif_in_ctls(codec, spec->dig_in_nid);
213 if (err < 0)
214 return err;
215 }
216 return 0;
229} 217}
230 218
231#ifdef STAC_TEST 219#ifdef STAC_TEST
232static unsigned int stac9200_pin_configs[8] = { 220static unsigned int stac9200_pin_configs[8] = {
233 0x40000100, 0x40000100, 0x0221401f, 0x01114010, 221 0x01c47010, 0x01447010, 0x0221401f, 0x01114010,
234 0x02a19020, 0x01a19021, 0x90100140, 0x01813122, 222 0x02a19020, 0x01a19021, 0x90100140, 0x01813122,
235}; 223};
236 224
237static unsigned int stac922x_pin_configs[14] = { 225static unsigned int stac922x_pin_configs[14] = {
238 0x40000100, 0x40000100, 0x40000100, 0x01114010, 226 0x40000100, 0x40000100, 0x40000100, 0x01114010,
239 0x01813122, 0x40000100, 0x40000100, 0x40000100, 227 0x01813122, 0x40000100, 0x01447010, 0x01c47010,
240 0x40000100, 0x40000100, 228 0x40000100, 0x40000100,
241}; 229};
242 230
@@ -299,29 +287,89 @@ static int stac92xx_set_vref(struct hda_codec *codec, hda_nid_t nid)
299 return 0; 287 return 0;
300} 288}
301 289
290/*
291 * retrieve the default device type from the default config value
292 */
293#define get_defcfg_type(cfg) ((cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT)
294#define get_defcfg_location(cfg) ((cfg & AC_DEFCFG_LOCATION) >> AC_DEFCFG_LOCATION_SHIFT)
295
302static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg) 296static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg)
303{ 297{
304 switch((pin_cfg & AC_DEFCFG_DEVICE) >> AC_DEFCFG_DEVICE_SHIFT) { 298 struct sigmatel_spec *spec = codec->spec;
299 u32 location = get_defcfg_location(pin_cfg);
300 char *label;
301 const char *type = NULL;
302 int ainput = 0;
303
304 switch(get_defcfg_type(pin_cfg)) {
305 case AC_JACK_HP_OUT: 305 case AC_JACK_HP_OUT:
306 /* Enable HP amp */ 306 /* Enable HP amp */
307 stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN); 307 stac92xx_set_pinctl(codec, nid, AC_PINCTL_HP_EN);
308 /* Fall through */ 308 /* Fall through */
309 case AC_JACK_SPDIF_OUT:
309 case AC_JACK_LINE_OUT: 310 case AC_JACK_LINE_OUT:
310 case AC_JACK_SPEAKER: 311 case AC_JACK_SPEAKER:
311 /* Enable output */ 312 /* Enable output */
312 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN); 313 stac92xx_set_pinctl(codec, nid, AC_PINCTL_OUT_EN);
313 break; 314 break;
315 case AC_JACK_SPDIF_IN:
316 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
317 break;
314 case AC_JACK_MIC_IN: 318 case AC_JACK_MIC_IN:
319 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
320 type = "Front Mic";
321 else
322 type = "Mic";
323 ainput = 1;
315 /* Set vref */ 324 /* Set vref */
316 stac92xx_set_vref(codec, nid); 325 stac92xx_set_vref(codec, nid);
326 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
327 break;
317 case AC_JACK_CD: 328 case AC_JACK_CD:
329 type = "CD";
330 ainput = 1;
331 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
332 break;
318 case AC_JACK_LINE_IN: 333 case AC_JACK_LINE_IN:
334 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
335 type = "Front Line";
336 else
337 type = "Line";
338 ainput = 1;
339 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
340 break;
319 case AC_JACK_AUX: 341 case AC_JACK_AUX:
320 /* Enable input */ 342 if ((location & 0x0f) == AC_JACK_LOC_FRONT)
343 type = "Front Aux";
344 else
345 type = "Aux";
346 ainput = 1;
321 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN); 347 stac92xx_set_pinctl(codec, nid, AC_PINCTL_IN_EN);
322 break; 348 break;
323 } 349 }
324 350
351 if (ainput) {
352 hda_nid_t con_lst[HDA_MAX_NUM_INPUTS];
353 int i, j, num_cons, index = -1;
354 if (!type)
355 type = "Input";
356 label = spec->input_labels[spec->input_mux.num_items];
357 strcpy(label, type);
358 spec->input_mux.items[spec->input_mux.num_items].label = label;
359 for (i=0; i<spec->num_muxes; i++) {
360 num_cons = snd_hda_get_connections(codec, spec->mux_nids[i], con_lst, HDA_MAX_NUM_INPUTS);
361 for (j=0; j<num_cons; j++)
362 if (con_lst[j] == nid) {
363 index = j;
364 break;
365 }
366 if (index >= 0)
367 break;
368 }
369 spec->input_mux.items[spec->input_mux.num_items].index = index;
370 spec->input_mux.num_items++;
371 }
372
325 return 0; 373 return 0;
326} 374}
327 375
@@ -402,6 +450,26 @@ static int stac92xx_playback_pcm_cleanup(struct hda_pcm_stream *hinfo,
402} 450}
403 451
404/* 452/*
453 * Digital playback callbacks
454 */
455static int stac92xx_dig_playback_pcm_open(struct hda_pcm_stream *hinfo,
456 struct hda_codec *codec,
457 snd_pcm_substream_t *substream)
458{
459 struct sigmatel_spec *spec = codec->spec;
460 return snd_hda_multi_out_dig_open(codec, &spec->multiout);
461}
462
463static int stac92xx_dig_playback_pcm_close(struct hda_pcm_stream *hinfo,
464 struct hda_codec *codec,
465 snd_pcm_substream_t *substream)
466{
467 struct sigmatel_spec *spec = codec->spec;
468 return snd_hda_multi_out_dig_close(codec, &spec->multiout);
469}
470
471
472/*
405 * Analog capture callbacks 473 * Analog capture callbacks
406 */ 474 */
407static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, 475static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo,
@@ -427,6 +495,24 @@ static int stac92xx_capture_pcm_cleanup(struct hda_pcm_stream *hinfo,
427 return 0; 495 return 0;
428} 496}
429 497
498static struct hda_pcm_stream stac92xx_pcm_digital_playback = {
499 .substreams = 1,
500 .channels_min = 2,
501 .channels_max = 2,
502 /* NID is set in stac92xx_build_pcms */
503 .ops = {
504 .open = stac92xx_dig_playback_pcm_open,
505 .close = stac92xx_dig_playback_pcm_close
506 },
507};
508
509static struct hda_pcm_stream stac92xx_pcm_digital_capture = {
510 .substreams = 1,
511 .channels_min = 2,
512 .channels_max = 2,
513 /* NID is set in stac92xx_build_pcms */
514};
515
430static struct hda_pcm_stream stac92xx_pcm_analog_playback = { 516static struct hda_pcm_stream stac92xx_pcm_analog_playback = {
431 .substreams = 1, 517 .substreams = 1,
432 .channels_min = 2, 518 .channels_min = 2,
@@ -464,6 +550,20 @@ static int stac92xx_build_pcms(struct hda_codec *codec)
464 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture; 550 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_analog_capture;
465 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid; 551 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->capture_nid;
466 552
553 if (spec->multiout.dig_out_nid || spec->dig_in_nid) {
554 codec->num_pcms++;
555 info++;
556 info->name = "STAC92xx Digital";
557 if (spec->multiout.dig_out_nid) {
558 info->stream[SNDRV_PCM_STREAM_PLAYBACK] = stac92xx_pcm_digital_playback;
559 info->stream[SNDRV_PCM_STREAM_PLAYBACK].nid = spec->multiout.dig_out_nid;
560 }
561 if (spec->dig_in_nid) {
562 info->stream[SNDRV_PCM_STREAM_CAPTURE] = stac92xx_pcm_digital_capture;
563 info->stream[SNDRV_PCM_STREAM_CAPTURE].nid = spec->dig_in_nid;
564 }
565 }
566
467 return 0; 567 return 0;
468} 568}
469 569
@@ -492,9 +592,12 @@ static int patch_stac9200(struct hda_codec *codec)
492 spec->multiout.max_channels = 2; 592 spec->multiout.max_channels = 2;
493 spec->multiout.num_dacs = 1; 593 spec->multiout.num_dacs = 1;
494 spec->multiout.dac_nids = stac9200_dac_nids; 594 spec->multiout.dac_nids = stac9200_dac_nids;
595 spec->multiout.dig_out_nid = 0x05;
596 spec->dig_in_nid = 0x04;
495 spec->adc_nids = stac9200_adc_nids; 597 spec->adc_nids = stac9200_adc_nids;
496 spec->mux_nids = stac9200_mux_nids; 598 spec->mux_nids = stac9200_mux_nids;
497 spec->input_mux = &stac9200_input_mux; 599 spec->num_muxes = 1;
600 spec->input_mux.num_items = 0;
498 spec->pstate_nids = stac9200_pstate_nids; 601 spec->pstate_nids = stac9200_pstate_nids;
499 spec->num_pstates = 3; 602 spec->num_pstates = 3;
500 spec->pin_nids = stac9200_pin_nids; 603 spec->pin_nids = stac9200_pin_nids;
@@ -525,11 +628,14 @@ static int patch_stac922x(struct hda_codec *codec)
525 spec->multiout.max_channels = 2; 628 spec->multiout.max_channels = 2;
526 spec->multiout.num_dacs = 4; 629 spec->multiout.num_dacs = 4;
527 spec->multiout.dac_nids = stac922x_dac_nids; 630 spec->multiout.dac_nids = stac922x_dac_nids;
631 spec->multiout.dig_out_nid = 0x08;
632 spec->dig_in_nid = 0x09;
528 spec->adc_nids = stac922x_adc_nids; 633 spec->adc_nids = stac922x_adc_nids;
529 spec->mux_nids = stac922x_mux_nids; 634 spec->mux_nids = stac922x_mux_nids;
530 spec->input_mux = &stac922x_input_mux; 635 spec->num_muxes = 2;
636 spec->input_mux.num_items = 0;
531 spec->pstate_nids = stac922x_pstate_nids; 637 spec->pstate_nids = stac922x_pstate_nids;
532 spec->num_pstates = 7; 638 spec->num_pstates = 8;
533 spec->pin_nids = stac922x_pin_nids; 639 spec->pin_nids = stac922x_pin_nids;
534#ifdef STAC_TEST 640#ifdef STAC_TEST
535 spec->pin_configs = stac922x_pin_configs; 641 spec->pin_configs = stac922x_pin_configs;