[PATCH 07/20] drm/bridge: tc358775: use regmap instead of open coded access functions

Daniel Semkowicz dse at thaumatec.com
Fri Sep 6 06:47:10 PDT 2024


Hello Michael,

Thank you for the patch!

On Mon, May 6, 2024 at 3:35 PM Michael Walle <mwalle at kernel.org> wrote:
>
> The DSI bridge also supports access via DSI in-band reads and writes.
> Prepare the driver for that by converting all the access functions to
> regmap. This also have the advantage that it will make tracing and
> debugging easier and we can use all the bit manipulation helpers from
> regmap.
>
> Signed-off-by: Michael Walle <mwalle at kernel.org>
> ---
>  drivers/gpu/drm/bridge/tc358775.c | 150 +++++++++++++++++---------------------
>  1 file changed, 68 insertions(+), 82 deletions(-)
>
> diff --git a/drivers/gpu/drm/bridge/tc358775.c b/drivers/gpu/drm/bridge/tc358775.c
> index 7ae86e8d4c72..b7f15164e655 100644
> --- a/drivers/gpu/drm/bridge/tc358775.c
> +++ b/drivers/gpu/drm/bridge/tc358775.c
> @@ -16,6 +16,7 @@
>  #include <linux/media-bus-format.h>
>  #include <linux/module.h>
>  #include <linux/of_device.h>
> +#include <linux/regmap.h>
>  #include <linux/regulator/consumer.h>
>  #include <linux/slab.h>
>
> @@ -238,7 +239,7 @@ enum tc3587x5_type {
>  };
>
>  struct tc_data {
> -       struct i2c_client       *i2c;

The 'i2c' node is removed here,

> +       struct regmap           *regmap;
>         struct device           *dev;
>
>         struct drm_bridge       bridge;
> @@ -309,42 +310,6 @@ static void tc_bridge_post_disable(struct drm_bridge *bridge)
>         usleep_range(10000, 11000);
>  }
>
> -static void d2l_read(struct i2c_client *i2c, u16 addr, u32 *val)
> -{
> -       int ret;
> -       u8 buf_addr[2];
> -
> -       put_unaligned_be16(addr, buf_addr);
> -       ret = i2c_master_send(i2c, buf_addr, sizeof(buf_addr));
> -       if (ret < 0)
> -               goto fail;
> -
> -       ret = i2c_master_recv(i2c, (u8 *)val, sizeof(*val));
> -       if (ret < 0)
> -               goto fail;
> -
> -       pr_debug("d2l: I2C : addr:%04x value:%08x\n", addr, *val);
> -       return;
> -
> -fail:
> -       dev_err(&i2c->dev, "Error %d reading from subaddress 0x%x\n",
> -               ret, addr);
> -}
> -
> -static void d2l_write(struct i2c_client *i2c, u16 addr, u32 val)
> -{
> -       u8 data[6];
> -       int ret;
> -
> -       put_unaligned_be16(addr, data);
> -       put_unaligned_le32(val, data + 2);
> -
> -       ret = i2c_master_send(i2c, data, ARRAY_SIZE(data));
> -       if (ret < 0)
> -               dev_err(&i2c->dev, "Error %d writing to subaddress 0x%x\n",
> -                       ret, addr);
> -}
> -
>  /* helper function to access bus_formats */
>  static struct drm_connector *get_connector(struct drm_encoder *encoder)
>  {
> @@ -358,12 +323,33 @@ static struct drm_connector *get_connector(struct drm_encoder *encoder)
>         return NULL;
>  }
>
> +static const struct reg_sequence tc_lvmux_vesa24[] = {
> +       { LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3) },
> +       { LV_MX0407, LV_MX(LVI_R4, LVI_R7, LVI_R5, LVI_G0) },
> +       { LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_G6, LVI_G7) },
> +       { LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0) },
> +       { LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2) },
> +       { LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0) },
> +       { LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6) },
> +};
> +
> +/* JEIDA-24/JEIDA-18 have the same mapping */
> +static const struct reg_sequence tc_lvmux_jeida18_24[] = {
> +       { LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5) },
> +       { LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2) },
> +       { LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1) },
> +       { LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2) },
> +       { LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4) },
> +       { LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0) },
> +       { LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0) },
> +};
> +
>  static void tc_bridge_enable(struct drm_bridge *bridge)
>  {
>         struct tc_data *tc = bridge_to_tc(bridge);
>         u32 hback_porch, hsync_len, hfront_porch, hactive, htime1, htime2;
>         u32 vback_porch, vsync_len, vfront_porch, vactive, vtime1, vtime2;
> -       u32 val = 0;
> +       unsigned int val = 0;
>         u16 dsiclk, clkdiv, byteclk, t1, t2, t3, vsdelay;
>         struct drm_display_mode *mode;
>         struct drm_connector *connector = get_connector(bridge->encoder);
> @@ -386,28 +372,29 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
>         htime2 = (hfront_porch << 16) + hactive;
>         vtime2 = (vfront_porch << 16) + vactive;
>
> -       d2l_read(tc->i2c, IDREG, &val);
> +       regmap_read(tc->regmap, IDREG, &val);
>
>         dev_info(tc->dev, "DSI2LVDS Chip ID.%02x Revision ID. %02x **\n",
>                  (val >> 8) & 0xFF, val & 0xFF);
>
> -       d2l_write(tc->i2c, SYSRST, SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM |
> -                 SYS_RST_LCD | SYS_RST_I2CM);
> +       regmap_write(tc->regmap, SYSRST,
> +                    SYS_RST_REG | SYS_RST_DSIRX | SYS_RST_BM | SYS_RST_LCD |
> +                    SYS_RST_I2CM);
>         usleep_range(30000, 40000);
>
> -       d2l_write(tc->i2c, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
> -       d2l_write(tc->i2c, PPI_LPTXTIMECNT, LPX_PERIOD);
> -       d2l_write(tc->i2c, PPI_D0S_CLRSIPOCOUNT, 3);
> -       d2l_write(tc->i2c, PPI_D1S_CLRSIPOCOUNT, 3);
> -       d2l_write(tc->i2c, PPI_D2S_CLRSIPOCOUNT, 3);
> -       d2l_write(tc->i2c, PPI_D3S_CLRSIPOCOUNT, 3);
> +       regmap_write(tc->regmap, PPI_TX_RX_TA, TTA_GET | TTA_SURE);
> +       regmap_write(tc->regmap, PPI_LPTXTIMECNT, LPX_PERIOD);
> +       regmap_write(tc->regmap, PPI_D0S_CLRSIPOCOUNT, 3);
> +       regmap_write(tc->regmap, PPI_D1S_CLRSIPOCOUNT, 3);
> +       regmap_write(tc->regmap, PPI_D2S_CLRSIPOCOUNT, 3);
> +       regmap_write(tc->regmap, PPI_D3S_CLRSIPOCOUNT, 3);
>
>         val = ((L0EN << tc->num_dsi_lanes) - L0EN) | DSI_CLEN_BIT;
> -       d2l_write(tc->i2c, PPI_LANEENABLE, val);
> -       d2l_write(tc->i2c, DSI_LANEENABLE, val);
> +       regmap_write(tc->regmap, PPI_LANEENABLE, val);
> +       regmap_write(tc->regmap, DSI_LANEENABLE, val);
>
> -       d2l_write(tc->i2c, PPI_STARTPPI, PPI_START_FUNCTION);
> -       d2l_write(tc->i2c, DSI_STARTDSI, DSI_RX_START);
> +       regmap_write(tc->regmap, PPI_STARTPPI, PPI_START_FUNCTION);
> +       regmap_write(tc->regmap, DSI_STARTDSI, DSI_RX_START);
>
>         /* Video event mode vs pulse mode bit, does not exist for tc358775 */
>         if (tc->type == TC358765)
> @@ -431,42 +418,28 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
>         vsdelay = (clkdiv * (t1 + t3) / byteclk) - hback_porch - hsync_len - hactive;
>
>         val |= TC358775_VPCTRL_VSDELAY(vsdelay);
> -       d2l_write(tc->i2c, VPCTRL, val);
> +       regmap_write(tc->regmap, VPCTRL, val);
>
> -       d2l_write(tc->i2c, HTIM1, htime1);
> -       d2l_write(tc->i2c, VTIM1, vtime1);
> -       d2l_write(tc->i2c, HTIM2, htime2);
> -       d2l_write(tc->i2c, VTIM2, vtime2);
> +       regmap_write(tc->regmap, HTIM1, htime1);
> +       regmap_write(tc->regmap, VTIM1, vtime1);
> +       regmap_write(tc->regmap, HTIM2, htime2);
> +       regmap_write(tc->regmap, VTIM2, vtime2);
>
> -       d2l_write(tc->i2c, VFUEN, VFUEN_EN);
> -       d2l_write(tc->i2c, SYSRST, SYS_RST_LCD);
> -       d2l_write(tc->i2c, LVPHY0, LV_PHY0_PRBS_ON(4) | LV_PHY0_ND(6));
> +       regmap_write(tc->regmap, VFUEN, VFUEN_EN);
> +       regmap_write(tc->regmap, SYSRST, SYS_RST_LCD);
> +       regmap_write(tc->regmap, LVPHY0, LV_PHY0_PRBS_ON(4) | LV_PHY0_ND(6));
>
>         dev_dbg(tc->dev, "bus_formats %04x bpc %d\n",
>                 connector->display_info.bus_formats[0],
>                 tc->bpc);
> -       if (connector->display_info.bus_formats[0] ==
> -               MEDIA_BUS_FMT_RGB888_1X7X4_SPWG) {
> -               /* VESA-24 */
> -               d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R0, LVI_R1, LVI_R2, LVI_R3));
> -               d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R4, LVI_R7, LVI_R5, LVI_G0));
> -               d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G1, LVI_G2, LVI_G6, LVI_G7));
> -               d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G3, LVI_G4, LVI_G5, LVI_B0));
> -               d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B6, LVI_B7, LVI_B1, LVI_B2));
> -               d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B3, LVI_B4, LVI_B5, LVI_L0));
> -               d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R6));
> -       } else {
> -               /* JEIDA-18 and JEIDA-24 */
> -               d2l_write(tc->i2c, LV_MX0003, LV_MX(LVI_R2, LVI_R3, LVI_R4, LVI_R5));
> -               d2l_write(tc->i2c, LV_MX0407, LV_MX(LVI_R6, LVI_R1, LVI_R7, LVI_G2));
> -               d2l_write(tc->i2c, LV_MX0811, LV_MX(LVI_G3, LVI_G4, LVI_G0, LVI_G1));
> -               d2l_write(tc->i2c, LV_MX1215, LV_MX(LVI_G5, LVI_G6, LVI_G7, LVI_B2));
> -               d2l_write(tc->i2c, LV_MX1619, LV_MX(LVI_B0, LVI_B1, LVI_B3, LVI_B4));
> -               d2l_write(tc->i2c, LV_MX2023, LV_MX(LVI_B5, LVI_B6, LVI_B7, LVI_L0));
> -               d2l_write(tc->i2c, LV_MX2427, LV_MX(LVI_HS, LVI_VS, LVI_DE, LVI_R0));
> -       }
> +       if (connector->display_info.bus_formats[0] == MEDIA_BUS_FMT_RGB888_1X7X4_SPWG)
> +               regmap_multi_reg_write(tc->regmap, tc_lvmux_vesa24,
> +                                      ARRAY_SIZE(tc_lvmux_vesa24));
> +       else
> +               regmap_multi_reg_write(tc->regmap, tc_lvmux_jeida18_24,
> +                                      ARRAY_SIZE(tc_lvmux_jeida18_24));
>
> -       d2l_write(tc->i2c, VFUEN, VFUEN_EN);
> +       regmap_write(tc->regmap, VFUEN, VFUEN_EN);
>
>         val = LVCFG_LVEN_BIT;
>         if (tc->lvds_link == DUAL_LINK) {
> @@ -475,7 +448,7 @@ static void tc_bridge_enable(struct drm_bridge *bridge)
>         } else {
>                 val |= TC358775_LVCFG_PCLKDIV(DIVIDE_BY_3);
>         }
> -       d2l_write(tc->i2c, LVCFG, val);
> +       regmap_write(tc->regmap, LVCFG, val);
>  }
>
>  /*
> @@ -617,7 +590,7 @@ static const struct drm_bridge_funcs tc_bridge_funcs = {
>
>  static int tc_attach_host(struct tc_data *tc)
>  {
> -       struct device *dev = &tc->i2c->dev;
> +       struct device *dev = tc->dev;
>         struct mipi_dsi_host *host;
>         struct mipi_dsi_device *dsi;
>         int ret;
> @@ -665,6 +638,14 @@ static int tc_attach_host(struct tc_data *tc)
>         return 0;
>  }
>
> +static const struct regmap_config tc358775_regmap_config = {
> +       .reg_bits = 16,
> +       .val_bits = 32,
> +       .max_register = 0xffff,
> +       .reg_format_endian = REGMAP_ENDIAN_BIG,
> +       .val_format_endian = REGMAP_ENDIAN_LITTLE,
> +};
> +
>  static int tc_probe(struct i2c_client *client)
>  {
>         struct device *dev = &client->dev;
> @@ -679,6 +660,11 @@ static int tc_probe(struct i2c_client *client)
>         tc->i2c = client;

so the assignment above is no longer correct and should
be also removed. Otherwise, this code will not compile.

>         tc->type = (enum tc3587x5_type)(unsigned long)of_device_get_match_data(dev);
>
> +       tc->regmap = devm_regmap_init_i2c(client, &tc358775_regmap_config);
> +       if (IS_ERR(tc->regmap))
> +               return dev_err_probe(dev, PTR_ERR(tc->regmap),
> +                                    "regmap i2c init failed\n");
> +
>         tc->panel_bridge = devm_drm_of_get_bridge(dev, dev->of_node,
>                                                   TC358775_LVDS_OUT0, 0);
>         if (IS_ERR(tc->panel_bridge))
>
> --
> 2.39.2
>

Kind regards
Daniel Semkowicz



More information about the Linux-mediatek mailing list