From 7229b12f5da33d5c376ee264f063703844b8092d Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Tue, 20 Feb 2018 17:33:45 +0100 Subject: ALSA: x86: hdmi: Add single_port option for compatible behavior The recent support for the multiple PCM devices allowed user to use multiple HDMI/DP outputs, but at the same time, the PCM stream assignment has been changed, too. Due to that, the former PCM#0 (there was only one stream in the past) is likely assigned to a different one (e.g. PCM#2), and it ends up with the regression when user sticks with the fixed configuration using the device#0. Although the multiple monitor support shouldn't matter when user deploys the backend like PulseAudio that checks the jack detection state, the behavior change isn't always acceptable for some users. As a mitigation, this patch introduces an option to switch the behavior back to the old-good-days: when the new option, single_port=1, is passed, the driver creates only a single PCM device, and it's assigned to the first connected one, like the earlier versions did. The option is turned off as default still to support the multiple monitors. Fixes: 8a2d6ae1f737 ("ALSA: x86: Register multiple PCM devices for the LPE audio card") Reported-and-tested-by: Hubert Mantel Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'sound/x86/intel_hdmi_audio.c') diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index a0951505c7f5..96115c401292 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -50,6 +50,7 @@ /*standard module options for ALSA. This module supports only one card*/ static int hdmi_card_index = SNDRV_DEFAULT_IDX1; static char *hdmi_card_id = SNDRV_DEFAULT_STR1; +static bool single_port; module_param_named(index, hdmi_card_index, int, 0444); MODULE_PARM_DESC(index, @@ -57,6 +58,9 @@ MODULE_PARM_DESC(index, module_param_named(id, hdmi_card_id, charp, 0444); MODULE_PARM_DESC(id, "ID string for INTEL Intel HDMI Audio controller."); +module_param(single_port, bool, 0444); +MODULE_PARM_DESC(single_port, + "Single-port mode (for compatibility)"); /* * ELD SA bits in the CEA Speaker Allocation data block @@ -1579,7 +1583,11 @@ static irqreturn_t display_pipe_interrupt_handler(int irq, void *dev_id) static void notify_audio_lpe(struct platform_device *pdev, int port) { struct snd_intelhad_card *card_ctx = platform_get_drvdata(pdev); - struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; + struct snd_intelhad *ctx; + + ctx = &card_ctx->pcm_ctx[single_port ? 0 : port]; + if (single_port) + ctx->port = port; schedule_work(&ctx->hdmi_audio_wq); } @@ -1816,7 +1824,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) init_channel_allocations(); card_ctx->num_pipes = pdata->num_pipes; - card_ctx->num_ports = pdata->num_ports; + card_ctx->num_ports = single_port ? 1 : pdata->num_ports; for_each_port(card_ctx, port) { struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; @@ -1824,7 +1832,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) ctx->card_ctx = card_ctx; ctx->dev = card_ctx->dev; - ctx->port = port; + ctx->port = single_port ? -1 : port; ctx->pipe = -1; INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); -- cgit From 350144069abf351c743d766b2fba9cb9b7cd32a1 Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Feb 2018 08:36:06 +0100 Subject: ALSA: x86: Fix missing spinlock and mutex initializations The commit change for supporting the multiple ports moved involved some code shuffling, and there the initializations of spinlock and mutex in snd_intelhad object were dropped mistakenly. This patch adds the missing initializations again for each port. Fixes: b4eb0d522fcb ("ALSA: x86: Split snd_intelhad into card and PCM specific structures") Cc: Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 2 ++ 1 file changed, 2 insertions(+) (limited to 'sound/x86/intel_hdmi_audio.c') diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index 96115c401292..cec62f9b7085 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1835,6 +1835,8 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) ctx->port = single_port ? -1 : port; ctx->pipe = -1; + spin_lock_init(&ctx->had_spinlock); + mutex_init(&ctx->mutex); INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, -- cgit From c77a6edb6d4d35204673cad7389c317bfb17492e Mon Sep 17 00:00:00 2001 From: Takashi Iwai Date: Wed, 28 Feb 2018 08:46:00 +0100 Subject: ALSA: x86: Fix potential crash at error path When LPE audio driver gets some error at probing, it may lead to a crash because of canceling the pending work in hdmi_lpe_audio_free(), since some of ports might be still not initialized. For assuring the proper free of each port, initialize all ports at the beginning of the probe. Fixes: b4eb0d522fcb ("ALSA: x86: Split snd_intelhad into card and PCM specific structures") Signed-off-by: Takashi Iwai --- sound/x86/intel_hdmi_audio.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) (limited to 'sound/x86/intel_hdmi_audio.c') diff --git a/sound/x86/intel_hdmi_audio.c b/sound/x86/intel_hdmi_audio.c index cec62f9b7085..4ed9d0c41843 100644 --- a/sound/x86/intel_hdmi_audio.c +++ b/sound/x86/intel_hdmi_audio.c @@ -1751,6 +1751,7 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) { struct snd_card *card; struct snd_intelhad_card *card_ctx; + struct snd_intelhad *ctx; struct snd_pcm *pcm; struct intel_hdmi_lpe_audio_pdata *pdata; int irq; @@ -1795,6 +1796,21 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) platform_set_drvdata(pdev, card_ctx); + card_ctx->num_pipes = pdata->num_pipes; + card_ctx->num_ports = single_port ? 1 : pdata->num_ports; + + for_each_port(card_ctx, port) { + ctx = &card_ctx->pcm_ctx[port]; + ctx->card_ctx = card_ctx; + ctx->dev = card_ctx->dev; + ctx->port = single_port ? -1 : port; + ctx->pipe = -1; + + spin_lock_init(&ctx->had_spinlock); + mutex_init(&ctx->mutex); + INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); + } + dev_dbg(&pdev->dev, "%s: mmio_start = 0x%x, mmio_end = 0x%x\n", __func__, (unsigned int)res_mmio->start, (unsigned int)res_mmio->end); @@ -1827,18 +1843,9 @@ static int hdmi_lpe_audio_probe(struct platform_device *pdev) card_ctx->num_ports = single_port ? 1 : pdata->num_ports; for_each_port(card_ctx, port) { - struct snd_intelhad *ctx = &card_ctx->pcm_ctx[port]; int i; - ctx->card_ctx = card_ctx; - ctx->dev = card_ctx->dev; - ctx->port = single_port ? -1 : port; - ctx->pipe = -1; - - spin_lock_init(&ctx->had_spinlock); - mutex_init(&ctx->mutex); - INIT_WORK(&ctx->hdmi_audio_wq, had_audio_wq); - + ctx = &card_ctx->pcm_ctx[port]; ret = snd_pcm_new(card, INTEL_HAD, port, MAX_PB_STREAMS, MAX_CAP_STREAMS, &pcm); if (ret) -- cgit