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