Skip to content

Commit

Permalink
drm/bridge: dw-hdmi: handle ELD when DRM_BRIDGE_ATTACH_NO_CONNECTOR
Browse files Browse the repository at this point in the history
The current ELD handling takes the internal connector ELD buffer and
shares it to the I2S and AHB sub-driver.

But with DRM_BRIDGE_ATTACH_NO_CONNECTOR, the connector is created
elsewhere (or not), and an eventual connector is known only
if the bridge chain up to a connector is enabled.

The current dw-hdmi code gets the current connector from
atomic_enable() so use the already stored connector pointer and
replace the buffer pointer with a callback returning the current
connector ELD buffer.

Since a connector is not always available, either pass an empty
ELD to the alsa HDMI driver or don't call snd_pcm_hw_constraint_eld()
in AHB driver.

Reported-by: Martin Blumenstingl <martin.blumenstingl@googlemail.com>
Signed-off-by: Neil Armstrong <narmstrong@baylibre.com>
[narmstrong: fixed typo in commit log]
Acked-by: Jernej Skrabec <jernej.skrabec@gmail.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20211029135947.3022875-1-narmstrong@baylibre.com
  • Loading branch information
Neil Armstrong committed Nov 12, 2021
1 parent e9d9f95 commit 3f2532d
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 8 deletions.
10 changes: 7 additions & 3 deletions drivers/gpu/drm/bridge/synopsys/dw-hdmi-ahb-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,13 +320,17 @@ static int dw_hdmi_open(struct snd_pcm_substream *substream)
struct snd_pcm_runtime *runtime = substream->runtime;
struct snd_dw_hdmi *dw = substream->private_data;
void __iomem *base = dw->data.base;
u8 *eld;
int ret;

runtime->hw = dw_hdmi_hw;

ret = snd_pcm_hw_constraint_eld(runtime, dw->data.eld);
if (ret < 0)
return ret;
eld = dw->data.get_eld(dw->data.hdmi);
if (eld) {
ret = snd_pcm_hw_constraint_eld(runtime, eld);
if (ret < 0)
return ret;
}

ret = snd_pcm_limit_hw_rates(runtime);
if (ret < 0)
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/bridge/synopsys/dw-hdmi-audio.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ struct dw_hdmi_audio_data {
void __iomem *base;
int irq;
struct dw_hdmi *hdmi;
u8 *eld;
u8 *(*get_eld)(struct dw_hdmi *hdmi);
};

struct dw_hdmi_i2s_audio_data {
struct dw_hdmi *hdmi;
u8 *eld;

void (*write)(struct dw_hdmi *hdmi, u8 val, int offset);
u8 (*read)(struct dw_hdmi *hdmi, int offset);
u8 *(*get_eld)(struct dw_hdmi *hdmi);
};

#endif
9 changes: 8 additions & 1 deletion drivers/gpu/drm/bridge/synopsys/dw-hdmi-i2s-audio.c
Original file line number Diff line number Diff line change
Expand Up @@ -135,8 +135,15 @@ static int dw_hdmi_i2s_get_eld(struct device *dev, void *data, uint8_t *buf,
size_t len)
{
struct dw_hdmi_i2s_audio_data *audio = data;
u8 *eld;

eld = audio->get_eld(audio->hdmi);
if (eld)
memcpy(buf, eld, min_t(size_t, MAX_ELD_BYTES, len));
else
/* Pass en empty ELD if connector not available */
memset(buf, 0, len);

memcpy(buf, audio->eld, min_t(size_t, MAX_ELD_BYTES, len));
return 0;
}

Expand Down
12 changes: 10 additions & 2 deletions drivers/gpu/drm/bridge/synopsys/dw-hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -757,6 +757,14 @@ static void hdmi_enable_audio_clk(struct dw_hdmi *hdmi, bool enable)
hdmi_writeb(hdmi, hdmi->mc_clkdis, HDMI_MC_CLKDIS);
}

static u8 *hdmi_audio_get_eld(struct dw_hdmi *hdmi)
{
if (!hdmi->curr_conn)
return NULL;

return hdmi->curr_conn->eld;
}

static void dw_hdmi_ahb_audio_enable(struct dw_hdmi *hdmi)
{
hdmi_set_cts_n(hdmi, hdmi->audio_cts, hdmi->audio_n);
Expand Down Expand Up @@ -3432,7 +3440,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
audio.base = hdmi->regs;
audio.irq = irq;
audio.hdmi = hdmi;
audio.eld = hdmi->connector.eld;
audio.get_eld = hdmi_audio_get_eld;
hdmi->enable_audio = dw_hdmi_ahb_audio_enable;
hdmi->disable_audio = dw_hdmi_ahb_audio_disable;

Expand All @@ -3445,7 +3453,7 @@ struct dw_hdmi *dw_hdmi_probe(struct platform_device *pdev,
struct dw_hdmi_i2s_audio_data audio;

audio.hdmi = hdmi;
audio.eld = hdmi->connector.eld;
audio.get_eld = hdmi_audio_get_eld;
audio.write = hdmi_writeb;
audio.read = hdmi_readb;
hdmi->enable_audio = dw_hdmi_i2s_audio_enable;
Expand Down

0 comments on commit 3f2532d

Please sign in to comment.