Skip to content

Commit

Permalink
vc4_hdmi: cec: Set hardware auto retry count
Browse files Browse the repository at this point in the history
Signed-off-by: popcornmix <popcornmix@gmail.com>
  • Loading branch information
popcornmix committed May 5, 2020
1 parent 73ca9f1 commit 5988614
Show file tree
Hide file tree
Showing 4 changed files with 56 additions and 4 deletions.
47 changes: 43 additions & 4 deletions drivers/gpu/drm/vc4/vc4_hdmi.c
Original file line number Diff line number Diff line change
Expand Up @@ -770,6 +770,38 @@ static u32 vc5_hdmi_calc_hsm_clock(struct vc4_hdmi *vc4_hdmi, unsigned long pixe
return max_t(unsigned long, 108000000, (pixel_rate / 100) * 101);
}


static void vc4_hdmi_set_cec_retries(struct vc4_hdmi *vc4_hdmi, u32 retries)
{
/* Not configurable */
return;
}

static void vc5_hdmi_set_cec_retries(struct vc4_hdmi *vc4_hdmi, u32 retries)
{
u32 val;
/* Hardware can retry between one and three times */
if (retries > 3)
retries = 3;
val = HDMI_READ(HDMI_CEC_CNTRL_6);
val &= ~VC4_HDMI_CEC_AUTO_RETRY_MASK;
val |= retries << VC4_HDMI_CEC_AUTO_RETRY_SHIFT;
HDMI_WRITE(HDMI_CEC_CNTRL_6, val);
}

static u32 vc4_hdmi_get_cec_retries(struct vc4_hdmi *vc4_hdmi)
{
/* Hardware always retries once */
return 1;
}

static u32 vc5_hdmi_get_cec_retries(struct vc4_hdmi *vc4_hdmi)
{
return (HDMI_READ(HDMI_CEC_CNTRL_6) & VC4_HDMI_CEC_AUTO_RETRY_MASK)
>> VC4_HDMI_CEC_AUTO_RETRY_SHIFT;
}


static u32 vc4_hdmi_channel_map(struct vc4_hdmi *vc4_hdmi, u32 channel_mask)
{
int i;
Expand Down Expand Up @@ -1248,11 +1280,11 @@ static irqreturn_t vc4_cec_irq_handler_thread(int irq, void *priv)
0, 0, 0, 0);
} else {
/*
* This CEC implementation makes 1 retry, so if we
* get a NACK, then that means it made 2 attempts.
* The number of attempts is one more than the number of retries
*/
cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK,
0, 2, 0, 0);
cec_transmit_done(vc4_hdmi->cec_adap, CEC_TX_STATUS_NACK, 0,
vc4_hdmi->variant->get_cec_retries(vc4_hdmi) + 1,
0, 0);
}
return IRQ_HANDLED;
}
Expand Down Expand Up @@ -1369,6 +1401,7 @@ static int vc4_hdmi_cec_adap_transmit(struct cec_adapter *adap, u8 attempts,
DRM_ERROR("Attempting to transmit too much data (%d)\n", msg->len);
return -ENOMEM;
}
vc4_hdmi->variant->set_cec_retries(vc4_hdmi, attempts - 1);
for (i = 0; i < msg->len; i += 4)
HDMI_WRITE(HDMI_CEC_TX_DATA_1 + (i>>2),
(msg->msg[i]) |
Expand Down Expand Up @@ -1786,6 +1819,8 @@ static const struct vc4_hdmi_variant bcm2835_variant = {
.phy_rng_disable = vc4_hdmi_phy_rng_disable,
.get_hsm_clock = vc4_hdmi_get_hsm_clock,
.calc_hsm_clock = vc4_hdmi_calc_hsm_clock,
.set_cec_retries = vc4_hdmi_set_cec_retries,
.get_cec_retries = vc4_hdmi_get_cec_retries,
.channel_map = vc4_hdmi_channel_map,

.cec_mask = VC4_HDMI_CPU_CEC,
Expand Down Expand Up @@ -1815,6 +1850,8 @@ static const struct vc4_hdmi_variant bcm2711_hdmi0_variant = {
.phy_rng_disable = vc5_hdmi_phy_rng_disable,
.get_hsm_clock = vc5_hdmi_get_hsm_clock,
.calc_hsm_clock = vc5_hdmi_calc_hsm_clock,
.set_cec_retries = vc5_hdmi_set_cec_retries,
.get_cec_retries = vc5_hdmi_get_cec_retries,
.channel_map = vc5_hdmi_channel_map,

.cec_mask = VC5_HDMI0_CPU_CEC_RX | VC5_HDMI0_CPU_CEC_TX | VC5_HDMI0_CPU_HOTPLUG_CONN | VC5_HDMI0_CPU_HOTPLUG_REM,
Expand Down Expand Up @@ -1843,6 +1880,8 @@ static const struct vc4_hdmi_variant bcm2711_hdmi1_variant = {
.phy_rng_disable = vc5_hdmi_phy_rng_disable,
.get_hsm_clock = vc5_hdmi_get_hsm_clock,
.calc_hsm_clock = vc5_hdmi_calc_hsm_clock,
.set_cec_retries = vc5_hdmi_set_cec_retries,
.get_cec_retries = vc5_hdmi_get_cec_retries,
.channel_map = vc5_hdmi_channel_map,

.cec_mask = VC5_HDMI1_CPU_CEC_RX | VC5_HDMI1_CPU_CEC_TX,
Expand Down
6 changes: 6 additions & 0 deletions drivers/gpu/drm/vc4/vc4_hdmi.h
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,12 @@ struct vc4_hdmi_variant {
/* Callback to get hsm clock */
u32 (*calc_hsm_clock)(struct vc4_hdmi *vc4_hdmi, unsigned long pixel_rate);

/* Callback to get hsm clock */
void (*set_cec_retries)(struct vc4_hdmi *vc4_hdmi, u32 retries);

/* Callback to get hsm clock */
u32 (*get_cec_retries)(struct vc4_hdmi *vc4_hdmi);

/* Callback to get channel map */
u32 (*channel_map)(struct vc4_hdmi *vc4_hdmi, u32 channel_mask);

Expand Down
3 changes: 3 additions & 0 deletions drivers/gpu/drm/vc4/vc4_hdmi_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ enum vc4_hdmi_field {
HDMI_CEC_CNTRL_3,
HDMI_CEC_CNTRL_4,
HDMI_CEC_CNTRL_5,
HDMI_CEC_CNTRL_6,
HDMI_CEC_CPU_STATUS,
HDMI_CEC_CPU_SET,
HDMI_CEC_CPU_CLEAR,
Expand Down Expand Up @@ -274,6 +275,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi0_fields[] = {
VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
VC5_CEC_REG(HDMI_CEC_CNTRL_6, 0x024),
VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
Expand Down Expand Up @@ -356,6 +358,7 @@ static const struct vc4_hdmi_register vc5_hdmi_hdmi1_fields[] = {
VC5_CEC_REG(HDMI_CEC_CNTRL_3, 0x018),
VC5_CEC_REG(HDMI_CEC_CNTRL_4, 0x01c),
VC5_CEC_REG(HDMI_CEC_CNTRL_5, 0x020),
VC5_CEC_REG(HDMI_CEC_CNTRL_6, 0x024),
VC5_CEC_REG(HDMI_CEC_TX_DATA_1, 0x028),
VC5_CEC_REG(HDMI_CEC_TX_DATA_2, 0x02c),
VC5_CEC_REG(HDMI_CEC_TX_DATA_3, 0x030),
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/vc4/vc4_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -677,6 +677,10 @@
# define VC5_HDMI1_CPU_HOTPLUG_CONN BIT(10)
# define VC5_HDMI1_CPU_HOTPLUG_REM BIT(11)

/* Set retry count on transmit without ACK */
# define VC4_HDMI_CEC_AUTO_RETRY_MASK VC4_MASK(25, 24)
# define VC4_HDMI_CEC_AUTO_RETRY_SHIFT 24

/* Debug: Current receive value on the CEC pad. */
# define VC4_HD_CECRXD BIT(9)
/* Debug: Override CEC output to 0. */
Expand Down

0 comments on commit 5988614

Please sign in to comment.