diff options
Diffstat (limited to 'drivers/gpu/drm/panel/panel-simple.c')
-rw-r--r-- | drivers/gpu/drm/panel/panel-simple.c | 203 |
1 files changed, 189 insertions, 14 deletions
diff --git a/drivers/gpu/drm/panel/panel-simple.c b/drivers/gpu/drm/panel/panel-simple.c index a25136132c31..4ce1db0a68ff 100644 --- a/drivers/gpu/drm/panel/panel-simple.c +++ b/drivers/gpu/drm/panel/panel-simple.c | |||
@@ -37,14 +37,35 @@ struct panel_desc { | |||
37 | const struct drm_display_mode *modes; | 37 | const struct drm_display_mode *modes; |
38 | unsigned int num_modes; | 38 | unsigned int num_modes; |
39 | 39 | ||
40 | unsigned int bpc; | ||
41 | |||
40 | struct { | 42 | struct { |
41 | unsigned int width; | 43 | unsigned int width; |
42 | unsigned int height; | 44 | unsigned int height; |
43 | } size; | 45 | } size; |
46 | |||
47 | /** | ||
48 | * @prepare: the time (in milliseconds) that it takes for the panel to | ||
49 | * become ready and start receiving video data | ||
50 | * @enable: the time (in milliseconds) that it takes for the panel to | ||
51 | * display the first valid frame after starting to receive | ||
52 | * video data | ||
53 | * @disable: the time (in milliseconds) that it takes for the panel to | ||
54 | * turn the display off (no content is visible) | ||
55 | * @unprepare: the time (in milliseconds) that it takes for the panel | ||
56 | * to power itself down completely | ||
57 | */ | ||
58 | struct { | ||
59 | unsigned int prepare; | ||
60 | unsigned int enable; | ||
61 | unsigned int disable; | ||
62 | unsigned int unprepare; | ||
63 | } delay; | ||
44 | }; | 64 | }; |
45 | 65 | ||
46 | struct panel_simple { | 66 | struct panel_simple { |
47 | struct drm_panel base; | 67 | struct drm_panel base; |
68 | bool prepared; | ||
48 | bool enabled; | 69 | bool enabled; |
49 | 70 | ||
50 | const struct panel_desc *desc; | 71 | const struct panel_desc *desc; |
@@ -87,6 +108,7 @@ static int panel_simple_get_fixed_modes(struct panel_simple *panel) | |||
87 | num++; | 108 | num++; |
88 | } | 109 | } |
89 | 110 | ||
111 | connector->display_info.bpc = panel->desc->bpc; | ||
90 | connector->display_info.width_mm = panel->desc->size.width; | 112 | connector->display_info.width_mm = panel->desc->size.width; |
91 | connector->display_info.height_mm = panel->desc->size.height; | 113 | connector->display_info.height_mm = panel->desc->size.height; |
92 | 114 | ||
@@ -105,21 +127,40 @@ static int panel_simple_disable(struct drm_panel *panel) | |||
105 | backlight_update_status(p->backlight); | 127 | backlight_update_status(p->backlight); |
106 | } | 128 | } |
107 | 129 | ||
130 | if (p->desc->delay.disable) | ||
131 | msleep(p->desc->delay.disable); | ||
132 | |||
133 | p->enabled = false; | ||
134 | |||
135 | return 0; | ||
136 | } | ||
137 | |||
138 | static int panel_simple_unprepare(struct drm_panel *panel) | ||
139 | { | ||
140 | struct panel_simple *p = to_panel_simple(panel); | ||
141 | |||
142 | if (!p->prepared) | ||
143 | return 0; | ||
144 | |||
108 | if (p->enable_gpio) | 145 | if (p->enable_gpio) |
109 | gpiod_set_value_cansleep(p->enable_gpio, 0); | 146 | gpiod_set_value_cansleep(p->enable_gpio, 0); |
110 | 147 | ||
111 | regulator_disable(p->supply); | 148 | regulator_disable(p->supply); |
112 | p->enabled = false; | 149 | |
150 | if (p->desc->delay.unprepare) | ||
151 | msleep(p->desc->delay.unprepare); | ||
152 | |||
153 | p->prepared = false; | ||
113 | 154 | ||
114 | return 0; | 155 | return 0; |
115 | } | 156 | } |
116 | 157 | ||
117 | static int panel_simple_enable(struct drm_panel *panel) | 158 | static int panel_simple_prepare(struct drm_panel *panel) |
118 | { | 159 | { |
119 | struct panel_simple *p = to_panel_simple(panel); | 160 | struct panel_simple *p = to_panel_simple(panel); |
120 | int err; | 161 | int err; |
121 | 162 | ||
122 | if (p->enabled) | 163 | if (p->prepared) |
123 | return 0; | 164 | return 0; |
124 | 165 | ||
125 | err = regulator_enable(p->supply); | 166 | err = regulator_enable(p->supply); |
@@ -131,6 +172,24 @@ static int panel_simple_enable(struct drm_panel *panel) | |||
131 | if (p->enable_gpio) | 172 | if (p->enable_gpio) |
132 | gpiod_set_value_cansleep(p->enable_gpio, 1); | 173 | gpiod_set_value_cansleep(p->enable_gpio, 1); |
133 | 174 | ||
175 | if (p->desc->delay.prepare) | ||
176 | msleep(p->desc->delay.prepare); | ||
177 | |||
178 | p->prepared = true; | ||
179 | |||
180 | return 0; | ||
181 | } | ||
182 | |||
183 | static int panel_simple_enable(struct drm_panel *panel) | ||
184 | { | ||
185 | struct panel_simple *p = to_panel_simple(panel); | ||
186 | |||
187 | if (p->enabled) | ||
188 | return 0; | ||
189 | |||
190 | if (p->desc->delay.enable) | ||
191 | msleep(p->desc->delay.enable); | ||
192 | |||
134 | if (p->backlight) { | 193 | if (p->backlight) { |
135 | p->backlight->props.power = FB_BLANK_UNBLANK; | 194 | p->backlight->props.power = FB_BLANK_UNBLANK; |
136 | backlight_update_status(p->backlight); | 195 | backlight_update_status(p->backlight); |
@@ -164,6 +223,8 @@ static int panel_simple_get_modes(struct drm_panel *panel) | |||
164 | 223 | ||
165 | static const struct drm_panel_funcs panel_simple_funcs = { | 224 | static const struct drm_panel_funcs panel_simple_funcs = { |
166 | .disable = panel_simple_disable, | 225 | .disable = panel_simple_disable, |
226 | .unprepare = panel_simple_unprepare, | ||
227 | .prepare = panel_simple_prepare, | ||
167 | .enable = panel_simple_enable, | 228 | .enable = panel_simple_enable, |
168 | .get_modes = panel_simple_get_modes, | 229 | .get_modes = panel_simple_get_modes, |
169 | }; | 230 | }; |
@@ -179,22 +240,21 @@ static int panel_simple_probe(struct device *dev, const struct panel_desc *desc) | |||
179 | return -ENOMEM; | 240 | return -ENOMEM; |
180 | 241 | ||
181 | panel->enabled = false; | 242 | panel->enabled = false; |
243 | panel->prepared = false; | ||
182 | panel->desc = desc; | 244 | panel->desc = desc; |
183 | 245 | ||
184 | panel->supply = devm_regulator_get(dev, "power"); | 246 | panel->supply = devm_regulator_get(dev, "power"); |
185 | if (IS_ERR(panel->supply)) | 247 | if (IS_ERR(panel->supply)) |
186 | return PTR_ERR(panel->supply); | 248 | return PTR_ERR(panel->supply); |
187 | 249 | ||
188 | panel->enable_gpio = devm_gpiod_get(dev, "enable"); | 250 | panel->enable_gpio = devm_gpiod_get_optional(dev, "enable"); |
189 | if (IS_ERR(panel->enable_gpio)) { | 251 | if (IS_ERR(panel->enable_gpio)) { |
190 | err = PTR_ERR(panel->enable_gpio); | 252 | err = PTR_ERR(panel->enable_gpio); |
191 | if (err != -ENOENT) { | 253 | dev_err(dev, "failed to request GPIO: %d\n", err); |
192 | dev_err(dev, "failed to request GPIO: %d\n", err); | 254 | return err; |
193 | return err; | 255 | } |
194 | } | ||
195 | 256 | ||
196 | panel->enable_gpio = NULL; | 257 | if (panel->enable_gpio) { |
197 | } else { | ||
198 | err = gpiod_direction_output(panel->enable_gpio, 0); | 258 | err = gpiod_direction_output(panel->enable_gpio, 0); |
199 | if (err < 0) { | 259 | if (err < 0) { |
200 | dev_err(dev, "failed to setup GPIO: %d\n", err); | 260 | dev_err(dev, "failed to setup GPIO: %d\n", err); |
@@ -285,6 +345,7 @@ static const struct drm_display_mode auo_b101aw03_mode = { | |||
285 | static const struct panel_desc auo_b101aw03 = { | 345 | static const struct panel_desc auo_b101aw03 = { |
286 | .modes = &auo_b101aw03_mode, | 346 | .modes = &auo_b101aw03_mode, |
287 | .num_modes = 1, | 347 | .num_modes = 1, |
348 | .bpc = 6, | ||
288 | .size = { | 349 | .size = { |
289 | .width = 223, | 350 | .width = 223, |
290 | .height = 125, | 351 | .height = 125, |
@@ -307,12 +368,40 @@ static const struct drm_display_mode auo_b133xtn01_mode = { | |||
307 | static const struct panel_desc auo_b133xtn01 = { | 368 | static const struct panel_desc auo_b133xtn01 = { |
308 | .modes = &auo_b133xtn01_mode, | 369 | .modes = &auo_b133xtn01_mode, |
309 | .num_modes = 1, | 370 | .num_modes = 1, |
371 | .bpc = 6, | ||
310 | .size = { | 372 | .size = { |
311 | .width = 293, | 373 | .width = 293, |
312 | .height = 165, | 374 | .height = 165, |
313 | }, | 375 | }, |
314 | }; | 376 | }; |
315 | 377 | ||
378 | static const struct drm_display_mode auo_b133htn01_mode = { | ||
379 | .clock = 150660, | ||
380 | .hdisplay = 1920, | ||
381 | .hsync_start = 1920 + 172, | ||
382 | .hsync_end = 1920 + 172 + 80, | ||
383 | .htotal = 1920 + 172 + 80 + 60, | ||
384 | .vdisplay = 1080, | ||
385 | .vsync_start = 1080 + 25, | ||
386 | .vsync_end = 1080 + 25 + 10, | ||
387 | .vtotal = 1080 + 25 + 10 + 10, | ||
388 | .vrefresh = 60, | ||
389 | }; | ||
390 | |||
391 | static const struct panel_desc auo_b133htn01 = { | ||
392 | .modes = &auo_b133htn01_mode, | ||
393 | .num_modes = 1, | ||
394 | .size = { | ||
395 | .width = 293, | ||
396 | .height = 165, | ||
397 | }, | ||
398 | .delay = { | ||
399 | .prepare = 105, | ||
400 | .enable = 20, | ||
401 | .unprepare = 50, | ||
402 | }, | ||
403 | }; | ||
404 | |||
316 | static const struct drm_display_mode chunghwa_claa101wa01a_mode = { | 405 | static const struct drm_display_mode chunghwa_claa101wa01a_mode = { |
317 | .clock = 72070, | 406 | .clock = 72070, |
318 | .hdisplay = 1366, | 407 | .hdisplay = 1366, |
@@ -329,6 +418,7 @@ static const struct drm_display_mode chunghwa_claa101wa01a_mode = { | |||
329 | static const struct panel_desc chunghwa_claa101wa01a = { | 418 | static const struct panel_desc chunghwa_claa101wa01a = { |
330 | .modes = &chunghwa_claa101wa01a_mode, | 419 | .modes = &chunghwa_claa101wa01a_mode, |
331 | .num_modes = 1, | 420 | .num_modes = 1, |
421 | .bpc = 6, | ||
332 | .size = { | 422 | .size = { |
333 | .width = 220, | 423 | .width = 220, |
334 | .height = 120, | 424 | .height = 120, |
@@ -351,6 +441,7 @@ static const struct drm_display_mode chunghwa_claa101wb01_mode = { | |||
351 | static const struct panel_desc chunghwa_claa101wb01 = { | 441 | static const struct panel_desc chunghwa_claa101wb01 = { |
352 | .modes = &chunghwa_claa101wb01_mode, | 442 | .modes = &chunghwa_claa101wb01_mode, |
353 | .num_modes = 1, | 443 | .num_modes = 1, |
444 | .bpc = 6, | ||
354 | .size = { | 445 | .size = { |
355 | .width = 223, | 446 | .width = 223, |
356 | .height = 125, | 447 | .height = 125, |
@@ -374,6 +465,7 @@ static const struct drm_display_mode edt_et057090dhu_mode = { | |||
374 | static const struct panel_desc edt_et057090dhu = { | 465 | static const struct panel_desc edt_et057090dhu = { |
375 | .modes = &edt_et057090dhu_mode, | 466 | .modes = &edt_et057090dhu_mode, |
376 | .num_modes = 1, | 467 | .num_modes = 1, |
468 | .bpc = 6, | ||
377 | .size = { | 469 | .size = { |
378 | .width = 115, | 470 | .width = 115, |
379 | .height = 86, | 471 | .height = 86, |
@@ -397,12 +489,82 @@ static const struct drm_display_mode edt_etm0700g0dh6_mode = { | |||
397 | static const struct panel_desc edt_etm0700g0dh6 = { | 489 | static const struct panel_desc edt_etm0700g0dh6 = { |
398 | .modes = &edt_etm0700g0dh6_mode, | 490 | .modes = &edt_etm0700g0dh6_mode, |
399 | .num_modes = 1, | 491 | .num_modes = 1, |
492 | .bpc = 6, | ||
400 | .size = { | 493 | .size = { |
401 | .width = 152, | 494 | .width = 152, |
402 | .height = 91, | 495 | .height = 91, |
403 | }, | 496 | }, |
404 | }; | 497 | }; |
405 | 498 | ||
499 | static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = { | ||
500 | .clock = 32260, | ||
501 | .hdisplay = 800, | ||
502 | .hsync_start = 800 + 168, | ||
503 | .hsync_end = 800 + 168 + 64, | ||
504 | .htotal = 800 + 168 + 64 + 88, | ||
505 | .vdisplay = 480, | ||
506 | .vsync_start = 480 + 37, | ||
507 | .vsync_end = 480 + 37 + 2, | ||
508 | .vtotal = 480 + 37 + 2 + 8, | ||
509 | .vrefresh = 60, | ||
510 | }; | ||
511 | |||
512 | static const struct panel_desc foxlink_fl500wvr00_a0t = { | ||
513 | .modes = &foxlink_fl500wvr00_a0t_mode, | ||
514 | .num_modes = 1, | ||
515 | .size = { | ||
516 | .width = 108, | ||
517 | .height = 65, | ||
518 | }, | ||
519 | }; | ||
520 | |||
521 | static const struct drm_display_mode innolux_n116bge_mode = { | ||
522 | .clock = 71000, | ||
523 | .hdisplay = 1366, | ||
524 | .hsync_start = 1366 + 64, | ||
525 | .hsync_end = 1366 + 64 + 6, | ||
526 | .htotal = 1366 + 64 + 6 + 64, | ||
527 | .vdisplay = 768, | ||
528 | .vsync_start = 768 + 8, | ||
529 | .vsync_end = 768 + 8 + 4, | ||
530 | .vtotal = 768 + 8 + 4 + 8, | ||
531 | .vrefresh = 60, | ||
532 | .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC, | ||
533 | }; | ||
534 | |||
535 | static const struct panel_desc innolux_n116bge = { | ||
536 | .modes = &innolux_n116bge_mode, | ||
537 | .num_modes = 1, | ||
538 | .bpc = 6, | ||
539 | .size = { | ||
540 | .width = 256, | ||
541 | .height = 144, | ||
542 | }, | ||
543 | }; | ||
544 | |||
545 | static const struct drm_display_mode innolux_n156bge_l21_mode = { | ||
546 | .clock = 69300, | ||
547 | .hdisplay = 1366, | ||
548 | .hsync_start = 1366 + 16, | ||
549 | .hsync_end = 1366 + 16 + 34, | ||
550 | .htotal = 1366 + 16 + 34 + 50, | ||
551 | .vdisplay = 768, | ||
552 | .vsync_start = 768 + 2, | ||
553 | .vsync_end = 768 + 2 + 6, | ||
554 | .vtotal = 768 + 2 + 6 + 12, | ||
555 | .vrefresh = 60, | ||
556 | }; | ||
557 | |||
558 | static const struct panel_desc innolux_n156bge_l21 = { | ||
559 | .modes = &innolux_n156bge_l21_mode, | ||
560 | .num_modes = 1, | ||
561 | .bpc = 6, | ||
562 | .size = { | ||
563 | .width = 344, | ||
564 | .height = 193, | ||
565 | }, | ||
566 | }; | ||
567 | |||
406 | static const struct drm_display_mode lg_lp129qe_mode = { | 568 | static const struct drm_display_mode lg_lp129qe_mode = { |
407 | .clock = 285250, | 569 | .clock = 285250, |
408 | .hdisplay = 2560, | 570 | .hdisplay = 2560, |
@@ -419,6 +581,7 @@ static const struct drm_display_mode lg_lp129qe_mode = { | |||
419 | static const struct panel_desc lg_lp129qe = { | 581 | static const struct panel_desc lg_lp129qe = { |
420 | .modes = &lg_lp129qe_mode, | 582 | .modes = &lg_lp129qe_mode, |
421 | .num_modes = 1, | 583 | .num_modes = 1, |
584 | .bpc = 8, | ||
422 | .size = { | 585 | .size = { |
423 | .width = 272, | 586 | .width = 272, |
424 | .height = 181, | 587 | .height = 181, |
@@ -441,6 +604,7 @@ static const struct drm_display_mode samsung_ltn101nt05_mode = { | |||
441 | static const struct panel_desc samsung_ltn101nt05 = { | 604 | static const struct panel_desc samsung_ltn101nt05 = { |
442 | .modes = &samsung_ltn101nt05_mode, | 605 | .modes = &samsung_ltn101nt05_mode, |
443 | .num_modes = 1, | 606 | .num_modes = 1, |
607 | .bpc = 6, | ||
444 | .size = { | 608 | .size = { |
445 | .width = 1024, | 609 | .width = 1024, |
446 | .height = 600, | 610 | .height = 600, |
@@ -452,6 +616,9 @@ static const struct of_device_id platform_of_match[] = { | |||
452 | .compatible = "auo,b101aw03", | 616 | .compatible = "auo,b101aw03", |
453 | .data = &auo_b101aw03, | 617 | .data = &auo_b101aw03, |
454 | }, { | 618 | }, { |
619 | .compatible = "auo,b133htn01", | ||
620 | .data = &auo_b133htn01, | ||
621 | }, { | ||
455 | .compatible = "auo,b133xtn01", | 622 | .compatible = "auo,b133xtn01", |
456 | .data = &auo_b133xtn01, | 623 | .data = &auo_b133xtn01, |
457 | }, { | 624 | }, { |
@@ -470,14 +637,21 @@ static const struct of_device_id platform_of_match[] = { | |||
470 | .compatible = "edt,etm0700g0dh6", | 637 | .compatible = "edt,etm0700g0dh6", |
471 | .data = &edt_etm0700g0dh6, | 638 | .data = &edt_etm0700g0dh6, |
472 | }, { | 639 | }, { |
640 | .compatible = "foxlink,fl500wvr00-a0t", | ||
641 | .data = &foxlink_fl500wvr00_a0t, | ||
642 | }, { | ||
643 | .compatible = "innolux,n116bge", | ||
644 | .data = &innolux_n116bge, | ||
645 | }, { | ||
646 | .compatible = "innolux,n156bge-l21", | ||
647 | .data = &innolux_n156bge_l21, | ||
648 | }, { | ||
473 | .compatible = "lg,lp129qe", | 649 | .compatible = "lg,lp129qe", |
474 | .data = &lg_lp129qe, | 650 | .data = &lg_lp129qe, |
475 | }, { | 651 | }, { |
476 | .compatible = "samsung,ltn101nt05", | 652 | .compatible = "samsung,ltn101nt05", |
477 | .data = &samsung_ltn101nt05, | 653 | .data = &samsung_ltn101nt05, |
478 | }, { | 654 | }, { |
479 | .compatible = "simple-panel", | ||
480 | }, { | ||
481 | /* sentinel */ | 655 | /* sentinel */ |
482 | } | 656 | } |
483 | }; | 657 | }; |
@@ -545,7 +719,7 @@ static const struct panel_desc_dsi lg_ld070wx3_sl01 = { | |||
545 | .height = 151, | 719 | .height = 151, |
546 | }, | 720 | }, |
547 | }, | 721 | }, |
548 | .flags = MIPI_DSI_MODE_VIDEO, | 722 | .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS, |
549 | .format = MIPI_DSI_FMT_RGB888, | 723 | .format = MIPI_DSI_FMT_RGB888, |
550 | .lanes = 4, | 724 | .lanes = 4, |
551 | }; | 725 | }; |
@@ -599,7 +773,8 @@ static const struct panel_desc_dsi panasonic_vvx10f004b00 = { | |||
599 | .height = 136, | 773 | .height = 136, |
600 | }, | 774 | }, |
601 | }, | 775 | }, |
602 | .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE, | 776 | .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE | |
777 | MIPI_DSI_CLOCK_NON_CONTINUOUS, | ||
603 | .format = MIPI_DSI_FMT_RGB888, | 778 | .format = MIPI_DSI_FMT_RGB888, |
604 | .lanes = 4, | 779 | .lanes = 4, |
605 | }; | 780 | }; |