diff options
author | Libin Yang <libin.yang@linux.intel.com> | 2016-02-23 03:33:37 -0500 |
---|---|---|
committer | Takashi Iwai <tiwai@suse.de> | 2016-02-23 04:33:44 -0500 |
commit | fb087eaaef72061b2bb4e35b70ab43865f541cad (patch) | |
tree | aa134e4ddc2a3340f1c19315d58230b9a19250fd /sound/pci/hda/patch_hdmi.c | |
parent | fe0d128c57bf927a713159f60a18d9f315d4d91d (diff) |
ALSA: hda - hdmi eld control created based on pcm
eld control is created based on pcm now.
When monitor is connected, eld control will be bound to
pin automatically.
Signed-off-by: Libin Yang <libin.yang@linux.intel.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Diffstat (limited to 'sound/pci/hda/patch_hdmi.c')
-rw-r--r-- | sound/pci/hda/patch_hdmi.c | 74 |
1 files changed, 48 insertions, 26 deletions
diff --git a/sound/pci/hda/patch_hdmi.c b/sound/pci/hda/patch_hdmi.c index 541986f414cb..21a2b28a2ceb 100644 --- a/sound/pci/hda/patch_hdmi.c +++ b/sound/pci/hda/patch_hdmi.c | |||
@@ -86,7 +86,6 @@ struct hdmi_spec_per_pin { | |||
86 | struct hdmi_eld sink_eld; | 86 | struct hdmi_eld sink_eld; |
87 | struct mutex lock; | 87 | struct mutex lock; |
88 | struct delayed_work work; | 88 | struct delayed_work work; |
89 | struct snd_kcontrol *eld_ctl; | ||
90 | struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ | 89 | struct hdmi_pcm *pcm; /* pointer to spec->pcm_rec[n] dynamically*/ |
91 | int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ | 90 | int pcm_idx; /* which pcm is attached. -1 means no pcm is attached */ |
92 | int repoll_count; | 91 | int repoll_count; |
@@ -136,6 +135,7 @@ struct hdmi_ops { | |||
136 | struct hdmi_pcm { | 135 | struct hdmi_pcm { |
137 | struct hda_pcm *pcm; | 136 | struct hda_pcm *pcm; |
138 | struct snd_jack *jack; | 137 | struct snd_jack *jack; |
138 | struct snd_kcontrol *eld_ctl; | ||
139 | }; | 139 | }; |
140 | 140 | ||
141 | struct hdmi_spec { | 141 | struct hdmi_spec { |
@@ -471,17 +471,22 @@ static int hdmi_eld_ctl_info(struct snd_kcontrol *kcontrol, | |||
471 | struct hdmi_spec *spec = codec->spec; | 471 | struct hdmi_spec *spec = codec->spec; |
472 | struct hdmi_spec_per_pin *per_pin; | 472 | struct hdmi_spec_per_pin *per_pin; |
473 | struct hdmi_eld *eld; | 473 | struct hdmi_eld *eld; |
474 | int pin_idx; | 474 | int pcm_idx; |
475 | 475 | ||
476 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; | 476 | uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; |
477 | 477 | ||
478 | pin_idx = kcontrol->private_value; | 478 | pcm_idx = kcontrol->private_value; |
479 | per_pin = get_pin(spec, pin_idx); | 479 | mutex_lock(&spec->pcm_lock); |
480 | per_pin = pcm_idx_to_pin(spec, pcm_idx); | ||
481 | if (!per_pin) { | ||
482 | /* no pin is bound to the pcm */ | ||
483 | uinfo->count = 0; | ||
484 | mutex_unlock(&spec->pcm_lock); | ||
485 | return 0; | ||
486 | } | ||
480 | eld = &per_pin->sink_eld; | 487 | eld = &per_pin->sink_eld; |
481 | |||
482 | mutex_lock(&per_pin->lock); | ||
483 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; | 488 | uinfo->count = eld->eld_valid ? eld->eld_size : 0; |
484 | mutex_unlock(&per_pin->lock); | 489 | mutex_unlock(&spec->pcm_lock); |
485 | 490 | ||
486 | return 0; | 491 | return 0; |
487 | } | 492 | } |
@@ -493,16 +498,23 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | |||
493 | struct hdmi_spec *spec = codec->spec; | 498 | struct hdmi_spec *spec = codec->spec; |
494 | struct hdmi_spec_per_pin *per_pin; | 499 | struct hdmi_spec_per_pin *per_pin; |
495 | struct hdmi_eld *eld; | 500 | struct hdmi_eld *eld; |
496 | int pin_idx; | 501 | int pcm_idx; |
497 | 502 | ||
498 | pin_idx = kcontrol->private_value; | 503 | pcm_idx = kcontrol->private_value; |
499 | per_pin = get_pin(spec, pin_idx); | 504 | mutex_lock(&spec->pcm_lock); |
505 | per_pin = pcm_idx_to_pin(spec, pcm_idx); | ||
506 | if (!per_pin) { | ||
507 | /* no pin is bound to the pcm */ | ||
508 | memset(ucontrol->value.bytes.data, 0, | ||
509 | ARRAY_SIZE(ucontrol->value.bytes.data)); | ||
510 | mutex_unlock(&spec->pcm_lock); | ||
511 | return 0; | ||
512 | } | ||
500 | eld = &per_pin->sink_eld; | 513 | eld = &per_pin->sink_eld; |
501 | 514 | ||
502 | mutex_lock(&per_pin->lock); | ||
503 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || | 515 | if (eld->eld_size > ARRAY_SIZE(ucontrol->value.bytes.data) || |
504 | eld->eld_size > ELD_MAX_SIZE) { | 516 | eld->eld_size > ELD_MAX_SIZE) { |
505 | mutex_unlock(&per_pin->lock); | 517 | mutex_unlock(&spec->pcm_lock); |
506 | snd_BUG(); | 518 | snd_BUG(); |
507 | return -EINVAL; | 519 | return -EINVAL; |
508 | } | 520 | } |
@@ -512,7 +524,7 @@ static int hdmi_eld_ctl_get(struct snd_kcontrol *kcontrol, | |||
512 | if (eld->eld_valid) | 524 | if (eld->eld_valid) |
513 | memcpy(ucontrol->value.bytes.data, eld->eld_buffer, | 525 | memcpy(ucontrol->value.bytes.data, eld->eld_buffer, |
514 | eld->eld_size); | 526 | eld->eld_size); |
515 | mutex_unlock(&per_pin->lock); | 527 | mutex_unlock(&spec->pcm_lock); |
516 | 528 | ||
517 | return 0; | 529 | return 0; |
518 | } | 530 | } |
@@ -525,7 +537,7 @@ static struct snd_kcontrol_new eld_bytes_ctl = { | |||
525 | .get = hdmi_eld_ctl_get, | 537 | .get = hdmi_eld_ctl_get, |
526 | }; | 538 | }; |
527 | 539 | ||
528 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | 540 | static int hdmi_create_eld_ctl(struct hda_codec *codec, int pcm_idx, |
529 | int device) | 541 | int device) |
530 | { | 542 | { |
531 | struct snd_kcontrol *kctl; | 543 | struct snd_kcontrol *kctl; |
@@ -535,14 +547,17 @@ static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, | |||
535 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); | 547 | kctl = snd_ctl_new1(&eld_bytes_ctl, codec); |
536 | if (!kctl) | 548 | if (!kctl) |
537 | return -ENOMEM; | 549 | return -ENOMEM; |
538 | kctl->private_value = pin_idx; | 550 | kctl->private_value = pcm_idx; |
539 | kctl->id.device = device; | 551 | kctl->id.device = device; |
540 | 552 | ||
541 | err = snd_hda_ctl_add(codec, get_pin(spec, pin_idx)->pin_nid, kctl); | 553 | /* no pin nid is associated with the kctl now |
554 | * tbd: associate pin nid to eld ctl later | ||
555 | */ | ||
556 | err = snd_hda_ctl_add(codec, 0, kctl); | ||
542 | if (err < 0) | 557 | if (err < 0) |
543 | return err; | 558 | return err; |
544 | 559 | ||
545 | get_pin(spec, pin_idx)->eld_ctl = kctl; | 560 | get_hdmi_pcm(spec, pcm_idx)->eld_ctl = kctl; |
546 | return 0; | 561 | return 0; |
547 | } | 562 | } |
548 | 563 | ||
@@ -1841,7 +1856,10 @@ static void update_eld(struct hda_codec *codec, | |||
1841 | struct hdmi_spec *spec = codec->spec; | 1856 | struct hdmi_spec *spec = codec->spec; |
1842 | bool old_eld_valid = pin_eld->eld_valid; | 1857 | bool old_eld_valid = pin_eld->eld_valid; |
1843 | bool eld_changed; | 1858 | bool eld_changed; |
1859 | int pcm_idx = -1; | ||
1844 | 1860 | ||
1861 | /* for monitor disconnection, save pcm_idx firstly */ | ||
1862 | pcm_idx = per_pin->pcm_idx; | ||
1845 | if (spec->dyn_pcm_assign) { | 1863 | if (spec->dyn_pcm_assign) { |
1846 | if (eld->eld_valid) { | 1864 | if (eld->eld_valid) { |
1847 | hdmi_attach_hda_pcm(spec, per_pin); | 1865 | hdmi_attach_hda_pcm(spec, per_pin); |
@@ -1851,6 +1869,11 @@ static void update_eld(struct hda_codec *codec, | |||
1851 | hdmi_detach_hda_pcm(spec, per_pin); | 1869 | hdmi_detach_hda_pcm(spec, per_pin); |
1852 | } | 1870 | } |
1853 | } | 1871 | } |
1872 | /* if pcm_idx == -1, it means this is in monitor connection event | ||
1873 | * we can get the correct pcm_idx now. | ||
1874 | */ | ||
1875 | if (pcm_idx == -1) | ||
1876 | pcm_idx = per_pin->pcm_idx; | ||
1854 | 1877 | ||
1855 | if (eld->eld_valid) | 1878 | if (eld->eld_valid) |
1856 | snd_hdmi_show_eld(codec, &eld->info); | 1879 | snd_hdmi_show_eld(codec, &eld->info); |
@@ -1884,11 +1907,11 @@ static void update_eld(struct hda_codec *codec, | |||
1884 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); | 1907 | hdmi_setup_audio_infoframe(codec, per_pin, per_pin->non_pcm); |
1885 | } | 1908 | } |
1886 | 1909 | ||
1887 | if (eld_changed) | 1910 | if (eld_changed && pcm_idx >= 0) |
1888 | snd_ctl_notify(codec->card, | 1911 | snd_ctl_notify(codec->card, |
1889 | SNDRV_CTL_EVENT_MASK_VALUE | | 1912 | SNDRV_CTL_EVENT_MASK_VALUE | |
1890 | SNDRV_CTL_EVENT_MASK_INFO, | 1913 | SNDRV_CTL_EVENT_MASK_INFO, |
1891 | &per_pin->eld_ctl->id); | 1914 | &get_hdmi_pcm(spec, pcm_idx)->eld_ctl->id); |
1892 | } | 1915 | } |
1893 | 1916 | ||
1894 | /* update ELD and jack state via HD-audio verbs */ | 1917 | /* update ELD and jack state via HD-audio verbs */ |
@@ -2629,17 +2652,16 @@ static int generic_hdmi_build_controls(struct hda_codec *codec) | |||
2629 | if (err < 0) | 2652 | if (err < 0) |
2630 | return err; | 2653 | return err; |
2631 | snd_hda_spdif_ctls_unassign(codec, pcm_idx); | 2654 | snd_hda_spdif_ctls_unassign(codec, pcm_idx); |
2632 | } | ||
2633 | |||
2634 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
2635 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | ||
2636 | 2655 | ||
2637 | /* add control for ELD Bytes */ | 2656 | /* add control for ELD Bytes */ |
2638 | err = hdmi_create_eld_ctl(codec, pin_idx, | 2657 | err = hdmi_create_eld_ctl(codec, pcm_idx, |
2639 | get_pcm_rec(spec, pin_idx)->device); | 2658 | get_pcm_rec(spec, pcm_idx)->device); |
2640 | |||
2641 | if (err < 0) | 2659 | if (err < 0) |
2642 | return err; | 2660 | return err; |
2661 | } | ||
2662 | |||
2663 | for (pin_idx = 0; pin_idx < spec->num_pins; pin_idx++) { | ||
2664 | struct hdmi_spec_per_pin *per_pin = get_pin(spec, pin_idx); | ||
2643 | 2665 | ||
2644 | hdmi_present_sense(per_pin, 0); | 2666 | hdmi_present_sense(per_pin, 0); |
2645 | } | 2667 | } |