Re: [PATCH v3] drm/sun4i: hdmi: Implement I2C adapter for A10s DDC bus
Hi Maxime, On 22 June 2017 at 07:26, Maxime Ripardwrote: > On Wed, Jun 21, 2017 at 07:42:47PM +1000, Jonathan Liu wrote: >> >> +static int wait_fifo_flag_unset(struct sun4i_hdmi *hdmi, u32 flag) >> >> +{ >> >> + /* 1 byte takes 9 clock cycles (8 bits + 1 ack) */ >> >> + unsigned long byte_time = DIV_ROUND_UP(USEC_PER_SEC, >> >> +clk_get_rate(hdmi->ddc_clk)) >> >> * 9; >> >> + ktime_t wait_timeout = ktime_add_us(ktime_get(), 10); >> >> + u32 reg; >> >> + >> >> + for (;;) { >> >> + /* Check for errors */ >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); >> >> + if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) { >> >> + writel(reg, hdmi->base + >> >> SUN4I_HDMI_DDC_INT_STATUS_REG); >> >> + return -EIO; >> >> + } >> >> + >> >> + /* Check if requested FIFO flag is unset */ >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_STATUS_REG); >> >> + if (!(reg & flag)) >> >> + return 0; >> >> + >> >> + /* Timeout */ >> >> + if (ktime_compare(ktime_get(), wait_timeout) > 0) >> >> + return -EIO; >> >> + >> >> + /* Wait for 1-2 bytes to transfer */ >> >> + usleep_range(byte_time, 2 * byte_time); >> >> + } >> >> + >> >> + return -EIO; >> >> +} >> >> + >> >> +static int wait_fifo_read_ready(struct sun4i_hdmi *hdmi) >> >> +{ >> >> + return wait_fifo_flag_unset(hdmi, SUN4I_HDMI_DDC_FIFO_STATUS_EMPTY); >> >> +} >> >> + >> >> +static int wait_fifo_write_ready(struct sun4i_hdmi *hdmi) >> >> +{ >> >> + return wait_fifo_flag_unset(hdmi, SUN4I_HDMI_DDC_FIFO_STATUS_FULL); >> >> +} >> > >> > Both of these can use readl_poll_timeout, and I'm not sure you need to >> > be that aggressive in your timings. >> > >> I have set my timings to minimize communication delays - e.g. when >> userspace is reading from I2C one byte at a time (like i2cdump from >> i2c-tools). > > I wouldn't try to optimise that too much. There's already a lot of > overhead, it's way inefficient, and it's not really a significant use > case anyway. > Ok. >> readl_poll_timeout can't be used to check 2 registers at >> once and I couldn't get DDC_FIFO_Request_Interrupt_Status_Bit in >> DDC_Int_Status register to behave properly. > > Can't you just use readl_poll_timeout, and then if it timed out check > for errors? > I think it is more flexible this way as I can adjust the usleep_range min. >> I also wanted to minimize the chance of FIFO underrun/overrun. >> >> >> + >> >> +static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg) >> >> +{ >> >> + u32 reg; >> >> + int i; >> >> + >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); >> >> + reg &= ~SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK; >> >> + writel(reg, hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); >> >> + >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); >> >> + reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; >> >> + reg |= (msg->flags & I2C_M_RD) ? >> >> +SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : >> >> +SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; >> >> + writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); >> >> + >> >> + writel(SUN4I_HDMI_DDC_ADDR_SLAVE(msg->addr), >> >> +hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); >> >> + >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); >> >> + writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR, >> >> +hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); >> >> + >> >> + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG, >> >> +reg, >> >> +!(reg & SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR), >> >> +100, 10)) >> >> + return -EIO; >> >> + >> >> + writel(msg->len, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); >> >> + writel(msg->flags & I2C_M_RD ? >> >> +SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : >> >> +SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE, >> >> +hdmi->base + SUN4I_HDMI_DDC_CMD_REG); >> >> + >> >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); >> >> + writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, >> >> +hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); >> >> + >> >> + if (msg->flags & I2C_M_RD) { >> >> + for (i = 0; i < msg->len; i++) { >> >> + if (wait_fifo_read_ready(hdmi)) >> >> + return -EIO; >> > >> > it seems weird that a function called read_ready would return 1 if >> > there's an error. >> >> I will change this so wait_fifo_flag_unset returns false on error >> and true on success. Then the wait_fifo_read_ready and >> wait_fifo_write_ready conditions will be inverted. > > Or just invert the return value, whatever makes
Re: [PATCH v3] drm/sun4i: hdmi: Implement I2C adapter for A10s DDC bus
Hi Maxime, On 21 June 2017 at 18:51, Maxime Ripardwrote: > On Thu, Jun 15, 2017 at 01:29:33AM +1000, Jonathan Liu wrote: >> The documentation for drm_do_get_edid in drivers/gpu/drm/drm_edid.c states: >> "As in the general case the DDC bus is accessible by the kernel at the I2C >> level, drivers must make all reasonable efforts to expose it as an I2C >> adapter and use drm_get_edid() instead of abusing this function." >> >> Exposing the DDC bus as an I2C adapter is more beneficial as it can be used >> for purposes other than reading the EDID such as modifying the EDID or >> using the HDMI DDC pins as an I2C bus through the I2C dev interface from >> userspace (e.g. i2c-tools). >> >> Implement this for A10s. >> >> Signed-off-by: Jonathan Liu >> --- >> Changes for v3: >> - Explain why drm_do_get_edid should be used and why it's better to expose >> it >>as an I2C adapter in commit message >> - Reorder bit defines in descending order for consistency >> - Keep old unused macros instead of removing them >> - The v2 algorithm split large transfers into 16 byte transfers but this may >>cause a large single write to be treated as multiple writes causing data >>corruption. The algorithm has been reworked to not split larger transfers >>and make more use of the FIFO to avoid this. >> - Moved the creation of the DDC clock from sun4i_hdmi_enc.c to >>sun4i_hdmi_i2c.c >> - Reformatted code >> - Instead of masking bits that we don't want to check for errors, explicitly >>check the error bits >> - Clear error bits at start of transfer in case of error from previous >> transfer >> - Poll for completion of FIFO clear after setting FIFO clear bit >> >> Changes for v2: >> - Rebased against Maxime's sunxi-drm/for-next branch >> - Fix up error paths in sun4i_hdmi_bind so that the I2C adapter is deleted >> if >>any of the calls after the I2C adapter is created fails >> - Remove unnecessary includes in sun4i_hdmi_i2c.c >> >> drivers/gpu/drm/sun4i/Makefile | 1 + >> drivers/gpu/drm/sun4i/sun4i_hdmi.h | 21 >> drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 101 ++- >> drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 220 >> + >> 4 files changed, 253 insertions(+), 90 deletions(-) >> create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c >> >> diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile >> index e29fd3a2ba9c..43c753cafc88 100644 >> --- a/drivers/gpu/drm/sun4i/Makefile >> +++ b/drivers/gpu/drm/sun4i/Makefile >> @@ -2,6 +2,7 @@ sun4i-drm-y += sun4i_drv.o >> sun4i-drm-y += sun4i_framebuffer.o >> >> sun4i-drm-hdmi-y += sun4i_hdmi_enc.o >> +sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o >> sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o >> sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o >> >> diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h >> b/drivers/gpu/drm/sun4i/sun4i_hdmi.h >> index 2f2f2ff1ea63..018af9cbb593 100644 >> --- a/drivers/gpu/drm/sun4i/sun4i_hdmi.h >> +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h >> @@ -96,6 +96,7 @@ >> #define SUN4I_HDMI_DDC_CTRL_ENABLE BIT(31) >> #define SUN4I_HDMI_DDC_CTRL_START_CMDBIT(30) >> #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASKBIT(8) >> +#define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE (1 << 8) >> #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ(0 << 8) >> #define SUN4I_HDMI_DDC_CTRL_RESETBIT(0) >> >> @@ -105,14 +106,30 @@ >> #define SUN4I_HDMI_DDC_ADDR_OFFSET(off) (((off) & 0xff) << 8) >> #define SUN4I_HDMI_DDC_ADDR_SLAVE(addr) ((addr) & 0xff) >> >> +#define SUN4I_HDMI_DDC_INT_STATUS_REG0x50c >> +#define SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION BIT(7) >> +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW BIT(6) >> +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_UNDERFLOW BIT(5) >> +#define SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST BIT(4) >> +#define SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR BIT(3) >> +#define SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR BIT(2) >> +#define SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR BIT(1) >> +#define SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE BIT(0) >> + >> #define SUN4I_HDMI_DDC_FIFO_CTRL_REG 0x510 >> #define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR BIT(31) >> >> +#define SUN4I_HDMI_DDC_FIFO_STATUS_REG 0x514 >> +#define SUN4I_HDMI_DDC_FIFO_STATUS_FULL BIT(6) >> +#define SUN4I_HDMI_DDC_FIFO_STATUS_EMPTY BIT(5) >> + > > The indentation of those bits and the ones above are weird, please > check them. > I will fix the inconsistent indentation. I only just realised the register field bits are indented more than the registry addresses. >> #define SUN4I_HDMI_DDC_FIFO_DATA_REG 0x518 >> #define SUN4I_HDMI_DDC_BYTE_COUNT_REG0x51c >> >> #define SUN4I_HDMI_DDC_CMD_REG 0x520 >> #define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ6 >> +#define
Re: [PATCH v3] drm/sun4i: hdmi: Implement I2C adapter for A10s DDC bus
On Wed, Jun 21, 2017 at 07:42:47PM +1000, Jonathan Liu wrote: > >> +static int wait_fifo_flag_unset(struct sun4i_hdmi *hdmi, u32 flag) > >> +{ > >> + /* 1 byte takes 9 clock cycles (8 bits + 1 ack) */ > >> + unsigned long byte_time = DIV_ROUND_UP(USEC_PER_SEC, > >> +clk_get_rate(hdmi->ddc_clk)) > >> * 9; > >> + ktime_t wait_timeout = ktime_add_us(ktime_get(), 10); > >> + u32 reg; > >> + > >> + for (;;) { > >> + /* Check for errors */ > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); > >> + if (reg & SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK) { > >> + writel(reg, hdmi->base + > >> SUN4I_HDMI_DDC_INT_STATUS_REG); > >> + return -EIO; > >> + } > >> + > >> + /* Check if requested FIFO flag is unset */ > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_STATUS_REG); > >> + if (!(reg & flag)) > >> + return 0; > >> + > >> + /* Timeout */ > >> + if (ktime_compare(ktime_get(), wait_timeout) > 0) > >> + return -EIO; > >> + > >> + /* Wait for 1-2 bytes to transfer */ > >> + usleep_range(byte_time, 2 * byte_time); > >> + } > >> + > >> + return -EIO; > >> +} > >> + > >> +static int wait_fifo_read_ready(struct sun4i_hdmi *hdmi) > >> +{ > >> + return wait_fifo_flag_unset(hdmi, SUN4I_HDMI_DDC_FIFO_STATUS_EMPTY); > >> +} > >> + > >> +static int wait_fifo_write_ready(struct sun4i_hdmi *hdmi) > >> +{ > >> + return wait_fifo_flag_unset(hdmi, SUN4I_HDMI_DDC_FIFO_STATUS_FULL); > >> +} > > > > Both of these can use readl_poll_timeout, and I'm not sure you need to > > be that aggressive in your timings. > > > I have set my timings to minimize communication delays - e.g. when > userspace is reading from I2C one byte at a time (like i2cdump from > i2c-tools). I wouldn't try to optimise that too much. There's already a lot of overhead, it's way inefficient, and it's not really a significant use case anyway. > readl_poll_timeout can't be used to check 2 registers at > once and I couldn't get DDC_FIFO_Request_Interrupt_Status_Bit in > DDC_Int_Status register to behave properly. Can't you just use readl_poll_timeout, and then if it timed out check for errors? > I also wanted to minimize the chance of FIFO underrun/overrun. > > >> + > >> +static int xfer_msg(struct sun4i_hdmi *hdmi, struct i2c_msg *msg) > >> +{ > >> + u32 reg; > >> + int i; > >> + > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); > >> + reg &= ~SUN4I_HDMI_DDC_INT_STATUS_ERROR_MASK; > >> + writel(reg, hdmi->base + SUN4I_HDMI_DDC_INT_STATUS_REG); > >> + > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); > >> + reg &= ~SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASK; > >> + reg |= (msg->flags & I2C_M_RD) ? > >> +SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ : > >> +SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE; > >> + writel(reg, hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); > >> + > >> + writel(SUN4I_HDMI_DDC_ADDR_SLAVE(msg->addr), > >> +hdmi->base + SUN4I_HDMI_DDC_ADDR_REG); > >> + > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); > >> + writel(reg | SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR, > >> +hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG); > >> + > >> + if (readl_poll_timeout(hdmi->base + SUN4I_HDMI_DDC_FIFO_CTRL_REG, > >> +reg, > >> +!(reg & SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR), > >> +100, 10)) > >> + return -EIO; > >> + > >> + writel(msg->len, hdmi->base + SUN4I_HDMI_DDC_BYTE_COUNT_REG); > >> + writel(msg->flags & I2C_M_RD ? > >> +SUN4I_HDMI_DDC_CMD_IMPLICIT_READ : > >> +SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE, > >> +hdmi->base + SUN4I_HDMI_DDC_CMD_REG); > >> + > >> + reg = readl(hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); > >> + writel(reg | SUN4I_HDMI_DDC_CTRL_START_CMD, > >> +hdmi->base + SUN4I_HDMI_DDC_CTRL_REG); > >> + > >> + if (msg->flags & I2C_M_RD) { > >> + for (i = 0; i < msg->len; i++) { > >> + if (wait_fifo_read_ready(hdmi)) > >> + return -EIO; > > > > it seems weird that a function called read_ready would return 1 if > > there's an error. > > I will change this so wait_fifo_flag_unset returns false on error > and true on success. Then the wait_fifo_read_ready and > wait_fifo_write_ready conditions will be inverted. Or just invert the return value, whatever makes sense > > > >> + > >> + *msg->buf++ = readb(hdmi->base + > >> + SUN4I_HDMI_DDC_FIFO_DATA_REG); > > > > Don't you have an hardware FIFO you can rely on intead of reading > > everything byte per byte? > > > Hardware FIFO by nature is transferring
Re: [PATCH v3] drm/sun4i: hdmi: Implement I2C adapter for A10s DDC bus
On Thu, Jun 15, 2017 at 01:29:33AM +1000, Jonathan Liu wrote: > The documentation for drm_do_get_edid in drivers/gpu/drm/drm_edid.c states: > "As in the general case the DDC bus is accessible by the kernel at the I2C > level, drivers must make all reasonable efforts to expose it as an I2C > adapter and use drm_get_edid() instead of abusing this function." > > Exposing the DDC bus as an I2C adapter is more beneficial as it can be used > for purposes other than reading the EDID such as modifying the EDID or > using the HDMI DDC pins as an I2C bus through the I2C dev interface from > userspace (e.g. i2c-tools). > > Implement this for A10s. > > Signed-off-by: Jonathan Liu> --- > Changes for v3: > - Explain why drm_do_get_edid should be used and why it's better to expose it >as an I2C adapter in commit message > - Reorder bit defines in descending order for consistency > - Keep old unused macros instead of removing them > - The v2 algorithm split large transfers into 16 byte transfers but this may >cause a large single write to be treated as multiple writes causing data >corruption. The algorithm has been reworked to not split larger transfers >and make more use of the FIFO to avoid this. > - Moved the creation of the DDC clock from sun4i_hdmi_enc.c to >sun4i_hdmi_i2c.c > - Reformatted code > - Instead of masking bits that we don't want to check for errors, explicitly >check the error bits > - Clear error bits at start of transfer in case of error from previous > transfer > - Poll for completion of FIFO clear after setting FIFO clear bit > > Changes for v2: > - Rebased against Maxime's sunxi-drm/for-next branch > - Fix up error paths in sun4i_hdmi_bind so that the I2C adapter is deleted if >any of the calls after the I2C adapter is created fails > - Remove unnecessary includes in sun4i_hdmi_i2c.c > > drivers/gpu/drm/sun4i/Makefile | 1 + > drivers/gpu/drm/sun4i/sun4i_hdmi.h | 21 > drivers/gpu/drm/sun4i/sun4i_hdmi_enc.c | 101 ++- > drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c | 220 > + > 4 files changed, 253 insertions(+), 90 deletions(-) > create mode 100644 drivers/gpu/drm/sun4i/sun4i_hdmi_i2c.c > > diff --git a/drivers/gpu/drm/sun4i/Makefile b/drivers/gpu/drm/sun4i/Makefile > index e29fd3a2ba9c..43c753cafc88 100644 > --- a/drivers/gpu/drm/sun4i/Makefile > +++ b/drivers/gpu/drm/sun4i/Makefile > @@ -2,6 +2,7 @@ sun4i-drm-y += sun4i_drv.o > sun4i-drm-y += sun4i_framebuffer.o > > sun4i-drm-hdmi-y += sun4i_hdmi_enc.o > +sun4i-drm-hdmi-y += sun4i_hdmi_i2c.o > sun4i-drm-hdmi-y += sun4i_hdmi_ddc_clk.o > sun4i-drm-hdmi-y += sun4i_hdmi_tmds_clk.o > > diff --git a/drivers/gpu/drm/sun4i/sun4i_hdmi.h > b/drivers/gpu/drm/sun4i/sun4i_hdmi.h > index 2f2f2ff1ea63..018af9cbb593 100644 > --- a/drivers/gpu/drm/sun4i/sun4i_hdmi.h > +++ b/drivers/gpu/drm/sun4i/sun4i_hdmi.h > @@ -96,6 +96,7 @@ > #define SUN4I_HDMI_DDC_CTRL_ENABLE BIT(31) > #define SUN4I_HDMI_DDC_CTRL_START_CMDBIT(30) > #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_MASKBIT(8) > +#define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_WRITE (1 << 8) > #define SUN4I_HDMI_DDC_CTRL_FIFO_DIR_READ(0 << 8) > #define SUN4I_HDMI_DDC_CTRL_RESETBIT(0) > > @@ -105,14 +106,30 @@ > #define SUN4I_HDMI_DDC_ADDR_OFFSET(off) (((off) & 0xff) << 8) > #define SUN4I_HDMI_DDC_ADDR_SLAVE(addr) ((addr) & 0xff) > > +#define SUN4I_HDMI_DDC_INT_STATUS_REG0x50c > +#define SUN4I_HDMI_DDC_INT_STATUS_ILLEGAL_FIFO_OPERATION BIT(7) > +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_RX_FIFO_UNDERFLOW BIT(6) > +#define SUN4I_HDMI_DDC_INT_STATUS_DDC_TX_FIFO_UNDERFLOW BIT(5) > +#define SUN4I_HDMI_DDC_INT_STATUS_FIFO_REQUEST BIT(4) > +#define SUN4I_HDMI_DDC_INT_STATUS_ARBITRATION_ERROR BIT(3) > +#define SUN4I_HDMI_DDC_INT_STATUS_ACK_ERROR BIT(2) > +#define SUN4I_HDMI_DDC_INT_STATUS_BUS_ERROR BIT(1) > +#define SUN4I_HDMI_DDC_INT_STATUS_TRANSFER_COMPLETE BIT(0) > + > #define SUN4I_HDMI_DDC_FIFO_CTRL_REG 0x510 > #define SUN4I_HDMI_DDC_FIFO_CTRL_CLEAR BIT(31) > > +#define SUN4I_HDMI_DDC_FIFO_STATUS_REG 0x514 > +#define SUN4I_HDMI_DDC_FIFO_STATUS_FULL BIT(6) > +#define SUN4I_HDMI_DDC_FIFO_STATUS_EMPTY BIT(5) > + The indentation of those bits and the ones above are weird, please check them. > #define SUN4I_HDMI_DDC_FIFO_DATA_REG 0x518 > #define SUN4I_HDMI_DDC_BYTE_COUNT_REG0x51c > > #define SUN4I_HDMI_DDC_CMD_REG 0x520 > #define SUN4I_HDMI_DDC_CMD_EXPLICIT_EDDC_READ6 > +#define SUN4I_HDMI_DDC_CMD_IMPLICIT_READ 5 > +#define SUN4I_HDMI_DDC_CMD_IMPLICIT_WRITE3 > > #define SUN4I_HDMI_DDC_CLK_REG 0x528 > #define SUN4I_HDMI_DDC_CLK_M(m) (((m) & 0x7) << 3) > @@ -123,6 +140,7 @@ > #define SUN4I_HDMI_DDC_LINE_CTRL_SCL_ENABLE BIT(8) > > #define SUN4I_HDMI_DDC_FIFO_SIZE 16 >