aboutsummaryrefslogtreecommitdiffstats
path: root/sound/pci/hda/patch_hdmi.c
diff options
context:
space:
mode:
authorLibin Yang <libin.yang@linux.intel.com>2016-02-23 03:33:37 -0500
committerTakashi Iwai <tiwai@suse.de>2016-02-23 04:33:44 -0500
commitfb087eaaef72061b2bb4e35b70ab43865f541cad (patch)
treeaa134e4ddc2a3340f1c19315d58230b9a19250fd /sound/pci/hda/patch_hdmi.c
parentfe0d128c57bf927a713159f60a18d9f315d4d91d (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.c74
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 {
136struct hdmi_pcm { 135struct 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
141struct hdmi_spec { 141struct 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
528static int hdmi_create_eld_ctl(struct hda_codec *codec, int pin_idx, 540static 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 }