1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * Copyright (c) 2018 MediaTek Inc. 4 * Author: Jitao Shi <jitao.shi@mediatek.com> 5 */ 6 7 #include <linux/delay.h> 8 #include <linux/gpio/consumer.h> 9 #include <linux/module.h> 10 #include <linux/of.h> 11 #include <linux/of_device.h> 12 #include <linux/regulator/consumer.h> 13 14 #include <drm/drm_crtc.h> 15 #include <drm/drm_mipi_dsi.h> 16 #include <drm/drm_panel.h> 17 18 #include <video/mipi_display.h> 19 20 struct panel_desc { 21 const struct drm_display_mode *modes; 22 unsigned int bpc; 23 24 /** 25 * @width_mm: width of the panel's active display area 26 * @height_mm: height of the panel's active display area 27 */ 28 struct { 29 unsigned int width_mm; 30 unsigned int height_mm; 31 } size; 32 33 unsigned long mode_flags; 34 enum mipi_dsi_pixel_format format; 35 const struct panel_init_cmd *init_cmds; 36 unsigned int lanes; 37 bool discharge_on_disable; 38 }; 39 40 struct boe_panel { 41 struct drm_panel base; 42 struct mipi_dsi_device *dsi; 43 44 const struct panel_desc *desc; 45 46 struct regulator *pp1800; 47 struct regulator *avee; 48 struct regulator *avdd; 49 struct gpio_desc *enable_gpio; 50 51 bool prepared; 52 }; 53 54 enum dsi_cmd_type { 55 INIT_DCS_CMD, 56 DELAY_CMD, 57 }; 58 59 struct panel_init_cmd { 60 enum dsi_cmd_type type; 61 size_t len; 62 const char *data; 63 }; 64 65 #define _INIT_DCS_CMD(...) { \ 66 .type = INIT_DCS_CMD, \ 67 .len = sizeof((char[]){__VA_ARGS__}), \ 68 .data = (char[]){__VA_ARGS__} } 69 70 #define _INIT_DELAY_CMD(...) { \ 71 .type = DELAY_CMD,\ 72 .len = sizeof((char[]){__VA_ARGS__}), \ 73 .data = (char[]){__VA_ARGS__} } 74 75 static const struct panel_init_cmd boe_init_cmd[] = { 76 _INIT_DELAY_CMD(24), 77 _INIT_DCS_CMD(0xB0, 0x05), 78 _INIT_DCS_CMD(0xB1, 0xE5), 79 _INIT_DCS_CMD(0xB3, 0x52), 80 _INIT_DCS_CMD(0xB0, 0x00), 81 _INIT_DCS_CMD(0xB3, 0x88), 82 _INIT_DCS_CMD(0xB0, 0x04), 83 _INIT_DCS_CMD(0xB8, 0x00), 84 _INIT_DCS_CMD(0xB0, 0x00), 85 _INIT_DCS_CMD(0xB6, 0x03), 86 _INIT_DCS_CMD(0xBA, 0x8B), 87 _INIT_DCS_CMD(0xBF, 0x1A), 88 _INIT_DCS_CMD(0xC0, 0x0F), 89 _INIT_DCS_CMD(0xC2, 0x0C), 90 _INIT_DCS_CMD(0xC3, 0x02), 91 _INIT_DCS_CMD(0xC4, 0x0C), 92 _INIT_DCS_CMD(0xC5, 0x02), 93 _INIT_DCS_CMD(0xB0, 0x01), 94 _INIT_DCS_CMD(0xE0, 0x26), 95 _INIT_DCS_CMD(0xE1, 0x26), 96 _INIT_DCS_CMD(0xDC, 0x00), 97 _INIT_DCS_CMD(0xDD, 0x00), 98 _INIT_DCS_CMD(0xCC, 0x26), 99 _INIT_DCS_CMD(0xCD, 0x26), 100 _INIT_DCS_CMD(0xC8, 0x00), 101 _INIT_DCS_CMD(0xC9, 0x00), 102 _INIT_DCS_CMD(0xD2, 0x03), 103 _INIT_DCS_CMD(0xD3, 0x03), 104 _INIT_DCS_CMD(0xE6, 0x04), 105 _INIT_DCS_CMD(0xE7, 0x04), 106 _INIT_DCS_CMD(0xC4, 0x09), 107 _INIT_DCS_CMD(0xC5, 0x09), 108 _INIT_DCS_CMD(0xD8, 0x0A), 109 _INIT_DCS_CMD(0xD9, 0x0A), 110 _INIT_DCS_CMD(0xC2, 0x0B), 111 _INIT_DCS_CMD(0xC3, 0x0B), 112 _INIT_DCS_CMD(0xD6, 0x0C), 113 _INIT_DCS_CMD(0xD7, 0x0C), 114 _INIT_DCS_CMD(0xC0, 0x05), 115 _INIT_DCS_CMD(0xC1, 0x05), 116 _INIT_DCS_CMD(0xD4, 0x06), 117 _INIT_DCS_CMD(0xD5, 0x06), 118 _INIT_DCS_CMD(0xCA, 0x07), 119 _INIT_DCS_CMD(0xCB, 0x07), 120 _INIT_DCS_CMD(0xDE, 0x08), 121 _INIT_DCS_CMD(0xDF, 0x08), 122 _INIT_DCS_CMD(0xB0, 0x02), 123 _INIT_DCS_CMD(0xC0, 0x00), 124 _INIT_DCS_CMD(0xC1, 0x0D), 125 _INIT_DCS_CMD(0xC2, 0x17), 126 _INIT_DCS_CMD(0xC3, 0x26), 127 _INIT_DCS_CMD(0xC4, 0x31), 128 _INIT_DCS_CMD(0xC5, 0x1C), 129 _INIT_DCS_CMD(0xC6, 0x2C), 130 _INIT_DCS_CMD(0xC7, 0x33), 131 _INIT_DCS_CMD(0xC8, 0x31), 132 _INIT_DCS_CMD(0xC9, 0x37), 133 _INIT_DCS_CMD(0xCA, 0x37), 134 _INIT_DCS_CMD(0xCB, 0x37), 135 _INIT_DCS_CMD(0xCC, 0x39), 136 _INIT_DCS_CMD(0xCD, 0x2E), 137 _INIT_DCS_CMD(0xCE, 0x2F), 138 _INIT_DCS_CMD(0xCF, 0x2F), 139 _INIT_DCS_CMD(0xD0, 0x07), 140 _INIT_DCS_CMD(0xD2, 0x00), 141 _INIT_DCS_CMD(0xD3, 0x0D), 142 _INIT_DCS_CMD(0xD4, 0x17), 143 _INIT_DCS_CMD(0xD5, 0x26), 144 _INIT_DCS_CMD(0xD6, 0x31), 145 _INIT_DCS_CMD(0xD7, 0x3F), 146 _INIT_DCS_CMD(0xD8, 0x3F), 147 _INIT_DCS_CMD(0xD9, 0x3F), 148 _INIT_DCS_CMD(0xDA, 0x3F), 149 _INIT_DCS_CMD(0xDB, 0x37), 150 _INIT_DCS_CMD(0xDC, 0x37), 151 _INIT_DCS_CMD(0xDD, 0x37), 152 _INIT_DCS_CMD(0xDE, 0x39), 153 _INIT_DCS_CMD(0xDF, 0x2E), 154 _INIT_DCS_CMD(0xE0, 0x2F), 155 _INIT_DCS_CMD(0xE1, 0x2F), 156 _INIT_DCS_CMD(0xE2, 0x07), 157 _INIT_DCS_CMD(0xB0, 0x03), 158 _INIT_DCS_CMD(0xC8, 0x0B), 159 _INIT_DCS_CMD(0xC9, 0x07), 160 _INIT_DCS_CMD(0xC3, 0x00), 161 _INIT_DCS_CMD(0xE7, 0x00), 162 _INIT_DCS_CMD(0xC5, 0x2A), 163 _INIT_DCS_CMD(0xDE, 0x2A), 164 _INIT_DCS_CMD(0xCA, 0x43), 165 _INIT_DCS_CMD(0xC9, 0x07), 166 _INIT_DCS_CMD(0xE4, 0xC0), 167 _INIT_DCS_CMD(0xE5, 0x0D), 168 _INIT_DCS_CMD(0xCB, 0x00), 169 _INIT_DCS_CMD(0xB0, 0x06), 170 _INIT_DCS_CMD(0xB8, 0xA5), 171 _INIT_DCS_CMD(0xC0, 0xA5), 172 _INIT_DCS_CMD(0xC7, 0x0F), 173 _INIT_DCS_CMD(0xD5, 0x32), 174 _INIT_DCS_CMD(0xB8, 0x00), 175 _INIT_DCS_CMD(0xC0, 0x00), 176 _INIT_DCS_CMD(0xBC, 0x00), 177 _INIT_DCS_CMD(0xB0, 0x07), 178 _INIT_DCS_CMD(0xB1, 0x00), 179 _INIT_DCS_CMD(0xB2, 0x02), 180 _INIT_DCS_CMD(0xB3, 0x0F), 181 _INIT_DCS_CMD(0xB4, 0x25), 182 _INIT_DCS_CMD(0xB5, 0x39), 183 _INIT_DCS_CMD(0xB6, 0x4E), 184 _INIT_DCS_CMD(0xB7, 0x72), 185 _INIT_DCS_CMD(0xB8, 0x97), 186 _INIT_DCS_CMD(0xB9, 0xDC), 187 _INIT_DCS_CMD(0xBA, 0x22), 188 _INIT_DCS_CMD(0xBB, 0xA4), 189 _INIT_DCS_CMD(0xBC, 0x2B), 190 _INIT_DCS_CMD(0xBD, 0x2F), 191 _INIT_DCS_CMD(0xBE, 0xA9), 192 _INIT_DCS_CMD(0xBF, 0x25), 193 _INIT_DCS_CMD(0xC0, 0x61), 194 _INIT_DCS_CMD(0xC1, 0x97), 195 _INIT_DCS_CMD(0xC2, 0xB2), 196 _INIT_DCS_CMD(0xC3, 0xCD), 197 _INIT_DCS_CMD(0xC4, 0xD9), 198 _INIT_DCS_CMD(0xC5, 0xE7), 199 _INIT_DCS_CMD(0xC6, 0xF4), 200 _INIT_DCS_CMD(0xC7, 0xFA), 201 _INIT_DCS_CMD(0xC8, 0xFC), 202 _INIT_DCS_CMD(0xC9, 0x00), 203 _INIT_DCS_CMD(0xCA, 0x00), 204 _INIT_DCS_CMD(0xCB, 0x16), 205 _INIT_DCS_CMD(0xCC, 0xAF), 206 _INIT_DCS_CMD(0xCD, 0xFF), 207 _INIT_DCS_CMD(0xCE, 0xFF), 208 _INIT_DCS_CMD(0xB0, 0x08), 209 _INIT_DCS_CMD(0xB1, 0x04), 210 _INIT_DCS_CMD(0xB2, 0x05), 211 _INIT_DCS_CMD(0xB3, 0x11), 212 _INIT_DCS_CMD(0xB4, 0x24), 213 _INIT_DCS_CMD(0xB5, 0x39), 214 _INIT_DCS_CMD(0xB6, 0x4F), 215 _INIT_DCS_CMD(0xB7, 0x72), 216 _INIT_DCS_CMD(0xB8, 0x98), 217 _INIT_DCS_CMD(0xB9, 0xDC), 218 _INIT_DCS_CMD(0xBA, 0x23), 219 _INIT_DCS_CMD(0xBB, 0xA6), 220 _INIT_DCS_CMD(0xBC, 0x2C), 221 _INIT_DCS_CMD(0xBD, 0x30), 222 _INIT_DCS_CMD(0xBE, 0xAA), 223 _INIT_DCS_CMD(0xBF, 0x26), 224 _INIT_DCS_CMD(0xC0, 0x62), 225 _INIT_DCS_CMD(0xC1, 0x9B), 226 _INIT_DCS_CMD(0xC2, 0xB5), 227 _INIT_DCS_CMD(0xC3, 0xCF), 228 _INIT_DCS_CMD(0xC4, 0xDB), 229 _INIT_DCS_CMD(0xC5, 0xE8), 230 _INIT_DCS_CMD(0xC6, 0xF5), 231 _INIT_DCS_CMD(0xC7, 0xFA), 232 _INIT_DCS_CMD(0xC8, 0xFC), 233 _INIT_DCS_CMD(0xC9, 0x00), 234 _INIT_DCS_CMD(0xCA, 0x00), 235 _INIT_DCS_CMD(0xCB, 0x16), 236 _INIT_DCS_CMD(0xCC, 0xAF), 237 _INIT_DCS_CMD(0xCD, 0xFF), 238 _INIT_DCS_CMD(0xCE, 0xFF), 239 _INIT_DCS_CMD(0xB0, 0x09), 240 _INIT_DCS_CMD(0xB1, 0x04), 241 _INIT_DCS_CMD(0xB2, 0x02), 242 _INIT_DCS_CMD(0xB3, 0x16), 243 _INIT_DCS_CMD(0xB4, 0x24), 244 _INIT_DCS_CMD(0xB5, 0x3B), 245 _INIT_DCS_CMD(0xB6, 0x4F), 246 _INIT_DCS_CMD(0xB7, 0x73), 247 _INIT_DCS_CMD(0xB8, 0x99), 248 _INIT_DCS_CMD(0xB9, 0xE0), 249 _INIT_DCS_CMD(0xBA, 0x26), 250 _INIT_DCS_CMD(0xBB, 0xAD), 251 _INIT_DCS_CMD(0xBC, 0x36), 252 _INIT_DCS_CMD(0xBD, 0x3A), 253 _INIT_DCS_CMD(0xBE, 0xAE), 254 _INIT_DCS_CMD(0xBF, 0x2A), 255 _INIT_DCS_CMD(0xC0, 0x66), 256 _INIT_DCS_CMD(0xC1, 0x9E), 257 _INIT_DCS_CMD(0xC2, 0xB8), 258 _INIT_DCS_CMD(0xC3, 0xD1), 259 _INIT_DCS_CMD(0xC4, 0xDD), 260 _INIT_DCS_CMD(0xC5, 0xE9), 261 _INIT_DCS_CMD(0xC6, 0xF6), 262 _INIT_DCS_CMD(0xC7, 0xFA), 263 _INIT_DCS_CMD(0xC8, 0xFC), 264 _INIT_DCS_CMD(0xC9, 0x00), 265 _INIT_DCS_CMD(0xCA, 0x00), 266 _INIT_DCS_CMD(0xCB, 0x16), 267 _INIT_DCS_CMD(0xCC, 0xAF), 268 _INIT_DCS_CMD(0xCD, 0xFF), 269 _INIT_DCS_CMD(0xCE, 0xFF), 270 _INIT_DCS_CMD(0xB0, 0x0A), 271 _INIT_DCS_CMD(0xB1, 0x00), 272 _INIT_DCS_CMD(0xB2, 0x02), 273 _INIT_DCS_CMD(0xB3, 0x0F), 274 _INIT_DCS_CMD(0xB4, 0x25), 275 _INIT_DCS_CMD(0xB5, 0x39), 276 _INIT_DCS_CMD(0xB6, 0x4E), 277 _INIT_DCS_CMD(0xB7, 0x72), 278 _INIT_DCS_CMD(0xB8, 0x97), 279 _INIT_DCS_CMD(0xB9, 0xDC), 280 _INIT_DCS_CMD(0xBA, 0x22), 281 _INIT_DCS_CMD(0xBB, 0xA4), 282 _INIT_DCS_CMD(0xBC, 0x2B), 283 _INIT_DCS_CMD(0xBD, 0x2F), 284 _INIT_DCS_CMD(0xBE, 0xA9), 285 _INIT_DCS_CMD(0xBF, 0x25), 286 _INIT_DCS_CMD(0xC0, 0x61), 287 _INIT_DCS_CMD(0xC1, 0x97), 288 _INIT_DCS_CMD(0xC2, 0xB2), 289 _INIT_DCS_CMD(0xC3, 0xCD), 290 _INIT_DCS_CMD(0xC4, 0xD9), 291 _INIT_DCS_CMD(0xC5, 0xE7), 292 _INIT_DCS_CMD(0xC6, 0xF4), 293 _INIT_DCS_CMD(0xC7, 0xFA), 294 _INIT_DCS_CMD(0xC8, 0xFC), 295 _INIT_DCS_CMD(0xC9, 0x00), 296 _INIT_DCS_CMD(0xCA, 0x00), 297 _INIT_DCS_CMD(0xCB, 0x16), 298 _INIT_DCS_CMD(0xCC, 0xAF), 299 _INIT_DCS_CMD(0xCD, 0xFF), 300 _INIT_DCS_CMD(0xCE, 0xFF), 301 _INIT_DCS_CMD(0xB0, 0x0B), 302 _INIT_DCS_CMD(0xB1, 0x04), 303 _INIT_DCS_CMD(0xB2, 0x05), 304 _INIT_DCS_CMD(0xB3, 0x11), 305 _INIT_DCS_CMD(0xB4, 0x24), 306 _INIT_DCS_CMD(0xB5, 0x39), 307 _INIT_DCS_CMD(0xB6, 0x4F), 308 _INIT_DCS_CMD(0xB7, 0x72), 309 _INIT_DCS_CMD(0xB8, 0x98), 310 _INIT_DCS_CMD(0xB9, 0xDC), 311 _INIT_DCS_CMD(0xBA, 0x23), 312 _INIT_DCS_CMD(0xBB, 0xA6), 313 _INIT_DCS_CMD(0xBC, 0x2C), 314 _INIT_DCS_CMD(0xBD, 0x30), 315 _INIT_DCS_CMD(0xBE, 0xAA), 316 _INIT_DCS_CMD(0xBF, 0x26), 317 _INIT_DCS_CMD(0xC0, 0x62), 318 _INIT_DCS_CMD(0xC1, 0x9B), 319 _INIT_DCS_CMD(0xC2, 0xB5), 320 _INIT_DCS_CMD(0xC3, 0xCF), 321 _INIT_DCS_CMD(0xC4, 0xDB), 322 _INIT_DCS_CMD(0xC5, 0xE8), 323 _INIT_DCS_CMD(0xC6, 0xF5), 324 _INIT_DCS_CMD(0xC7, 0xFA), 325 _INIT_DCS_CMD(0xC8, 0xFC), 326 _INIT_DCS_CMD(0xC9, 0x00), 327 _INIT_DCS_CMD(0xCA, 0x00), 328 _INIT_DCS_CMD(0xCB, 0x16), 329 _INIT_DCS_CMD(0xCC, 0xAF), 330 _INIT_DCS_CMD(0xCD, 0xFF), 331 _INIT_DCS_CMD(0xCE, 0xFF), 332 _INIT_DCS_CMD(0xB0, 0x0C), 333 _INIT_DCS_CMD(0xB1, 0x04), 334 _INIT_DCS_CMD(0xB2, 0x02), 335 _INIT_DCS_CMD(0xB3, 0x16), 336 _INIT_DCS_CMD(0xB4, 0x24), 337 _INIT_DCS_CMD(0xB5, 0x3B), 338 _INIT_DCS_CMD(0xB6, 0x4F), 339 _INIT_DCS_CMD(0xB7, 0x73), 340 _INIT_DCS_CMD(0xB8, 0x99), 341 _INIT_DCS_CMD(0xB9, 0xE0), 342 _INIT_DCS_CMD(0xBA, 0x26), 343 _INIT_DCS_CMD(0xBB, 0xAD), 344 _INIT_DCS_CMD(0xBC, 0x36), 345 _INIT_DCS_CMD(0xBD, 0x3A), 346 _INIT_DCS_CMD(0xBE, 0xAE), 347 _INIT_DCS_CMD(0xBF, 0x2A), 348 _INIT_DCS_CMD(0xC0, 0x66), 349 _INIT_DCS_CMD(0xC1, 0x9E), 350 _INIT_DCS_CMD(0xC2, 0xB8), 351 _INIT_DCS_CMD(0xC3, 0xD1), 352 _INIT_DCS_CMD(0xC4, 0xDD), 353 _INIT_DCS_CMD(0xC5, 0xE9), 354 _INIT_DCS_CMD(0xC6, 0xF6), 355 _INIT_DCS_CMD(0xC7, 0xFA), 356 _INIT_DCS_CMD(0xC8, 0xFC), 357 _INIT_DCS_CMD(0xC9, 0x00), 358 _INIT_DCS_CMD(0xCA, 0x00), 359 _INIT_DCS_CMD(0xCB, 0x16), 360 _INIT_DCS_CMD(0xCC, 0xAF), 361 _INIT_DCS_CMD(0xCD, 0xFF), 362 _INIT_DCS_CMD(0xCE, 0xFF), 363 _INIT_DCS_CMD(0xB0, 0x00), 364 _INIT_DCS_CMD(0xB3, 0x08), 365 _INIT_DCS_CMD(0xB0, 0x04), 366 _INIT_DCS_CMD(0xB8, 0x68), 367 _INIT_DELAY_CMD(150), 368 {}, 369 }; 370 371 static const struct panel_init_cmd auo_kd101n80_45na_init_cmd[] = { 372 _INIT_DELAY_CMD(24), 373 _INIT_DCS_CMD(0x11), 374 _INIT_DELAY_CMD(120), 375 _INIT_DCS_CMD(0x29), 376 _INIT_DELAY_CMD(120), 377 {}, 378 }; 379 380 static const struct panel_init_cmd auo_b101uan08_3_init_cmd[] = { 381 _INIT_DELAY_CMD(24), 382 _INIT_DCS_CMD(0xB0, 0x01), 383 _INIT_DCS_CMD(0xC0, 0x48), 384 _INIT_DCS_CMD(0xC1, 0x48), 385 _INIT_DCS_CMD(0xC2, 0x47), 386 _INIT_DCS_CMD(0xC3, 0x47), 387 _INIT_DCS_CMD(0xC4, 0x46), 388 _INIT_DCS_CMD(0xC5, 0x46), 389 _INIT_DCS_CMD(0xC6, 0x45), 390 _INIT_DCS_CMD(0xC7, 0x45), 391 _INIT_DCS_CMD(0xC8, 0x64), 392 _INIT_DCS_CMD(0xC9, 0x64), 393 _INIT_DCS_CMD(0xCA, 0x4F), 394 _INIT_DCS_CMD(0xCB, 0x4F), 395 _INIT_DCS_CMD(0xCC, 0x40), 396 _INIT_DCS_CMD(0xCD, 0x40), 397 _INIT_DCS_CMD(0xCE, 0x66), 398 _INIT_DCS_CMD(0xCF, 0x66), 399 _INIT_DCS_CMD(0xD0, 0x4F), 400 _INIT_DCS_CMD(0xD1, 0x4F), 401 _INIT_DCS_CMD(0xD2, 0x41), 402 _INIT_DCS_CMD(0xD3, 0x41), 403 _INIT_DCS_CMD(0xD4, 0x48), 404 _INIT_DCS_CMD(0xD5, 0x48), 405 _INIT_DCS_CMD(0xD6, 0x47), 406 _INIT_DCS_CMD(0xD7, 0x47), 407 _INIT_DCS_CMD(0xD8, 0x46), 408 _INIT_DCS_CMD(0xD9, 0x46), 409 _INIT_DCS_CMD(0xDA, 0x45), 410 _INIT_DCS_CMD(0xDB, 0x45), 411 _INIT_DCS_CMD(0xDC, 0x64), 412 _INIT_DCS_CMD(0xDD, 0x64), 413 _INIT_DCS_CMD(0xDE, 0x4F), 414 _INIT_DCS_CMD(0xDF, 0x4F), 415 _INIT_DCS_CMD(0xE0, 0x40), 416 _INIT_DCS_CMD(0xE1, 0x40), 417 _INIT_DCS_CMD(0xE2, 0x66), 418 _INIT_DCS_CMD(0xE3, 0x66), 419 _INIT_DCS_CMD(0xE4, 0x4F), 420 _INIT_DCS_CMD(0xE5, 0x4F), 421 _INIT_DCS_CMD(0xE6, 0x41), 422 _INIT_DCS_CMD(0xE7, 0x41), 423 _INIT_DELAY_CMD(150), 424 {}, 425 }; 426 427 static inline struct boe_panel *to_boe_panel(struct drm_panel *panel) 428 { 429 return container_of(panel, struct boe_panel, base); 430 } 431 432 static int boe_panel_init_dcs_cmd(struct boe_panel *boe) 433 { 434 struct mipi_dsi_device *dsi = boe->dsi; 435 struct drm_panel *panel = &boe->base; 436 int i, err = 0; 437 438 if (boe->desc->init_cmds) { 439 const struct panel_init_cmd *init_cmds = boe->desc->init_cmds; 440 441 for (i = 0; init_cmds[i].len != 0; i++) { 442 const struct panel_init_cmd *cmd = &init_cmds[i]; 443 444 switch (cmd->type) { 445 case DELAY_CMD: 446 msleep(cmd->data[0]); 447 err = 0; 448 break; 449 450 case INIT_DCS_CMD: 451 err = mipi_dsi_dcs_write(dsi, cmd->data[0], 452 cmd->len <= 1 ? NULL : 453 &cmd->data[1], 454 cmd->len - 1); 455 break; 456 457 default: 458 err = -EINVAL; 459 } 460 461 if (err < 0) { 462 dev_err(panel->dev, 463 "failed to write command %u\n", i); 464 return err; 465 } 466 } 467 } 468 return 0; 469 } 470 471 static int boe_panel_enter_sleep_mode(struct boe_panel *boe) 472 { 473 struct mipi_dsi_device *dsi = boe->dsi; 474 int ret; 475 476 dsi->mode_flags &= ~MIPI_DSI_MODE_LPM; 477 478 ret = mipi_dsi_dcs_set_display_off(dsi); 479 if (ret < 0) 480 return ret; 481 482 ret = mipi_dsi_dcs_enter_sleep_mode(dsi); 483 if (ret < 0) 484 return ret; 485 486 return 0; 487 } 488 489 static int boe_panel_unprepare(struct drm_panel *panel) 490 { 491 struct boe_panel *boe = to_boe_panel(panel); 492 int ret; 493 494 if (!boe->prepared) 495 return 0; 496 497 ret = boe_panel_enter_sleep_mode(boe); 498 if (ret < 0) { 499 dev_err(panel->dev, "failed to set panel off: %d\n", ret); 500 return ret; 501 } 502 503 msleep(150); 504 505 if (boe->desc->discharge_on_disable) { 506 regulator_disable(boe->avee); 507 regulator_disable(boe->avdd); 508 usleep_range(5000, 7000); 509 gpiod_set_value(boe->enable_gpio, 0); 510 usleep_range(5000, 7000); 511 regulator_disable(boe->pp1800); 512 } else { 513 gpiod_set_value(boe->enable_gpio, 0); 514 usleep_range(500, 1000); 515 regulator_disable(boe->avee); 516 regulator_disable(boe->avdd); 517 usleep_range(5000, 7000); 518 regulator_disable(boe->pp1800); 519 } 520 521 boe->prepared = false; 522 523 return 0; 524 } 525 526 static int boe_panel_prepare(struct drm_panel *panel) 527 { 528 struct boe_panel *boe = to_boe_panel(panel); 529 int ret; 530 531 if (boe->prepared) 532 return 0; 533 534 gpiod_set_value(boe->enable_gpio, 0); 535 usleep_range(1000, 1500); 536 537 ret = regulator_enable(boe->pp1800); 538 if (ret < 0) 539 return ret; 540 541 usleep_range(3000, 5000); 542 543 ret = regulator_enable(boe->avdd); 544 if (ret < 0) 545 goto poweroff1v8; 546 ret = regulator_enable(boe->avee); 547 if (ret < 0) 548 goto poweroffavdd; 549 550 usleep_range(5000, 10000); 551 552 gpiod_set_value(boe->enable_gpio, 1); 553 usleep_range(1000, 2000); 554 gpiod_set_value(boe->enable_gpio, 0); 555 usleep_range(1000, 2000); 556 gpiod_set_value(boe->enable_gpio, 1); 557 usleep_range(6000, 10000); 558 559 ret = boe_panel_init_dcs_cmd(boe); 560 if (ret < 0) { 561 dev_err(panel->dev, "failed to init panel: %d\n", ret); 562 goto poweroff; 563 } 564 565 boe->prepared = true; 566 567 return 0; 568 569 poweroff: 570 regulator_disable(boe->avee); 571 poweroffavdd: 572 regulator_disable(boe->avdd); 573 poweroff1v8: 574 usleep_range(5000, 7000); 575 regulator_disable(boe->pp1800); 576 gpiod_set_value(boe->enable_gpio, 0); 577 578 return ret; 579 } 580 581 static int boe_panel_enable(struct drm_panel *panel) 582 { 583 msleep(130); 584 return 0; 585 } 586 587 static const struct drm_display_mode boe_tv101wum_nl6_default_mode = { 588 .clock = 159425, 589 .hdisplay = 1200, 590 .hsync_start = 1200 + 100, 591 .hsync_end = 1200 + 100 + 40, 592 .htotal = 1200 + 100 + 40 + 24, 593 .vdisplay = 1920, 594 .vsync_start = 1920 + 10, 595 .vsync_end = 1920 + 10 + 14, 596 .vtotal = 1920 + 10 + 14 + 4, 597 }; 598 599 static const struct panel_desc boe_tv101wum_nl6_desc = { 600 .modes = &boe_tv101wum_nl6_default_mode, 601 .bpc = 8, 602 .size = { 603 .width_mm = 135, 604 .height_mm = 216, 605 }, 606 .lanes = 4, 607 .format = MIPI_DSI_FMT_RGB888, 608 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 609 MIPI_DSI_MODE_LPM, 610 .init_cmds = boe_init_cmd, 611 .discharge_on_disable = false, 612 }; 613 614 static const struct drm_display_mode auo_kd101n80_45na_default_mode = { 615 .clock = 157000, 616 .hdisplay = 1200, 617 .hsync_start = 1200 + 60, 618 .hsync_end = 1200 + 60 + 24, 619 .htotal = 1200 + 60 + 24 + 56, 620 .vdisplay = 1920, 621 .vsync_start = 1920 + 16, 622 .vsync_end = 1920 + 16 + 4, 623 .vtotal = 1920 + 16 + 4 + 16, 624 }; 625 626 static const struct panel_desc auo_kd101n80_45na_desc = { 627 .modes = &auo_kd101n80_45na_default_mode, 628 .bpc = 8, 629 .size = { 630 .width_mm = 135, 631 .height_mm = 216, 632 }, 633 .lanes = 4, 634 .format = MIPI_DSI_FMT_RGB888, 635 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 636 MIPI_DSI_MODE_LPM, 637 .init_cmds = auo_kd101n80_45na_init_cmd, 638 .discharge_on_disable = true, 639 }; 640 641 static const struct drm_display_mode boe_tv101wum_n53_default_mode = { 642 .clock = 159916, 643 .hdisplay = 1200, 644 .hsync_start = 1200 + 80, 645 .hsync_end = 1200 + 80 + 24, 646 .htotal = 1200 + 80 + 24 + 60, 647 .vdisplay = 1920, 648 .vsync_start = 1920 + 20, 649 .vsync_end = 1920 + 20 + 4, 650 .vtotal = 1920 + 20 + 4 + 10, 651 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 652 }; 653 654 static const struct panel_desc boe_tv101wum_n53_desc = { 655 .modes = &boe_tv101wum_n53_default_mode, 656 .bpc = 8, 657 .size = { 658 .width_mm = 135, 659 .height_mm = 216, 660 }, 661 .lanes = 4, 662 .format = MIPI_DSI_FMT_RGB888, 663 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 664 MIPI_DSI_MODE_LPM, 665 .init_cmds = boe_init_cmd, 666 }; 667 668 static const struct drm_display_mode auo_b101uan08_3_default_mode = { 669 .clock = 159667, 670 .hdisplay = 1200, 671 .hsync_start = 1200 + 60, 672 .hsync_end = 1200 + 60 + 4, 673 .htotal = 1200 + 60 + 4 + 80, 674 .vdisplay = 1920, 675 .vsync_start = 1920 + 34, 676 .vsync_end = 1920 + 34 + 2, 677 .vtotal = 1920 + 34 + 2 + 24, 678 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 679 }; 680 681 static const struct panel_desc auo_b101uan08_3_desc = { 682 .modes = &auo_b101uan08_3_default_mode, 683 .bpc = 8, 684 .size = { 685 .width_mm = 135, 686 .height_mm = 216, 687 }, 688 .lanes = 4, 689 .format = MIPI_DSI_FMT_RGB888, 690 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 691 MIPI_DSI_MODE_LPM, 692 .init_cmds = auo_b101uan08_3_init_cmd, 693 }; 694 695 static const struct drm_display_mode boe_tv105wum_nw0_default_mode = { 696 .clock = 159916, 697 .hdisplay = 1200, 698 .hsync_start = 1200 + 80, 699 .hsync_end = 1200 + 80 + 24, 700 .htotal = 1200 + 80 + 24 + 60, 701 .vdisplay = 1920, 702 .vsync_start = 1920 + 20, 703 .vsync_end = 1920 + 20 + 4, 704 .vtotal = 1920 + 20 + 4 + 10, 705 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 706 }; 707 708 static const struct panel_desc boe_tv105wum_nw0_desc = { 709 .modes = &boe_tv105wum_nw0_default_mode, 710 .bpc = 8, 711 .size = { 712 .width_mm = 141, 713 .height_mm = 226, 714 }, 715 .lanes = 4, 716 .format = MIPI_DSI_FMT_RGB888, 717 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 718 MIPI_DSI_MODE_LPM, 719 .init_cmds = boe_init_cmd, 720 }; 721 722 static int boe_panel_get_modes(struct drm_panel *panel, 723 struct drm_connector *connector) 724 { 725 struct boe_panel *boe = to_boe_panel(panel); 726 const struct drm_display_mode *m = boe->desc->modes; 727 struct drm_display_mode *mode; 728 729 mode = drm_mode_duplicate(connector->dev, m); 730 if (!mode) { 731 dev_err(panel->dev, "failed to add mode %ux%u@%u\n", 732 m->hdisplay, m->vdisplay, drm_mode_vrefresh(m)); 733 return -ENOMEM; 734 } 735 736 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 737 drm_mode_set_name(mode); 738 drm_mode_probed_add(connector, mode); 739 740 connector->display_info.width_mm = boe->desc->size.width_mm; 741 connector->display_info.height_mm = boe->desc->size.height_mm; 742 connector->display_info.bpc = boe->desc->bpc; 743 744 return 1; 745 } 746 747 static const struct drm_panel_funcs boe_panel_funcs = { 748 .unprepare = boe_panel_unprepare, 749 .prepare = boe_panel_prepare, 750 .enable = boe_panel_enable, 751 .get_modes = boe_panel_get_modes, 752 }; 753 754 static int boe_panel_add(struct boe_panel *boe) 755 { 756 struct device *dev = &boe->dsi->dev; 757 int err; 758 759 boe->avdd = devm_regulator_get(dev, "avdd"); 760 if (IS_ERR(boe->avdd)) 761 return PTR_ERR(boe->avdd); 762 763 boe->avee = devm_regulator_get(dev, "avee"); 764 if (IS_ERR(boe->avee)) 765 return PTR_ERR(boe->avee); 766 767 boe->pp1800 = devm_regulator_get(dev, "pp1800"); 768 if (IS_ERR(boe->pp1800)) 769 return PTR_ERR(boe->pp1800); 770 771 boe->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 772 if (IS_ERR(boe->enable_gpio)) { 773 dev_err(dev, "cannot get reset-gpios %ld\n", 774 PTR_ERR(boe->enable_gpio)); 775 return PTR_ERR(boe->enable_gpio); 776 } 777 778 gpiod_set_value(boe->enable_gpio, 0); 779 780 drm_panel_init(&boe->base, dev, &boe_panel_funcs, 781 DRM_MODE_CONNECTOR_DSI); 782 783 err = drm_panel_of_backlight(&boe->base); 784 if (err) 785 return err; 786 787 boe->base.funcs = &boe_panel_funcs; 788 boe->base.dev = &boe->dsi->dev; 789 790 return drm_panel_add(&boe->base); 791 } 792 793 static int boe_panel_probe(struct mipi_dsi_device *dsi) 794 { 795 struct boe_panel *boe; 796 int ret; 797 const struct panel_desc *desc; 798 799 boe = devm_kzalloc(&dsi->dev, sizeof(*boe), GFP_KERNEL); 800 if (!boe) 801 return -ENOMEM; 802 803 desc = of_device_get_match_data(&dsi->dev); 804 dsi->lanes = desc->lanes; 805 dsi->format = desc->format; 806 dsi->mode_flags = desc->mode_flags; 807 boe->desc = desc; 808 boe->dsi = dsi; 809 ret = boe_panel_add(boe); 810 if (ret < 0) 811 return ret; 812 813 mipi_dsi_set_drvdata(dsi, boe); 814 815 ret = mipi_dsi_attach(dsi); 816 if (ret) 817 drm_panel_remove(&boe->base); 818 819 return ret; 820 } 821 822 static void boe_panel_shutdown(struct mipi_dsi_device *dsi) 823 { 824 struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); 825 826 drm_panel_disable(&boe->base); 827 drm_panel_unprepare(&boe->base); 828 } 829 830 static int boe_panel_remove(struct mipi_dsi_device *dsi) 831 { 832 struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); 833 int ret; 834 835 boe_panel_shutdown(dsi); 836 837 ret = mipi_dsi_detach(dsi); 838 if (ret < 0) 839 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); 840 841 if (boe->base.dev) 842 drm_panel_remove(&boe->base); 843 844 return 0; 845 } 846 847 static const struct of_device_id boe_of_match[] = { 848 { .compatible = "boe,tv101wum-nl6", 849 .data = &boe_tv101wum_nl6_desc 850 }, 851 { .compatible = "auo,kd101n80-45na", 852 .data = &auo_kd101n80_45na_desc 853 }, 854 { .compatible = "boe,tv101wum-n53", 855 .data = &boe_tv101wum_n53_desc 856 }, 857 { .compatible = "auo,b101uan08.3", 858 .data = &auo_b101uan08_3_desc 859 }, 860 { .compatible = "boe,tv105wum-nw0", 861 .data = &boe_tv105wum_nw0_desc 862 }, 863 { /* sentinel */ } 864 }; 865 MODULE_DEVICE_TABLE(of, boe_of_match); 866 867 static struct mipi_dsi_driver boe_panel_driver = { 868 .driver = { 869 .name = "panel-boe-tv101wum-nl6", 870 .of_match_table = boe_of_match, 871 }, 872 .probe = boe_panel_probe, 873 .remove = boe_panel_remove, 874 .shutdown = boe_panel_shutdown, 875 }; 876 module_mipi_dsi_driver(boe_panel_driver); 877 878 MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>"); 879 MODULE_DESCRIPTION("BOE tv101wum-nl6 1200x1920 video mode panel driver"); 880 MODULE_LICENSE("GPL v2"); 881