1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Rohm BU18RL82-based panel driver 4 * 5 * (C) Copyright 2022 Rockchip Electronics Co., Ltd 6 */ 7 8 #include <config.h> 9 #include <common.h> 10 #include <backlight.h> 11 #include <errno.h> 12 #include <malloc.h> 13 #include <video.h> 14 15 #include <asm/gpio.h> 16 #include <dm/device.h> 17 #include <dm/read.h> 18 #include <dm/pinctrl.h> 19 #include <dm/uclass-id.h> 20 #include <linux/media-bus-format.h> 21 22 #include "rockchip_display.h" 23 #include "rockchip_panel.h" 24 25 struct bu18rl82; 26 27 struct panel_desc { 28 const char *name; 29 int (*prepare)(struct bu18rl82 *rl82); 30 int (*unprepare)(struct bu18rl82 *rl82); 31 int (*enable)(struct bu18rl82 *rl82); 32 int (*disable)(struct bu18rl82 *rl82); 33 int (*backlight_enable)(struct bu18rl82 *rl82); 34 int (*backlight_disable)(struct bu18rl82 *rl82); 35 }; 36 37 struct bu18rl82 { 38 struct udevice *dev; 39 struct udevice *backlight; 40 const struct panel_desc *desc; 41 }; 42 43 static void bu18rl82_panel_prepare(struct rockchip_panel *panel) 44 { 45 struct bu18rl82 *rl82 = dev_get_priv(panel->dev); 46 const struct panel_desc *desc = rl82->desc; 47 48 if (desc->prepare) 49 desc->prepare(rl82); 50 } 51 52 static void bu18rl82_panel_unprepare(struct rockchip_panel *panel) 53 { 54 struct bu18rl82 *rl82 = dev_get_priv(panel->dev); 55 const struct panel_desc *desc = rl82->desc; 56 57 if (desc->unprepare) 58 desc->unprepare(rl82); 59 } 60 61 static void bu18rl82_panel_enable(struct rockchip_panel *panel) 62 { 63 struct bu18rl82 *rl82 = dev_get_priv(panel->dev); 64 const struct panel_desc *desc = rl82->desc; 65 66 if (desc->enable) 67 desc->enable(rl82); 68 69 if (rl82->backlight) 70 backlight_enable(rl82->backlight); 71 72 if (desc->backlight_enable) 73 desc->backlight_enable(rl82); 74 } 75 76 static void bu18rl82_panel_disable(struct rockchip_panel *panel) 77 { 78 struct bu18rl82 *rl82 = dev_get_priv(panel->dev); 79 const struct panel_desc *desc = rl82->desc; 80 81 if (desc->backlight_disable) 82 desc->backlight_disable(rl82); 83 84 if (rl82->backlight) 85 backlight_disable(rl82->backlight); 86 87 if (desc->disable) 88 desc->disable(rl82); 89 } 90 91 static const struct rockchip_panel_funcs bu18rl82_panel_funcs = { 92 .prepare = bu18rl82_panel_prepare, 93 .unprepare = bu18rl82_panel_unprepare, 94 .enable = bu18rl82_panel_enable, 95 .disable = bu18rl82_panel_disable, 96 }; 97 98 static int bu18rl82_probe(struct udevice *dev) 99 { 100 struct bu18rl82 *rl82 = dev_get_priv(dev); 101 struct rockchip_panel *panel; 102 int ret; 103 104 ret = i2c_set_chip_offset_len(dev, 2); 105 if (ret) 106 return ret; 107 108 rl82->dev = dev; 109 rl82->desc = (const struct panel_desc *)dev_get_driver_data(dev); 110 111 ret = uclass_get_device_by_phandle(UCLASS_PANEL_BACKLIGHT, dev, 112 "backlight", &rl82->backlight); 113 if (ret && ret != -ENOENT) { 114 dev_err(dev, "%s: Cannot get backlight: %d\n", __func__, ret); 115 return ret; 116 } 117 118 panel = calloc(1, sizeof(*panel)); 119 if (!panel) 120 return -ENOMEM; 121 122 dev->driver_data = (ulong)panel; 123 panel->dev = dev; 124 panel->bus_format = MEDIA_BUS_FMT_RGB888_1X24; 125 panel->funcs = &bu18rl82_panel_funcs; 126 127 return 0; 128 } 129 130 #define rohm_deserializer_write(rl82, reg, val) do { \ 131 int ret; \ 132 ret = dm_i2c_reg_write(rl82->dev, reg, val); \ 133 if (ret) { \ 134 dev_err(rl82->dev, \ 135 "failed to set register 0x%04x\n", \ 136 reg); \ 137 return ret; \ 138 } \ 139 } while (0) 140 141 static int csot_mg1561b01_prepare(struct bu18rl82 *rl82) 142 { 143 const struct reg_sequence { 144 u16 reg; 145 u8 def; 146 } regs[] = { 147 { 0x0011, 0x03 }, { 0x0012, 0x03 }, 148 { 0x001f, 0x02 }, { 0x0020, 0x02 }, 149 { 0x0031, 0x41 }, { 0x0032, 0x41 }, 150 { 0x0073, 0x80 }, { 0x0074, 0x07 }, 151 { 0x007b, 0x38 }, { 0x007c, 0x04 }, 152 { 0x0079, 0x0a }, 153 { 0x0429, 0x0a }, { 0x045d, 0x01 }, 154 { 0x0529, 0x0a }, { 0x055d, 0x01 }, 155 { 0x060a, 0xb0 }, { 0x060b, 0xff }, { 0x060c, 0xff }, 156 { 0x0644, 0x18 }, { 0x0645, 0x01 }, { 0x0646, 0x2d }, 157 }; 158 int i; 159 160 for (i = 0; i < ARRAY_SIZE(regs); i++) 161 rohm_deserializer_write(rl82, regs[i].reg, regs[i].def); 162 163 /* BL_PWM - GPIO0 */ 164 rohm_deserializer_write(rl82, 0x0057, 0x00); 165 rohm_deserializer_write(rl82, 0x0058, 0x02); 166 167 /* TP_INT - GPIO3 */ 168 rohm_deserializer_write(rl82, 0x0060, 0x08); 169 rohm_deserializer_write(rl82, 0x042e, 0x05); 170 171 /* TP_RST - GPIO4 */ 172 rohm_deserializer_write(rl82, 0x0063, 0x00); 173 rohm_deserializer_write(rl82, 0x0064, 0x01); 174 175 return 0; 176 } 177 178 static int csot_mg1561b01_unprepare(struct bu18rl82 *rl82) 179 { 180 /* TP_RST - GPIO4 */ 181 rohm_deserializer_write(rl82, 0x0064, 0x00); 182 183 return 0; 184 } 185 186 static int csot_mg1561b01_enable(struct bu18rl82 *rl82) 187 { 188 rohm_deserializer_write(rl82, 0x0091, 0x03); 189 rohm_deserializer_write(rl82, 0x0090, 0x01); 190 191 return 0; 192 } 193 194 static int csot_mg1561b01_disable(struct bu18rl82 *rl82) 195 { 196 rohm_deserializer_write(rl82, 0x0090, 0x00); 197 rohm_deserializer_write(rl82, 0x0091, 0x00); 198 199 return 0; 200 } 201 202 static int csot_mg1561b01_backlight_enable(struct bu18rl82 *rl82) 203 { 204 /* BL_EN - GPIO1 */ 205 rohm_deserializer_write(rl82, 0x005a, 0x00); 206 rohm_deserializer_write(rl82, 0x005b, 0x01); 207 208 return 0; 209 } 210 211 static int csot_mg1561b01_backlight_disable(struct bu18rl82 *rl82) 212 { 213 /* BL_EN - GPIO1 */ 214 rohm_deserializer_write(rl82, 0x005b, 0x00); 215 216 return 0; 217 } 218 219 static const struct panel_desc csot_mg1561b01 = { 220 .name = "csot,mg1561b01", 221 .prepare = csot_mg1561b01_prepare, 222 .unprepare = csot_mg1561b01_unprepare, 223 .enable = csot_mg1561b01_enable, 224 .disable = csot_mg1561b01_disable, 225 .backlight_enable = csot_mg1561b01_backlight_enable, 226 .backlight_disable = csot_mg1561b01_backlight_disable, 227 }; 228 229 static int touch_china_v123awf3_r1_prepare(struct bu18rl82 *rl82) 230 { 231 const struct reg_sequence { 232 u16 reg; 233 u8 def; 234 } regs[] = { 235 { 0x0011, 0x03 }, { 0x0012, 0x03 }, 236 { 0x001f, 0x02 }, { 0x0020, 0x02 }, 237 { 0x0031, 0x48 }, { 0x0032, 0x48 }, 238 { 0x0073, 0x80 }, { 0x0074, 0x07 }, 239 { 0x007b, 0xd0 }, { 0x007c, 0x02 }, 240 { 0x0079, 0x0a }, 241 { 0x0429, 0x0a }, { 0x045d, 0x01 }, 242 { 0x0529, 0x0a }, { 0x055d, 0x01 }, 243 { 0x060a, 0xb0 }, { 0x060b, 0xff }, { 0x060c, 0xff }, 244 { 0x0644, 0x90 }, { 0x0646, 0xd2 }, 245 }; 246 int i; 247 248 for (i = 0; i < ARRAY_SIZE(regs); i++) 249 rohm_deserializer_write(rl82, regs[i].reg, regs[i].def); 250 251 /* TP_INT - GPIO4 */ 252 rohm_deserializer_write(rl82, 0x0063, 0x08); 253 rohm_deserializer_write(rl82, 0x042f, 0x06); 254 255 /* TP_RST - GPIO3 */ 256 rohm_deserializer_write(rl82, 0x0060, 0x00); 257 rohm_deserializer_write(rl82, 0x0061, 0x00); 258 259 /* LCD_BIAS_EN - GPIO2 */ 260 rohm_deserializer_write(rl82, 0x005d, 0x00); 261 rohm_deserializer_write(rl82, 0x005e, 0x01); 262 mdelay(6); 263 264 return 0; 265 } 266 267 static int touch_china_v123awf3_r1_unprepare(struct bu18rl82 *rl82) 268 { 269 /* LCD_BIAS_EN - GPIO2 */ 270 rohm_deserializer_write(rl82, 0x005e, 0x00); 271 272 return 0; 273 } 274 275 static int touch_china_v123awf3_r1_enable(struct bu18rl82 *rl82) 276 { 277 rohm_deserializer_write(rl82, 0x0091, 0x03); 278 rohm_deserializer_write(rl82, 0x0090, 0x01); 279 280 /* RSEX - GPIO5 */ 281 rohm_deserializer_write(rl82, 0x0066, 0x00); 282 rohm_deserializer_write(rl82, 0x0067, 0x01); 283 /* TP_RST - GPIO3 */ 284 rohm_deserializer_write(rl82, 0x0060, 0x00); 285 rohm_deserializer_write(rl82, 0x0061, 0x01); 286 mdelay(20); 287 /* LCD_PON - GPIO1 */ 288 rohm_deserializer_write(rl82, 0x005a, 0x00); 289 rohm_deserializer_write(rl82, 0x005b, 0x01); 290 291 return 0; 292 } 293 294 static int touch_china_v123awf3_r1_disable(struct bu18rl82 *rl82) 295 { 296 rohm_deserializer_write(rl82, 0x0090, 0x00); 297 rohm_deserializer_write(rl82, 0x0091, 0x00); 298 299 /* LCD_PON - GPIO1 */ 300 rohm_deserializer_write(rl82, 0x005b, 0x00); 301 mdelay(100); 302 /* TP_RST - GPIO3 */ 303 rohm_deserializer_write(rl82, 0x0061, 0x00); 304 /* RSEX - GPIO5 */ 305 rohm_deserializer_write(rl82, 0x0067, 0x00); 306 307 return 0; 308 } 309 310 static int touch_china_v123awf3_r1_backlight_enable(struct bu18rl82 *rl82) 311 { 312 /* BL_PWM - GPIO0 */ 313 rohm_deserializer_write(rl82, 0x0057, 0x00); 314 rohm_deserializer_write(rl82, 0x0058, 0x02); 315 316 return 0; 317 } 318 319 static int touch_china_v123awf3_r1_backlight_disable(struct bu18rl82 *rl82) 320 { 321 /* BL_PWM - GPIO0 */ 322 rohm_deserializer_write(rl82, 0x0058, 0x00); 323 324 return 0; 325 } 326 327 static const struct panel_desc touch_china_v123awf3_r1 = { 328 .name = "touch-china,v123awf3-r1", 329 .prepare = touch_china_v123awf3_r1_prepare, 330 .unprepare = touch_china_v123awf3_r1_unprepare, 331 .enable = touch_china_v123awf3_r1_enable, 332 .disable = touch_china_v123awf3_r1_disable, 333 .backlight_enable = touch_china_v123awf3_r1_backlight_enable, 334 .backlight_disable = touch_china_v123awf3_r1_backlight_disable, 335 }; 336 337 static const struct udevice_id bu18rl82_of_match[] = { 338 { .compatible = "csot,mg1561b01", .data = (ulong)&csot_mg1561b01 }, 339 { .compatible = "touch-china,v123awf3-r1", .data = (ulong)&touch_china_v123awf3_r1 }, 340 {} 341 }; 342 343 U_BOOT_DRIVER(panel_rohm_bu18rl82) = { 344 .name = "panel-rohm-bu18rl82", 345 .id = UCLASS_PANEL, 346 .of_match = bu18rl82_of_match, 347 .probe = bu18rl82_probe, 348 .priv_auto_alloc_size = sizeof(struct bu18rl82), 349 }; 350