From ad8f45b6ce3440607b041b2333d97f7f2a231dea Mon Sep 17 00:00:00 2001 From: Zhang Yubing Date: Mon, 22 May 2023 18:02:26 +0800 Subject: [PATCH] mfd: rkx110_x120: support pattern generator for V1 Signed-off-by: Zhang Yubing Change-Id: I0fef8a64dd5602ac8642142b247b4198baef56cb --- drivers/mfd/rkx110_x120/hal/cru_rkx111.c | 5 +- drivers/mfd/rkx110_x120/pattern_gen.c | 310 +++++++++++++++++- drivers/mfd/rkx110_x120/rkx110.c | 9 + drivers/mfd/rkx110_x120/rkx110_linktx.c | 32 ++ drivers/mfd/rkx110_x120/rkx110_x120.h | 11 +- drivers/mfd/rkx110_x120/rkx110_x120_display.c | 2 +- drivers/mfd/rkx110_x120/rkx110_x120_display.h | 2 + drivers/mfd/rkx110_x120/rkx110_x120_panel.c | 8 +- drivers/mfd/rkx110_x120/rkx120.c | 15 +- 9 files changed, 374 insertions(+), 20 deletions(-) diff --git a/drivers/mfd/rkx110_x120/hal/cru_rkx111.c b/drivers/mfd/rkx110_x120/hal/cru_rkx111.c index 5f24c6223919..41da74fb027b 100644 --- a/drivers/mfd/rkx110_x120/hal/cru_rkx111.c +++ b/drivers/mfd/rkx110_x120/hal/cru_rkx111.c @@ -341,6 +341,8 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName /* link(dclk): Allowed to change PLL rate if need ! */ case RKX111_CPS_DCLK_D_DSI_0_REC: case RKX111_CPS_DCLK_D_DSI_1_REC: + case RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN: + case RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN: case RKX110_CPS_CLK_2X_LVDS_RKLINK_TX: /* i2s */ case RKX110_CPS_CLK_I2S_SRC_RKLINK_TX: @@ -384,9 +386,6 @@ static HAL_Status RKX11x_HAL_CRU_ClkSetFreq(struct hwclk *hw, uint32_t clockName /* bus */ case RKX110_CPS_DCLK_RX_PRE: case RKX111_CPS_DCLK_RX_PRE_200M: - /* lvds */ - case RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN: - case RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN: /* camera */ case RKX110_CPS_CLK_CAM0_OUT2IO: case RKX110_CPS_CLK_CAM1_OUT2IO: diff --git a/drivers/mfd/rkx110_x120/pattern_gen.c b/drivers/mfd/rkx110_x120/pattern_gen.c index 488d372b536b..8ad25745280a 100644 --- a/drivers/mfd/rkx110_x120/pattern_gen.c +++ b/drivers/mfd/rkx110_x120/pattern_gen.c @@ -8,6 +8,8 @@ #include #include "rkx110_x120.h" +#include "rkx110_x120_display.h" +#include "hal/cru_api.h" #define PATTERN_GEN_PATTERN_CTRL 0x0000 #define PATTERN_START_PCLK BIT(31) @@ -29,11 +31,10 @@ #define PATTERN_GEN_VALUE0 0x0014 #define PATTERN_GEN_VALUE1 0x0018 -static void pattern_gen_enable(struct pattern_gen *pattern_gen) +static void pattern_gen_config(struct i2c_client *client, struct pattern_gen *pattern_gen, + struct videomode *vm) { - struct i2c_client *client = pattern_gen->chip->client; struct rk_serdes *serdes = pattern_gen->chip->serdes; - const struct videomode *vm = serdes->vm; serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL, PATTERN_RECTANGLE_H | PATTERN_RECTANGLE_V, @@ -53,24 +54,311 @@ static void pattern_gen_enable(struct pattern_gen *pattern_gen) serdes->i2c_write_reg(client, pattern_gen->base + PATTERN_GEN_PATERN_VH_CFG3, FIELD_PREP(PATTERN_HSA, vm->hsync_len)); - serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL, - PATTERN_START_PCLK, - FIELD_PREP(PATTERN_START_PCLK, 1)); serdes->i2c_write_reg(client, pattern_gen->link_src_reg, BIT(pattern_gen->link_src_offset + 16) | BIT(pattern_gen->link_src_offset)); } +static void pattern_stop_stream(struct pattern_gen *pattern_gen) +{ + struct rk_serdes *serdes = pattern_gen->chip->serdes; + + if (serdes->version != SERDES_V1) + return; + + if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL]) + return; + + rk_serdes_display_video_start(serdes, pattern_gen->route, false); + + if (!strcmp(pattern_gen->name, "lvds0")) { + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX); + } else if (!strcmp(pattern_gen->name, "lvds1")) { + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX); + } else if (!strcmp(pattern_gen->name, "dual-lvds")) { + rkx110_set_stream_source(serdes, RK_SERDES_RGB_RX, DEVICE_LOCAL); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX); + } else if (!strcmp(pattern_gen->name, "dsi0")) { + serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314, + 0x1400140); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX); + rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, false); + } else if (!strcmp(pattern_gen->name, "dsi1")) { + serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314, + 0x2800280); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX); + hwclk_reset(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX); + rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, false); + } +} + +static void pattern_start_stream(struct pattern_gen *pattern_gen, bool is_pattern_stream) +{ + struct rk_serdes *serdes = pattern_gen->chip->serdes; + struct videomode *vm = &pattern_gen->route->vm; + u32 delay_length; + + if (serdes->version != SERDES_V1) + return; + + if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL]) + return; + + if (!strcmp(pattern_gen->name, "lvds0")) { + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX); + } else if (!strcmp(pattern_gen->name, "lvds1")) { + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX); + } else if (!strcmp(pattern_gen->name, "dual-lvds")) { + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_2X_LVDS_RKLINK_TX); + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS0_RKLINK_TX); + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_LVDS1_RKLINK_TX); + rkx110_set_stream_source(serdes, RK_SERDES_DUAL_LVDS_RX, + DEVICE_LOCAL); + } else if (!strcmp(pattern_gen->name, "dsi0")) { + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_DSI_0_RKLINK_TX); + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX111_SRST_RESETN_D_DSI_0_REC_RKLINK_TX); + serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314, + 0x1400000); + + rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 0, + is_pattern_stream ? false : true); + if (is_pattern_stream) + delay_length = vm->hsync_len + vm->hback_porch + + vm->hactive + vm->hfront_porch; + else + delay_length = (vm->vfront_porch + 1) * (vm->hsync_len + + vm->hback_porch + vm->hactive + vm->hfront_porch); + rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 0, delay_length); + rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 0, true); + } else if (!strcmp(pattern_gen->name, "dsi1")) { + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX110_SRST_RESETN_D_DSI_1_RKLINK_TX); + hwclk_reset_deassert(serdes->chip[DEVICE_LOCAL].hwclk, + RKX111_SRST_RESETN_D_DSI_1_REC_RKLINK_TX); + serdes->i2c_write_reg(serdes->chip[DEVICE_LOCAL].client, 0x0314, + 0x2800000); + + rkx110_linktx_dsi_type_select(serdes, DEVICE_LOCAL, 1, + is_pattern_stream ? false : true); + if (is_pattern_stream) + delay_length = vm->hsync_len + vm->hback_porch + + vm->hactive + vm->hfront_porch; + else + delay_length = (vm->vfront_porch + 1) * (vm->hsync_len + + vm->hback_porch + vm->hactive + vm->hfront_porch); + rkx110_linktx_dsi_deley_length_config(serdes, DEVICE_LOCAL, 1, delay_length); + rkx110_linktx_dsi_rec_start(serdes, DEVICE_LOCAL, 1, true); + } + + rk_serdes_display_video_start(serdes, pattern_gen->route, true); +} + +static void pattern_switch_clk_to_pattern(struct pattern_gen *pattern_gen, struct videomode *vm) +{ + struct rk_serdes *serdes = pattern_gen->chip->serdes; + struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk; + + if (serdes->version != SERDES_V1) + return; + + if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL]) + return; + + if (!strcmp(pattern_gen->name, "lvds0")) { + hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock); + dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n", + hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN)); + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN); + } else if (!strcmp(pattern_gen->name, "lvds1")) { + hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock); + dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n", + hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN)); + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN); + } else if (!strcmp(pattern_gen->name, "dual-lvds")) { + hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN, vm->pixelclock); + dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN:%d\n", + hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS0_PATTERN_GEN)); + hwclk_set_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN, vm->pixelclock); + dev_info(serdes->dev, "RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN:%d\n", + hwclk_get_rate(hwclk, RKX111_CPS_CLK_D_LVDS1_PATTERN_GEN)); + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_PATTERN_GEN); + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_PATTERN_GEN); + } else if (!strcmp(pattern_gen->name, "dsi0")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL, + RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_PATTERN_GEN); + } else if (!strcmp(pattern_gen->name, "dsi1")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL, + RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_PATTERN_GEN); + } +} + +static void pattern_switch_clk_to_stream(struct pattern_gen *pattern_gen) +{ + struct rk_serdes *serdes = pattern_gen->chip->serdes; + struct hwclk *hwclk = serdes->chip[DEVICE_LOCAL].hwclk; + + if (serdes->version != SERDES_V1) + return; + + if (pattern_gen->chip != &serdes->chip[DEVICE_LOCAL]) + return; + + if (!strcmp(pattern_gen->name, "lvds0")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE); + } else if (!strcmp(pattern_gen->name, "lvds1")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE); + } else if (!strcmp(pattern_gen->name, "dual-lvds")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS0_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS0_RKLINK_TX_SEL_CLK_D_LVDS0_RKLINK_TX_PRE); + hwclk_set_mux(hwclk, RKX111_CLK_D_LVDS1_RKLINK_TX_SEL, + RKX111_CLK_D_LVDS1_RKLINK_TX_SEL_CLK_D_LVDS1_RKLINK_TX_PRE); + } else if (!strcmp(pattern_gen->name, "dsi0")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_0_RKLINK_TX_SEL, + RKX111_CLK_D_DSI_0_RKLINK_TX_SEL_CLK_D_DSI_0_RKLINK_TX_PRE); + } else if (!strcmp(pattern_gen->name, "dsi1")) { + hwclk_set_mux(hwclk, RKX111_CLK_D_DSI_1_RKLINK_TX_SEL, + RKX111_CLK_D_DSI_1_RKLINK_TX_SEL_CLK_D_DSI_1_RKLINK_TX_PRE); + } +} + +static int pattern_get_route(struct pattern_gen *pattern_gen) +{ + struct rk_serdes *serdes = pattern_gen->chip->serdes; + struct rk_serdes_route *route; + int i; + + for (i = 0; i < serdes->route_nr; i++) { + route = serdes->route[i]; + + if (pattern_gen->chip == &serdes->chip[DEVICE_LOCAL]) { + if ((pattern_gen->type == route->local_port0) || + (pattern_gen->type == route->local_port1)) { + pattern_gen->route = route; + break; + } + } + if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE0]) { + if ((pattern_gen->type == route->remote0_port0) || + (pattern_gen->type == route->remote0_port1)) { + pattern_gen->route = route; + break; + } + } + + if (pattern_gen->chip == &serdes->chip[DEVICE_REMOTE1]) { + if ((pattern_gen->type == route->remote1_port0) || + (pattern_gen->type == route->remote1_port1)) { + pattern_gen->route = route; + break; + } + } + } + + if (i >= serdes->route_nr) { + dev_info(serdes->dev, "can't find the %s in route\n", pattern_gen->name); + return -EINVAL; + } + + return 0; +} + +static void pattern_gen_enable(struct pattern_gen *pattern_gen) +{ + struct i2c_client *client = pattern_gen->chip->client; + struct rk_serdes *serdes = pattern_gen->chip->serdes; + struct videomode vm; + int ret; + + ret = pattern_get_route(pattern_gen); + if (ret) + return; + + memcpy(&vm, &pattern_gen->route->vm, sizeof(vm)); + + pattern_stop_stream(pattern_gen); + if (!strcmp(pattern_gen->name, "dual-lvds")) { + struct pattern_gen *lvds0_pat = pattern_gen + 1; + struct pattern_gen *lvds1_pat = pattern_gen + 2; + + vm.hactive /= 2; + vm.hfront_porch /= 2; + vm.hback_porch /= 2; + vm.hsync_len /= 2; + vm.pixelclock /= 2; + + pattern_switch_clk_to_pattern(pattern_gen, &vm); + pattern_gen_config(client, lvds0_pat, &vm); + pattern_gen_config(client, lvds1_pat, &vm); + serdes->i2c_write_reg(client, pattern_gen->link_src_reg, + BIT(pattern_gen->link_src_offset + 16) | + BIT(pattern_gen->link_src_offset)); + } else { + pattern_switch_clk_to_pattern(pattern_gen, &vm); + pattern_gen_config(client, pattern_gen, &vm); + serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL, + PATTERN_START_PCLK, + FIELD_PREP(PATTERN_START_PCLK, 1)); + } + + pattern_start_stream(pattern_gen, true); +} + static void pattern_gen_disable(struct pattern_gen *pattern_gen) { struct i2c_client *client = pattern_gen->chip->client; struct rk_serdes *serdes = pattern_gen->chip->serdes; + int ret; - serdes->i2c_write_reg(client, pattern_gen->link_src_reg, - BIT(pattern_gen->link_src_offset + 16)); - serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL, - PATTERN_START_PCLK, - FIELD_PREP(PATTERN_START_PCLK, 0)); + ret = pattern_get_route(pattern_gen); + if (ret) + return; + + pattern_stop_stream(pattern_gen); + if (!strcmp(pattern_gen->name, "dual-lvds")) { + struct pattern_gen *lvds0_pat = pattern_gen + 1; + struct pattern_gen *lvds1_pat = pattern_gen + 2; + + serdes->i2c_write_reg(client, lvds0_pat->link_src_reg, + BIT(lvds0_pat->link_src_offset + 16)); + serdes->i2c_write_reg(client, lvds1_pat->link_src_reg, + BIT(lvds1_pat->link_src_offset + 16)); + serdes->i2c_write_reg(client, pattern_gen->link_src_reg, + BIT(pattern_gen->link_src_offset + 16)); + } else { + serdes->i2c_write_reg(client, pattern_gen->link_src_reg, + BIT(pattern_gen->link_src_offset + 16)); + serdes->i2c_update_bits(client, pattern_gen->base + PATTERN_GEN_PATTERN_CTRL, + PATTERN_START_PCLK, + FIELD_PREP(PATTERN_START_PCLK, 0)); + } + + pattern_switch_clk_to_stream(pattern_gen); + pattern_start_stream(pattern_gen, false); } static ssize_t pattern_gen_write(struct file *file, const char __user *ubuf, diff --git a/drivers/mfd/rkx110_x120/rkx110.c b/drivers/mfd/rkx110_x120/rkx110.c index 8b80aff6733a..7a670ce4827d 100644 --- a/drivers/mfd/rkx110_x120/rkx110.c +++ b/drivers/mfd/rkx110_x120/rkx110.c @@ -15,21 +15,30 @@ static struct pattern_gen rkx110_pattern_gen[] = { .base = RKX110_PATTERN_GEN_DSI0_BASE, .link_src_reg = SER_GRF_SOC_CON4, .link_src_offset = 12, + .type = RK_SERDES_DSI_RX0, }, { .name = "dsi1", .base = RKX110_PATTERN_GEN_DSI1_BASE, .link_src_reg = SER_GRF_SOC_CON4, .link_src_offset = 13, + .type = RK_SERDES_DSI_RX1, + }, { + .name = "dual-lvds", + .link_src_reg = SER_GRF_SOC_CON1, + .link_src_offset = 14, + .type = RK_SERDES_DUAL_LVDS_RX, }, { .name = "lvds0", .base = RKX110_PATTERN_GEN_LVDS0_BASE, .link_src_reg = SER_GRF_SOC_CON4, .link_src_offset = 14, + .type = RK_SERDES_LVDS_RX0, }, { .name = "lvds1", .base = RKX110_PATTERN_GEN_LVDS1_BASE, .link_src_reg = SER_GRF_SOC_CON4, .link_src_offset = 15, + .type = RK_SERDES_LVDS_RX1, }, { /* sentinel */ } }; diff --git a/drivers/mfd/rkx110_x120/rkx110_linktx.c b/drivers/mfd/rkx110_x120/rkx110_linktx.c index 8b32318bf2ed..89cb11a70d62 100644 --- a/drivers/mfd/rkx110_x120/rkx110_linktx.c +++ b/drivers/mfd/rkx110_x120/rkx110_linktx.c @@ -93,6 +93,7 @@ #define DSI_VSA(x) UPDATE(x, 9, 0) #define SER_RKLINK_DSI_REC3(x) LINK_REG(0x0014 + 0x10 * x) + #define DSI_DELAY_LENGTH_MASK GENMASK(31, 12) #define DSI_DELAY_LENGTH(x) UPDATE(x, 31, 12) #define DSI_HSA(x) UPDATE(x, 11, 0) @@ -552,6 +553,37 @@ static int rkx110_linktx_input_port_cfg(struct rk_serdes *serdes, u8 dev_id, u32 return 0; } +int rkx110_linktx_dsi_rec_start(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool enable) +{ + struct i2c_client *client = serdes->chip[dev_id].client; + + serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC0(dsi_id), DSI_REC_START, + enable ? DSI_REC_START : 0); + + return 0; +} + +int rkx110_linktx_dsi_type_select(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, bool is_cmd) +{ + struct i2c_client *client = serdes->chip[dev_id].client; + + serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC0(dsi_id), DSI_CMD_TYPE, + is_cmd ? DSI_CMD_TYPE : 0); + + return 0; +} + +int rkx110_linktx_dsi_deley_length_config(struct rk_serdes *serdes, u8 dev_id, u8 dsi_id, + u32 length) +{ + struct i2c_client *client = serdes->chip[dev_id].client; + + serdes->i2c_update_bits(client, SER_RKLINK_DSI_REC3(dsi_id), DSI_DELAY_LENGTH_MASK, + DSI_DELAY_LENGTH(length)); + + return 0; +} + static int rk_serdes_link_tx_dsi_enable(struct rk_serdes *serdes, struct rk_serdes_route *route, int id) { diff --git a/drivers/mfd/rkx110_x120/rkx110_x120.h b/drivers/mfd/rkx110_x120/rkx110_x120.h index 493980a9c505..b4824cea49fa 100644 --- a/drivers/mfd/rkx110_x120/rkx110_x120.h +++ b/drivers/mfd/rkx110_x120/rkx110_x120.h @@ -13,7 +13,7 @@ #include #include