drm/panel: simple: Add proper definition for prepare and unprepare
[deliverable/linux.git] / drivers / gpu / drm / panel / panel-simple.c
CommitLineData
280921de
TR
1/*
2 * Copyright (C) 2013, NVIDIA Corporation. All rights reserved.
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sub license,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the
12 * next paragraph) shall be included in all copies or substantial portions
13 * of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
21 * DEALINGS IN THE SOFTWARE.
22 */
23
24#include <linux/backlight.h>
cfdf0549 25#include <linux/gpio/consumer.h>
280921de 26#include <linux/module.h>
280921de
TR
27#include <linux/of_platform.h>
28#include <linux/platform_device.h>
29#include <linux/regulator/consumer.h>
30
31#include <drm/drmP.h>
32#include <drm/drm_crtc.h>
210fcd9d 33#include <drm/drm_mipi_dsi.h>
280921de
TR
34#include <drm/drm_panel.h>
35
36struct panel_desc {
37 const struct drm_display_mode *modes;
38 unsigned int num_modes;
39
0208d511
SM
40 unsigned int bpc;
41
280921de
TR
42 struct {
43 unsigned int width;
44 unsigned int height;
45 } size;
46};
47
280921de
TR
48struct panel_simple {
49 struct drm_panel base;
613a633e 50 bool prepared;
280921de
TR
51 bool enabled;
52
53 const struct panel_desc *desc;
54
55 struct backlight_device *backlight;
56 struct regulator *supply;
57 struct i2c_adapter *ddc;
58
cfdf0549 59 struct gpio_desc *enable_gpio;
280921de
TR
60};
61
62static inline struct panel_simple *to_panel_simple(struct drm_panel *panel)
63{
64 return container_of(panel, struct panel_simple, base);
65}
66
67static int panel_simple_get_fixed_modes(struct panel_simple *panel)
68{
69 struct drm_connector *connector = panel->base.connector;
70 struct drm_device *drm = panel->base.drm;
71 struct drm_display_mode *mode;
72 unsigned int i, num = 0;
73
74 if (!panel->desc)
75 return 0;
76
77 for (i = 0; i < panel->desc->num_modes; i++) {
78 const struct drm_display_mode *m = &panel->desc->modes[i];
79
80 mode = drm_mode_duplicate(drm, m);
81 if (!mode) {
82 dev_err(drm->dev, "failed to add mode %ux%u@%u\n",
83 m->hdisplay, m->vdisplay, m->vrefresh);
84 continue;
85 }
86
87 drm_mode_set_name(mode);
88
89 drm_mode_probed_add(connector, mode);
90 num++;
91 }
92
0208d511 93 connector->display_info.bpc = panel->desc->bpc;
280921de
TR
94 connector->display_info.width_mm = panel->desc->size.width;
95 connector->display_info.height_mm = panel->desc->size.height;
96
97 return num;
98}
99
100static int panel_simple_disable(struct drm_panel *panel)
101{
102 struct panel_simple *p = to_panel_simple(panel);
103
104 if (!p->enabled)
105 return 0;
106
107 if (p->backlight) {
108 p->backlight->props.power = FB_BLANK_POWERDOWN;
109 backlight_update_status(p->backlight);
110 }
111
280921de
TR
112 p->enabled = false;
113
114 return 0;
115}
116
c0e1d170
AK
117static int panel_simple_unprepare(struct drm_panel *panel)
118{
613a633e
AK
119 struct panel_simple *p = to_panel_simple(panel);
120
121 if (!p->prepared)
122 return 0;
123
124 if (p->enable_gpio)
125 gpiod_set_value_cansleep(p->enable_gpio, 0);
126
127 regulator_disable(p->supply);
128
129 p->prepared = false;
c0e1d170 130
c0e1d170
AK
131 return 0;
132}
133
613a633e 134static int panel_simple_prepare(struct drm_panel *panel)
280921de
TR
135{
136 struct panel_simple *p = to_panel_simple(panel);
137 int err;
138
613a633e 139 if (p->prepared)
280921de
TR
140 return 0;
141
142 err = regulator_enable(p->supply);
143 if (err < 0) {
144 dev_err(panel->dev, "failed to enable supply: %d\n", err);
145 return err;
146 }
147
cfdf0549 148 if (p->enable_gpio)
15c1a919 149 gpiod_set_value_cansleep(p->enable_gpio, 1);
280921de 150
613a633e
AK
151 p->prepared = true;
152
153 return 0;
154}
155
156static int panel_simple_enable(struct drm_panel *panel)
157{
158 struct panel_simple *p = to_panel_simple(panel);
159
160 if (p->enabled)
161 return 0;
162
280921de
TR
163 if (p->backlight) {
164 p->backlight->props.power = FB_BLANK_UNBLANK;
165 backlight_update_status(p->backlight);
166 }
167
168 p->enabled = true;
169
170 return 0;
171}
172
173static int panel_simple_get_modes(struct drm_panel *panel)
174{
175 struct panel_simple *p = to_panel_simple(panel);
176 int num = 0;
177
178 /* probe EDID if a DDC bus is available */
179 if (p->ddc) {
180 struct edid *edid = drm_get_edid(panel->connector, p->ddc);
70bf6878 181 drm_mode_connector_update_edid_property(panel->connector, edid);
280921de
TR
182 if (edid) {
183 num += drm_add_edid_modes(panel->connector, edid);
184 kfree(edid);
185 }
186 }
187
188 /* add hard-coded panel modes */
189 num += panel_simple_get_fixed_modes(p);
190
191 return num;
192}
193
194static const struct drm_panel_funcs panel_simple_funcs = {
195 .disable = panel_simple_disable,
c0e1d170
AK
196 .unprepare = panel_simple_unprepare,
197 .prepare = panel_simple_prepare,
280921de
TR
198 .enable = panel_simple_enable,
199 .get_modes = panel_simple_get_modes,
200};
201
202static int panel_simple_probe(struct device *dev, const struct panel_desc *desc)
203{
204 struct device_node *backlight, *ddc;
205 struct panel_simple *panel;
280921de
TR
206 int err;
207
208 panel = devm_kzalloc(dev, sizeof(*panel), GFP_KERNEL);
209 if (!panel)
210 return -ENOMEM;
211
212 panel->enabled = false;
613a633e 213 panel->prepared = false;
280921de
TR
214 panel->desc = desc;
215
216 panel->supply = devm_regulator_get(dev, "power");
217 if (IS_ERR(panel->supply))
218 return PTR_ERR(panel->supply);
219
cfdf0549
AC
220 panel->enable_gpio = devm_gpiod_get(dev, "enable");
221 if (IS_ERR(panel->enable_gpio)) {
222 err = PTR_ERR(panel->enable_gpio);
223 if (err != -ENOENT) {
224 dev_err(dev, "failed to request GPIO: %d\n", err);
280921de
TR
225 return err;
226 }
227
cfdf0549
AC
228 panel->enable_gpio = NULL;
229 } else {
230 err = gpiod_direction_output(panel->enable_gpio, 0);
280921de 231 if (err < 0) {
cfdf0549
AC
232 dev_err(dev, "failed to setup GPIO: %d\n", err);
233 return err;
280921de
TR
234 }
235 }
236
237 backlight = of_parse_phandle(dev->of_node, "backlight", 0);
238 if (backlight) {
239 panel->backlight = of_find_backlight_by_node(backlight);
240 of_node_put(backlight);
241
cfdf0549
AC
242 if (!panel->backlight)
243 return -EPROBE_DEFER;
280921de
TR
244 }
245
246 ddc = of_parse_phandle(dev->of_node, "ddc-i2c-bus", 0);
247 if (ddc) {
248 panel->ddc = of_find_i2c_adapter_by_node(ddc);
249 of_node_put(ddc);
250
251 if (!panel->ddc) {
252 err = -EPROBE_DEFER;
253 goto free_backlight;
254 }
255 }
256
257 drm_panel_init(&panel->base);
258 panel->base.dev = dev;
259 panel->base.funcs = &panel_simple_funcs;
260
261 err = drm_panel_add(&panel->base);
262 if (err < 0)
263 goto free_ddc;
264
265 dev_set_drvdata(dev, panel);
266
267 return 0;
268
269free_ddc:
270 if (panel->ddc)
271 put_device(&panel->ddc->dev);
272free_backlight:
273 if (panel->backlight)
274 put_device(&panel->backlight->dev);
280921de
TR
275
276 return err;
277}
278
279static int panel_simple_remove(struct device *dev)
280{
281 struct panel_simple *panel = dev_get_drvdata(dev);
282
283 drm_panel_detach(&panel->base);
284 drm_panel_remove(&panel->base);
285
286 panel_simple_disable(&panel->base);
287
288 if (panel->ddc)
289 put_device(&panel->ddc->dev);
290
291 if (panel->backlight)
292 put_device(&panel->backlight->dev);
293
280921de
TR
294 return 0;
295}
296
d02fd93e
TR
297static void panel_simple_shutdown(struct device *dev)
298{
299 struct panel_simple *panel = dev_get_drvdata(dev);
300
301 panel_simple_disable(&panel->base);
302}
303
280921de
TR
304static const struct drm_display_mode auo_b101aw03_mode = {
305 .clock = 51450,
306 .hdisplay = 1024,
307 .hsync_start = 1024 + 156,
308 .hsync_end = 1024 + 156 + 8,
309 .htotal = 1024 + 156 + 8 + 156,
310 .vdisplay = 600,
311 .vsync_start = 600 + 16,
312 .vsync_end = 600 + 16 + 6,
313 .vtotal = 600 + 16 + 6 + 16,
314 .vrefresh = 60,
315};
316
317static const struct panel_desc auo_b101aw03 = {
318 .modes = &auo_b101aw03_mode,
319 .num_modes = 1,
0208d511 320 .bpc = 6,
280921de
TR
321 .size = {
322 .width = 223,
323 .height = 125,
324 },
325};
326
a333f7ad
SM
327static const struct drm_display_mode auo_b133xtn01_mode = {
328 .clock = 69500,
329 .hdisplay = 1366,
330 .hsync_start = 1366 + 48,
331 .hsync_end = 1366 + 48 + 32,
332 .htotal = 1366 + 48 + 32 + 20,
333 .vdisplay = 768,
334 .vsync_start = 768 + 3,
335 .vsync_end = 768 + 3 + 6,
336 .vtotal = 768 + 3 + 6 + 13,
337 .vrefresh = 60,
338};
339
340static const struct panel_desc auo_b133xtn01 = {
341 .modes = &auo_b133xtn01_mode,
342 .num_modes = 1,
0208d511 343 .bpc = 6,
a333f7ad
SM
344 .size = {
345 .width = 293,
346 .height = 165,
347 },
348};
349
4c930757
SW
350static const struct drm_display_mode chunghwa_claa101wa01a_mode = {
351 .clock = 72070,
352 .hdisplay = 1366,
353 .hsync_start = 1366 + 58,
354 .hsync_end = 1366 + 58 + 58,
355 .htotal = 1366 + 58 + 58 + 58,
356 .vdisplay = 768,
357 .vsync_start = 768 + 4,
358 .vsync_end = 768 + 4 + 4,
359 .vtotal = 768 + 4 + 4 + 4,
360 .vrefresh = 60,
361};
362
363static const struct panel_desc chunghwa_claa101wa01a = {
364 .modes = &chunghwa_claa101wa01a_mode,
365 .num_modes = 1,
0208d511 366 .bpc = 6,
4c930757
SW
367 .size = {
368 .width = 220,
369 .height = 120,
370 },
371};
372
280921de
TR
373static const struct drm_display_mode chunghwa_claa101wb01_mode = {
374 .clock = 69300,
375 .hdisplay = 1366,
376 .hsync_start = 1366 + 48,
377 .hsync_end = 1366 + 48 + 32,
378 .htotal = 1366 + 48 + 32 + 20,
379 .vdisplay = 768,
380 .vsync_start = 768 + 16,
381 .vsync_end = 768 + 16 + 8,
382 .vtotal = 768 + 16 + 8 + 16,
383 .vrefresh = 60,
384};
385
386static const struct panel_desc chunghwa_claa101wb01 = {
387 .modes = &chunghwa_claa101wb01_mode,
388 .num_modes = 1,
0208d511 389 .bpc = 6,
280921de
TR
390 .size = {
391 .width = 223,
392 .height = 125,
393 },
394};
395
26ab0065
SA
396static const struct drm_display_mode edt_et057090dhu_mode = {
397 .clock = 25175,
398 .hdisplay = 640,
399 .hsync_start = 640 + 16,
400 .hsync_end = 640 + 16 + 30,
401 .htotal = 640 + 16 + 30 + 114,
402 .vdisplay = 480,
403 .vsync_start = 480 + 10,
404 .vsync_end = 480 + 10 + 3,
405 .vtotal = 480 + 10 + 3 + 32,
406 .vrefresh = 60,
407 .flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
408};
409
410static const struct panel_desc edt_et057090dhu = {
411 .modes = &edt_et057090dhu_mode,
412 .num_modes = 1,
0208d511 413 .bpc = 6,
26ab0065
SA
414 .size = {
415 .width = 115,
416 .height = 86,
417 },
418};
419
fff5de45
PZ
420static const struct drm_display_mode edt_etm0700g0dh6_mode = {
421 .clock = 33260,
422 .hdisplay = 800,
423 .hsync_start = 800 + 40,
424 .hsync_end = 800 + 40 + 128,
425 .htotal = 800 + 40 + 128 + 88,
426 .vdisplay = 480,
427 .vsync_start = 480 + 10,
428 .vsync_end = 480 + 10 + 2,
429 .vtotal = 480 + 10 + 2 + 33,
430 .vrefresh = 60,
431 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
432};
433
434static const struct panel_desc edt_etm0700g0dh6 = {
435 .modes = &edt_etm0700g0dh6_mode,
436 .num_modes = 1,
0208d511 437 .bpc = 6,
fff5de45
PZ
438 .size = {
439 .width = 152,
440 .height = 91,
441 },
442};
443
102932b0
BB
444static const struct drm_display_mode foxlink_fl500wvr00_a0t_mode = {
445 .clock = 32260,
446 .hdisplay = 800,
447 .hsync_start = 800 + 168,
448 .hsync_end = 800 + 168 + 64,
449 .htotal = 800 + 168 + 64 + 88,
450 .vdisplay = 480,
451 .vsync_start = 480 + 37,
452 .vsync_end = 480 + 37 + 2,
453 .vtotal = 480 + 37 + 2 + 8,
454 .vrefresh = 60,
455};
456
457static const struct panel_desc foxlink_fl500wvr00_a0t = {
458 .modes = &foxlink_fl500wvr00_a0t_mode,
459 .num_modes = 1,
460 .size = {
461 .width = 108,
462 .height = 65,
463 },
464};
465
0a2288c0
TR
466static const struct drm_display_mode innolux_n116bge_mode = {
467 .clock = 71000,
468 .hdisplay = 1366,
469 .hsync_start = 1366 + 64,
470 .hsync_end = 1366 + 64 + 6,
471 .htotal = 1366 + 64 + 6 + 64,
472 .vdisplay = 768,
473 .vsync_start = 768 + 8,
474 .vsync_end = 768 + 8 + 4,
475 .vtotal = 768 + 8 + 4 + 8,
476 .vrefresh = 60,
477 .flags = DRM_MODE_FLAG_NHSYNC | DRM_MODE_FLAG_NVSYNC,
478};
479
480static const struct panel_desc innolux_n116bge = {
481 .modes = &innolux_n116bge_mode,
482 .num_modes = 1,
483 .bpc = 6,
484 .size = {
485 .width = 256,
486 .height = 144,
487 },
488};
489
ea44739d
AB
490static const struct drm_display_mode innolux_n156bge_l21_mode = {
491 .clock = 69300,
492 .hdisplay = 1366,
493 .hsync_start = 1366 + 16,
494 .hsync_end = 1366 + 16 + 34,
495 .htotal = 1366 + 16 + 34 + 50,
496 .vdisplay = 768,
497 .vsync_start = 768 + 2,
498 .vsync_end = 768 + 2 + 6,
499 .vtotal = 768 + 2 + 6 + 12,
500 .vrefresh = 60,
501};
502
503static const struct panel_desc innolux_n156bge_l21 = {
504 .modes = &innolux_n156bge_l21_mode,
505 .num_modes = 1,
0208d511 506 .bpc = 6,
ea44739d
AB
507 .size = {
508 .width = 344,
509 .height = 193,
510 },
511};
512
ec7c5653
TR
513static const struct drm_display_mode lg_lp129qe_mode = {
514 .clock = 285250,
515 .hdisplay = 2560,
516 .hsync_start = 2560 + 48,
517 .hsync_end = 2560 + 48 + 32,
518 .htotal = 2560 + 48 + 32 + 80,
519 .vdisplay = 1700,
520 .vsync_start = 1700 + 3,
521 .vsync_end = 1700 + 3 + 10,
522 .vtotal = 1700 + 3 + 10 + 36,
523 .vrefresh = 60,
524};
525
526static const struct panel_desc lg_lp129qe = {
527 .modes = &lg_lp129qe_mode,
528 .num_modes = 1,
0208d511 529 .bpc = 8,
ec7c5653
TR
530 .size = {
531 .width = 272,
532 .height = 181,
533 },
534};
535
6d54e3d2
MD
536static const struct drm_display_mode samsung_ltn101nt05_mode = {
537 .clock = 54030,
538 .hdisplay = 1024,
539 .hsync_start = 1024 + 24,
540 .hsync_end = 1024 + 24 + 136,
541 .htotal = 1024 + 24 + 136 + 160,
542 .vdisplay = 600,
543 .vsync_start = 600 + 3,
544 .vsync_end = 600 + 3 + 6,
545 .vtotal = 600 + 3 + 6 + 61,
546 .vrefresh = 60,
547};
548
549static const struct panel_desc samsung_ltn101nt05 = {
550 .modes = &samsung_ltn101nt05_mode,
551 .num_modes = 1,
0208d511 552 .bpc = 6,
6d54e3d2
MD
553 .size = {
554 .width = 1024,
555 .height = 600,
556 },
557};
558
280921de
TR
559static const struct of_device_id platform_of_match[] = {
560 {
561 .compatible = "auo,b101aw03",
562 .data = &auo_b101aw03,
a333f7ad
SM
563 }, {
564 .compatible = "auo,b133xtn01",
565 .data = &auo_b133xtn01,
4c930757
SW
566 }, {
567 .compatible = "chunghwa,claa101wa01a",
568 .data = &chunghwa_claa101wa01a
280921de
TR
569 }, {
570 .compatible = "chunghwa,claa101wb01",
571 .data = &chunghwa_claa101wb01
26ab0065
SA
572 }, {
573 .compatible = "edt,et057090dhu",
574 .data = &edt_et057090dhu,
fff5de45
PZ
575 }, {
576 .compatible = "edt,et070080dh6",
577 .data = &edt_etm0700g0dh6,
578 }, {
579 .compatible = "edt,etm0700g0dh6",
580 .data = &edt_etm0700g0dh6,
102932b0
BB
581 }, {
582 .compatible = "foxlink,fl500wvr00-a0t",
583 .data = &foxlink_fl500wvr00_a0t,
0a2288c0
TR
584 }, {
585 .compatible = "innolux,n116bge",
586 .data = &innolux_n116bge,
ea44739d
AB
587 }, {
588 .compatible = "innolux,n156bge-l21",
589 .data = &innolux_n156bge_l21,
ec7c5653
TR
590 }, {
591 .compatible = "lg,lp129qe",
592 .data = &lg_lp129qe,
6d54e3d2
MD
593 }, {
594 .compatible = "samsung,ltn101nt05",
595 .data = &samsung_ltn101nt05,
280921de
TR
596 }, {
597 /* sentinel */
598 }
599};
600MODULE_DEVICE_TABLE(of, platform_of_match);
601
602static int panel_simple_platform_probe(struct platform_device *pdev)
603{
604 const struct of_device_id *id;
605
606 id = of_match_node(platform_of_match, pdev->dev.of_node);
607 if (!id)
608 return -ENODEV;
609
610 return panel_simple_probe(&pdev->dev, id->data);
611}
612
613static int panel_simple_platform_remove(struct platform_device *pdev)
614{
615 return panel_simple_remove(&pdev->dev);
616}
617
d02fd93e
TR
618static void panel_simple_platform_shutdown(struct platform_device *pdev)
619{
620 panel_simple_shutdown(&pdev->dev);
621}
622
280921de
TR
623static struct platform_driver panel_simple_platform_driver = {
624 .driver = {
625 .name = "panel-simple",
626 .owner = THIS_MODULE,
627 .of_match_table = platform_of_match,
628 },
629 .probe = panel_simple_platform_probe,
630 .remove = panel_simple_platform_remove,
d02fd93e 631 .shutdown = panel_simple_platform_shutdown,
280921de
TR
632};
633
210fcd9d
TR
634struct panel_desc_dsi {
635 struct panel_desc desc;
636
462658b8 637 unsigned long flags;
210fcd9d
TR
638 enum mipi_dsi_pixel_format format;
639 unsigned int lanes;
640};
641
712ac1ba
AC
642static const struct drm_display_mode lg_ld070wx3_sl01_mode = {
643 .clock = 71000,
644 .hdisplay = 800,
645 .hsync_start = 800 + 32,
646 .hsync_end = 800 + 32 + 1,
647 .htotal = 800 + 32 + 1 + 57,
648 .vdisplay = 1280,
649 .vsync_start = 1280 + 28,
650 .vsync_end = 1280 + 28 + 1,
651 .vtotal = 1280 + 28 + 1 + 14,
652 .vrefresh = 60,
653};
654
655static const struct panel_desc_dsi lg_ld070wx3_sl01 = {
656 .desc = {
657 .modes = &lg_ld070wx3_sl01_mode,
658 .num_modes = 1,
659 .size = {
660 .width = 94,
661 .height = 151,
662 },
663 },
5e4cc278 664 .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_CLOCK_NON_CONTINUOUS,
712ac1ba
AC
665 .format = MIPI_DSI_FMT_RGB888,
666 .lanes = 4,
667};
668
499ce85a
AC
669static const struct drm_display_mode lg_lh500wx1_sd03_mode = {
670 .clock = 67000,
671 .hdisplay = 720,
672 .hsync_start = 720 + 12,
673 .hsync_end = 720 + 12 + 4,
674 .htotal = 720 + 12 + 4 + 112,
675 .vdisplay = 1280,
676 .vsync_start = 1280 + 8,
677 .vsync_end = 1280 + 8 + 4,
678 .vtotal = 1280 + 8 + 4 + 12,
679 .vrefresh = 60,
680};
681
682static const struct panel_desc_dsi lg_lh500wx1_sd03 = {
683 .desc = {
684 .modes = &lg_lh500wx1_sd03_mode,
685 .num_modes = 1,
686 .size = {
687 .width = 62,
688 .height = 110,
689 },
690 },
691 .flags = MIPI_DSI_MODE_VIDEO,
692 .format = MIPI_DSI_FMT_RGB888,
693 .lanes = 4,
694};
695
280921de
TR
696static const struct drm_display_mode panasonic_vvx10f004b00_mode = {
697 .clock = 157200,
698 .hdisplay = 1920,
699 .hsync_start = 1920 + 154,
700 .hsync_end = 1920 + 154 + 16,
701 .htotal = 1920 + 154 + 16 + 32,
702 .vdisplay = 1200,
703 .vsync_start = 1200 + 17,
704 .vsync_end = 1200 + 17 + 2,
705 .vtotal = 1200 + 17 + 2 + 16,
706 .vrefresh = 60,
707};
708
210fcd9d
TR
709static const struct panel_desc_dsi panasonic_vvx10f004b00 = {
710 .desc = {
711 .modes = &panasonic_vvx10f004b00_mode,
712 .num_modes = 1,
713 .size = {
714 .width = 217,
715 .height = 136,
716 },
280921de 717 },
5e4cc278
AC
718 .flags = MIPI_DSI_MODE_VIDEO | MIPI_DSI_MODE_VIDEO_SYNC_PULSE |
719 MIPI_DSI_CLOCK_NON_CONTINUOUS,
210fcd9d
TR
720 .format = MIPI_DSI_FMT_RGB888,
721 .lanes = 4,
722};
723
724static const struct of_device_id dsi_of_match[] = {
725 {
712ac1ba
AC
726 .compatible = "lg,ld070wx3-sl01",
727 .data = &lg_ld070wx3_sl01
728 }, {
499ce85a
AC
729 .compatible = "lg,lh500wx1-sd03",
730 .data = &lg_lh500wx1_sd03
731 }, {
210fcd9d
TR
732 .compatible = "panasonic,vvx10f004b00",
733 .data = &panasonic_vvx10f004b00
734 }, {
735 /* sentinel */
736 }
737};
738MODULE_DEVICE_TABLE(of, dsi_of_match);
739
740static int panel_simple_dsi_probe(struct mipi_dsi_device *dsi)
741{
742 const struct panel_desc_dsi *desc;
743 const struct of_device_id *id;
744 int err;
745
746 id = of_match_node(dsi_of_match, dsi->dev.of_node);
747 if (!id)
748 return -ENODEV;
749
750 desc = id->data;
751
752 err = panel_simple_probe(&dsi->dev, &desc->desc);
753 if (err < 0)
754 return err;
755
462658b8 756 dsi->mode_flags = desc->flags;
210fcd9d
TR
757 dsi->format = desc->format;
758 dsi->lanes = desc->lanes;
759
760 return mipi_dsi_attach(dsi);
761}
762
763static int panel_simple_dsi_remove(struct mipi_dsi_device *dsi)
764{
765 int err;
766
767 err = mipi_dsi_detach(dsi);
768 if (err < 0)
769 dev_err(&dsi->dev, "failed to detach from DSI host: %d\n", err);
770
771 return panel_simple_remove(&dsi->dev);
772}
773
d02fd93e
TR
774static void panel_simple_dsi_shutdown(struct mipi_dsi_device *dsi)
775{
776 panel_simple_shutdown(&dsi->dev);
777}
778
210fcd9d
TR
779static struct mipi_dsi_driver panel_simple_dsi_driver = {
780 .driver = {
781 .name = "panel-simple-dsi",
782 .owner = THIS_MODULE,
783 .of_match_table = dsi_of_match,
784 },
785 .probe = panel_simple_dsi_probe,
786 .remove = panel_simple_dsi_remove,
d02fd93e 787 .shutdown = panel_simple_dsi_shutdown,
280921de
TR
788};
789
790static int __init panel_simple_init(void)
791{
210fcd9d
TR
792 int err;
793
794 err = platform_driver_register(&panel_simple_platform_driver);
795 if (err < 0)
796 return err;
797
798 if (IS_ENABLED(CONFIG_DRM_MIPI_DSI)) {
799 err = mipi_dsi_driver_register(&panel_simple_dsi_driver);
800 if (err < 0)
801 return err;
802 }
803
804 return 0;
280921de
TR
805}
806module_init(panel_simple_init);
807
808static void __exit panel_simple_exit(void)
809{
210fcd9d
TR
810 if (IS_ENABLED(CONFIG_DRM_MIPI_DSI))
811 mipi_dsi_driver_unregister(&panel_simple_dsi_driver);
812
280921de
TR
813 platform_driver_unregister(&panel_simple_platform_driver);
814}
815module_exit(panel_simple_exit);
816
817MODULE_AUTHOR("Thierry Reding <treding@nvidia.com>");
818MODULE_DESCRIPTION("DRM Driver for Simple Panels");
819MODULE_LICENSE("GPL and additional rights");
This page took 0.072583 seconds and 5 git commands to generate.