1 // SPDX-License-Identifier: GPL-2.0-or-later 2 /* 3 * serdes-bridge.c -- display bridge for different serdes chips 4 * 5 * Copyright (c) 2023 Rockchip Electronics Co. Ltd. 6 * 7 * Author: luowei <lw@rock-chips.com> 8 */ 9 10 #include <serdes-display-core.h> 11 12 static void serdes_bridge_init(struct serdes *serdes) 13 { 14 if (serdes->vpower_supply) 15 regulator_set_enable(serdes->vpower_supply, true); 16 17 if (dm_gpio_is_valid(&serdes->enable_gpio)) 18 dm_gpio_set_value(&serdes->enable_gpio, 1); 19 20 mdelay(5); 21 22 video_bridge_set_active(serdes->dev, true); 23 24 if (serdes->chip_data->bridge_ops->init) 25 serdes->chip_data->bridge_ops->init(serdes); 26 27 serdes_i2c_set_sequence(serdes); 28 29 SERDES_DBG_MFD("%s: %s %s\n", __func__, 30 serdes->dev->name, 31 serdes->chip_data->name); 32 } 33 34 static void serdes_bridge_pre_enable(struct rockchip_bridge *bridge) 35 { 36 struct udevice *dev = bridge->dev; 37 struct serdes *serdes = dev_get_priv(dev); 38 39 //serdes_bridge_init(serdes); 40 41 if (serdes->chip_data->bridge_ops->pre_enable) 42 serdes->chip_data->bridge_ops->pre_enable(serdes); 43 44 SERDES_DBG_MFD("%s: %s %s\n", __func__, 45 serdes->dev->name, 46 serdes->chip_data->name); 47 } 48 49 static void serdes_bridge_post_disable(struct rockchip_bridge *bridge) 50 { 51 struct udevice *dev = bridge->dev; 52 struct serdes *serdes = dev_get_priv(dev); 53 54 if (serdes->chip_data->bridge_ops->post_disable) 55 serdes->chip_data->bridge_ops->post_disable(serdes); 56 57 SERDES_DBG_MFD("%s: %s %s\n", __func__, 58 serdes->dev->name, 59 serdes->chip_data->name); 60 } 61 62 static void serdes_bridge_enable(struct rockchip_bridge *bridge) 63 { 64 struct udevice *dev = bridge->dev; 65 struct serdes *serdes = dev_get_priv(dev); 66 67 if (serdes->chip_data->serdes_type == TYPE_DES) 68 serdes_bridge_init(serdes); 69 70 if (serdes->chip_data->bridge_ops->enable) 71 serdes->chip_data->bridge_ops->enable(serdes); 72 73 SERDES_DBG_MFD("%s: %s %s\n", __func__, 74 serdes->dev->name, 75 serdes->chip_data->name); 76 } 77 78 static void serdes_bridge_disable(struct rockchip_bridge *bridge) 79 { 80 struct udevice *dev = bridge->dev; 81 struct serdes *serdes = dev_get_priv(dev); 82 83 if (serdes->chip_data->bridge_ops->disable) 84 serdes->chip_data->bridge_ops->disable(serdes); 85 86 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 87 serdes->chip_data->name); 88 } 89 90 static void serdes_bridge_mode_set(struct rockchip_bridge *bridge, 91 const struct drm_display_mode *mode) 92 { 93 struct udevice *dev = bridge->dev; 94 struct serdes *serdes = dev_get_priv(dev); 95 96 memcpy(&serdes->serdes_bridge->mode, mode, 97 sizeof(struct drm_display_mode)); 98 99 SERDES_DBG_MFD("%s: %s %s\n", __func__, serdes->dev->name, 100 serdes->chip_data->name); 101 } 102 103 static bool serdes_bridge_detect(struct rockchip_bridge *bridge) 104 { 105 bool ret = true; 106 struct serdes *serdes = dev_get_priv(bridge->dev); 107 108 if (serdes->chip_data->bridge_ops->detect) 109 ret = serdes->chip_data->bridge_ops->detect(serdes); 110 111 SERDES_DBG_MFD("%s: %s %s %s\n", __func__, serdes->dev->name, 112 serdes->chip_data->name, (ret == true) ? "detected" : "no detected"); 113 114 return ret; 115 } 116 117 struct rockchip_bridge_funcs serdes_bridge_ops = { 118 .pre_enable = serdes_bridge_pre_enable, 119 .post_disable = serdes_bridge_post_disable, 120 .enable = serdes_bridge_enable, 121 .disable = serdes_bridge_disable, 122 .mode_set = serdes_bridge_mode_set, 123 .detect = serdes_bridge_detect, 124 }; 125 126 static int serdes_bridge_probe(struct udevice *dev) 127 { 128 struct serdes *serdes = dev_get_priv(dev); 129 struct serdes_bridge *serdes_bridge = NULL; 130 struct serdes_pinctrl *serdes_pinctrl = NULL; 131 struct rockchip_bridge *bridge = NULL; 132 int ret; 133 134 ret = i2c_set_chip_offset_len(dev, 2); 135 if (ret) 136 return ret; 137 138 serdes->dev = dev; 139 serdes->chip_data = (struct serdes_chip_data *)dev_get_driver_data(dev); 140 serdes->type = serdes->chip_data->serdes_type; 141 142 SERDES_DBG_MFD("serdes %s %s probe start\n", 143 serdes->dev->name, serdes->chip_data->name); 144 145 ret = uclass_get_device_by_phandle(UCLASS_REGULATOR, dev, 146 "vpower-supply", &serdes->vpower_supply); 147 if (ret && ret != -ENOENT) 148 SERDES_DBG_MFD("%s: Cannot get power supply: %d\n", 149 __func__, ret); 150 151 ret = gpio_request_by_name(dev, "enable-gpios", 0, 152 &serdes->enable_gpio, GPIOD_IS_OUT); 153 if (ret) 154 SERDES_DBG_MFD("%s: failed to get enable gpio: %d\n", 155 __func__, ret); 156 157 ret = gpio_request_by_name(dev, "lock-gpios", 0, &serdes->lock_gpio, 158 GPIOD_IS_IN); 159 if (ret) 160 SERDES_DBG_MFD("%s: failed to get lock gpio: %d\n", 161 __func__, ret); 162 163 ret = gpio_request_by_name(dev, "err-gpios", 0, &serdes->err_gpio, 164 GPIOD_IS_IN); 165 if (ret) 166 SERDES_DBG_MFD("%s: failed to err gpio: %d\n", 167 __func__, ret); 168 169 if (serdes->chip_data->serdes_type != TYPE_SER) 170 SERDES_DBG_MFD("warning: this chip is not ser type\n"); 171 172 if (serdes->chip_data->serdes_type == TYPE_OTHER) { 173 SERDES_DBG_MFD("TYPE_OTHER just need only init i2c\n"); 174 serdes_bridge_init(serdes); 175 return 0; 176 } 177 178 if (!serdes->chip_data->bridge_ops) { 179 SERDES_DBG_MFD("%s %s no bridge ops\n", 180 __func__, serdes->chip_data->name); 181 return -1; 182 } 183 184 serdes_bridge = calloc(1, sizeof(*serdes_bridge)); 185 if (!serdes_bridge) 186 return -ENOMEM; 187 188 serdes->sel_mipi = dev_read_bool(dev, "sel-mipi"); 189 if (serdes->sel_mipi) { 190 struct mipi_dsi_device *device = dev_get_platdata(dev); 191 192 device->dev = dev; 193 device->lanes = dev_read_u32_default(dev, "dsi,lanes", 4); 194 device->format = dev_read_u32_default(dev, "dsi,format", 195 MIPI_DSI_FMT_RGB888); 196 device->mode_flags = MIPI_DSI_MODE_VIDEO | 197 MIPI_DSI_MODE_VIDEO_BURST | 198 MIPI_DSI_MODE_VIDEO_HBP | 199 MIPI_DSI_MODE_LPM | 200 MIPI_DSI_MODE_EOT_PACKET; 201 device->channel = dev_read_u32_default(dev, "reg", 0); 202 } 203 204 bridge = calloc(1, sizeof(*bridge)); 205 if (!bridge) 206 return -ENOMEM; 207 208 dev->driver_data = (ulong)bridge; 209 bridge->dev = dev; 210 bridge->funcs = &serdes_bridge_ops; 211 212 serdes->serdes_bridge = serdes_bridge; 213 serdes->serdes_bridge->bridge = bridge; 214 215 serdes_pinctrl = calloc(1, sizeof(*serdes_pinctrl)); 216 if (!serdes_pinctrl) 217 return -ENOMEM; 218 219 serdes->serdes_pinctrl = serdes_pinctrl; 220 221 ret = serdes_pinctrl_register(dev, serdes); 222 if (ret) 223 return ret; 224 225 ret = serdes_get_init_seq(serdes); 226 if (ret) 227 return ret; 228 229 if (serdes->chip_data->serdes_type == TYPE_SER) 230 serdes_bridge_init(serdes); 231 232 printf("%s %s %s successful\n", 233 __func__, 234 serdes->dev->name, 235 serdes->chip_data->name); 236 237 return 0; 238 } 239 240 static const struct udevice_id serdes_of_match[] = { 241 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18TL82) 242 { .compatible = "rohm,bu18tl82", .data = (ulong)&serdes_bu18tl82_data }, 243 #endif 244 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROHM_BU18RL82) 245 { .compatible = "rohm,bu18rl82", .data = (ulong)&serdes_bu18rl82_data }, 246 #endif 247 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96745) 248 { .compatible = "maxim,max96745", .data = (ulong)&serdes_max96745_data }, 249 #endif 250 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_MAXIM_MAX96755) 251 { .compatible = "maxim,max96755", .data = (ulong)&serdes_max96755_data }, 252 #endif 253 #if IS_ENABLED(CONFIG_SERDES_DISPLAY_CHIP_ROCKCHIP_RKX111) 254 { .compatible = "rockchip,rkx111", .data = (ulong)&serdes_rkx111_data }, 255 #endif 256 { } 257 }; 258 259 U_BOOT_DRIVER(serdes_bridge) = { 260 .name = "serdes-bridge", 261 .id = UCLASS_VIDEO_BRIDGE, 262 .of_match = serdes_of_match, 263 .probe = serdes_bridge_probe, 264 .priv_auto_alloc_size = sizeof(struct serdes), 265 .platdata_auto_alloc_size = sizeof(struct mipi_dsi_device), 266 }; 267