diff --git a/drivers/mfd/display-serdes/core.h b/drivers/mfd/display-serdes/core.h index e05ff39236c3..9df22c28aba9 100644 --- a/drivers/mfd/display-serdes/core.h +++ b/drivers/mfd/display-serdes/core.h @@ -188,6 +188,7 @@ struct serdes_chip_data { int same_chip_count; u8 bank_num; + int (*chip_init)(struct serdes *serdes); struct regmap_config *regmap_config; struct serdes_chip_pinctrl_info *pinctrl_info; struct serdes_chip_bridge_ops *bridge_ops; @@ -305,6 +306,7 @@ struct serdes { bool use_delay_work; struct pinctrl *pinctrl_node; struct pinctrl_state *pins_default; + struct pinctrl_state *pins_init; struct pinctrl_state *pins_sleep; struct serdes_init_seq *serdes_init_seq; diff --git a/drivers/mfd/display-serdes/rohm/rohm-bu18rl82.c b/drivers/mfd/display-serdes/rohm/rohm-bu18rl82.c index d0e8f7157196..385b26691495 100644 --- a/drivers/mfd/display-serdes/rohm/rohm-bu18rl82.c +++ b/drivers/mfd/display-serdes/rohm/rohm-bu18rl82.c @@ -45,6 +45,7 @@ static int BU18RL82_GPIO7_pins[] = {7}; struct serdes_function_data { u8 gpio_rx_en:1; u16 gpio_id; + u16 mdelay; }; static const char *serdes_gpio_groups[] = { @@ -74,6 +75,16 @@ static const char *serdes_gpio_groups[] = { }, \ } \ +#define FUNCTION_DES_DELAY_MS(ms) \ +{ \ + .name = "DELAY_"#ms"MS", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .mdelay = ms, } \ + }, \ +} \ + /*des -> device*/ #define FUNCTION_DESC_GPIO_OUTPUT_HIGH() \ { \ @@ -154,6 +165,12 @@ static struct function_desc bu18rl82_functions_desc[] = { FUNCTION_DESC_GPIO_OUTPUT_HIGH(), FUNCTION_DESC_GPIO_OUTPUT_LOW(), + + FUNCTION_DES_DELAY_MS(10), + FUNCTION_DES_DELAY_MS(50), + FUNCTION_DES_DELAY_MS(100), + FUNCTION_DES_DELAY_MS(200), + FUNCTION_DES_DELAY_MS(500), }; static struct serdes_chip_pinctrl_info bu18rl82_pinctrl_info = { @@ -203,34 +220,33 @@ static void bu18rl82_enable_hwint(struct serdes *serdes, int enable) static int bu18rl82_bridge_init(struct serdes *serdes) { - return 0; - bu18rl82_bridge_swrst(serdes); return 0; } -static int bu18rl82_bridge_enable(struct serdes *serdes) +static int bu18rl82_bridge_pre_enable(struct serdes *serdes) { int ret = 0; /* 1:enable 0:disable */ bu18rl82_enable_hwint(serdes, 0); + msleep(100); + SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", __func__, serdes->chip_data->name, ret); return ret; } -static int bu18rl82_bridge_disable(struct serdes *serdes) +static int bu18rl82_bridge_post_disable(struct serdes *serdes) { return 0; } static struct serdes_chip_bridge_ops bu18rl82_bridge_ops = { - .init = bu18rl82_bridge_init, - .enable = bu18rl82_bridge_enable, - .disable = bu18rl82_bridge_disable, + .enable = bu18rl82_bridge_pre_enable, + .disable = bu18rl82_bridge_post_disable, }; static int bu18rl82_pinctrl_config_get(struct serdes *serdes, @@ -320,6 +336,7 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes, struct function_desc *func; struct group_desc *grp; int i, offset; + u16 ms; func = pinmux_generic_get_function(pinctrl->pctl, function); if (!func) @@ -335,6 +352,7 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes, if (func->data) { struct serdes_function_data *fdata = func->data; + ms = fdata->mdelay; for (i = 0; i < grp->num_pins; i++) { offset = grp->pins[i] - pinctrl->pin_base; @@ -344,22 +362,29 @@ static int bu18rl82_pinctrl_set_mux(struct serdes *serdes, else SERDES_DBG_CHIP("%s: serdes chip %s gpio_id=0x%x, offset=%d\n", __func__, serdes->chip_data->name, fdata->gpio_id, offset); - serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg, - bu18rl82_gpio_oen[offset].mask, - FIELD_PREP(BIT(3), fdata->gpio_rx_en)); - serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg, - bu18rl82_gpio_id_low[offset].mask, - FIELD_PREP(GENMASK(7, 0), - (fdata->gpio_id & 0xff))); + if (!ms) { + serdes_set_bits(serdes, bu18rl82_gpio_oen[offset].reg, + bu18rl82_gpio_oen[offset].mask, + FIELD_PREP(BIT(3), fdata->gpio_rx_en)); - serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg, - bu18rl82_gpio_id_high[offset].mask, - FIELD_PREP(GENMASK(2, 0), - ((fdata->gpio_id >> 8) & 0x7))); - serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg, - bu18rl82_gpio_pden[offset].mask, - FIELD_PREP(BIT(4), 0)); + serdes_set_bits(serdes, bu18rl82_gpio_id_low[offset].reg, + bu18rl82_gpio_id_low[offset].mask, + FIELD_PREP(GENMASK(7, 0), + (fdata->gpio_id & 0xff))); + + serdes_set_bits(serdes, bu18rl82_gpio_id_high[offset].reg, + bu18rl82_gpio_id_high[offset].mask, + FIELD_PREP(GENMASK(2, 0), + ((fdata->gpio_id >> 8) & 0x7))); + serdes_set_bits(serdes, bu18rl82_gpio_pden[offset].reg, + bu18rl82_gpio_pden[offset].mask, + FIELD_PREP(BIT(4), 0)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %d ms\n", + __func__, ms); + } } } @@ -447,6 +472,7 @@ struct serdes_chip_data serdes_bu18rl82_data = { .serdes_id = ROHM_ID_BU18RL82, .bridge_type = TYPE_BRIDGE_BRIDGE, .connector_type = DRM_MODE_CONNECTOR_LVDS, + .chip_init = bu18rl82_bridge_init, .regmap_config = &bu18rl82_regmap_config, .pinctrl_info = &bu18rl82_pinctrl_info, .bridge_ops = &bu18rl82_bridge_ops, diff --git a/drivers/mfd/display-serdes/rohm/rohm-bu18tl82.c b/drivers/mfd/display-serdes/rohm/rohm-bu18tl82.c index 824ea3879195..1e23cd4a9d77 100644 --- a/drivers/mfd/display-serdes/rohm/rohm-bu18tl82.c +++ b/drivers/mfd/display-serdes/rohm/rohm-bu18tl82.c @@ -146,8 +146,6 @@ static void bu18tl82_bridge_swrst(struct serdes *serdes) struct device *dev = serdes->dev; int ret; - return; - ret = serdes_reg_write(serdes, BU18TL82_REG_SWRST_INTERNAL, 0x00ef); if (ret < 0) dev_err(dev, "%s: failed to reset serdes 0x11 ret=%d\n", __func__, ret); @@ -229,7 +227,6 @@ static int bu18tl82_bridge_pre_enable(struct serdes *serdes) } static struct serdes_chip_bridge_ops bu18tl82_bridge_ops = { - .init = bu18tl82_bridge_init, .get_modes = bu18tl82_bridge_get_modes, .pre_enable = bu18tl82_bridge_pre_enable, .enable = bu18tl82_bridge_enable, @@ -445,9 +442,10 @@ struct serdes_chip_data serdes_bu18tl82_data = { .name = "bu18tl82", .serdes_type = TYPE_SER, .serdes_id = ROHM_ID_BU18TL82, - .sequence_init = 1, + .sequence_init = 1, .bridge_type = TYPE_BRIDGE_BRIDGE, .connector_type = DRM_MODE_CONNECTOR_eDP, + .chip_init = bu18tl82_bridge_init, .regmap_config = &bu18tl82_regmap_config, .pinctrl_info = &bu18tl82_pinctrl_info, .bridge_ops = &bu18tl82_bridge_ops, diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 235d1305976d..0ff047d69a5b 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -164,18 +164,18 @@ static void serdes_bridge_pre_enable(struct drm_bridge *bridge) struct serdes *serdes = serdes_bridge->parent; int ret = 0; - if (serdes->chip_data->bridge_ops->init) - ret = serdes->chip_data->bridge_ops->init(serdes); - - if (serdes->chip_data->serdes_type == TYPE_DES) - serdes_i2c_set_sequence(serdes); - - if (serdes_bridge->panel) - ret = drm_panel_prepare(serdes_bridge->panel); + if (serdes->chip_data->serdes_type == TYPE_DES) { + if (serdes->chip_data->chip_init) + serdes->chip_data->chip_init(serdes); + ret = serdes_i2c_set_sequence(serdes); + } if (serdes->chip_data->bridge_ops->pre_enable) ret = serdes->chip_data->bridge_ops->pre_enable(serdes); + if (serdes_bridge->panel) + ret = drm_panel_prepare(serdes_bridge->panel); + serdes_set_pinctrl_default(serdes); SERDES_DBG_MFD("%s: %s ret=%d\n", __func__, dev_name(serdes->dev), ret); diff --git a/drivers/mfd/display-serdes/serdes-core.c b/drivers/mfd/display-serdes/serdes-core.c index 08805244f928..cb6db15dc595 100644 --- a/drivers/mfd/display-serdes/serdes-core.c +++ b/drivers/mfd/display-serdes/serdes-core.c @@ -322,7 +322,14 @@ int serdes_set_pinctrl_default(struct serdes *serdes) ret = pinctrl_select_state(serdes->pinctrl_node, serdes->pins_default); if (ret) dev_err(serdes->dev, "could not set default pins\n"); - SERDES_DBG_MFD("%s: name=%s\n", __func__, dev_name(serdes->dev)); + SERDES_DBG_MFD("%s: name=%s default\n", __func__, dev_name(serdes->dev)); + } + + if ((!IS_ERR(serdes->pinctrl_node)) && (!IS_ERR(serdes->pins_init))) { + ret = pinctrl_select_state(serdes->pinctrl_node, serdes->pins_init); + if (ret) + dev_err(serdes->dev, "could not set init pins\n"); + SERDES_DBG_MFD("%s: name=%s init\n", __func__, dev_name(serdes->dev)); } return ret; diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index c95469bc07bb..21d0c1d4b817 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -125,8 +125,11 @@ static int serdes_get_init_seq(struct serdes *serdes) /* init ser register(not des register) more early if uboot logo disabled */ serdes->route_enable = of_property_read_bool(dev->of_node, "route-enable"); - if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER)) + if ((!serdes->route_enable) && (serdes->chip_data->serdes_type == TYPE_SER)) { + if (serdes->chip_data->chip_init) + serdes->chip_data->chip_init(serdes); ret = serdes_i2c_set_sequence(serdes); + } return ret; } @@ -213,7 +216,7 @@ static int serdes_i2c_probe(struct i2c_client *client, queue_delayed_work(serdes->mfd_wq, &serdes->mfd_delay_work, msecs_to_jiffies(300)); SERDES_DBG_MFD("%s: use_delay_work=%d\n", __func__, serdes->use_delay_work); } else { - ret = serdes_device_init(serdes); + serdes_device_init(serdes); SERDES_DBG_MFD("%s: use_delay_work=%d\n", __func__, serdes->use_delay_work); } diff --git a/drivers/mfd/display-serdes/serdes-pinctrl.c b/drivers/mfd/display-serdes/serdes-pinctrl.c index 9564e3d41b14..13e741e7409b 100644 --- a/drivers/mfd/display-serdes/serdes-pinctrl.c +++ b/drivers/mfd/display-serdes/serdes-pinctrl.c @@ -344,6 +344,8 @@ static int serdes_pinctrl_probe(struct platform_device *pdev) if (!IS_ERR(serdes->pinctrl_node)) { serdes->pins_default = pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_DEFAULT); + serdes->pins_init = + pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_INIT); serdes->pins_sleep = pinctrl_lookup_state(serdes->pinctrl_node, PINCTRL_STATE_SLEEP); }