diff options
author | Dom Cobley <popcornmix@gmail.com> | 2021-01-11 15:22:57 +0100 |
---|---|---|
committer | Maxime Ripard <maxime@cerno.tech> | 2021-01-28 10:27:26 +0100 |
commit | e9c9481f373eb7344f9e973eb28fc6e9d0f46485 (patch) | |
tree | 6f8af58099c85d8fff606ade29d1a9821428c662 /drivers/gpu/drm/vc4 | |
parent | 7155334f15f360f5c98391c5c7e12af4c13395c4 (diff) | |
download | linux-e9c9481f373eb7344f9e973eb28fc6e9d0f46485.tar.bz2 |
drm/vc4: hdmi: Fix register offset with longer CEC messages
The code prior to 311e305fdb4e ("drm/vc4: hdmi: Implement a register
layout abstraction") was relying on the fact that the register offset
was incremented by 4 for each readl call. That worked since the register
width is 4 bytes.
However, since that commit the HDMI_READ macro is now taking an enum,
and the offset doesn't increment by 4 but 1 now. Divide the index by 4
to fix this.
Fixes: 311e305fdb4e ("drm/vc4: hdmi: Implement a register layout abstraction")
Reviewed-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
Signed-off-by: Dom Cobley <popcornmix@gmail.com>
Signed-off-by: Maxime Ripard <maxime@cerno.tech>
Acked-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Tested-by: Hans Verkuil <hverkuil-cisco@xs4all.nl>
Link: https://patchwork.freedesktop.org/patch/msgid/20210111142309.193441-4-maxime@cerno.tech
Diffstat (limited to 'drivers/gpu/drm/vc4')
-rw-r--r-- | drivers/gpu/drm/vc4/vc4_hdmi.c | 17 |
1 files changed, 15 insertions, 2 deletions
diff --git a/drivers/gpu/drm/vc4/vc4_hdmi.c b/drivers/gpu/drm/vc4/vc4_hdmi.c index cb4594e7df6f..7945dbcee78c 100644 --- a/drivers/gpu/drm/vc4/vc4_hdmi.c +++ b/drivers/gpu/drm/vc4/vc4_hdmi.c @@ -1443,13 +1443,20 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv) static void vc4_cec_read_msg(struct vc4_hdmi *vc4_hdmi, u32 cntrl1) { + struct drm_device *dev = vc4_hdmi->connector.dev; struct cec_msg *msg = &vc4_hdmi->cec_rx_msg; unsigned int i; msg->len = 1 + ((cntrl1 & VC4_HDMI_CEC_REC_WRD_CNT_MASK) >> VC4_HDMI_CEC_REC_WRD_CNT_SHIFT); + + if (msg->len > 16) { + drm_err(dev, "Attempting to read too much data (%d)\n", msg->len); + return; + } + for (i = 0; i < msg->len; i += 4) { - u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + i); + u32 val = HDMI_READ(HDMI_CEC_RX_DATA_1 + (i >> 2)); msg->msg[i] = val & 0xff; msg->msg[i + 1] = (val >> 8) & 0xff; @@ -1542,11 +1549,17 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts, u32 signal_free_time, struct cec_msg *msg) { struct vc4_hdmi *vc4_hdmi = cec_get_drvdata(adap); + struct drm_device *dev = vc4_hdmi->connector.dev; u32 val; unsigned int i; + if (msg->len > 16) { + drm_err(dev, "Attempting to transmit too much data (%d)\n", msg->len); + return -ENOMEM; + } + for (i = 0; i < msg->len; i += 4) - HDMI_WRITE(HDMI_CEC_TX_DATA_1 + i, + HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i >> 2), (msg->msg[i]) | (msg->msg[i + 1] << 8) | (msg->msg[i + 2] << 16) | |