[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