diff options
Diffstat (limited to 'sound/pci/hda/hda_codec.c')
-rw-r--r-- | sound/pci/hda/hda_codec.c | 195 |
1 files changed, 137 insertions, 58 deletions
diff --git a/sound/pci/hda/hda_codec.c b/sound/pci/hda/hda_codec.c index 41ca803a1fff..f25c24c743f9 100644 --- a/sound/pci/hda/hda_codec.c +++ b/sound/pci/hda/hda_codec.c | |||
@@ -1184,6 +1184,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1184 | { | 1184 | { |
1185 | if (!codec) | 1185 | if (!codec) |
1186 | return; | 1186 | return; |
1187 | snd_hda_jack_tbl_clear(codec); | ||
1187 | restore_init_pincfgs(codec); | 1188 | restore_init_pincfgs(codec); |
1188 | #ifdef CONFIG_SND_HDA_POWER_SAVE | 1189 | #ifdef CONFIG_SND_HDA_POWER_SAVE |
1189 | cancel_delayed_work(&codec->power_work); | 1190 | cancel_delayed_work(&codec->power_work); |
@@ -1192,6 +1193,7 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1192 | list_del(&codec->list); | 1193 | list_del(&codec->list); |
1193 | snd_array_free(&codec->mixers); | 1194 | snd_array_free(&codec->mixers); |
1194 | snd_array_free(&codec->nids); | 1195 | snd_array_free(&codec->nids); |
1196 | snd_array_free(&codec->cvt_setups); | ||
1195 | snd_array_free(&codec->conn_lists); | 1197 | snd_array_free(&codec->conn_lists); |
1196 | snd_array_free(&codec->spdif_out); | 1198 | snd_array_free(&codec->spdif_out); |
1197 | codec->bus->caddr_tbl[codec->addr] = NULL; | 1199 | codec->bus->caddr_tbl[codec->addr] = NULL; |
@@ -1207,6 +1209,9 @@ static void snd_hda_codec_free(struct hda_codec *codec) | |||
1207 | kfree(codec); | 1209 | kfree(codec); |
1208 | } | 1210 | } |
1209 | 1211 | ||
1212 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, | ||
1213 | hda_nid_t fg, unsigned int power_state); | ||
1214 | |||
1210 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 1215 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
1211 | unsigned int power_state); | 1216 | unsigned int power_state); |
1212 | 1217 | ||
@@ -1315,6 +1320,10 @@ int /*__devinit*/ snd_hda_codec_new(struct hda_bus *bus, | |||
1315 | AC_VERB_GET_SUBSYSTEM_ID, 0); | 1320 | AC_VERB_GET_SUBSYSTEM_ID, 0); |
1316 | } | 1321 | } |
1317 | 1322 | ||
1323 | codec->epss = snd_hda_codec_get_supported_ps(codec, | ||
1324 | codec->afg ? codec->afg : codec->mfg, | ||
1325 | AC_PWRST_EPSS); | ||
1326 | |||
1318 | /* power-up all before initialization */ | 1327 | /* power-up all before initialization */ |
1319 | hda_set_power_state(codec, | 1328 | hda_set_power_state(codec, |
1320 | codec->afg ? codec->afg : codec->mfg, | 1329 | codec->afg ? codec->afg : codec->mfg, |
@@ -1384,6 +1393,44 @@ int snd_hda_codec_configure(struct hda_codec *codec) | |||
1384 | } | 1393 | } |
1385 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); | 1394 | EXPORT_SYMBOL_HDA(snd_hda_codec_configure); |
1386 | 1395 | ||
1396 | /* update the stream-id if changed */ | ||
1397 | static void update_pcm_stream_id(struct hda_codec *codec, | ||
1398 | struct hda_cvt_setup *p, hda_nid_t nid, | ||
1399 | u32 stream_tag, int channel_id) | ||
1400 | { | ||
1401 | unsigned int oldval, newval; | ||
1402 | |||
1403 | if (p->stream_tag != stream_tag || p->channel_id != channel_id) { | ||
1404 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | ||
1405 | newval = (stream_tag << 4) | channel_id; | ||
1406 | if (oldval != newval) | ||
1407 | snd_hda_codec_write(codec, nid, 0, | ||
1408 | AC_VERB_SET_CHANNEL_STREAMID, | ||
1409 | newval); | ||
1410 | p->stream_tag = stream_tag; | ||
1411 | p->channel_id = channel_id; | ||
1412 | } | ||
1413 | } | ||
1414 | |||
1415 | /* update the format-id if changed */ | ||
1416 | static void update_pcm_format(struct hda_codec *codec, struct hda_cvt_setup *p, | ||
1417 | hda_nid_t nid, int format) | ||
1418 | { | ||
1419 | unsigned int oldval; | ||
1420 | |||
1421 | if (p->format_id != format) { | ||
1422 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
1423 | AC_VERB_GET_STREAM_FORMAT, 0); | ||
1424 | if (oldval != format) { | ||
1425 | msleep(1); | ||
1426 | snd_hda_codec_write(codec, nid, 0, | ||
1427 | AC_VERB_SET_STREAM_FORMAT, | ||
1428 | format); | ||
1429 | } | ||
1430 | p->format_id = format; | ||
1431 | } | ||
1432 | } | ||
1433 | |||
1387 | /** | 1434 | /** |
1388 | * snd_hda_codec_setup_stream - set up the codec for streaming | 1435 | * snd_hda_codec_setup_stream - set up the codec for streaming |
1389 | * @codec: the CODEC to set up | 1436 | * @codec: the CODEC to set up |
@@ -1398,7 +1445,6 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1398 | { | 1445 | { |
1399 | struct hda_codec *c; | 1446 | struct hda_codec *c; |
1400 | struct hda_cvt_setup *p; | 1447 | struct hda_cvt_setup *p; |
1401 | unsigned int oldval, newval; | ||
1402 | int type; | 1448 | int type; |
1403 | int i; | 1449 | int i; |
1404 | 1450 | ||
@@ -1411,29 +1457,13 @@ void snd_hda_codec_setup_stream(struct hda_codec *codec, hda_nid_t nid, | |||
1411 | p = get_hda_cvt_setup(codec, nid); | 1457 | p = get_hda_cvt_setup(codec, nid); |
1412 | if (!p) | 1458 | if (!p) |
1413 | return; | 1459 | return; |
1414 | /* update the stream-id if changed */ | 1460 | |
1415 | if (p->stream_tag != stream_tag || p->channel_id != channel_id) { | 1461 | if (codec->pcm_format_first) |
1416 | oldval = snd_hda_codec_read(codec, nid, 0, AC_VERB_GET_CONV, 0); | 1462 | update_pcm_format(codec, p, nid, format); |
1417 | newval = (stream_tag << 4) | channel_id; | 1463 | update_pcm_stream_id(codec, p, nid, stream_tag, channel_id); |
1418 | if (oldval != newval) | 1464 | if (!codec->pcm_format_first) |
1419 | snd_hda_codec_write(codec, nid, 0, | 1465 | update_pcm_format(codec, p, nid, format); |
1420 | AC_VERB_SET_CHANNEL_STREAMID, | 1466 | |
1421 | newval); | ||
1422 | p->stream_tag = stream_tag; | ||
1423 | p->channel_id = channel_id; | ||
1424 | } | ||
1425 | /* update the format-id if changed */ | ||
1426 | if (p->format_id != format) { | ||
1427 | oldval = snd_hda_codec_read(codec, nid, 0, | ||
1428 | AC_VERB_GET_STREAM_FORMAT, 0); | ||
1429 | if (oldval != format) { | ||
1430 | msleep(1); | ||
1431 | snd_hda_codec_write(codec, nid, 0, | ||
1432 | AC_VERB_SET_STREAM_FORMAT, | ||
1433 | format); | ||
1434 | } | ||
1435 | p->format_id = format; | ||
1436 | } | ||
1437 | p->active = 1; | 1467 | p->active = 1; |
1438 | p->dirty = 0; | 1468 | p->dirty = 0; |
1439 | 1469 | ||
@@ -2333,6 +2363,8 @@ int snd_hda_codec_reset(struct hda_codec *codec) | |||
2333 | /* free only driver_pins so that init_pins + user_pins are restored */ | 2363 | /* free only driver_pins so that init_pins + user_pins are restored */ |
2334 | snd_array_free(&codec->driver_pins); | 2364 | snd_array_free(&codec->driver_pins); |
2335 | restore_pincfgs(codec); | 2365 | restore_pincfgs(codec); |
2366 | snd_array_free(&codec->cvt_setups); | ||
2367 | snd_array_free(&codec->spdif_out); | ||
2336 | codec->num_pcms = 0; | 2368 | codec->num_pcms = 0; |
2337 | codec->pcm_info = NULL; | 2369 | codec->pcm_info = NULL; |
2338 | codec->preset = NULL; | 2370 | codec->preset = NULL; |
@@ -2672,25 +2704,6 @@ int snd_hda_mixer_amp_switch_put(struct snd_kcontrol *kcontrol, | |||
2672 | } | 2704 | } |
2673 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); | 2705 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put); |
2674 | 2706 | ||
2675 | #ifdef CONFIG_SND_HDA_INPUT_BEEP | ||
2676 | /** | ||
2677 | * snd_hda_mixer_amp_switch_put_beep - Put callback for a beep AMP switch | ||
2678 | * | ||
2679 | * This function calls snd_hda_enable_beep_device(), which behaves differently | ||
2680 | * depending on beep_mode option. | ||
2681 | */ | ||
2682 | int snd_hda_mixer_amp_switch_put_beep(struct snd_kcontrol *kcontrol, | ||
2683 | struct snd_ctl_elem_value *ucontrol) | ||
2684 | { | ||
2685 | struct hda_codec *codec = snd_kcontrol_chip(kcontrol); | ||
2686 | long *valp = ucontrol->value.integer.value; | ||
2687 | |||
2688 | snd_hda_enable_beep_device(codec, *valp); | ||
2689 | return snd_hda_mixer_amp_switch_put(kcontrol, ucontrol); | ||
2690 | } | ||
2691 | EXPORT_SYMBOL_HDA(snd_hda_mixer_amp_switch_put_beep); | ||
2692 | #endif /* CONFIG_SND_HDA_INPUT_BEEP */ | ||
2693 | |||
2694 | /* | 2707 | /* |
2695 | * bound volume controls | 2708 | * bound volume controls |
2696 | * | 2709 | * |
@@ -3505,22 +3518,51 @@ void snd_hda_codec_set_power_to_all(struct hda_codec *codec, hda_nid_t fg, | |||
3505 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); | 3518 | EXPORT_SYMBOL_HDA(snd_hda_codec_set_power_to_all); |
3506 | 3519 | ||
3507 | /* | 3520 | /* |
3521 | * supported power states check | ||
3522 | */ | ||
3523 | static bool snd_hda_codec_get_supported_ps(struct hda_codec *codec, hda_nid_t fg, | ||
3524 | unsigned int power_state) | ||
3525 | { | ||
3526 | int sup = snd_hda_param_read(codec, fg, AC_PAR_POWER_STATE); | ||
3527 | |||
3528 | if (sup == -1) | ||
3529 | return false; | ||
3530 | if (sup & power_state) | ||
3531 | return true; | ||
3532 | else | ||
3533 | return false; | ||
3534 | } | ||
3535 | |||
3536 | /* | ||
3508 | * set power state of the codec | 3537 | * set power state of the codec |
3509 | */ | 3538 | */ |
3510 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, | 3539 | static void hda_set_power_state(struct hda_codec *codec, hda_nid_t fg, |
3511 | unsigned int power_state) | 3540 | unsigned int power_state) |
3512 | { | 3541 | { |
3542 | int count; | ||
3543 | unsigned int state; | ||
3544 | |||
3513 | if (codec->patch_ops.set_power_state) { | 3545 | if (codec->patch_ops.set_power_state) { |
3514 | codec->patch_ops.set_power_state(codec, fg, power_state); | 3546 | codec->patch_ops.set_power_state(codec, fg, power_state); |
3515 | return; | 3547 | return; |
3516 | } | 3548 | } |
3517 | 3549 | ||
3518 | /* this delay seems necessary to avoid click noise at power-down */ | 3550 | /* this delay seems necessary to avoid click noise at power-down */ |
3519 | if (power_state == AC_PWRST_D3) | 3551 | if (power_state == AC_PWRST_D3) { |
3520 | msleep(100); | 3552 | /* transition time less than 10ms for power down */ |
3521 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | 3553 | msleep(codec->epss ? 10 : 100); |
3522 | power_state); | 3554 | } |
3523 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | 3555 | |
3556 | /* repeat power states setting at most 10 times*/ | ||
3557 | for (count = 0; count < 10; count++) { | ||
3558 | snd_hda_codec_read(codec, fg, 0, AC_VERB_SET_POWER_STATE, | ||
3559 | power_state); | ||
3560 | snd_hda_codec_set_power_to_all(codec, fg, power_state, true); | ||
3561 | state = snd_hda_codec_read(codec, fg, 0, | ||
3562 | AC_VERB_GET_POWER_STATE, 0); | ||
3563 | if (!(state & AC_PWRST_ERROR)) | ||
3564 | break; | ||
3565 | } | ||
3524 | } | 3566 | } |
3525 | 3567 | ||
3526 | #ifdef CONFIG_SND_HDA_HWDEP | 3568 | #ifdef CONFIG_SND_HDA_HWDEP |
@@ -3541,7 +3583,7 @@ static inline void hda_exec_init_verbs(struct hda_codec *codec) {} | |||
3541 | static void hda_call_codec_suspend(struct hda_codec *codec) | 3583 | static void hda_call_codec_suspend(struct hda_codec *codec) |
3542 | { | 3584 | { |
3543 | if (codec->patch_ops.suspend) | 3585 | if (codec->patch_ops.suspend) |
3544 | codec->patch_ops.suspend(codec, PMSG_SUSPEND); | 3586 | codec->patch_ops.suspend(codec); |
3545 | hda_cleanup_all_streams(codec); | 3587 | hda_cleanup_all_streams(codec); |
3546 | hda_set_power_state(codec, | 3588 | hda_set_power_state(codec, |
3547 | codec->afg ? codec->afg : codec->mfg, | 3589 | codec->afg ? codec->afg : codec->mfg, |
@@ -4393,20 +4435,19 @@ void snd_hda_update_power_acct(struct hda_codec *codec) | |||
4393 | codec->power_jiffies += delta; | 4435 | codec->power_jiffies += delta; |
4394 | } | 4436 | } |
4395 | 4437 | ||
4396 | /** | 4438 | /* Transition to powered up, if wait_power_down then wait for a pending |
4397 | * snd_hda_power_up - Power-up the codec | 4439 | * transition to D3 to complete. A pending D3 transition is indicated |
4398 | * @codec: HD-audio codec | 4440 | * with power_transition == -1. */ |
4399 | * | 4441 | static void __snd_hda_power_up(struct hda_codec *codec, bool wait_power_down) |
4400 | * Increment the power-up counter and power up the hardware really when | ||
4401 | * not turned on yet. | ||
4402 | */ | ||
4403 | void snd_hda_power_up(struct hda_codec *codec) | ||
4404 | { | 4442 | { |
4405 | struct hda_bus *bus = codec->bus; | 4443 | struct hda_bus *bus = codec->bus; |
4406 | 4444 | ||
4407 | spin_lock(&codec->power_lock); | 4445 | spin_lock(&codec->power_lock); |
4408 | codec->power_count++; | 4446 | codec->power_count++; |
4409 | if (codec->power_on || codec->power_transition > 0) { | 4447 | /* Return if power_on or transitioning to power_on, unless currently |
4448 | * powering down. */ | ||
4449 | if ((codec->power_on || codec->power_transition > 0) && | ||
4450 | !(wait_power_down && codec->power_transition < 0)) { | ||
4410 | spin_unlock(&codec->power_lock); | 4451 | spin_unlock(&codec->power_lock); |
4411 | return; | 4452 | return; |
4412 | } | 4453 | } |
@@ -4415,6 +4456,15 @@ void snd_hda_power_up(struct hda_codec *codec) | |||
4415 | cancel_delayed_work_sync(&codec->power_work); | 4456 | cancel_delayed_work_sync(&codec->power_work); |
4416 | 4457 | ||
4417 | spin_lock(&codec->power_lock); | 4458 | spin_lock(&codec->power_lock); |
4459 | /* If the power down delayed work was cancelled above before starting, | ||
4460 | * then there is no need to go through power up here. | ||
4461 | */ | ||
4462 | if (codec->power_on) { | ||
4463 | if (codec->power_transition < 0) | ||
4464 | codec->power_transition = 0; | ||
4465 | spin_unlock(&codec->power_lock); | ||
4466 | return; | ||
4467 | } | ||
4418 | trace_hda_power_up(codec); | 4468 | trace_hda_power_up(codec); |
4419 | snd_hda_update_power_acct(codec); | 4469 | snd_hda_update_power_acct(codec); |
4420 | codec->power_on = 1; | 4470 | codec->power_on = 1; |
@@ -4430,8 +4480,37 @@ void snd_hda_power_up(struct hda_codec *codec) | |||
4430 | codec->power_transition = 0; | 4480 | codec->power_transition = 0; |
4431 | spin_unlock(&codec->power_lock); | 4481 | spin_unlock(&codec->power_lock); |
4432 | } | 4482 | } |
4483 | |||
4484 | /** | ||
4485 | * snd_hda_power_up - Power-up the codec | ||
4486 | * @codec: HD-audio codec | ||
4487 | * | ||
4488 | * Increment the power-up counter and power up the hardware really when | ||
4489 | * not turned on yet. | ||
4490 | */ | ||
4491 | void snd_hda_power_up(struct hda_codec *codec) | ||
4492 | { | ||
4493 | __snd_hda_power_up(codec, false); | ||
4494 | } | ||
4433 | EXPORT_SYMBOL_HDA(snd_hda_power_up); | 4495 | EXPORT_SYMBOL_HDA(snd_hda_power_up); |
4434 | 4496 | ||
4497 | /** | ||
4498 | * snd_hda_power_up_d3wait - Power-up the codec after waiting for any pending | ||
4499 | * D3 transition to complete. This differs from snd_hda_power_up() when | ||
4500 | * power_transition == -1. snd_hda_power_up sees this case as a nop, | ||
4501 | * snd_hda_power_up_d3wait waits for the D3 transition to complete then powers | ||
4502 | * back up. | ||
4503 | * @codec: HD-audio codec | ||
4504 | * | ||
4505 | * Cancel any power down operation hapenning on the work queue, then power up. | ||
4506 | */ | ||
4507 | void snd_hda_power_up_d3wait(struct hda_codec *codec) | ||
4508 | { | ||
4509 | /* This will cancel and wait for pending power_work to complete. */ | ||
4510 | __snd_hda_power_up(codec, true); | ||
4511 | } | ||
4512 | EXPORT_SYMBOL_HDA(snd_hda_power_up_d3wait); | ||
4513 | |||
4435 | #define power_save(codec) \ | 4514 | #define power_save(codec) \ |
4436 | ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) | 4515 | ((codec)->bus->power_save ? *(codec)->bus->power_save : 0) |
4437 | 4516 | ||