From d2ce9f696f0f9bb73ff65ccaa37cb9c05814a162 Mon Sep 17 00:00:00 2001 From: Luo Wei Date: Thu, 2 Nov 2023 15:33:07 +0800 Subject: [PATCH] mfd: display-serdes: improve pinctrl interface for maxim chip Signed-off-by: Luo Wei Change-Id: I3e05160c5cadc4c930185a2667f2135ed6f1c83f --- drivers/mfd/display-serdes/core.h | 3 + drivers/mfd/display-serdes/gpio.h | 64 +- .../mfd/display-serdes/maxim/maxim-max96745.c | 157 +++-- .../mfd/display-serdes/maxim/maxim-max96752.c | 495 +++++++++++--- .../mfd/display-serdes/maxim/maxim-max96752.h | 24 + .../mfd/display-serdes/maxim/maxim-max96755.c | 27 +- .../mfd/display-serdes/maxim/maxim-max96772.c | 642 +++++++++++++++--- .../mfd/display-serdes/maxim/maxim-max96772.h | 24 + .../mfd/display-serdes/maxim/maxim-max96789.c | 465 +++++++++++-- .../mfd/display-serdes/maxim/maxim-max96789.h | 175 +++++ drivers/mfd/display-serdes/serdes-bridge.c | 27 +- drivers/mfd/display-serdes/serdes-core.c | 27 +- drivers/mfd/display-serdes/serdes-gpio.c | 1 + drivers/mfd/display-serdes/serdes-i2c.c | 3 + drivers/mfd/display-serdes/serdes-irq.c | 15 +- drivers/mfd/display-serdes/serdes-panel.c | 48 +- drivers/mfd/display-serdes/serdes-pinctrl.c | 3 +- 17 files changed, 1816 insertions(+), 384 deletions(-) diff --git a/drivers/mfd/display-serdes/core.h b/drivers/mfd/display-serdes/core.h index 9df22c28aba9..22b962b35f2a 100644 --- a/drivers/mfd/display-serdes/core.h +++ b/drivers/mfd/display-serdes/core.h @@ -46,6 +46,7 @@ #include #include #include +#include #include #include #include @@ -69,6 +70,8 @@ #include "../../../../drivers/pinctrl/pinconf.h" #include "../../../../drivers/pinctrl/pinmux.h" #include "../../../../drivers/gpio/gpiolib.h" +#include "../../../../drivers/extcon/extcon.h" +#include "../../../../drivers/base/regmap/internal.h" /* * if enable all the debug information, diff --git a/drivers/mfd/display-serdes/gpio.h b/drivers/mfd/display-serdes/gpio.h index 7a9d630d993d..66708b80906a 100644 --- a/drivers/mfd/display-serdes/gpio.h +++ b/drivers/mfd/display-serdes/gpio.h @@ -108,22 +108,22 @@ enum max96745_gpio_list { }; enum max96752_gpio_list { - MAXIM_MAX96752_MFP0 = 0, - MAXIM_MAX96752_MFP1, - MAXIM_MAX96752_MFP2, - MAXIM_MAX96752_MFP3, - MAXIM_MAX96752_MFP4, - MAXIM_MAX96752_MFP5, - MAXIM_MAX96752_MFP6, - MAXIM_MAX96752_MFP7, - MAXIM_MAX96752_MFP8, - MAXIM_MAX96752_MFP9, - MAXIM_MAX96752_MFP10, - MAXIM_MAX96752_MFP11, - MAXIM_MAX96752_MFP12, - MAXIM_MAX96752_MFP13, - MAXIM_MAX96752_MFP14, - MAXIM_MAX96752_MFP15, + MAXIM_MAX96752_GPIO0 = 0, + MAXIM_MAX96752_GPIO1, + MAXIM_MAX96752_GPIO2, + MAXIM_MAX96752_GPIO3, + MAXIM_MAX96752_GPIO4, + MAXIM_MAX96752_GPIO5, + MAXIM_MAX96752_GPIO6, + MAXIM_MAX96752_GPIO7, + MAXIM_MAX96752_GPIO8, + MAXIM_MAX96752_GPIO9, + MAXIM_MAX96752_GPIO10, + MAXIM_MAX96752_GPIO11, + MAXIM_MAX96752_GPIO12, + MAXIM_MAX96752_GPIO13, + MAXIM_MAX96752_GPIO14, + MAXIM_MAX96752_GPIO15, }; enum max96755_gpio_list { @@ -151,22 +151,22 @@ enum max96755_gpio_list { }; enum max96722_gpio_list { - MAXIM_MAX96772_MFP0 = 0, - MAXIM_MAX96772_MFP1, - MAXIM_MAX96772_MFP2, - MAXIM_MAX96772_MFP3, - MAXIM_MAX96772_MFP4, - MAXIM_MAX96772_MFP5, - MAXIM_MAX96772_MFP6, - MAXIM_MAX96772_MFP7, - MAXIM_MAX96772_MFP8, - MAXIM_MAX96772_MFP9, - MAXIM_MAX96772_MFP10, - MAXIM_MAX96772_MFP11, - MAXIM_MAX96772_MFP12, - MAXIM_MAX96772_MFP13, - MAXIM_MAX96772_MFP14, - MAXIM_MAX96772_MFP15, + MAXIM_MAX96772_GPIO0 = 0, + MAXIM_MAX96772_GPIO1, + MAXIM_MAX96772_GPIO2, + MAXIM_MAX96772_GPIO3, + MAXIM_MAX96772_GPIO4, + MAXIM_MAX96772_GPIO5, + MAXIM_MAX96772_GPIO6, + MAXIM_MAX96772_GPIO7, + MAXIM_MAX96772_GPIO8, + MAXIM_MAX96772_GPIO9, + MAXIM_MAX96772_GPIO10, + MAXIM_MAX96772_GPIO11, + MAXIM_MAX96772_GPIO12, + MAXIM_MAX96772_GPIO13, + MAXIM_MAX96772_GPIO14, + MAXIM_MAX96772_GPIO15, }; enum max96789_gpio_list { diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96745.c b/drivers/mfd/display-serdes/maxim/maxim-max96745.c index 27369365dae7..3c83a8be9968 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96745.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96745.c @@ -377,12 +377,26 @@ static struct serdes_chip_pinctrl_info max96745_pinctrl_info = { static bool max96745_vid_tx_active(struct serdes *serdes) { u32 val; + int i = 0, ret = 0; - if (serdes_reg_read(serdes, 0x0107, &val)) - return false; + for (i = 0; i < 5; i++) { + ret = serdes_reg_read(serdes, 0x0107, &val); + if (!ret) + break; - if (!FIELD_GET(VID_TX_ACTIVE_A | VID_TX_ACTIVE_B, val)) + SERDES_DBG_CHIP("serdes %s: false val=%d i=%d ret=%d\n", __func__, val, i, ret); + msleep(20); + } + + if (ret) { + SERDES_DBG_CHIP("serdes %s: false val=%d ret=%d\n", __func__, val, ret); return false; + } + + if (!FIELD_GET(VID_TX_ACTIVE_A | VID_TX_ACTIVE_B, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); + return false; + } return true; } @@ -391,9 +405,9 @@ static int max96745_bridge_init(struct serdes *serdes) { if (max96745_vid_tx_active(serdes)) { extcon_set_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT, true); - pr_info("%s, extcon is true\n", __func__); + pr_info("serdes %s, extcon is true state=%d\n", __func__, serdes->extcon->state); } else { - pr_info("%s, extcon is false\n", __func__); + pr_info("serdes %s, extcon is false\n", __func__); } return 0; @@ -403,14 +417,21 @@ static bool max96745_bridge_link_locked(struct serdes *serdes) { u32 val; - if (serdes->lock_gpio) - return gpiod_get_value_cansleep(serdes->lock_gpio); + if (serdes->lock_gpio) { + val = gpiod_get_value_cansleep(serdes->lock_gpio); + SERDES_DBG_CHIP("serdes %s:val=%d\n", __func__, val); + return val; + } - if (serdes_reg_read(serdes, 0x002a, &val)) + if (serdes_reg_read(serdes, 0x002a, &val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); return false; + } - if (!FIELD_GET(LINK_LOCKED, val)) + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("serdes %s: false val=%d\n", __func__, val); return false; + } return true; } @@ -444,11 +465,13 @@ max96745_bridge_detect(struct serdes *serdes) if (atomic_cmpxchg(&serdes_bridge->triggered, 1, 0)) { status = connector_status_disconnected; + SERDES_DBG_CHIP("1 status=%d state=%d\n", status, serdes->extcon->state); goto out; } if (serdes_reg_read(serdes, 0x641a, &dprx_trn_status2)) { status = connector_status_disconnected; + SERDES_DBG_CHIP("2 status=%d state=%d\n", status, serdes->extcon->state); goto out; } @@ -456,15 +479,20 @@ max96745_bridge_detect(struct serdes *serdes) dev_err(serdes->dev, "Training State: 0x%lx\n", FIELD_GET(DPRX_TRAIN_STATE, dprx_trn_status2)); status = connector_status_disconnected; + SERDES_DBG_CHIP("3 status=%d state=%d\n", status, serdes->extcon->state); goto out; } } else { atomic_set(&serdes_bridge->triggered, 0); + SERDES_DBG_CHIP("4 status=%d state=%d\n", status, serdes->extcon->state); } + if (serdes_bridge->next_bridge && (serdes_bridge->next_bridge->ops & DRM_BRIDGE_OP_DETECT)) + return drm_bridge_detect(serdes_bridge->next_bridge); + out: serdes_bridge->status = status; - SERDES_DBG_MFD("%s: status=%d\n", __func__, status); + SERDES_DBG_CHIP("5 status=%d state=%d\n", status, serdes->extcon->state); return status; } @@ -472,7 +500,8 @@ static int max96745_bridge_enable(struct serdes *serdes) { int ret = 0; - SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret); + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d state=%d\n", + __func__, serdes->chip_data->name, ret, serdes->extcon->state); return ret; } @@ -491,6 +520,59 @@ static struct serdes_chip_bridge_ops max96745_bridge_ops = { .disable = max96745_bridge_disable, }; +static int max96745_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) +{ + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, + func->name, func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *data = func->data; + + for (i = 0; i < grp->num_pins; i++) { + serdes_set_bits(serdes, + GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS, + FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis)); + if (data->gpio_tx_en_a || data->gpio_tx_en_b) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id)); + if (data->gpio_rx_en_a || data->gpio_rx_en_b) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id)); + serdes_set_bits(serdes, + GPIO_D_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN | + GPIO_RX_EN_A | GPIO_RX_EN_B, + FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) | + FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) | + FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) | + FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) | + FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en)); + } + } + + return 0; +} + static int max96745_pinctrl_config_get(struct serdes *serdes, unsigned int pin, unsigned long *config) { @@ -635,59 +717,6 @@ static int max96745_pinctrl_config_set(struct serdes *serdes, return 0; } -static int max96745_pinctrl_set_mux(struct serdes *serdes, - unsigned int function, unsigned int group) -{ - struct serdes_pinctrl *pinctrl = serdes->pinctrl; - struct function_desc *func; - struct group_desc *grp; - int i; - - func = pinmux_generic_get_function(pinctrl->pctl, function); - if (!func) - return -EINVAL; - - grp = pinctrl_generic_get_group(pinctrl->pctl, group); - if (!grp) - return -EINVAL; - - SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", - __func__, serdes->chip_data->name, - func->name, func->data, grp->name, grp->data, grp->num_pins); - - if (func->data) { - struct serdes_function_data *data = func->data; - - for (i = 0; i < grp->num_pins; i++) { - serdes_set_bits(serdes, - GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), - GPIO_OUT_DIS, - FIELD_PREP(GPIO_OUT_DIS, data->gpio_out_dis)); - if (data->gpio_tx_en_a || data->gpio_tx_en_b) - serdes_set_bits(serdes, - GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), - GPIO_TX_ID, - FIELD_PREP(GPIO_TX_ID, data->gpio_tx_id)); - if (data->gpio_rx_en_a || data->gpio_rx_en_b) - serdes_set_bits(serdes, - GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), - GPIO_RX_ID, - FIELD_PREP(GPIO_RX_ID, data->gpio_rx_id)); - serdes_set_bits(serdes, - GPIO_D_REG(grp->pins[i] - pinctrl->pin_base), - GPIO_TX_EN_A | GPIO_TX_EN_B | GPIO_IO_RX_EN | - GPIO_RX_EN_A | GPIO_RX_EN_B, - FIELD_PREP(GPIO_TX_EN_A, data->gpio_tx_en_a) | - FIELD_PREP(GPIO_TX_EN_B, data->gpio_tx_en_b) | - FIELD_PREP(GPIO_RX_EN_A, data->gpio_rx_en_a) | - FIELD_PREP(GPIO_RX_EN_B, data->gpio_rx_en_b) | - FIELD_PREP(GPIO_IO_RX_EN, data->gpio_io_rx_en)); - } - } - - return 0; -} - static struct serdes_chip_pinctrl_ops max96745_pinctrl_ops = { .pin_config_get = max96745_pinctrl_config_get, .pin_config_set = max96745_pinctrl_config_set, diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96752.c b/drivers/mfd/display-serdes/maxim/maxim-max96752.c index 2eddb3937a2a..49515098946a 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96752.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96752.c @@ -27,23 +27,34 @@ static struct regmap_config max96752_regmap_config = { .rd_table = &max96752_readable_table, }; -static int MAX96752_MFP0_pins[] = {0}; -static int MAX96752_MFP1_pins[] = {1}; -static int MAX96752_MFP2_pins[] = {2}; -static int MAX96752_MFP3_pins[] = {3}; -static int MAX96752_MFP4_pins[] = {4}; -static int MAX96752_MFP5_pins[] = {5}; -static int MAX96752_MFP6_pins[] = {6}; -static int MAX96752_MFP7_pins[] = {7}; +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; -static int MAX96752_MFP8_pins[] = {8}; -static int MAX96752_MFP9_pins[] = {9}; -static int MAX96752_MFP10_pins[] = {10}; -static int MAX96752_MFP11_pins[] = {11}; -static int MAX96752_MFP12_pins[] = {12}; -static int MAX96752_MFP13_pins[] = {13}; -static int MAX96752_MFP14_pins[] = {14}; -static int MAX96752_MFP15_pins[] = {15}; +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96752_GPIO0_pins[] = {0}; +static int MAX96752_GPIO1_pins[] = {1}; +static int MAX96752_GPIO2_pins[] = {2}; +static int MAX96752_GPIO3_pins[] = {3}; +static int MAX96752_GPIO4_pins[] = {4}; +static int MAX96752_GPIO5_pins[] = {5}; +static int MAX96752_GPIO6_pins[] = {6}; +static int MAX96752_GPIO7_pins[] = {7}; + +static int MAX96752_GPIO8_pins[] = {8}; +static int MAX96752_GPIO9_pins[] = {9}; +static int MAX96752_GPIO10_pins[] = {10}; +static int MAX96752_GPIO11_pins[] = {11}; +static int MAX96752_GPIO12_pins[] = {12}; +static int MAX96752_GPIO13_pins[] = {13}; +static int MAX96752_GPIO14_pins[] = {14}; +static int MAX96752_GPIO15_pins[] = {15}; #define GROUP_DESC(nm) \ { \ @@ -56,21 +67,24 @@ struct serdes_function_data { u8 gpio_out_dis:1; u8 gpio_tx_en:1; u8 gpio_rx_en:1; + u8 gpio_in_level:1; + u8 gpio_out_level:1; u8 gpio_tx_id; u8 gpio_rx_id; + u16 mdelay; }; static const char *serdes_gpio_groups[] = { - "MAX96752_MFP0", "MAX96752_MFP1", "MAX96752_MFP2", "MAX96752_MFP3", - "MAX96752_MFP4", "MAX96752_MFP5", "MAX96752_MFP6", "MAX96752_MFP7", + "MAX96752_GPIO0", "MAX96752_GPIO1", "MAX96752_GPIO2", "MAX96752_GPIO3", + "MAX96752_GPIO4", "MAX96752_GPIO5", "MAX96752_GPIO6", "MAX96752_GPIO7", - "MAX96752_MFP8", "MAX96752_MFP9", "MAX96752_MFP10", "MAX96752_MFP11", - "MAX96752_MFP12", "MAX96752_MFP13", "MAX96752_MFP14", "MAX96752_MFP15", + "MAX96752_GPIO8", "MAX96752_GPIO9", "MAX96752_GPIO10", "MAX96752_GPIO11", + "MAX96752_GPIO12", "MAX96752_GPIO13", "MAX96752_GPIO14", "MAX96752_GPIO15", }; -#define FUNCTION_DESC_GPIO_INPUT(id) \ +#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \ { \ - .name = "MFP"#id"_INPUT", \ + .name = "SER_TO_DES_GPIO"#id, \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -78,9 +92,9 @@ static const char *serdes_gpio_groups[] = { }, \ } \ -#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \ { \ - .name = "MFP"#id"_OUTPUT", \ + .name = "DES_GPIO"#id"_TO_SER", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -88,83 +102,156 @@ static const char *serdes_gpio_groups[] = { }, \ } \ -static struct pinctrl_pin_desc max96752_pins_desc[] = { - PINCTRL_PIN(MAXIM_MAX96752_MFP0, "MAX96752_MFP0"), - PINCTRL_PIN(MAXIM_MAX96752_MFP1, "MAX96752_MFP1"), - PINCTRL_PIN(MAXIM_MAX96752_MFP2, "MAX96752_MFP2"), - PINCTRL_PIN(MAXIM_MAX96752_MFP3, "MAX96752_MFP3"), - PINCTRL_PIN(MAXIM_MAX96752_MFP4, "MAX96752_MFP4"), - PINCTRL_PIN(MAXIM_MAX96752_MFP5, "MAX96752_MFP5"), - PINCTRL_PIN(MAXIM_MAX96752_MFP6, "MAX96752_MFP6"), - PINCTRL_PIN(MAXIM_MAX96752_MFP7, "MAX96752_MFP7"), +#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \ +{ \ + .name = "DES_GPIO"#id"_OUTPUT_LOW", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \ + }, \ +} \ - PINCTRL_PIN(MAXIM_MAX96752_MFP8, "MAX96752_MFP8"), - PINCTRL_PIN(MAXIM_MAX96752_MFP9, "MAX96752_MFP9"), - PINCTRL_PIN(MAXIM_MAX96752_MFP10, "MAX96752_MFP10"), - PINCTRL_PIN(MAXIM_MAX96752_MFP11, "MAX96752_MFP11"), - PINCTRL_PIN(MAXIM_MAX96752_MFP12, "MAX96752_MFP12"), - PINCTRL_PIN(MAXIM_MAX96752_MFP13, "MAX96752_MFP13"), - PINCTRL_PIN(MAXIM_MAX96752_MFP14, "MAX96752_MFP14"), - PINCTRL_PIN(MAXIM_MAX96752_MFP15, "MAX96752_MFP15"), +#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \ +{ \ + .name = "DES_GPIO"#id"_OUTPUT_HIGH", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#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, } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96752_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96752_GPIO0, "MAX96752_GPIO0"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO1, "MAX96752_GPIO1"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO2, "MAX96752_GPIO2"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO3, "MAX96752_GPIO3"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO4, "MAX96752_GPIO4"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO5, "MAX96752_GPIO5"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO6, "MAX96752_GPIO6"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO7, "MAX96752_GPIO7"), + + PINCTRL_PIN(MAXIM_MAX96752_GPIO8, "MAX96752_GPIO8"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO9, "MAX96752_GPIO9"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO10, "MAX96752_GPIO10"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO11, "MAX96752_GPIO11"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO12, "MAX96752_GPIO12"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO13, "MAX96752_GPIO13"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO14, "MAX96752_GPIO14"), + PINCTRL_PIN(MAXIM_MAX96752_GPIO15, "MAX96752_GPIO15"), }; static struct group_desc max96752_groups_desc[] = { - GROUP_DESC(MAX96752_MFP0), - GROUP_DESC(MAX96752_MFP1), - GROUP_DESC(MAX96752_MFP2), - GROUP_DESC(MAX96752_MFP3), - GROUP_DESC(MAX96752_MFP4), - GROUP_DESC(MAX96752_MFP5), - GROUP_DESC(MAX96752_MFP6), - GROUP_DESC(MAX96752_MFP7), + GROUP_DESC(MAX96752_GPIO0), + GROUP_DESC(MAX96752_GPIO1), + GROUP_DESC(MAX96752_GPIO2), + GROUP_DESC(MAX96752_GPIO3), + GROUP_DESC(MAX96752_GPIO4), + GROUP_DESC(MAX96752_GPIO5), + GROUP_DESC(MAX96752_GPIO6), + GROUP_DESC(MAX96752_GPIO7), - GROUP_DESC(MAX96752_MFP8), - GROUP_DESC(MAX96752_MFP9), - GROUP_DESC(MAX96752_MFP10), - GROUP_DESC(MAX96752_MFP11), - GROUP_DESC(MAX96752_MFP12), - GROUP_DESC(MAX96752_MFP13), - GROUP_DESC(MAX96752_MFP14), - GROUP_DESC(MAX96752_MFP15), + GROUP_DESC(MAX96752_GPIO8), + GROUP_DESC(MAX96752_GPIO9), + GROUP_DESC(MAX96752_GPIO10), + GROUP_DESC(MAX96752_GPIO11), + GROUP_DESC(MAX96752_GPIO12), + GROUP_DESC(MAX96752_GPIO13), + GROUP_DESC(MAX96752_GPIO14), + GROUP_DESC(MAX96752_GPIO15), }; static struct function_desc max96752_functions_desc[] = { - FUNCTION_DESC_GPIO_INPUT(0), - FUNCTION_DESC_GPIO_INPUT(1), - FUNCTION_DESC_GPIO_INPUT(2), - FUNCTION_DESC_GPIO_INPUT(3), - FUNCTION_DESC_GPIO_INPUT(4), - FUNCTION_DESC_GPIO_INPUT(5), - FUNCTION_DESC_GPIO_INPUT(6), - FUNCTION_DESC_GPIO_INPUT(7), + FUNCTION_DESC_GPIO_INPUT_BYPASS(0), + FUNCTION_DESC_GPIO_INPUT_BYPASS(1), + FUNCTION_DESC_GPIO_INPUT_BYPASS(2), + FUNCTION_DESC_GPIO_INPUT_BYPASS(3), + FUNCTION_DESC_GPIO_INPUT_BYPASS(4), + FUNCTION_DESC_GPIO_INPUT_BYPASS(5), + FUNCTION_DESC_GPIO_INPUT_BYPASS(6), + FUNCTION_DESC_GPIO_INPUT_BYPASS(7), - FUNCTION_DESC_GPIO_INPUT(8), - FUNCTION_DESC_GPIO_INPUT(9), - FUNCTION_DESC_GPIO_INPUT(10), - FUNCTION_DESC_GPIO_INPUT(11), - FUNCTION_DESC_GPIO_INPUT(12), - FUNCTION_DESC_GPIO_INPUT(13), - FUNCTION_DESC_GPIO_INPUT(14), - FUNCTION_DESC_GPIO_INPUT(15), + FUNCTION_DESC_GPIO_INPUT_BYPASS(8), + FUNCTION_DESC_GPIO_INPUT_BYPASS(9), + FUNCTION_DESC_GPIO_INPUT_BYPASS(10), + FUNCTION_DESC_GPIO_INPUT_BYPASS(11), + FUNCTION_DESC_GPIO_INPUT_BYPASS(12), + FUNCTION_DESC_GPIO_INPUT_BYPASS(13), + FUNCTION_DESC_GPIO_INPUT_BYPASS(14), + FUNCTION_DESC_GPIO_INPUT_BYPASS(15), - FUNCTION_DESC_GPIO_OUTPUT(0), - FUNCTION_DESC_GPIO_OUTPUT(1), - FUNCTION_DESC_GPIO_OUTPUT(2), - FUNCTION_DESC_GPIO_OUTPUT(3), - FUNCTION_DESC_GPIO_OUTPUT(4), - FUNCTION_DESC_GPIO_OUTPUT(5), - FUNCTION_DESC_GPIO_OUTPUT(6), - FUNCTION_DESC_GPIO_OUTPUT(7), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7), - FUNCTION_DESC_GPIO_OUTPUT(8), - FUNCTION_DESC_GPIO_OUTPUT(9), - FUNCTION_DESC_GPIO_OUTPUT(10), - FUNCTION_DESC_GPIO_OUTPUT(11), - FUNCTION_DESC_GPIO_OUTPUT(12), - FUNCTION_DESC_GPIO_OUTPUT(13), - FUNCTION_DESC_GPIO_OUTPUT(14), - FUNCTION_DESC_GPIO_OUTPUT(15), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15), + FUNCTION_DESC_GPIO_OUTPUT_LOW(0), + FUNCTION_DESC_GPIO_OUTPUT_LOW(1), + FUNCTION_DESC_GPIO_OUTPUT_LOW(2), + FUNCTION_DESC_GPIO_OUTPUT_LOW(3), + FUNCTION_DESC_GPIO_OUTPUT_LOW(4), + FUNCTION_DESC_GPIO_OUTPUT_LOW(5), + FUNCTION_DESC_GPIO_OUTPUT_LOW(6), + FUNCTION_DESC_GPIO_OUTPUT_LOW(7), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(8), + FUNCTION_DESC_GPIO_OUTPUT_LOW(9), + FUNCTION_DESC_GPIO_OUTPUT_LOW(10), + FUNCTION_DESC_GPIO_OUTPUT_LOW(11), + FUNCTION_DESC_GPIO_OUTPUT_LOW(12), + FUNCTION_DESC_GPIO_OUTPUT_LOW(13), + FUNCTION_DESC_GPIO_OUTPUT_LOW(14), + FUNCTION_DESC_GPIO_OUTPUT_LOW(15), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(0), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(1), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(2), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(3), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(4), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(5), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(6), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(7), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(8), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(9), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(10), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(11), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(12), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(13), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(14), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(15), + + 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 max96752_pinctrl_info = { @@ -205,24 +292,233 @@ static struct serdes_chip_panel_ops max96752_panel_ops = { .disable = max96752_panel_disable, }; -static int max96752_pinctrl_config_get(struct serdes *serdes, - unsigned int pin, - unsigned long *config) +static int max96752_bridge_pre_enable(struct serdes *serdes) { + int ret = 0; + + SERDES_DBG_CHIP("%s: serdes %s ret=%d\n", __func__, + serdes->chip_data->name, ret); + return ret; +} + +static int max96752_bridge_post_disable(struct serdes *serdes) +{ + return 0; +} + +static struct serdes_chip_bridge_ops max96752_bridge_ops = { + .enable = max96752_bridge_pre_enable, + .disable = max96752_bridge_post_disable, +}; + + +static int max96752_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) +{ + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + u16 ms; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + for (i = 0; i < grp->num_pins; i++) { + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %d ms\n", + __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96752_pinctrl_config_get(struct serdes *serdes, + unsigned int pin, unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int gpio_a_reg, gpio_b_reg; + u16 arg = 0; + + serdes_reg_read(serdes, GPIO_A_REG(pin), &gpio_a_reg); + serdes_reg_read(serdes, GPIO_B_REG(pin), &gpio_b_reg); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_OUTPUT: + if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) + return -EINVAL; + + arg = FIELD_GET(GPIO_OUT, gpio_a_reg); + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; } static int max96752_pinctrl_config_set(struct serdes *serdes, - unsigned int pin, - unsigned long *configs, + unsigned int pin, unsigned long *configs, unsigned int num_configs) { - return 0; -} + enum pin_config_param param; + u32 arg; + u8 res_cfg; + int i; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, arg)); + break; + default: + return -EOPNOTSUPP; + } + } -static int max96752_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector, - unsigned int group_selector) -{ return 0; } @@ -309,6 +605,7 @@ struct serdes_chip_data serdes_max96752_data = { .regmap_config = &max96752_regmap_config, .pinctrl_info = &max96752_pinctrl_info, .panel_ops = &max96752_panel_ops, + .bridge_ops = &max96752_bridge_ops, .pinctrl_ops = &max96752_pinctrl_ops, .gpio_ops = &max96752_gpio_ops, .pm_ops = &max96752_pm_ops, diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96752.h b/drivers/mfd/display-serdes/maxim/maxim-max96752.h index 079be4c2cb92..7e3e4aa551c3 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96752.h +++ b/drivers/mfd/display-serdes/maxim/maxim-max96752.h @@ -11,4 +11,28 @@ #ifndef __MFD_SERDES_MAXIM_MAX96752_H__ #define __MFD_SERDES_MAXIM_MAX96752_H__ +#define GPIO_A_REG(gpio) (0x0200 + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x0201 + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x0202 + ((gpio) * 3)) + + +/* 0200h */ +#define RES_CFG BIT(7) +#define RSVD BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 0201h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 0202h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + #endif diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96755.c b/drivers/mfd/display-serdes/maxim/maxim-max96755.c index c042eb3427a1..f32fb2630522 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96755.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96755.c @@ -34,7 +34,7 @@ static struct regmap_config max96755_regmap_config = { .name = "max96755", .reg_bits = 16, .val_bits = 8, - .max_register = 0x8000, + .max_register = 0x2000, .volatile_reg = max96755_volatile_reg, .cache_type = REGCACHE_RBTREE, }; @@ -202,17 +202,17 @@ static const char *MAX96755_UART_groups[] = { "MAX96755_UART" }; #define FUNCTION_DESC_GPIO_INPUT(id) \ { \ - .name = "DES_GPIO"#id"_INPUT", \ + .name = "DES_GPIO"#id"_TO_SER", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ - { .gpio_rx_en = 1, .gpio_rx_id = id } \ + { .gpio_out_dis = 0, .gpio_rx_en = 1, .gpio_rx_id = id } \ }, \ } \ #define FUNCTION_DESC_GPIO_OUTPUT(id) \ { \ - .name = "DES_GPIO"#id"_OUTPUT", \ + .name = "SER_TO_DES_GPIO"#id, \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -345,14 +345,23 @@ static bool max96755_bridge_link_locked(struct serdes *serdes) { u32 val; - if (serdes->lock_gpio) - return gpiod_get_value_cansleep(serdes->lock_gpio); + if (serdes->lock_gpio) { + val = gpiod_get_value_cansleep(serdes->lock_gpio); + SERDES_DBG_CHIP("%s: lock_gpio val=%d\n", __func__, val); + return val; + } - if (serdes_reg_read(serdes, 0x0013, &val)) + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); return false; + } - if (!FIELD_GET(LOCKED, val)) + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); return false; + } + + SERDES_DBG_CHIP("%s: return true\n", __func__); return true; } @@ -396,7 +405,7 @@ max96755_bridge_detect(struct serdes *serdes) out: serdes_bridge->status = status; - SERDES_DBG_MFD("%s: status=%d\n", __func__, status); + SERDES_DBG_CHIP("%s: status=%d\n", __func__, status); return status; } diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96772.c b/drivers/mfd/display-serdes/maxim/maxim-max96772.c index c9b1394d2df7..b37fddb00c93 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96772.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96772.c @@ -32,23 +32,34 @@ static struct regmap_config max96772_regmap_config = { .rd_table = &max96772_readable_table, }; -static int MAX96772_MFP0_pins[] = {0}; -static int MAX96772_MFP1_pins[] = {1}; -static int MAX96772_MFP2_pins[] = {2}; -static int MAX96772_MFP3_pins[] = {3}; -static int MAX96772_MFP4_pins[] = {4}; -static int MAX96772_MFP5_pins[] = {5}; -static int MAX96772_MFP6_pins[] = {6}; -static int MAX96772_MFP7_pins[] = {7}; +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; -static int MAX96772_MFP8_pins[] = {8}; -static int MAX96772_MFP9_pins[] = {9}; -static int MAX96772_MFP10_pins[] = {10}; -static int MAX96772_MFP11_pins[] = {11}; -static int MAX96772_MFP12_pins[] = {12}; -static int MAX96772_MFP13_pins[] = {13}; -static int MAX96772_MFP14_pins[] = {14}; -static int MAX96772_MFP15_pins[] = {15}; +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + +static int MAX96772_GPIO0_pins[] = {0}; +static int MAX96772_GPIO1_pins[] = {1}; +static int MAX96772_GPIO2_pins[] = {2}; +static int MAX96772_GPIO3_pins[] = {3}; +static int MAX96772_GPIO4_pins[] = {4}; +static int MAX96772_GPIO5_pins[] = {5}; +static int MAX96772_GPIO6_pins[] = {6}; +static int MAX96772_GPIO7_pins[] = {7}; + +static int MAX96772_GPIO8_pins[] = {8}; +static int MAX96772_GPIO9_pins[] = {9}; +static int MAX96772_GPIO10_pins[] = {10}; +static int MAX96772_GPIO11_pins[] = {11}; +static int MAX96772_GPIO12_pins[] = {12}; +static int MAX96772_GPIO13_pins[] = {13}; +static int MAX96772_GPIO14_pins[] = {14}; +static int MAX96772_GPIO15_pins[] = {15}; #define GROUP_DESC(nm) \ { \ @@ -61,21 +72,24 @@ struct serdes_function_data { u8 gpio_out_dis:1; u8 gpio_tx_en:1; u8 gpio_rx_en:1; + u8 gpio_in_level:1; + u8 gpio_out_level:1; u8 gpio_tx_id; u8 gpio_rx_id; + u16 mdelay; }; static const char *serdes_gpio_groups[] = { - "MAX96772_MFP0", "MAX96772_MFP1", "MAX96772_MFP2", "MAX96772_MFP3", - "MAX96772_MFP4", "MAX96772_MFP5", "MAX96772_MFP6", "MAX96772_MFP7", + "MAX96772_GPIO0", "MAX96772_GPIO1", "MAX96772_GPIO2", "MAX96772_GPIO3", + "MAX96772_GPIO4", "MAX96772_GPIO5", "MAX96772_GPIO6", "MAX96772_GPIO7", - "MAX96772_MFP8", "MAX96772_MFP9", "MAX96772_MFP10", "MAX96772_MFP11", - "MAX96772_MFP12", "MAX96772_MFP13", "MAX96772_MFP14", "MAX96772_MFP15", + "MAX96772_GPIO8", "MAX96772_GPIO9", "MAX96772_GPIO10", "MAX96772_GPIO11", + "MAX96772_GPIO12", "MAX96772_GPIO13", "MAX96772_GPIO14", "MAX96772_GPIO15", }; -#define FUNCTION_DESC_GPIO_INPUT(id) \ +#define FUNCTION_DESC_GPIO_INPUT_BYPASS(id) \ { \ - .name = "MFP"#id"_INPUT", \ + .name = "SER_TO_DES_GPIO"#id, \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -83,9 +97,9 @@ static const char *serdes_gpio_groups[] = { }, \ } \ -#define FUNCTION_DESC_GPIO_OUTPUT(id) \ +#define FUNCTION_DESC_GPIO_OUTPUT_BYPASS(id) \ { \ - .name = "MFP"#id"_OUTPUT", \ + .name = "DES_GPIO"#id"_TO_SER", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -93,83 +107,156 @@ static const char *serdes_gpio_groups[] = { }, \ } \ -static struct pinctrl_pin_desc max96772_pins_desc[] = { - PINCTRL_PIN(MAXIM_MAX96772_MFP0, "MAX96772_MFP0"), - PINCTRL_PIN(MAXIM_MAX96772_MFP1, "MAX96772_MFP1"), - PINCTRL_PIN(MAXIM_MAX96772_MFP2, "MAX96772_MFP2"), - PINCTRL_PIN(MAXIM_MAX96772_MFP3, "MAX96772_MFP3"), - PINCTRL_PIN(MAXIM_MAX96772_MFP4, "MAX96772_MFP4"), - PINCTRL_PIN(MAXIM_MAX96772_MFP5, "MAX96772_MFP5"), - PINCTRL_PIN(MAXIM_MAX96772_MFP6, "MAX96772_MFP6"), - PINCTRL_PIN(MAXIM_MAX96772_MFP7, "MAX96772_MFP7"), +#define FUNCTION_DESC_GPIO_OUTPUT_LOW(id) \ +{ \ + .name = "DES_GPIO"#id"_OUTPUT_LOW", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 0, .gpio_tx_id = id } \ + }, \ +} \ - PINCTRL_PIN(MAXIM_MAX96772_MFP8, "MAX96772_MFP8"), - PINCTRL_PIN(MAXIM_MAX96772_MFP9, "MAX96772_MFP9"), - PINCTRL_PIN(MAXIM_MAX96772_MFP10, "MAX96772_MFP10"), - PINCTRL_PIN(MAXIM_MAX96772_MFP11, "MAX96772_MFP11"), - PINCTRL_PIN(MAXIM_MAX96772_MFP12, "MAX96772_MFP12"), - PINCTRL_PIN(MAXIM_MAX96772_MFP13, "MAX96772_MFP13"), - PINCTRL_PIN(MAXIM_MAX96772_MFP14, "MAX96772_MFP14"), - PINCTRL_PIN(MAXIM_MAX96772_MFP15, "MAX96772_MFP15"), +#define FUNCTION_DESC_GPIO_OUTPUT_HIGH(id) \ +{ \ + .name = "DES_GPIO"#id"_OUTPUT_HIGH", \ + .group_names = serdes_gpio_groups, \ + .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ + .data = (void *)(const struct serdes_function_data []) { \ + { .gpio_out_dis = 0, .gpio_tx_en = 0, \ + .gpio_rx_en = 0, .gpio_out_level = 1, .gpio_tx_id = id } \ + }, \ +} \ + +#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, } \ + }, \ +} \ + +static struct pinctrl_pin_desc max96772_pins_desc[] = { + PINCTRL_PIN(MAXIM_MAX96772_GPIO0, "MAX96772_GPIO0"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO1, "MAX96772_GPIO1"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO2, "MAX96772_GPIO2"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO3, "MAX96772_GPIO3"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO4, "MAX96772_GPIO4"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO5, "MAX96772_GPIO5"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO6, "MAX96772_GPIO6"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO7, "MAX96772_GPIO7"), + + PINCTRL_PIN(MAXIM_MAX96772_GPIO8, "MAX96772_GPIO8"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO9, "MAX96772_GPIO9"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO10, "MAX96772_GPIO10"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO11, "MAX96772_GPIO11"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO12, "MAX96772_GPIO12"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO13, "MAX96772_GPIO13"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO14, "MAX96772_GPIO14"), + PINCTRL_PIN(MAXIM_MAX96772_GPIO15, "MAX96772_GPIO15"), }; static struct group_desc max96772_groups_desc[] = { - GROUP_DESC(MAX96772_MFP0), - GROUP_DESC(MAX96772_MFP1), - GROUP_DESC(MAX96772_MFP2), - GROUP_DESC(MAX96772_MFP3), - GROUP_DESC(MAX96772_MFP4), - GROUP_DESC(MAX96772_MFP5), - GROUP_DESC(MAX96772_MFP6), - GROUP_DESC(MAX96772_MFP7), + GROUP_DESC(MAX96772_GPIO0), + GROUP_DESC(MAX96772_GPIO1), + GROUP_DESC(MAX96772_GPIO2), + GROUP_DESC(MAX96772_GPIO3), + GROUP_DESC(MAX96772_GPIO4), + GROUP_DESC(MAX96772_GPIO5), + GROUP_DESC(MAX96772_GPIO6), + GROUP_DESC(MAX96772_GPIO7), - GROUP_DESC(MAX96772_MFP8), - GROUP_DESC(MAX96772_MFP9), - GROUP_DESC(MAX96772_MFP10), - GROUP_DESC(MAX96772_MFP11), - GROUP_DESC(MAX96772_MFP12), - GROUP_DESC(MAX96772_MFP13), - GROUP_DESC(MAX96772_MFP14), - GROUP_DESC(MAX96772_MFP15), + GROUP_DESC(MAX96772_GPIO8), + GROUP_DESC(MAX96772_GPIO9), + GROUP_DESC(MAX96772_GPIO10), + GROUP_DESC(MAX96772_GPIO11), + GROUP_DESC(MAX96772_GPIO12), + GROUP_DESC(MAX96772_GPIO13), + GROUP_DESC(MAX96772_GPIO14), + GROUP_DESC(MAX96772_GPIO15), }; static struct function_desc max96772_functions_desc[] = { - FUNCTION_DESC_GPIO_INPUT(0), - FUNCTION_DESC_GPIO_INPUT(1), - FUNCTION_DESC_GPIO_INPUT(2), - FUNCTION_DESC_GPIO_INPUT(3), - FUNCTION_DESC_GPIO_INPUT(4), - FUNCTION_DESC_GPIO_INPUT(5), - FUNCTION_DESC_GPIO_INPUT(6), - FUNCTION_DESC_GPIO_INPUT(7), + FUNCTION_DESC_GPIO_INPUT_BYPASS(0), + FUNCTION_DESC_GPIO_INPUT_BYPASS(1), + FUNCTION_DESC_GPIO_INPUT_BYPASS(2), + FUNCTION_DESC_GPIO_INPUT_BYPASS(3), + FUNCTION_DESC_GPIO_INPUT_BYPASS(4), + FUNCTION_DESC_GPIO_INPUT_BYPASS(5), + FUNCTION_DESC_GPIO_INPUT_BYPASS(6), + FUNCTION_DESC_GPIO_INPUT_BYPASS(7), - FUNCTION_DESC_GPIO_INPUT(8), - FUNCTION_DESC_GPIO_INPUT(9), - FUNCTION_DESC_GPIO_INPUT(10), - FUNCTION_DESC_GPIO_INPUT(11), - FUNCTION_DESC_GPIO_INPUT(12), - FUNCTION_DESC_GPIO_INPUT(13), - FUNCTION_DESC_GPIO_INPUT(14), - FUNCTION_DESC_GPIO_INPUT(15), + FUNCTION_DESC_GPIO_INPUT_BYPASS(8), + FUNCTION_DESC_GPIO_INPUT_BYPASS(9), + FUNCTION_DESC_GPIO_INPUT_BYPASS(10), + FUNCTION_DESC_GPIO_INPUT_BYPASS(11), + FUNCTION_DESC_GPIO_INPUT_BYPASS(12), + FUNCTION_DESC_GPIO_INPUT_BYPASS(13), + FUNCTION_DESC_GPIO_INPUT_BYPASS(14), + FUNCTION_DESC_GPIO_INPUT_BYPASS(15), - FUNCTION_DESC_GPIO_OUTPUT(0), - FUNCTION_DESC_GPIO_OUTPUT(1), - FUNCTION_DESC_GPIO_OUTPUT(2), - FUNCTION_DESC_GPIO_OUTPUT(3), - FUNCTION_DESC_GPIO_OUTPUT(4), - FUNCTION_DESC_GPIO_OUTPUT(5), - FUNCTION_DESC_GPIO_OUTPUT(6), - FUNCTION_DESC_GPIO_OUTPUT(7), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(0), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(1), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(2), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(3), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(4), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(5), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(6), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(7), - FUNCTION_DESC_GPIO_OUTPUT(8), - FUNCTION_DESC_GPIO_OUTPUT(9), - FUNCTION_DESC_GPIO_OUTPUT(10), - FUNCTION_DESC_GPIO_OUTPUT(11), - FUNCTION_DESC_GPIO_OUTPUT(12), - FUNCTION_DESC_GPIO_OUTPUT(13), - FUNCTION_DESC_GPIO_OUTPUT(14), - FUNCTION_DESC_GPIO_OUTPUT(15), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(8), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(9), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(10), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(11), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(12), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(13), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(14), + FUNCTION_DESC_GPIO_OUTPUT_BYPASS(15), + FUNCTION_DESC_GPIO_OUTPUT_LOW(0), + FUNCTION_DESC_GPIO_OUTPUT_LOW(1), + FUNCTION_DESC_GPIO_OUTPUT_LOW(2), + FUNCTION_DESC_GPIO_OUTPUT_LOW(3), + FUNCTION_DESC_GPIO_OUTPUT_LOW(4), + FUNCTION_DESC_GPIO_OUTPUT_LOW(5), + FUNCTION_DESC_GPIO_OUTPUT_LOW(6), + FUNCTION_DESC_GPIO_OUTPUT_LOW(7), + + FUNCTION_DESC_GPIO_OUTPUT_LOW(8), + FUNCTION_DESC_GPIO_OUTPUT_LOW(9), + FUNCTION_DESC_GPIO_OUTPUT_LOW(10), + FUNCTION_DESC_GPIO_OUTPUT_LOW(11), + FUNCTION_DESC_GPIO_OUTPUT_LOW(12), + FUNCTION_DESC_GPIO_OUTPUT_LOW(13), + FUNCTION_DESC_GPIO_OUTPUT_LOW(14), + FUNCTION_DESC_GPIO_OUTPUT_LOW(15), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(0), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(1), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(2), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(3), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(4), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(5), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(6), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(7), + + FUNCTION_DESC_GPIO_OUTPUT_HIGH(8), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(9), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(10), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(11), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(12), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(13), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(14), + FUNCTION_DESC_GPIO_OUTPUT_HIGH(15), + + 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 max96772_pinctrl_info = { @@ -181,6 +268,69 @@ static struct serdes_chip_pinctrl_info max96772_pinctrl_info = { .num_functions = ARRAY_SIZE(max96772_functions_desc), }; +static const struct reg_sequence max96772_clk_ref[3][14] = { + { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0xcc }, + { 0xe7b5, 0x44 }, + { 0xe7b6, 0x81 }, + { 0xe7b7, 0x30 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x10 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x50 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0x00 }, + { 0xe7b5, 0x40 }, + { 0xe7b6, 0x6c }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x07 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x01 }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x00 }, + { 0xe7be, 0x52 }, + { 0xe7bf, 0x00 }, + }, { + { 0xe7b2, 0x30 }, + { 0xe7b3, 0x00 }, + { 0xe7b4, 0x00 }, + { 0xe7b5, 0x40 }, + { 0xe7b6, 0x6c }, + { 0xe7b7, 0x20 }, + { 0xe7b8, 0x14 }, + { 0xe7b9, 0x00 }, + { 0xe7ba, 0x2e }, + { 0xe7bb, 0x00 }, + { 0xe7bc, 0x00 }, + { 0xe7bd, 0x01 }, + { 0xe7be, 0x32 }, + { 0xe7bf, 0x00 }, + } +}; + +static int max96772_aux_dpcd_read(struct serdes *serdes, unsigned int reg, unsigned int *value) +{ + serdes_reg_write(serdes, 0xe778, reg & 0xff); + serdes_reg_write(serdes, 0xe779, (reg >> 8) & 0xff); + serdes_reg_write(serdes, 0xe77c, (reg >> 16) & 0xff); + serdes_reg_write(serdes, 0xe776, 0x10); + serdes_reg_write(serdes, 0xe777, 0x80); + /* FIXME */ + msleep(50); + serdes_reg_read(serdes, 0xe77a, value); + + return 0; +} + static int max96772_panel_init(struct serdes *serdes) { return 0; @@ -188,6 +338,86 @@ static int max96772_panel_init(struct serdes *serdes) static int max96772_panel_prepare(struct serdes *serdes) { + const struct drm_display_mode *mode = &serdes->serdes_panel->mode; + u32 hfp, hsa, hbp, hact; + u32 vact, vsa, vfp, vbp; + u64 hwords, mvid; + bool hsync_pol, vsync_pol; + + serdes_reg_write(serdes, 0xe790, serdes->serdes_panel->link_rate); + serdes_reg_write(serdes, 0xe792, serdes->serdes_panel->lane_count); + + if (serdes->serdes_panel->ssc) { + serdes_reg_write(serdes, 0xe7b0, 0x01); + serdes_reg_write(serdes, 0xe7b1, 0x10); + } else { + serdes_reg_write(serdes, 0xe7b1, 0x00); + } + + switch (serdes->serdes_panel->link_rate) { + case DP_LINK_BW_5_4: + serdes_multi_reg_write(serdes, max96772_clk_ref[2], + ARRAY_SIZE(max96772_clk_ref[2])); + break; + case DP_LINK_BW_2_7: + serdes_multi_reg_write(serdes, max96772_clk_ref[1], + ARRAY_SIZE(max96772_clk_ref[1])); + break; + case DP_LINK_BW_1_62: + default: + serdes_multi_reg_write(serdes, max96772_clk_ref[0], + ARRAY_SIZE(max96772_clk_ref[0])); + break; + } + + vact = mode->vdisplay; + vsa = mode->vsync_end - mode->vsync_start; + vfp = mode->vsync_start - mode->vdisplay; + vbp = mode->vtotal - mode->vsync_end; + hact = mode->hdisplay; + hsa = mode->hsync_end - mode->hsync_start; + hfp = mode->hsync_start - mode->hdisplay; + hbp = mode->htotal - mode->hsync_end; + + serdes_reg_write(serdes, 0xe794, hact & 0xff); + serdes_reg_write(serdes, 0xe795, (hact >> 8) & 0xff); + serdes_reg_write(serdes, 0xe796, hfp & 0xff); + serdes_reg_write(serdes, 0xe797, (hfp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe798, hsa & 0xff); + serdes_reg_write(serdes, 0xe799, (hsa >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79a, hbp & 0xff); + serdes_reg_write(serdes, 0xe79b, (hbp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79c, vact & 0xff); + serdes_reg_write(serdes, 0xe79d, (vact >> 8) & 0xff); + serdes_reg_write(serdes, 0xe79e, vfp & 0xff); + serdes_reg_write(serdes, 0xe79f, (vfp >> 8) & 0xff); + serdes_reg_write(serdes, 0xe7a0, vsa & 0xff); + serdes_reg_write(serdes, 0xe7a1, (vsa >> 8) & 0xff); + serdes_reg_write(serdes, 0xe7a2, vbp & 0xff); + serdes_reg_write(serdes, 0xe7a3, (vbp >> 8) & 0xff); + + hsync_pol = !!(mode->flags & DRM_MODE_FLAG_NHSYNC); + vsync_pol = !!(mode->flags & DRM_MODE_FLAG_NVSYNC); + serdes_reg_write(serdes, 0xe7ac, hsync_pol | (vsync_pol << 1)); + + /* NVID should always be set to 0x8000 */ + serdes_reg_write(serdes, 0xe7a8, 0); + serdes_reg_write(serdes, 0xe7a9, 0x80); + + /* HWORDS = ((HRES x bits / pixel) / 16) - LANE_COUNT */ + hwords = DIV_ROUND_CLOSEST_ULL(hact * 24, 16) - serdes->serdes_panel->lane_count; + serdes_reg_write(serdes, 0xe7a4, hwords); + serdes_reg_write(serdes, 0xe7a5, hwords >> 8); + + /* MVID = (PCLK x NVID) x 10 / Link Rate */ + mvid = DIV_ROUND_CLOSEST_ULL((u64)mode->clock * 32768, + drm_dp_bw_code_to_link_rate(serdes->serdes_panel->link_rate)); + serdes_reg_write(serdes, 0xe7a6, mvid & 0xff); + serdes_reg_write(serdes, 0xe7a7, (mvid >> 8) & 0xff); + + serdes_reg_write(serdes, 0xe7aa, 0x40); + serdes_reg_write(serdes, 0xe7ab, 0x00); + return 0; } @@ -198,6 +428,31 @@ static int max96772_panel_unprepare(struct serdes *serdes) static int max96772_panel_enable(struct serdes *serdes) { + u32 status[2]; + u32 val; + int ret; + + /* Run link training */ + serdes_reg_write(serdes, 0xe776, 0x02); + serdes_reg_write(serdes, 0xe777, 0x80); + + ret = regmap_read_poll_timeout(serdes->regmap, 0x07f0, val, + val & 0x01, MSEC_PER_SEC, + 500 * MSEC_PER_SEC); + if (!ret) + return 0; + + ret = max96772_aux_dpcd_read(serdes, DP_LANE0_1_STATUS, &status[0]); + if (ret) + return ret; + + ret = max96772_aux_dpcd_read(serdes, DP_LANE2_3_STATUS, &status[1]); + if (ret) + return ret; + + dev_err(serdes->dev, "Link Training failed: LANE0_1_STATUS=0x%02x, LANE2_3_STATUS=0x%02x\n", + status[0], status[1]); + return 0; } @@ -214,24 +469,213 @@ static struct serdes_chip_panel_ops max96772_panel_ops = { .disable = max96772_panel_disable, }; -static int max96772_pinctrl_config_get(struct serdes *serdes, - unsigned int pin, - unsigned long *config) +static int max96772_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) { + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + u16 ms; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + ms = fdata->mdelay; + for (i = 0; i < grp->num_pins; i++) { + if (!ms) { + serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en) | + FIELD_PREP(GPIO_OUT, fdata->gpio_out_level)); + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } else { + mdelay(ms); + SERDES_DBG_CHIP("%s: delay %d ms\n", + __func__, ms); + } + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96772_pinctrl_config_get(struct serdes *serdes, + unsigned int pin, unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int gpio_a_reg, gpio_b_reg; + u16 arg = 0; + + serdes_reg_read(serdes, GPIO_A_REG(pin), &gpio_a_reg); + serdes_reg_read(serdes, GPIO_B_REG(pin), &gpio_b_reg); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_OUTPUT: + if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) + return -EINVAL; + + arg = FIELD_GET(GPIO_OUT, gpio_a_reg); + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; } static int max96772_pinctrl_config_set(struct serdes *serdes, - unsigned int pin, - unsigned long *configs, + unsigned int pin, unsigned long *configs, unsigned int num_configs) { - return 0; -} + enum pin_config_param param; + u32 arg; + u8 res_cfg; + int i; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, arg)); + break; + default: + return -EOPNOTSUPP; + } + } -static int max96772_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector, - unsigned int group_selector) -{ return 0; } diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96772.h b/drivers/mfd/display-serdes/maxim/maxim-max96772.h index 1a961e615a67..df5da5327254 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96772.h +++ b/drivers/mfd/display-serdes/maxim/maxim-max96772.h @@ -11,4 +11,28 @@ #ifndef __MFD_SERDES_MAXIM_MAX96772_H__ #define __MFD_SERDES_MAXIM_MAX96772_H__ +#define GPIO_A_REG(gpio) (0x02b0 + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02b1 + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02b2 + ((gpio) * 3)) + + +/* 02b0h */ +#define RES_CFG BIT(7) +#define RSVD BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 02b1h */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 02b2h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + #endif diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96789.c b/drivers/mfd/display-serdes/maxim/maxim-max96789.c index 494763e97f5a..b970f10ed786 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96789.c +++ b/drivers/mfd/display-serdes/maxim/maxim-max96789.c @@ -13,13 +13,17 @@ static bool max96789_volatile_reg(struct device *dev, unsigned int reg) { switch (reg) { - case 0x0076: - case 0x0086: - case 0x0100: - case 0x0200 ... 0x02ce: - case 0x7000: - case 0x7070: - case 0x7074: + case 0x0002: + case 0x0010: + case 0x0013: + case 0x0053: + case 0x0057: + case 0x02be ... 0x02fc: + case 0x0311: + case 0x032a: + case 0x0330 ... 0x0331: + case 0x0385 ... 0x0387: + case 0x03a4 ... 0x03ae: return false; default: return true; @@ -30,11 +34,30 @@ static struct regmap_config max96789_regmap_config = { .name = "max96789", .reg_bits = 16, .val_bits = 8, - .max_register = 0x8000, + .max_register = 0x2000, .volatile_reg = max96789_volatile_reg, .cache_type = REGCACHE_RBTREE, }; +struct serdes_function_data { + u8 gpio_out_dis:1; + u8 gpio_tx_en:1; + u8 gpio_rx_en:1; + u8 gpio_tx_id; + u8 gpio_rx_id; +}; + +struct config_desc { + u16 reg; + u8 mask; + u8 val; +}; + +struct serdes_group_data { + const struct config_desc *configs; + int num_configs; +}; + static int MAX96789_MFP0_pins[] = {0}; static int MAX96789_MFP1_pins[] = {1}; static int MAX96789_MFP2_pins[] = {2}; @@ -58,6 +81,8 @@ static int MAX96789_MFP17_pins[] = {17}; static int MAX96789_MFP18_pins[] = {18}; static int MAX96789_MFP19_pins[] = {19}; static int MAX96789_MFP20_pins[] = {20}; +static int MAX96789_I2C_pins[] = {19, 20}; +static int MAX96789_UART_pins[] = {19, 20}; #define GROUP_DESC(nm) \ { \ @@ -66,12 +91,91 @@ static int MAX96789_MFP20_pins[] = {20}; .num_pins = ARRAY_SIZE(nm ## _pins), \ } -struct serdes_function_data { - u8 gpio_out_dis:1; - u8 gpio_tx_en:1; - u8 gpio_rx_en:1; - u8 gpio_tx_id; - u8 gpio_rx_id; +#define GROUP_DESC_CONFIG(nm) \ +{ \ + .name = #nm, \ + .pins = nm ## _pins, \ + .num_pins = ARRAY_SIZE(nm ## _pins), \ + .data = (void *)(const struct serdes_group_data []) { \ + { \ + .configs = nm ## _configs, \ + .num_configs = ARRAY_SIZE(nm ## _configs), \ + } \ + }, \ +} + +static const struct config_desc MAX96789_MFP0_configs[] = { + { 0x0005, LOCK_EN, 0 }, + { 0x0048, LOC_MS_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP1_configs[] = { + { 0x0005, ERRB_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP4_configs[] = { + { 0x070, SPI_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP5_configs[] = { + { 0x006, RCLKEN, 0 }, +}; + +static const struct config_desc MAX96789_MFP7_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP8_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP9_configs[] = { + { 0x0002, AUD_TX_EN_X, 0 }, + { 0x0002, AUD_TX_EN_Y, 0 } +}; + +static const struct config_desc MAX96789_MFP10_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP11_configs[] = { + { 0x0001, IIC_2_EN, 0 }, + { 0x0003, UART_2_EN, 0 }, + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP12_configs[] = { + { 0x0140, AUD_RX_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP13_configs[] = { + { 0x0005, PU_LF0, 0 }, +}; + +static const struct config_desc MAX96789_MFP14_configs[] = { + { 0x0005, PU_LF1, 0 }, +}; + +static const struct config_desc MAX96789_MFP15_configs[] = { + { 0x0005, PU_LF2, 0 }, +}; + +static const struct config_desc MAX96789_MFP16_configs[] = { + { 0x0005, PU_LF3, 0 }, +}; + +static const struct config_desc MAX96789_MFP17_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, +}; + +static const struct config_desc MAX96789_MFP18_configs[] = { + { 0x0001, IIC_1_EN, 0 }, + { 0x0003, UART_1_EN, 0 }, }; static const char *serdes_gpio_groups[] = { @@ -85,19 +189,29 @@ static const char *serdes_gpio_groups[] = { "MAX96789_MFP20", }; +static const char *MAX96789_I2C_groups[] = { "MAX96789_I2C" }; +static const char *MAX96789_UART_groups[] = { "MAX96789_UART" }; + +#define FUNCTION_DESC(nm) \ +{ \ + .name = #nm, \ + .group_names = nm##_groups, \ + .num_group_names = ARRAY_SIZE(nm##_groups), \ +} \ + #define FUNCTION_DESC_GPIO_INPUT(id) \ { \ - .name = "DES_GPIO"#id"_INPUT", \ + .name = "DES_GPIO"#id"_TO_SER", \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ - { .gpio_rx_en = 1, .gpio_rx_id = id } \ + { .gpio_out_dis = 0, .gpio_rx_en = 1, .gpio_rx_id = id } \ }, \ } \ #define FUNCTION_DESC_GPIO_OUTPUT(id) \ { \ - .name = "DES_GPIO"#id"_OUTPUT", \ + .name = "SER_TO_DES_GPIO"#id, \ .group_names = serdes_gpio_groups, \ .num_group_names = ARRAY_SIZE(serdes_gpio_groups), \ .data = (void *)(const struct serdes_function_data []) { \ @@ -132,29 +246,31 @@ static struct pinctrl_pin_desc max96789_pins_desc[] = { }; static struct group_desc max96789_groups_desc[] = { - GROUP_DESC(MAX96789_MFP0), - GROUP_DESC(MAX96789_MFP1), + GROUP_DESC_CONFIG(MAX96789_MFP0), + GROUP_DESC_CONFIG(MAX96789_MFP1), GROUP_DESC(MAX96789_MFP2), GROUP_DESC(MAX96789_MFP3), - GROUP_DESC(MAX96789_MFP4), - GROUP_DESC(MAX96789_MFP5), + GROUP_DESC_CONFIG(MAX96789_MFP4), + GROUP_DESC_CONFIG(MAX96789_MFP5), GROUP_DESC(MAX96789_MFP6), - GROUP_DESC(MAX96789_MFP7), + GROUP_DESC_CONFIG(MAX96789_MFP7), - GROUP_DESC(MAX96789_MFP8), - GROUP_DESC(MAX96789_MFP9), - GROUP_DESC(MAX96789_MFP10), - GROUP_DESC(MAX96789_MFP11), - GROUP_DESC(MAX96789_MFP12), - GROUP_DESC(MAX96789_MFP13), - GROUP_DESC(MAX96789_MFP14), - GROUP_DESC(MAX96789_MFP15), + GROUP_DESC_CONFIG(MAX96789_MFP8), + GROUP_DESC_CONFIG(MAX96789_MFP9), + GROUP_DESC_CONFIG(MAX96789_MFP10), + GROUP_DESC_CONFIG(MAX96789_MFP11), + GROUP_DESC_CONFIG(MAX96789_MFP12), + GROUP_DESC_CONFIG(MAX96789_MFP13), + GROUP_DESC_CONFIG(MAX96789_MFP14), + GROUP_DESC_CONFIG(MAX96789_MFP15), - GROUP_DESC(MAX96789_MFP16), - GROUP_DESC(MAX96789_MFP17), - GROUP_DESC(MAX96789_MFP18), + GROUP_DESC_CONFIG(MAX96789_MFP16), + GROUP_DESC_CONFIG(MAX96789_MFP17), + GROUP_DESC_CONFIG(MAX96789_MFP18), GROUP_DESC(MAX96789_MFP19), GROUP_DESC(MAX96789_MFP20), + GROUP_DESC(MAX96789_I2C), + GROUP_DESC(MAX96789_UART), }; static struct function_desc max96789_functions_desc[] = { @@ -206,6 +322,8 @@ static struct function_desc max96789_functions_desc[] = { FUNCTION_DESC_GPIO_OUTPUT(19), FUNCTION_DESC_GPIO_OUTPUT(20), + FUNCTION_DESC(MAX96789_I2C), + FUNCTION_DESC(MAX96789_UART), }; static struct serdes_chip_pinctrl_info max96789_pinctrl_info = { @@ -222,40 +340,297 @@ static int max96789_bridge_init(struct serdes *serdes) return 0; } +static bool max96789_bridge_link_locked(struct serdes *serdes) +{ + u32 val; + + if (serdes->lock_gpio) { + val = gpiod_get_value_cansleep(serdes->lock_gpio); + SERDES_DBG_CHIP("%s: lock_gpio val=%d\n", __func__, val); + return val; + } + + if (serdes_reg_read(serdes, 0x0013, &val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); + return false; + } + + if (!FIELD_GET(LOCKED, val)) { + SERDES_DBG_CHIP("%s: false val=%d\n", __func__, val); + return false; + } + + SERDES_DBG_CHIP("%s: return true\n", __func__); + + return true; +} + +static int max96789_bridge_attach(struct serdes *serdes) +{ + if (max96789_bridge_link_locked(serdes)) + serdes->serdes_bridge->status = connector_status_connected; + else + serdes->serdes_bridge->status = connector_status_disconnected; + + return 0; +} + +static enum drm_connector_status +max96789_bridge_detect(struct serdes *serdes) +{ + struct serdes_bridge *serdes_bridge = serdes->serdes_bridge; + enum drm_connector_status status = connector_status_connected; + + if (!drm_kms_helper_is_poll_worker()) + return serdes_bridge->status; + + if (!max96789_bridge_link_locked(serdes)) { + status = connector_status_disconnected; + goto out; + } + + if (extcon_get_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT)) { + if (atomic_cmpxchg(&serdes_bridge->triggered, 1, 0)) { + status = connector_status_disconnected; + goto out; + } + + } else { + atomic_set(&serdes_bridge->triggered, 0); + } + + if (serdes_bridge->next_bridge && (serdes_bridge->next_bridge->ops & DRM_BRIDGE_OP_DETECT)) + return drm_bridge_detect(serdes_bridge->next_bridge); + +out: + serdes_bridge->status = status; + SERDES_DBG_CHIP("%s: status=%d\n", __func__, status); + return status; +} + static int max96789_bridge_enable(struct serdes *serdes) { - return 0; + int ret = 0; + + SERDES_DBG_CHIP("%s: serdes chip %s ret=%d\n", __func__, serdes->chip_data->name, ret); + return ret; } static int max96789_bridge_disable(struct serdes *serdes) { - return 0; + int ret = 0; + + return ret; } static struct serdes_chip_bridge_ops max96789_bridge_ops = { .init = max96789_bridge_init, + .attach = max96789_bridge_attach, + .detect = max96789_bridge_detect, .enable = max96789_bridge_enable, .disable = max96789_bridge_disable, }; -static int max96789_pinctrl_config_get(struct serdes *serdes, - unsigned int pin, - unsigned long *config) +static int max96789_pinctrl_set_mux(struct serdes *serdes, + unsigned int function, unsigned int group) { + struct serdes_pinctrl *pinctrl = serdes->pinctrl; + struct function_desc *func; + struct group_desc *grp; + int i; + + func = pinmux_generic_get_function(pinctrl->pctl, function); + if (!func) + return -EINVAL; + + grp = pinctrl_generic_get_group(pinctrl->pctl, group); + if (!grp) + return -EINVAL; + + SERDES_DBG_CHIP("%s: serdes chip %s func=%s data=%p group=%s data=%p, num_pin=%d\n", + __func__, serdes->chip_data->name, func->name, + func->data, grp->name, grp->data, grp->num_pins); + + if (func->data) { + struct serdes_function_data *fdata = func->data; + + for (i = 0; i < grp->num_pins; i++) { + serdes_set_bits(serdes, GPIO_A_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_OUT_DIS | GPIO_RX_EN | GPIO_TX_EN, + FIELD_PREP(GPIO_OUT_DIS, fdata->gpio_out_dis) | + FIELD_PREP(GPIO_RX_EN, fdata->gpio_rx_en) | + FIELD_PREP(GPIO_TX_EN, fdata->gpio_tx_en)); + + if (fdata->gpio_tx_en) + serdes_set_bits(serdes, + GPIO_B_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_TX_ID, + FIELD_PREP(GPIO_TX_ID, fdata->gpio_tx_id)); + + if (fdata->gpio_rx_en) + serdes_set_bits(serdes, + GPIO_C_REG(grp->pins[i] - pinctrl->pin_base), + GPIO_RX_ID, + FIELD_PREP(GPIO_RX_ID, fdata->gpio_rx_id)); + } + } + + if (grp->data) { + struct serdes_group_data *gdata = grp->data; + + for (i = 0; i < gdata->num_configs; i++) { + const struct config_desc *config = &gdata->configs[i]; + + serdes_set_bits(serdes, config->reg, + config->mask, config->val); + } + } + + return 0; +} + +static int max96789_pinctrl_config_get(struct serdes *serdes, + unsigned int pin, unsigned long *config) +{ + enum pin_config_param param = pinconf_to_config_param(*config); + unsigned int gpio_a_reg, gpio_b_reg; + u16 arg = 0; + + serdes_reg_read(serdes, GPIO_A_REG(pin), &gpio_a_reg); + serdes_reg_read(serdes, GPIO_B_REG(pin), &gpio_b_reg); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + if (FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + if (!FIELD_GET(OUT_TYPE, gpio_b_reg)) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_DISABLE: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 0) + return -EINVAL; + break; + case PIN_CONFIG_BIAS_PULL_UP: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 1) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + if (FIELD_GET(PULL_UPDN_SEL, gpio_b_reg) != 2) + return -EINVAL; + switch (FIELD_GET(RES_CFG, gpio_a_reg)) { + case 0: + arg = 40000; + break; + case 1: + arg = 10000; + break; + } + break; + case PIN_CONFIG_OUTPUT: + if (FIELD_GET(GPIO_OUT_DIS, gpio_a_reg)) + return -EINVAL; + + arg = FIELD_GET(GPIO_OUT, gpio_a_reg); + break; + default: + return -EOPNOTSUPP; + } + + *config = pinconf_to_config_packed(param, arg); + return 0; } static int max96789_pinctrl_config_set(struct serdes *serdes, - unsigned int pin, - unsigned long *configs, + unsigned int pin, unsigned long *configs, unsigned int num_configs) { - return 0; -} + enum pin_config_param param; + u32 arg; + u8 res_cfg; + int i; + + for (i = 0; i < num_configs; i++) { + param = pinconf_to_config_param(configs[i]); + arg = pinconf_to_config_argument(configs[i]); + + SERDES_DBG_CHIP("%s: serdes chip %s pin=%d param=%d\n", __func__, + serdes->chip_data->name, pin, param); + + switch (param) { + case PIN_CONFIG_DRIVE_OPEN_DRAIN: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 0)); + break; + case PIN_CONFIG_DRIVE_PUSH_PULL: + serdes_set_bits(serdes, GPIO_B_REG(pin), + OUT_TYPE, FIELD_PREP(OUT_TYPE, 1)); + break; + case PIN_CONFIG_BIAS_DISABLE: + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 0)); + break; + case PIN_CONFIG_BIAS_PULL_UP: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 1)); + break; + case PIN_CONFIG_BIAS_PULL_DOWN: + switch (arg) { + case 40000: + res_cfg = 0; + break; + case 1000000: + res_cfg = 1; + break; + default: + return -EINVAL; + } + + serdes_set_bits(serdes, GPIO_A_REG(pin), + RES_CFG, FIELD_PREP(RES_CFG, res_cfg)); + serdes_set_bits(serdes, GPIO_C_REG(pin), + PULL_UPDN_SEL, + FIELD_PREP(PULL_UPDN_SEL, 2)); + break; + case PIN_CONFIG_OUTPUT: + serdes_set_bits(serdes, GPIO_A_REG(pin), + GPIO_OUT_DIS | GPIO_OUT, + FIELD_PREP(GPIO_OUT_DIS, 0) | + FIELD_PREP(GPIO_OUT, arg)); + break; + default: + return -EOPNOTSUPP; + } + } -static int max96789_pinctrl_set_mux(struct serdes *serdes, unsigned int func_selector, - unsigned int group_selector) -{ return 0; } diff --git a/drivers/mfd/display-serdes/maxim/maxim-max96789.h b/drivers/mfd/display-serdes/maxim/maxim-max96789.h index 1988b376afba..7026e506dc81 100644 --- a/drivers/mfd/display-serdes/maxim/maxim-max96789.h +++ b/drivers/mfd/display-serdes/maxim/maxim-max96789.h @@ -11,4 +11,179 @@ #ifndef __MFD_SERDES_MAXIM_MAX96789_H__ #define __MFD_SERDES_MAXIM_MAX96789_H__ +#include + +#define GPIO_A_REG(gpio) (0x02be + ((gpio) * 3)) +#define GPIO_B_REG(gpio) (0x02bf + ((gpio) * 3)) +#define GPIO_C_REG(gpio) (0x02c0 + ((gpio) * 3)) + +/* 0000h */ +#define DEV_ADDR GENMASK(7, 1) +#define CFG_BLOCK BIT(0) + +/* 0001h */ +#define IIC_2_EN BIT(7) +#define IIC_1_EN BIT(6) +#define DIS_REM_CC BIT(4) +#define TX_RATE GENMASK(3, 2) + +/* 0002h */ +#define VID_TX_EN_U BIT(7) +#define VID_TX_EN_Z BIT(6) +#define VID_TX_EN_Y BIT(5) +#define VID_TX_EN_X BIT(4) +#define AUD_TX_EN_Y BIT(3) +#define AUD_TX_EN_X BIT(2) + +/* 0003h */ +#define UART_2_EN BIT(5) +#define UART_1_EN BIT(4) + +/* 0005h */ +#define LOCK_EN BIT(7) +#define ERRB_EN BIT(6) +#define PU_LF3 BIT(3) +#define PU_LF2 BIT(2) +#define PU_LF1 BIT(1) +#define PU_LF0 BIT(0) + +/* 0006h */ +#define RCLKEN BIT(5) + +/* 0010h */ +#define RESET_ALL BIT(7) +#define RESET_LINK BIT(6) +#define RESET_ONESHOT BIT(5) +#define AUTO_LINK BIT(4) +#define SLEEP BIT(3) +#define REG_ENABLE BIT(2) +#define LINK_CFG GENMASK(1, 0) + +/* 0013h */ +#define LINK_MODE GENMASK(5, 4) +#define LOCKED BIT(3) + +/* 0026h */ +#define LF_1 GENMASK(6, 4) +#define LF_0 GENMASK(2, 0) + +/* 0048h */ +#define REM_MS_EN BIT(5) +#define LOC_MS_EN BIT(4) + +/* 0053h */ +#define TX_SPLIT_MASK_B BIT(5) +#define TX_SPLIT_MASK_A BIT(4) +#define TX_STR_SEL GENMASK(1, 0) + +/* 0140h */ +#define AUD_RX_EN BIT(0) + +/* 0170h */ +#define SPI_EN BIT(0) + +/* 01e5h */ +#define PATGEN_MODE GENMASK(1, 0) + +/* 02beh */ +#define RES_CFG BIT(7) +#define TX_PRIO BIT(6) +#define TX_COMP_EN BIT(5) +#define GPIO_OUT BIT(4) +#define GPIO_IN BIT(3) +#define GPIO_RX_EN BIT(2) +#define GPIO_TX_EN BIT(1) +#define GPIO_OUT_DIS BIT(0) + +/* 02bfh */ +#define PULL_UPDN_SEL GENMASK(7, 6) +#define OUT_TYPE BIT(5) +#define GPIO_TX_ID GENMASK(4, 0) + +/* 02c0h */ +#define OVR_RES_CFG BIT(7) +#define GPIO_RX_ID GENMASK(4, 0) + +/* 0311h */ +#define START_PORTBU BIT(7) +#define START_PORTBZ BIT(6) +#define START_PORTBY BIT(5) +#define START_PORTBX BIT(4) +#define START_PORTAU BIT(3) +#define START_PORTAZ BIT(2) +#define START_PORTAY BIT(1) +#define START_PORTAX BIT(0) + +/* 032ah */ +#define DV_LOCK BIT(7) +#define DV_SWP_AB BIT(6) +#define LINE_ALT BIT(5) +#define DV_CONV BIT(2) +#define DV_SPL BIT(1) +#define DV_EN BIT(0) + +/* 0330h */ +#define PHY_CONFIG GENMASK(2, 0) +#define MIPI_RX_RESET BIT(3) + +/* 0331h */ +#define NUM_LANES GENMASK(1, 0) + +/* 0385h */ +#define DPI_HSYNC_WIDTH_L GENMASK(7, 0) + +/* 0386h */ +#define DPI_VYSNC_WIDTH_L GENMASK(7, 0) + +/* 0387h */ +#define DPI_HSYNC_WIDTH_H GENMASK(3, 0) +#define DPI_VSYNC_WIDTH_H GENMASK(7, 4) + +/* 03a4h */ +#define DPI_DE_SKEW_SEL BIT(1) +#define DPI_DESKEW_EN BIT(0) + +/* 03a5h */ +#define DPI_VFP_L GENMASK(7, 0) + +/* 03a6h */ +#define DPI_VFP_H GENMASK(3, 0) +#define DPI_VBP_L GENMASK(7, 4) + +/* 03a7h */ +#define DPI_VBP_H GENMASK(7, 0) + +/* 03a8h */ +#define DPI_VACT_L GENMASK(7, 0) + +/* 03a9h */ +#define DPI_VACT_H GENMASK(3, 0) + +/* 03aah */ +#define DPI_HFP_L GENMASK(7, 0) + +/* 03abh */ +#define DPI_HFP_H GENMASK(3, 0) +#define DPI_HBP_L GENMASK(7, 4) + +/* 03ach */ +#define DPI_HBP_H GENMASK(7, 0) + +/* 03adh */ +#define DPI_HACT_L GENMASK(7, 0) + +/* 03aeh */ +#define DPI_HACT_H GENMASK(4, 0) + +/* 055dh */ +#define VS_DET BIT(5) +#define HS_DET BIT(4) + +enum link_mode { + DUAL_LINK, + LINKA, + LINKB, + SPLITTER_MODE, +}; + #endif diff --git a/drivers/mfd/display-serdes/serdes-bridge.c b/drivers/mfd/display-serdes/serdes-bridge.c index 0ff047d69a5b..a9448e609315 100644 --- a/drivers/mfd/display-serdes/serdes-bridge.c +++ b/drivers/mfd/display-serdes/serdes-bridge.c @@ -49,13 +49,17 @@ static struct mipi_dsi_device *serdes_attach_dsi(struct serdes_bridge *serdes_br (!strcmp(serdes->chip_data->name, "bu18rl82"))) { dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_BURST | MIPI_DSI_MODE_LPM | MIPI_DSI_MODE_EOT_PACKET; - SERDES_DBG_MFD("%s: dsi mode MIPI_DSI_MODE_VIDEO_BURST 0x%lx\n", - __func__, dsi->mode_flags); + SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_BURST 0x%lx\n", + __func__, serdes->chip_data->name, dsi->mode_flags); + } else { + dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; + SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n", + __func__, serdes->chip_data->name, dsi->mode_flags); } } else { dsi->mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE; - SERDES_DBG_MFD("%s: dsi mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n", - __func__, dsi->mode_flags); + SERDES_DBG_MFD("%s: %s dsi_mode MIPI_DSI_MODE_VIDEO_SYNC_PULSE 0x%lx\n", + __func__, serdes->chip_data->name, dsi->mode_flags); } ret = mipi_dsi_attach(dsi); @@ -164,6 +168,9 @@ 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) { if (serdes->chip_data->chip_init) serdes->chip_data->chip_init(serdes); @@ -198,7 +205,8 @@ static void serdes_bridge_enable(struct drm_bridge *bridge) SERDES_DBG_MFD("%s: extcon is true\n", __func__); } - SERDES_DBG_MFD("%s: %s ret=%d\n", __func__, dev_name(serdes->dev), ret); + SERDES_DBG_MFD("%s: %s-%s ret=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, ret); } static enum drm_connector_status @@ -230,8 +238,8 @@ static int serdes_bridge_get_modes(struct drm_bridge *bridge, if (serdes_bridge->panel) ret = drm_panel_get_modes(serdes_bridge->panel, connector); - SERDES_DBG_MFD("%s:name=%s, type=%d\n", __func__, - serdes->chip_data->name, serdes->type); + SERDES_DBG_MFD("%s:name=%s, node=%s\n", __func__, + serdes->chip_data->name, serdes_bridge->dev->of_node->name); return ret; } @@ -291,7 +299,7 @@ static int serdes_bridge_probe(struct platform_device *pdev) SERDES_DBG_MFD("%s: type DRM_MODE_CONNECTOR_DSI\n", __func__); } else if (serdes_bridge->parent->chip_data->connector_type) { serdes_bridge->base_bridge.type = serdes_bridge->parent->chip_data->connector_type; - SERDES_DBG_MFD("%s: type 0x%x\n", __func__, serdes_bridge->base_bridge.type); + SERDES_DBG_MFD("%s: type %d\n", __func__, serdes_bridge->base_bridge.type); } else { serdes_bridge->base_bridge.type = DRM_MODE_CONNECTOR_eDP; SERDES_DBG_MFD("%s: type DRM_MODE_CONNECTOR_LVDS\n", __func__); @@ -319,9 +327,8 @@ static const struct of_device_id serdes_bridge_of_match[] = { { .compatible = "rohm,bu18tl82-bridge", }, { .compatible = "rohm,bu18rl82-bridge", }, { .compatible = "maxim,max96745-bridge", }, - { .compatible = "maxim,max96752-bridge", }, { .compatible = "maxim,max96755-bridge", }, - { .compatible = "maxim,max96772-bridge", }, + { .compatible = "maxim,max96789-bridge", }, { .compatible = "rockchip,rkx111-bridge", }, { .compatible = "rockchip,rkx121-bridge", }, { } diff --git a/drivers/mfd/display-serdes/serdes-core.c b/drivers/mfd/display-serdes/serdes-core.c index cb6db15dc595..ed671eb9892c 100644 --- a/drivers/mfd/display-serdes/serdes-core.c +++ b/drivers/mfd/display-serdes/serdes-core.c @@ -127,8 +127,8 @@ int serdes_reg_read(struct serdes *serdes, unsigned int reg, unsigned int *val) int ret; ret = regmap_read(serdes->regmap, reg, val); - SERDES_DBG_I2C("%s %s Read Reg%04x %04x\n", __func__, - serdes->chip_data->name, reg, *val); + SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x ret=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, reg, *val, ret); return ret; } EXPORT_SYMBOL_GPL(serdes_reg_read); @@ -148,8 +148,9 @@ int serdes_bulk_read(struct serdes *serdes, unsigned int reg, ret = regmap_bulk_read(serdes->regmap, reg, buf, count); for (i = 0; i < count; i++) { - SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x\n", __func__, dev_name(serdes->dev), - serdes->chip_data->name, reg + i, buf[i]); + SERDES_DBG_I2C("%s %s %s Read Reg%04x %04x ret=%d\n", + __func__, dev_name(serdes->dev), + serdes->chip_data->name, reg + i, buf[i], ret); } return ret; @@ -166,9 +167,10 @@ int serdes_bulk_write(struct serdes *serdes, unsigned int reg, mutex_lock(&serdes->io_lock); for (i = 0; i < count; i++) { - SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x\n", __func__, dev_name(serdes->dev), - serdes->chip_data->name, reg, buf[i]); ret = regmap_write(serdes->regmap, reg, buf[i]); + SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x ret=%d\n", + __func__, dev_name(serdes->dev), + serdes->chip_data->name, reg, buf[i], ret); if (ret != 0) { mutex_unlock(&serdes->io_lock); return ret; @@ -193,12 +195,11 @@ int serdes_multi_reg_write(struct serdes *serdes, const struct reg_sequence *reg SERDES_DBG_I2C("%s %s %s num=%d\n", __func__, dev_name(serdes->dev), serdes->chip_data->name, num_regs); - for (i = 0; i < num_regs; i++) { - SERDES_DBG_I2C("serdes %s Write Reg%04x %04x\n", - serdes->chip_data->name, regs[i].reg, regs[i].def); - } - ret = regmap_multi_reg_write(serdes->regmap, regs, num_regs); + for (i = 0; i < num_regs; i++) { + SERDES_DBG_I2C("serdes %s Write Reg%04x %04x ret=%d\n", + serdes->chip_data->name, regs[i].reg, regs[i].def, ret); + } return ret; } @@ -216,9 +217,9 @@ int serdes_reg_write(struct serdes *serdes, unsigned int reg, { int ret; - SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x)\n", __func__, dev_name(serdes->dev), - serdes->chip_data->name, reg, val); ret = regmap_write(serdes->regmap, reg, val); + SERDES_DBG_I2C("%s %s %s Write Reg%04x %04x ret=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, reg, val, ret); if (ret != 0) return ret; diff --git a/drivers/mfd/display-serdes/serdes-gpio.c b/drivers/mfd/display-serdes/serdes-gpio.c index 8e8645510af9..24b0a9b4f02f 100644 --- a/drivers/mfd/display-serdes/serdes-gpio.c +++ b/drivers/mfd/display-serdes/serdes-gpio.c @@ -221,6 +221,7 @@ static const struct of_device_id serdes_gpio_of_match[] = { { .compatible = "maxim,max96752-gpio", }, { .compatible = "maxim,max96755-gpio", }, { .compatible = "maxim,max96772-gpio", }, + { .compatible = "maxim,max96789-gpio", }, { .compatible = "rockchip,rkx111-gpio", }, { .compatible = "rockchip,rkx121-gpio", }, { .compatible = "novo,nca9539-gpio", }, diff --git a/drivers/mfd/display-serdes/serdes-i2c.c b/drivers/mfd/display-serdes/serdes-i2c.c index 21d0c1d4b817..49748d3a8322 100644 --- a/drivers/mfd/display-serdes/serdes-i2c.c +++ b/drivers/mfd/display-serdes/serdes-i2c.c @@ -299,6 +299,9 @@ static const struct of_device_id serdes_of_match[] = { #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96772) { .compatible = "maxim,max96772", .data = &serdes_max96772_data }, #endif +#if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96789) + { .compatible = "maxim,max96789", .data = &serdes_max96789_data }, +#endif #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) { .compatible = "rockchip,rkx111", .data = &serdes_rkx111_data }, #endif diff --git a/drivers/mfd/display-serdes/serdes-irq.c b/drivers/mfd/display-serdes/serdes-irq.c index f4d7740f0f75..5aa685a20075 100644 --- a/drivers/mfd/display-serdes/serdes-irq.c +++ b/drivers/mfd/display-serdes/serdes-irq.c @@ -20,7 +20,8 @@ static irqreturn_t serdes_bridge_lock_irq_handler(int irq, void *arg) if (extcon_get_state(serdes->extcon, EXTCON_JACK_VIDEO_OUT)) atomic_set(&serdes->serdes_bridge->triggered, 1); - SERDES_DBG_MFD("%s: ret=%d\n", __func__, ret); + SERDES_DBG_MFD("%s %s %s ret=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, ret); return IRQ_HANDLED; } @@ -33,14 +34,15 @@ static irqreturn_t serdes_bridge_err_irq_handler(int irq, void *arg) if (serdes->chip_data->irq_ops->err_handle) ret = serdes->chip_data->irq_ops->err_handle(serdes); - SERDES_DBG_MFD("%s: ret=%d\n", __func__, ret); + SERDES_DBG_MFD("%s %s %s ret=%d\n", __func__, dev_name(serdes->dev), + serdes->chip_data->name, ret); return IRQ_HANDLED; } int serdes_irq_init(struct serdes *serdes) { - int ret; + int ret = 0; mutex_init(&serdes->irq_lock); @@ -55,8 +57,9 @@ int serdes_irq_init(struct serdes *serdes) if (serdes->lock_irq < 0) return serdes->lock_irq; - SERDES_DBG_MFD("%s %s lock_irq=%d\n", __func__, - serdes->chip_data->name, serdes->lock_irq); + SERDES_DBG_MFD("%s %s lock_irq=%d gpio=%d\n", __func__, + serdes->chip_data->name, serdes->lock_irq, + desc_to_gpio(serdes->lock_gpio)); ret = devm_request_threaded_irq(serdes->dev, serdes->lock_irq, NULL, serdes_bridge_lock_irq_handler, @@ -64,7 +67,7 @@ int serdes_irq_init(struct serdes *serdes) dev_name(serdes->dev), serdes); if (ret) return dev_err_probe(serdes->dev, ret, - "failed to request serdes lock IRQ\n"); + "failed to request serdes lock IRQ\n"); } /* error irq */ diff --git a/drivers/mfd/display-serdes/serdes-panel.c b/drivers/mfd/display-serdes/serdes-panel.c index 9e5cc9568377..2a8b9357c227 100644 --- a/drivers/mfd/display-serdes/serdes-panel.c +++ b/drivers/mfd/display-serdes/serdes-panel.c @@ -91,7 +91,7 @@ static int serdes_panel_get_modes(struct drm_panel *panel, struct serdes *serdes = serdes_panel->parent; struct drm_display_mode *mode; u32 bus_format = MEDIA_BUS_FMT_RGB888_1X24; - int ret = 0; + int ret = 1; connector->display_info.width_mm = serdes_panel->width_mm; //323; //346; connector->display_info.height_mm = serdes_panel->height_mm; //182; //194; @@ -108,8 +108,18 @@ static int serdes_panel_get_modes(struct drm_panel *panel, if (serdes->chip_data->panel_ops && serdes->chip_data->panel_ops->get_modes) ret = serdes->chip_data->panel_ops->get_modes(serdes); - SERDES_DBG_MFD("%s: %s node=%s\n", __func__, - serdes->chip_data->name, panel->dev->of_node->name); + dev_info(serdes->dev, "%s wxh=%dx%d mode clock %u kHz, flags[0x%x]\n" + " H: %04d %04d %04d %04d\n" + " V: %04d %04d %04d %04d\n" + "bus_format: 0x%x\n", + panel->dev->of_node->name, + serdes_panel->width_mm, serdes_panel->height_mm, + mode->clock, mode->flags, + mode->hdisplay, mode->hsync_start, + mode->hsync_end, mode->htotal, + mode->vdisplay, mode->vsync_start, + mode->vsync_end, mode->vtotal, + bus_format); return ret; } @@ -129,12 +139,22 @@ static int serdes_panel_parse_dt(struct serdes_panel *serdes_panel) struct videomode vm; int ret, len; unsigned int panel_size[2] = {320, 180}; + unsigned int link_rate_count_ssc[3] = {DP_LINK_BW_2_7, 4, 0}; serdes_panel->width_mm = panel_size[0]; serdes_panel->height_mm = panel_size[1]; + serdes_panel->link_rate = link_rate_count_ssc[0]; + serdes_panel->lane_count = link_rate_count_ssc[1]; + serdes_panel->ssc = link_rate_count_ssc[2]; + if (of_find_property(dev->of_node, "panel-size", &len)) { len /= sizeof(unsigned int); + if (len != 2) { + dev_err(dev, "panel-size length is error, set 2 default\n", + dev->of_node); + len = 2; + } ret = of_property_read_u32_array(dev->of_node, "panel-size", panel_size, len); if (!ret) { @@ -143,8 +163,25 @@ static int serdes_panel_parse_dt(struct serdes_panel *serdes_panel) } } - dev_info(dev, "panle size %dx%d\n", - serdes_panel->width_mm, serdes_panel->height_mm); + if (of_find_property(dev->of_node, "rate-count-ssc", &len)) { + len /= sizeof(unsigned int); + if (len != 3) { + dev_err(dev, "rate-count-ssc length is error, set 3 default\n", + dev->of_node); + len = 3; + } + ret = of_property_read_u32_array(dev->of_node, "rate-count-ssc", + link_rate_count_ssc, len); + if (!ret) { + serdes_panel->link_rate = link_rate_count_ssc[0]; + serdes_panel->lane_count = link_rate_count_ssc[1]; + serdes_panel->ssc = link_rate_count_ssc[2]; + } + } + + dev_info(dev, "panle size %dx%d, rate=%d, cnt=%d, ssc=%d\n", + serdes_panel->width_mm, serdes_panel->height_mm, + serdes_panel->link_rate, serdes_panel->lane_count, serdes_panel->ssc); ret = of_get_display_timing(dev->of_node, "panel-timing", &dt); if (ret < 0) { @@ -211,7 +248,6 @@ static int serdes_panel_remove(struct platform_device *pdev) } static const struct of_device_id serdes_panel_of_match[] = { - { .compatible = "rohm,bu18tl82-panel" }, { .compatible = "rohm,bu18rl82-panel" }, { .compatible = "maxim,max96752-panel" }, { .compatible = "maxim,max96772-panel" }, diff --git a/drivers/mfd/display-serdes/serdes-pinctrl.c b/drivers/mfd/display-serdes/serdes-pinctrl.c index 13e741e7409b..d6bc9009a87d 100644 --- a/drivers/mfd/display-serdes/serdes-pinctrl.c +++ b/drivers/mfd/display-serdes/serdes-pinctrl.c @@ -309,7 +309,7 @@ static int serdes_pinctrl_probe(struct platform_device *pdev) for (j = 0; j < group->num_pins; j++) { grp_pins[j] = pinctrl_info->groups[i].pins[j] + pin_base; - SERDES_DBG_MFD("%s group name %s pin %d base=%d\n", __func__, + SERDES_DBG_MFD("%s group name %s pin=%d base=%d\n", __func__, pinctrl_info->groups[i].name, grp_pins[j], pin_base); } @@ -363,6 +363,7 @@ static const struct of_device_id serdes_pinctrl_of_match[] = { { .compatible = "maxim,max96752-pinctrl" }, { .compatible = "maxim,max96755-pinctrl" }, { .compatible = "maxim,max96772-pinctrl" }, + { .compatible = "maxim,max96789-pinctrl" }, { .compatible = "rockchip,rkx111-pinctrl" }, { .compatible = "rockchip,rkx121-pinctrl" }, { .compatible = "novo,nca9539-pinctrl" },