diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 82f48fbcd74b..f49520117dd6 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1669,21 +1669,51 @@ static int had_iec958_put(struct snd_kcontrol *kcontrol, return changed; } -static struct snd_kcontrol_new had_control_iec958_mask = { - .access = SNDRV_CTL_ELEM_ACCESS_READ, - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), - .info = had_iec958_info, /* shared */ - .get = had_iec958_mask_get, +static int had_ctl_eld_info(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_info *uinfo) +{ + uinfo->type = SNDRV_CTL_ELEM_TYPE_BYTES; + uinfo->count = HDMI_MAX_ELD_BYTES; + return 0; +} + +static int had_ctl_eld_get(struct snd_kcontrol *kcontrol, + struct snd_ctl_elem_value *ucontrol) +{ + struct snd_intelhad *intelhaddata = snd_kcontrol_chip(kcontrol); + + mutex_lock(&intelhaddata->mutex); + memcpy(ucontrol->value.bytes.data, intelhaddata->eld, + HDMI_MAX_ELD_BYTES); + mutex_unlock(&intelhaddata->mutex); + return 0; +} + +static struct snd_kcontrol_new had_controls[] = { + { + .access = SNDRV_CTL_ELEM_ACCESS_READ, + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, MASK), + .info = had_iec958_info, /* shared */ + .get = had_iec958_mask_get, + }, + { + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), + .info = had_iec958_info, + .get = had_iec958_get, + .put = had_iec958_put, + }, + { + .access = (SNDRV_CTL_ELEM_ACCESS_READ | + SNDRV_CTL_ELEM_ACCESS_VOLATILE), + .iface = SNDRV_CTL_ELEM_IFACE_PCM, + .name = "ELD", + .info = had_ctl_eld_info, + .get = had_ctl_eld_get, + }, }; -static struct snd_kcontrol_new had_control_iec958 = { - .iface = SNDRV_CTL_ELEM_IFACE_PCM, - .name = SNDRV_CTL_NAME_IEC958("", PLAYBACK, DEFAULT), - .info = had_iec958_info, - .get = had_iec958_get, - .put = had_iec958_put -}; static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) { @@ -1724,6 +1754,7 @@ static void had_audio_wq(struct work_struct *work) if (!pdata->hdmi_connected) { dev_dbg(ctx->dev, "%s: Event: HAD_NOTIFY_HOT_UNPLUG\n", __func__); + memset(ctx->eld, 0, sizeof(ctx->eld)); /* clear the old ELD */ had_process_hot_unplug(ctx); } else { struct intel_hdmi_lpe_audio_eld *eld = &pdata->eld; @@ -1826,7 +1857,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) struct intel_hdmi_lpe_audio_pdata *pdata; int irq; struct resource *res_mmio; - int ret; + int i, ret; dev_dbg(&pdev->dev, "dma_mask: %p\n", pdev->dev.dma_mask); @@ -1918,13 +1949,12 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) SNDRV_DMA_TYPE_DEV, NULL, HAD_MAX_BUFFER, HAD_MAX_BUFFER); - /* IEC958 controls */ - ret = snd_ctl_add(card, snd_ctl_new1(&had_control_iec958_mask, ctx)); - if (ret < 0) - goto err; - ret = snd_ctl_add(card, snd_ctl_new1(&had_control_iec958, ctx)); - if (ret < 0) - goto err; + /* create controls */ + for (i = 0; i < ARRAY_SIZE(had_controls); i++) { + ret = snd_ctl_add(card, snd_ctl_new1(&had_controls[i], ctx)); + if (ret < 0) + goto err; + } init_channel_allocations();