diff options
| -rw-r--r-- | sound/pci/hda/patch_sigmatel.c | 184 |
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 | ||
| 108 | static hda_nid_t stac922x_pstate_nids[7] = { | 111 | static 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 | ||
| 112 | static hda_nid_t stac922x_pin_nids[10] = { | 115 | static 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 | ||
| 124 | static int stac92xx_mux_enum_get(snd_kcontrol_t *kcontrol, snd_ctl_elem_value_t *ucontrol) | 127 | static 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 | ||
| 195 | static 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 | |||
| 206 | static 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 | |||
| 219 | static int stac92xx_build_controls(struct hda_codec *codec) | 198 | static 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 |
| 232 | static unsigned int stac9200_pin_configs[8] = { | 220 | static 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 | ||
| 237 | static unsigned int stac922x_pin_configs[14] = { | 225 | static 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 | |||
| 302 | static int stac92xx_config_pin(struct hda_codec *codec, hda_nid_t nid, unsigned int pin_cfg) | 296 | static 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 | */ | ||
| 455 | static 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 | |||
| 463 | static 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 | */ |
| 407 | static int stac92xx_capture_pcm_prepare(struct hda_pcm_stream *hinfo, | 475 | static 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 | ||
| 498 | static 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 | |||
| 509 | static 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 | |||
| 430 | static struct hda_pcm_stream stac92xx_pcm_analog_playback = { | 516 | static 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; |
