Files
linux/drivers/gpu/drm/bridge/adv7511/adv7511_cec.c

381 lines
10 KiB
C
Raw Normal View History

// SPDX-License-Identifier: GPL-2.0-only
/*
* adv7511_cec.c - Analog Devices ADV7511/33 cec driver
*
* Copyright 2017 Cisco Systems, Inc. and/or its affiliates. All rights reserved.
*/
#include <linux/device.h>
#include <linux/module.h>
#include <linux/of_device.h>
#include <linux/slab.h>
#include <linux/clk.h>
#include <media/cec.h>
#include "adv7511.h"
#define ADV7511_INT1_CEC_MASK \
(ADV7511_INT1_CEC_TX_READY | ADV7511_INT1_CEC_TX_ARBIT_LOST | \
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
ADV7511_INT1_CEC_TX_RETRY_TIMEOUT | ADV7511_INT1_CEC_RX_READY1 | \
ADV7511_INT1_CEC_RX_READY2 | ADV7511_INT1_CEC_RX_READY3)
static void adv_cec_tx_raw_status(struct adv7511 *adv7511, u8 tx_raw_status)
{
unsigned int offset = adv7511->reg_cec_offset;
unsigned int val;
if (regmap_read(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_ENABLE + offset, &val))
return;
if ((val & 0x01) == 0)
return;
if (tx_raw_status & ADV7511_INT1_CEC_TX_ARBIT_LOST) {
cec_transmit_attempt_done(adv7511->cec_adap,
CEC_TX_STATUS_ARB_LOST);
return;
}
if (tx_raw_status & ADV7511_INT1_CEC_TX_RETRY_TIMEOUT) {
u8 status;
u8 err_cnt = 0;
u8 nack_cnt = 0;
u8 low_drive_cnt = 0;
unsigned int cnt;
/*
* We set this status bit since this hardware performs
* retransmissions.
*/
status = CEC_TX_STATUS_MAX_RETRIES;
if (regmap_read(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_LOW_DRV_CNT + offset, &cnt)) {
err_cnt = 1;
status |= CEC_TX_STATUS_ERROR;
} else {
nack_cnt = cnt & 0xf;
if (nack_cnt)
status |= CEC_TX_STATUS_NACK;
low_drive_cnt = cnt >> 4;
if (low_drive_cnt)
status |= CEC_TX_STATUS_LOW_DRIVE;
}
cec_transmit_done(adv7511->cec_adap, status,
0, nack_cnt, low_drive_cnt, err_cnt);
return;
}
if (tx_raw_status & ADV7511_INT1_CEC_TX_READY) {
cec_transmit_attempt_done(adv7511->cec_adap, CEC_TX_STATUS_OK);
return;
}
}
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
static void adv7511_cec_rx(struct adv7511 *adv7511, int rx_buf)
{
unsigned int offset = adv7511->reg_cec_offset;
struct cec_msg msg = {};
unsigned int len;
unsigned int val;
u8 i;
if (regmap_read(adv7511->regmap_cec,
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
ADV7511_REG_CEC_RX_FRAME_LEN[rx_buf] + offset, &len))
return;
msg.len = len & 0x1f;
if (msg.len > 16)
msg.len = 16;
if (!msg.len)
return;
for (i = 0; i < msg.len; i++) {
regmap_read(adv7511->regmap_cec,
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
i + ADV7511_REG_CEC_RX_FRAME_HDR[rx_buf] + offset,
&val);
msg.msg[i] = val;
}
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
/* Toggle RX Ready Clear bit to re-enable this RX buffer */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf),
BIT(rx_buf));
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_RX_BUFFERS + offset, BIT(rx_buf), 0);
cec_received_msg(adv7511->cec_adap, &msg);
}
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
void adv7511_cec_irq_process(struct adv7511 *adv7511, unsigned int irq1)
{
unsigned int offset = adv7511->reg_cec_offset;
const u32 irq_tx_mask = ADV7511_INT1_CEC_TX_READY |
ADV7511_INT1_CEC_TX_ARBIT_LOST |
ADV7511_INT1_CEC_TX_RETRY_TIMEOUT;
const u32 irq_rx_mask = ADV7511_INT1_CEC_RX_READY1 |
ADV7511_INT1_CEC_RX_READY2 |
ADV7511_INT1_CEC_RX_READY3;
unsigned int rx_status;
int rx_order[3] = { -1, -1, -1 };
int i;
if (irq1 & irq_tx_mask)
adv_cec_tx_raw_status(adv7511, irq1);
if (!(irq1 & irq_rx_mask))
return;
if (regmap_read(adv7511->regmap_cec,
ADV7511_REG_CEC_RX_STATUS + offset, &rx_status))
return;
/*
* ADV7511_REG_CEC_RX_STATUS[5:0] contains the reception order of RX
* buffers 0, 1, and 2 in bits [1:0], [3:2], and [5:4] respectively.
* The values are to be interpreted as follows:
*
* 0 = buffer unused
* 1 = buffer contains oldest received frame (if applicable)
* 2 = buffer contains second oldest received frame (if applicable)
* 3 = buffer contains third oldest received frame (if applicable)
*
* Fill rx_order with the sequence of RX buffer indices to
* read from in order, where -1 indicates that there are no
* more buffers to process.
*/
for (i = 0; i < 3; i++) {
unsigned int timestamp = (rx_status >> (2 * i)) & 0x3;
if (timestamp)
rx_order[timestamp - 1] = i;
}
/* Read CEC RX buffers in the appropriate order as prescribed above */
for (i = 0; i < 3; i++) {
int rx_buf = rx_order[i];
if (rx_buf < 0)
break;
adv7511_cec_rx(adv7511, rx_buf);
}
}
static int adv7511_cec_adap_enable(struct cec_adapter *adap, bool enable)
{
struct adv7511 *adv7511 = cec_get_drvdata(adap);
unsigned int offset = adv7511->reg_cec_offset;
if (adv7511->i2c_cec == NULL)
return -EIO;
if (!adv7511->cec_enabled_adap && enable) {
/* power up cec section */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_CLK_DIV + offset,
0x03, 0x01);
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
/* non-legacy mode and clear all rx buffers */
regmap_write(adv7511->regmap_cec,
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
ADV7511_REG_CEC_RX_BUFFERS + offset, 0x0f);
regmap_write(adv7511->regmap_cec,
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
/* initially disable tx */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_ENABLE + offset, 1, 0);
/* enabled irqs: */
/* tx: ready */
/* tx: arbitration lost */
/* tx: retry timeout */
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
/* rx: ready 1-3 */
regmap_update_bits(adv7511->regmap,
ADV7511_REG_INT_ENABLE(1), 0x3f,
ADV7511_INT1_CEC_MASK);
} else if (adv7511->cec_enabled_adap && !enable) {
regmap_update_bits(adv7511->regmap,
ADV7511_REG_INT_ENABLE(1), 0x3f, 0);
/* disable address mask 1-3 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0x70, 0x00);
/* power down cec section */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_CLK_DIV + offset,
0x03, 0x00);
adv7511->cec_valid_addrs = 0;
}
adv7511->cec_enabled_adap = enable;
return 0;
}
static int adv7511_cec_adap_log_addr(struct cec_adapter *adap, u8 addr)
{
struct adv7511 *adv7511 = cec_get_drvdata(adap);
unsigned int offset = adv7511->reg_cec_offset;
unsigned int i, free_idx = ADV7511_MAX_ADDRS;
if (!adv7511->cec_enabled_adap)
return addr == CEC_LOG_ADDR_INVALID ? 0 : -EIO;
if (addr == CEC_LOG_ADDR_INVALID) {
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0x70, 0);
adv7511->cec_valid_addrs = 0;
return 0;
}
for (i = 0; i < ADV7511_MAX_ADDRS; i++) {
bool is_valid = adv7511->cec_valid_addrs & (1 << i);
if (free_idx == ADV7511_MAX_ADDRS && !is_valid)
free_idx = i;
if (is_valid && adv7511->cec_addr[i] == addr)
return 0;
}
if (i == ADV7511_MAX_ADDRS) {
i = free_idx;
if (i == ADV7511_MAX_ADDRS)
return -ENXIO;
}
adv7511->cec_addr[i] = addr;
adv7511->cec_valid_addrs |= 1 << i;
switch (i) {
case 0:
/* enable address mask 0 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0x10, 0x10);
/* set address for mask 0 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
0x0f, addr);
break;
case 1:
/* enable address mask 1 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0x20, 0x20);
/* set address for mask 1 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_0_1 + offset,
0xf0, addr << 4);
break;
case 2:
/* enable address mask 2 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_MASK + offset,
0x40, 0x40);
/* set address for mask 1 */
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_LOG_ADDR_2 + offset,
0x0f, addr);
break;
}
return 0;
}
static int adv7511_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
u32 signal_free_time, struct cec_msg *msg)
{
struct adv7511 *adv7511 = cec_get_drvdata(adap);
unsigned int offset = adv7511->reg_cec_offset;
u8 len = msg->len;
unsigned int i;
/*
* The number of retries is the number of attempts - 1, but retry
* at least once. It's not clear if a value of 0 is allowed, so
* let's do at least one retry.
*/
regmap_update_bits(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_RETRY + offset,
0x70, max(1, attempts - 1) << 4);
/* blocking, clear cec tx irq status */
regmap_update_bits(adv7511->regmap, ADV7511_REG_INT(1), 0x38, 0x38);
/* write data */
for (i = 0; i < len; i++)
regmap_write(adv7511->regmap_cec,
i + ADV7511_REG_CEC_TX_FRAME_HDR + offset,
msg->msg[i]);
/* set length (data + header) */
regmap_write(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_FRAME_LEN + offset, len);
/* start transmit, enable tx */
regmap_write(adv7511->regmap_cec,
ADV7511_REG_CEC_TX_ENABLE + offset, 0x01);
return 0;
}
static const struct cec_adap_ops adv7511_cec_adap_ops = {
.adap_enable = adv7511_cec_adap_enable,
.adap_log_addr = adv7511_cec_adap_log_addr,
.adap_transmit = adv7511_cec_adap_transmit,
};
static int adv7511_cec_parse_dt(struct device *dev, struct adv7511 *adv7511)
{
adv7511->cec_clk = devm_clk_get(dev, "cec");
if (IS_ERR(adv7511->cec_clk)) {
int ret = PTR_ERR(adv7511->cec_clk);
adv7511->cec_clk = NULL;
return ret;
}
clk_prepare_enable(adv7511->cec_clk);
adv7511->cec_clk_freq = clk_get_rate(adv7511->cec_clk);
return 0;
}
drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling If the device tree for a board did not specify a cec clock, then adv7511_cec_init would return an error, which would cause adv7511_probe() to fail and thus there is no HDMI output. There is no need to have adv7511_probe() fail if the CEC initialization fails, so just change adv7511_cec_init() to a void function. In addition, adv7511_cec_init() should just return silently if the cec clock isn't found and show a message for any other errors. An otherwise correct cleanup patch from Dan Carpenter turned this broken failure handling into a kernel Oops, so bisection points to commit 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support"). Based on earlier patches from Arnd and John. Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org> Cc: Xinliang Liu <xinliang.liu@linaro.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Archit Taneja <architt@codeaurora.org> Cc: John Stultz <john.stultz@linaro.org> Link: https://bugs.linaro.org/show_bug.cgi?id=3345 Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551 Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Tested-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Link: https://patchwork.freedesktop.org/patch/msgid/9097b2a4-b6b9-5fca-e039-0a17694b1143@xs4all.nl
2017-11-21 09:17:43 +01:00
int adv7511_cec_init(struct device *dev, struct adv7511 *adv7511)
{
unsigned int offset = adv7511->reg_cec_offset;
int ret = adv7511_cec_parse_dt(dev, adv7511);
if (ret)
drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling If the device tree for a board did not specify a cec clock, then adv7511_cec_init would return an error, which would cause adv7511_probe() to fail and thus there is no HDMI output. There is no need to have adv7511_probe() fail if the CEC initialization fails, so just change adv7511_cec_init() to a void function. In addition, adv7511_cec_init() should just return silently if the cec clock isn't found and show a message for any other errors. An otherwise correct cleanup patch from Dan Carpenter turned this broken failure handling into a kernel Oops, so bisection points to commit 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support"). Based on earlier patches from Arnd and John. Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org> Cc: Xinliang Liu <xinliang.liu@linaro.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Archit Taneja <architt@codeaurora.org> Cc: John Stultz <john.stultz@linaro.org> Link: https://bugs.linaro.org/show_bug.cgi?id=3345 Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551 Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Tested-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Link: https://patchwork.freedesktop.org/patch/msgid/9097b2a4-b6b9-5fca-e039-0a17694b1143@xs4all.nl
2017-11-21 09:17:43 +01:00
goto err_cec_parse_dt;
adv7511->cec_adap = cec_allocate_adapter(&adv7511_cec_adap_ops,
adv7511, dev_name(dev), CEC_CAP_DEFAULTS, ADV7511_MAX_ADDRS);
drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling If the device tree for a board did not specify a cec clock, then adv7511_cec_init would return an error, which would cause adv7511_probe() to fail and thus there is no HDMI output. There is no need to have adv7511_probe() fail if the CEC initialization fails, so just change adv7511_cec_init() to a void function. In addition, adv7511_cec_init() should just return silently if the cec clock isn't found and show a message for any other errors. An otherwise correct cleanup patch from Dan Carpenter turned this broken failure handling into a kernel Oops, so bisection points to commit 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support"). Based on earlier patches from Arnd and John. Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org> Cc: Xinliang Liu <xinliang.liu@linaro.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Archit Taneja <architt@codeaurora.org> Cc: John Stultz <john.stultz@linaro.org> Link: https://bugs.linaro.org/show_bug.cgi?id=3345 Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551 Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Tested-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Link: https://patchwork.freedesktop.org/patch/msgid/9097b2a4-b6b9-5fca-e039-0a17694b1143@xs4all.nl
2017-11-21 09:17:43 +01:00
if (IS_ERR(adv7511->cec_adap)) {
ret = PTR_ERR(adv7511->cec_adap);
goto err_cec_alloc;
}
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset, 0);
/* cec soft reset */
regmap_write(adv7511->regmap_cec,
ADV7511_REG_CEC_SOFT_RESET + offset, 0x01);
regmap_write(adv7511->regmap_cec,
ADV7511_REG_CEC_SOFT_RESET + offset, 0x00);
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
/* non-legacy mode - use all three RX buffers */
regmap_write(adv7511->regmap_cec,
drm: bridge: adv7511: use non-legacy mode for CEC RX The ADV7511 family of bridges supports two modes for CEC RX: legacy and non-legacy mode. The only difference is whether the chip uses a single CEC RX buffer, or uses all three available RX buffers. Currently the adv7511 driver uses legacy mode. While debugging a stall in CEC RX on an ADV7535, we reached out to Analog Devices, who suggested to use non-legacy mode instead. According to the programming guide for the ADV7511 [1], and the register control manual of the ADV7535 [2], this is the default behaviour on reset. As previously stated, the adv7511 driver currently overrides this to legacy mode. This patch updates the adv7511 driver to instead use non-legacy mode with all three CEC RX buffers. As a result of this change, we no longer experience any stalling of CEC RX with the ADV7535. It is not known why non-legacy mode solves this particular issue, but besides this, no functional change is to be expected by this patch. Please note that this has only been tested on an ADV7535. What follows is a brief description of the non-legacy mode interrupt handling behaviour. The programming guide in [1] gives a more detailed explanation. With three RX buffers, the interrupt handler checks the CEC_RX_STATUS register (renamed from CEC_RX_ENABLE in this patch), which contains 2-bit psuedo-timestamps for each of the RX buffers. The RX timestamps for each buffer represent the time of arrival for the CEC frame held in a given buffer, with lower timestamp values indicating chronologically older frames. A special value of 0 indicates that the given RX buffer is inactive and should be skipped. The interrupt handler parses these timestamps and then reads the active RX buffers in the prescribed order using the same logic as before. Changes have been made to ensure that the correct RX buffer is cleared after processing. This clearing procesure also sets the timestamp of the given RX buffer to 0 to mark it as inactive. [1] https://www.analog.com/media/en/technical-documentation/user-guides/ADV7511_Programming_Guide.pdf cf. CEC Map, register 0x4A, bit 3, default value 1: 0 = Use only buffer 0 to store CEC frames (Legacy mode) 1 = Use all 3 buffers to stores the CEC frames (Non-legacy mode) [2] The ADV7535 register control manual is under NDA, but trust me when I say that non-legacy CEC RX mode is the default here too. Here the register is offset by 0x70 and has an address of 0xBA in the DSI_CEC regiser map. Signed-off-by: Alvin Šipraga <alsi@bang-olufsen.dk> Reviewed-by: Robert Foss <robert.foss@linaro.org> Signed-off-by: Robert Foss <robert.foss@linaro.org> Link: https://patchwork.freedesktop.org/patch/msgid/20220423120854.1503163-3-alvin@pqrs.dk
2022-04-23 14:08:53 +02:00
ADV7511_REG_CEC_RX_BUFFERS + offset, 0x08);
regmap_write(adv7511->regmap_cec,
ADV7511_REG_CEC_CLK_DIV + offset,
((adv7511->cec_clk_freq / 750000) - 1) << 2);
ret = cec_register_adapter(adv7511->cec_adap, dev);
drm/bridge: adv7511/33: Fix adv7511_cec_init() failure handling If the device tree for a board did not specify a cec clock, then adv7511_cec_init would return an error, which would cause adv7511_probe() to fail and thus there is no HDMI output. There is no need to have adv7511_probe() fail if the CEC initialization fails, so just change adv7511_cec_init() to a void function. In addition, adv7511_cec_init() should just return silently if the cec clock isn't found and show a message for any other errors. An otherwise correct cleanup patch from Dan Carpenter turned this broken failure handling into a kernel Oops, so bisection points to commit 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") rather than 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support"). Based on earlier patches from Arnd and John. Reported-by: Naresh Kamboju <naresh.kamboju@linaro.org> Cc: Xinliang Liu <xinliang.liu@linaro.org> Cc: Dan Carpenter <dan.carpenter@oracle.com> Cc: Sean Paul <seanpaul@chromium.org> Cc: Archit Taneja <architt@codeaurora.org> Cc: John Stultz <john.stultz@linaro.org> Link: https://bugs.linaro.org/show_bug.cgi?id=3345 Link: https://lkft.validation.linaro.org/scheduler/job/48017#L3551 Fixes: 7af35b0addbc ("drm/kirin: Checking for IS_ERR() instead of NULL") Fixes: 3b1b975003e4 ("drm: adv7511/33: add HDMI CEC support") Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Tested-by: Hans Verkuil <hans.verkuil@cisco.com> Reviewed-by: Laurent Pinchart <laurent.pinchart@ideasonboard.com> Tested-by: John Stultz <john.stultz@linaro.org> Signed-off-by: Archit Taneja <architt@codeaurora.org> Link: https://patchwork.freedesktop.org/patch/msgid/9097b2a4-b6b9-5fca-e039-0a17694b1143@xs4all.nl
2017-11-21 09:17:43 +01:00
if (ret)
goto err_cec_register;
return 0;
err_cec_register:
cec_delete_adapter(adv7511->cec_adap);
adv7511->cec_adap = NULL;
err_cec_alloc:
dev_info(dev, "Initializing CEC failed with error %d, disabling CEC\n",
ret);
err_cec_parse_dt:
regmap_write(adv7511->regmap, ADV7511_REG_CEC_CTRL + offset,
ADV7511_CEC_CTRL_POWER_DOWN);
return ret == -EPROBE_DEFER ? ret : 0;
}