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 .vrefresh = 60, 598 }; 599 600 static const struct panel_desc boe_tv101wum_nl6_desc = { 601 .modes = &boe_tv101wum_nl6_default_mode, 602 .bpc = 8, 603 .size = { 604 .width_mm = 135, 605 .height_mm = 216, 606 }, 607 .lanes = 4, 608 .format = MIPI_DSI_FMT_RGB888, 609 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 610 MIPI_DSI_MODE_LPM, 611 .init_cmds = boe_init_cmd, 612 .discharge_on_disable = false, 613 }; 614 615 static const struct drm_display_mode auo_kd101n80_45na_default_mode = { 616 .clock = 157000, 617 .hdisplay = 1200, 618 .hsync_start = 1200 + 80, 619 .hsync_end = 1200 + 80 + 24, 620 .htotal = 1200 + 80 + 24 + 36, 621 .vdisplay = 1920, 622 .vsync_start = 1920 + 16, 623 .vsync_end = 1920 + 16 + 4, 624 .vtotal = 1920 + 16 + 4 + 16, 625 .vrefresh = 60, 626 }; 627 628 static const struct panel_desc auo_kd101n80_45na_desc = { 629 .modes = &auo_kd101n80_45na_default_mode, 630 .bpc = 8, 631 .size = { 632 .width_mm = 135, 633 .height_mm = 216, 634 }, 635 .lanes = 4, 636 .format = MIPI_DSI_FMT_RGB888, 637 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 638 MIPI_DSI_MODE_LPM, 639 .init_cmds = auo_kd101n80_45na_init_cmd, 640 .discharge_on_disable = true, 641 }; 642 643 static const struct drm_display_mode boe_tv101wum_n53_default_mode = { 644 .clock = 159916, 645 .hdisplay = 1200, 646 .hsync_start = 1200 + 80, 647 .hsync_end = 1200 + 80 + 24, 648 .htotal = 1200 + 80 + 24 + 60, 649 .vdisplay = 1920, 650 .vsync_start = 1920 + 20, 651 .vsync_end = 1920 + 20 + 4, 652 .vtotal = 1920 + 20 + 4 + 10, 653 .vrefresh = 60, 654 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 655 }; 656 657 static const struct panel_desc boe_tv101wum_n53_desc = { 658 .modes = &boe_tv101wum_n53_default_mode, 659 .bpc = 8, 660 .size = { 661 .width_mm = 135, 662 .height_mm = 216, 663 }, 664 .lanes = 4, 665 .format = MIPI_DSI_FMT_RGB888, 666 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 667 MIPI_DSI_MODE_LPM, 668 .init_cmds = boe_init_cmd, 669 }; 670 671 static const struct drm_display_mode auo_b101uan08_3_default_mode = { 672 .clock = 159667, 673 .hdisplay = 1200, 674 .hsync_start = 1200 + 60, 675 .hsync_end = 1200 + 60 + 4, 676 .htotal = 1200 + 60 + 4 + 80, 677 .vdisplay = 1920, 678 .vsync_start = 1920 + 34, 679 .vsync_end = 1920 + 34 + 2, 680 .vtotal = 1920 + 34 + 2 + 24, 681 .vrefresh = 60, 682 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 683 }; 684 685 static const struct panel_desc auo_b101uan08_3_desc = { 686 .modes = &auo_b101uan08_3_default_mode, 687 .bpc = 8, 688 .size = { 689 .width_mm = 135, 690 .height_mm = 216, 691 }, 692 .lanes = 4, 693 .format = MIPI_DSI_FMT_RGB888, 694 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 695 MIPI_DSI_MODE_LPM, 696 .init_cmds = auo_b101uan08_3_init_cmd, 697 }; 698 699 static const struct drm_display_mode boe_tv105wum_nw0_default_mode = { 700 .clock = 159916, 701 .hdisplay = 1200, 702 .hsync_start = 1200 + 80, 703 .hsync_end = 1200 + 80 + 24, 704 .htotal = 1200 + 80 + 24 + 60, 705 .vdisplay = 1920, 706 .vsync_start = 1920 + 20, 707 .vsync_end = 1920 + 20 + 4, 708 .vtotal = 1920 + 20 + 4 + 10, 709 .vrefresh = 60, 710 .type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED, 711 }; 712 713 static const struct panel_desc boe_tv105wum_nw0_desc = { 714 .modes = &boe_tv105wum_nw0_default_mode, 715 .bpc = 8, 716 .size = { 717 .width_mm = 141, 718 .height_mm = 226, 719 }, 720 .lanes = 4, 721 .format = MIPI_DSI_FMT_RGB888, 722 .mode_flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | 723 MIPI_DSI_MODE_LPM, 724 .init_cmds = boe_init_cmd, 725 }; 726 727 static int boe_panel_get_modes(struct drm_panel *panel, 728 struct drm_connector *connector) 729 { 730 struct boe_panel *boe = to_boe_panel(panel); 731 const struct drm_display_mode *m = boe->desc->modes; 732 struct drm_display_mode *mode; 733 734 mode = drm_mode_duplicate(connector->dev, m); 735 if (!mode) { 736 dev_err(panel->dev, "failed to add mode %ux%u@%u\n", 737 m->hdisplay, m->vdisplay, m->vrefresh); 738 return -ENOMEM; 739 } 740 741 mode->type = DRM_MODE_TYPE_DRIVER | DRM_MODE_TYPE_PREFERRED; 742 drm_mode_set_name(mode); 743 drm_mode_probed_add(connector, mode); 744 745 connector->display_info.width_mm = boe->desc->size.width_mm; 746 connector->display_info.height_mm = boe->desc->size.height_mm; 747 connector->display_info.bpc = boe->desc->bpc; 748 749 return 1; 750 } 751 752 static const struct drm_panel_funcs boe_panel_funcs = { 753 .unprepare = boe_panel_unprepare, 754 .prepare = boe_panel_prepare, 755 .enable = boe_panel_enable, 756 .get_modes = boe_panel_get_modes, 757 }; 758 759 static int boe_panel_add(struct boe_panel *boe) 760 { 761 struct device *dev = &boe->dsi->dev; 762 int err; 763 764 boe->avdd = devm_regulator_get(dev, "avdd"); 765 if (IS_ERR(boe->avdd)) 766 return PTR_ERR(boe->avdd); 767 768 boe->avee = devm_regulator_get(dev, "avee"); 769 if (IS_ERR(boe->avee)) 770 return PTR_ERR(boe->avee); 771 772 boe->pp1800 = devm_regulator_get(dev, "pp1800"); 773 if (IS_ERR(boe->pp1800)) 774 return PTR_ERR(boe->pp1800); 775 776 boe->enable_gpio = devm_gpiod_get(dev, "enable", GPIOD_OUT_LOW); 777 if (IS_ERR(boe->enable_gpio)) { 778 dev_err(dev, "cannot get reset-gpios %ld\n", 779 PTR_ERR(boe->enable_gpio)); 780 return PTR_ERR(boe->enable_gpio); 781 } 782 783 gpiod_set_value(boe->enable_gpio, 0); 784 785 drm_panel_init(&boe->base, dev, &boe_panel_funcs, 786 DRM_MODE_CONNECTOR_DSI); 787 788 err = drm_panel_of_backlight(&boe->base); 789 if (err) 790 return err; 791 792 boe->base.funcs = &boe_panel_funcs; 793 boe->base.dev = &boe->dsi->dev; 794 795 return drm_panel_add(&boe->base); 796 } 797 798 static int boe_panel_probe(struct mipi_dsi_device *dsi) 799 { 800 struct boe_panel *boe; 801 int ret; 802 const struct panel_desc *desc; 803 804 boe = devm_kzalloc(&dsi->dev, sizeof(*boe), GFP_KERNEL); 805 if (!boe) 806 return -ENOMEM; 807 808 desc = of_device_get_match_data(&dsi->dev); 809 dsi->lanes = desc->lanes; 810 dsi->format = desc->format; 811 dsi->mode_flags = desc->mode_flags; 812 boe->desc = desc; 813 boe->dsi = dsi; 814 ret = boe_panel_add(boe); 815 if (ret < 0) 816 return ret; 817 818 mipi_dsi_set_drvdata(dsi, boe); 819 820 ret = mipi_dsi_attach(dsi); 821 if (ret) 822 drm_panel_remove(&boe->base); 823 824 return ret; 825 } 826 827 static void boe_panel_shutdown(struct mipi_dsi_device *dsi) 828 { 829 struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); 830 831 drm_panel_disable(&boe->base); 832 drm_panel_unprepare(&boe->base); 833 } 834 835 static int boe_panel_remove(struct mipi_dsi_device *dsi) 836 { 837 struct boe_panel *boe = mipi_dsi_get_drvdata(dsi); 838 int ret; 839 840 boe_panel_shutdown(dsi); 841 842 ret = mipi_dsi_detach(dsi); 843 if (ret < 0) 844 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", ret); 845 846 if (boe->base.dev) 847 drm_panel_remove(&boe->base); 848 849 return 0; 850 } 851 852 static const struct of_device_id boe_of_match[] = { 853 { .compatible = "boe,tv101wum-nl6", 854 .data = &boe_tv101wum_nl6_desc 855 }, 856 { .compatible = "auo,kd101n80-45na", 857 .data = &auo_kd101n80_45na_desc 858 }, 859 { .compatible = "boe,tv101wum-n53", 860 .data = &boe_tv101wum_n53_desc 861 }, 862 { .compatible = "auo,b101uan08.3", 863 .data = &auo_b101uan08_3_desc 864 }, 865 { .compatible = "boe,tv105wum-nw0", 866 .data = &boe_tv105wum_nw0_desc 867 }, 868 { /* sentinel */ } 869 }; 870 MODULE_DEVICE_TABLE(of, boe_of_match); 871 872 static struct mipi_dsi_driver boe_panel_driver = { 873 .driver = { 874 .name = "panel-boe-tv101wum-nl6", 875 .of_match_table = boe_of_match, 876 }, 877 .probe = boe_panel_probe, 878 .remove = boe_panel_remove, 879 .shutdown = boe_panel_shutdown, 880 }; 881 module_mipi_dsi_driver(boe_panel_driver); 882 883 MODULE_AUTHOR("Jitao Shi <jitao.shi@mediatek.com>"); 884 MODULE_DESCRIPTION("BOE tv101wum-nl6 1200x1920 video mode panel driver"); 885 MODULE_LICENSE("GPL v2"); 886