Loading...
Note: File does not exist in v3.1.
1// SPDX-License-Identifier: GPL-2.0+
2/*
3 * rcar_du_drv.c -- R-Car Display Unit DRM driver
4 *
5 * Copyright (C) 2013-2015 Renesas Electronics Corporation
6 *
7 * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
8 */
9
10#include <linux/clk.h>
11#include <linux/io.h>
12#include <linux/mm.h>
13#include <linux/module.h>
14#include <linux/of_device.h>
15#include <linux/platform_device.h>
16#include <linux/pm.h>
17#include <linux/slab.h>
18#include <linux/wait.h>
19
20#include <drm/drm_atomic_helper.h>
21#include <drm/drm_drv.h>
22#include <drm/drm_fb_cma_helper.h>
23#include <drm/drm_fb_helper.h>
24#include <drm/drm_gem_cma_helper.h>
25#include <drm/drm_managed.h>
26#include <drm/drm_probe_helper.h>
27
28#include "rcar_du_drv.h"
29#include "rcar_du_kms.h"
30#include "rcar_du_of.h"
31#include "rcar_du_regs.h"
32
33/* -----------------------------------------------------------------------------
34 * Device Information
35 */
36
37static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
38 .gen = 2,
39 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
40 | RCAR_DU_FEATURE_INTERLACED
41 | RCAR_DU_FEATURE_TVM_SYNC,
42 .channels_mask = BIT(1) | BIT(0),
43 .routes = {
44 /*
45 * R8A774[34] has one RGB output and one LVDS output
46 */
47 [RCAR_DU_OUTPUT_DPAD0] = {
48 .possible_crtcs = BIT(1) | BIT(0),
49 .port = 0,
50 },
51 [RCAR_DU_OUTPUT_LVDS0] = {
52 .possible_crtcs = BIT(0),
53 .port = 1,
54 },
55 },
56 .num_lvds = 1,
57};
58
59static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
60 .gen = 2,
61 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
62 | RCAR_DU_FEATURE_INTERLACED
63 | RCAR_DU_FEATURE_TVM_SYNC,
64 .channels_mask = BIT(1) | BIT(0),
65 .routes = {
66 /*
67 * R8A7745 has two RGB outputs
68 */
69 [RCAR_DU_OUTPUT_DPAD0] = {
70 .possible_crtcs = BIT(0),
71 .port = 0,
72 },
73 [RCAR_DU_OUTPUT_DPAD1] = {
74 .possible_crtcs = BIT(1),
75 .port = 1,
76 },
77 },
78};
79
80static const struct rcar_du_device_info rzg1_du_r8a77470_info = {
81 .gen = 2,
82 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
83 | RCAR_DU_FEATURE_INTERLACED
84 | RCAR_DU_FEATURE_TVM_SYNC,
85 .channels_mask = BIT(1) | BIT(0),
86 .routes = {
87 /*
88 * R8A77470 has two RGB outputs, one LVDS output, and
89 * one (currently unsupported) analog video output
90 */
91 [RCAR_DU_OUTPUT_DPAD0] = {
92 .possible_crtcs = BIT(0),
93 .port = 0,
94 },
95 [RCAR_DU_OUTPUT_DPAD1] = {
96 .possible_crtcs = BIT(1),
97 .port = 1,
98 },
99 [RCAR_DU_OUTPUT_LVDS0] = {
100 .possible_crtcs = BIT(0) | BIT(1),
101 .port = 2,
102 },
103 },
104};
105
106static const struct rcar_du_device_info rcar_du_r8a774a1_info = {
107 .gen = 3,
108 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
109 | RCAR_DU_FEATURE_VSP1_SOURCE
110 | RCAR_DU_FEATURE_INTERLACED
111 | RCAR_DU_FEATURE_TVM_SYNC,
112 .channels_mask = BIT(2) | BIT(1) | BIT(0),
113 .routes = {
114 /*
115 * R8A774A1 has one RGB output, one LVDS output and one HDMI
116 * output.
117 */
118 [RCAR_DU_OUTPUT_DPAD0] = {
119 .possible_crtcs = BIT(2),
120 .port = 0,
121 },
122 [RCAR_DU_OUTPUT_HDMI0] = {
123 .possible_crtcs = BIT(1),
124 .port = 1,
125 },
126 [RCAR_DU_OUTPUT_LVDS0] = {
127 .possible_crtcs = BIT(0),
128 .port = 2,
129 },
130 },
131 .num_lvds = 1,
132 .dpll_mask = BIT(1),
133};
134
135static const struct rcar_du_device_info rcar_du_r8a774b1_info = {
136 .gen = 3,
137 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
138 | RCAR_DU_FEATURE_VSP1_SOURCE
139 | RCAR_DU_FEATURE_INTERLACED
140 | RCAR_DU_FEATURE_TVM_SYNC,
141 .channels_mask = BIT(3) | BIT(1) | BIT(0),
142 .routes = {
143 /*
144 * R8A774B1 has one RGB output, one LVDS output and one HDMI
145 * output.
146 */
147 [RCAR_DU_OUTPUT_DPAD0] = {
148 .possible_crtcs = BIT(2),
149 .port = 0,
150 },
151 [RCAR_DU_OUTPUT_HDMI0] = {
152 .possible_crtcs = BIT(1),
153 .port = 1,
154 },
155 [RCAR_DU_OUTPUT_LVDS0] = {
156 .possible_crtcs = BIT(0),
157 .port = 2,
158 },
159 },
160 .num_lvds = 1,
161 .dpll_mask = BIT(1),
162};
163
164static const struct rcar_du_device_info rcar_du_r8a774c0_info = {
165 .gen = 3,
166 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
167 | RCAR_DU_FEATURE_VSP1_SOURCE,
168 .channels_mask = BIT(1) | BIT(0),
169 .routes = {
170 /*
171 * R8A774C0 has one RGB output and two LVDS outputs
172 */
173 [RCAR_DU_OUTPUT_DPAD0] = {
174 .possible_crtcs = BIT(0) | BIT(1),
175 .port = 0,
176 },
177 [RCAR_DU_OUTPUT_LVDS0] = {
178 .possible_crtcs = BIT(0),
179 .port = 1,
180 },
181 [RCAR_DU_OUTPUT_LVDS1] = {
182 .possible_crtcs = BIT(1),
183 .port = 2,
184 },
185 },
186 .num_lvds = 2,
187 .lvds_clk_mask = BIT(1) | BIT(0),
188};
189
190static const struct rcar_du_device_info rcar_du_r8a774e1_info = {
191 .gen = 3,
192 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
193 | RCAR_DU_FEATURE_VSP1_SOURCE
194 | RCAR_DU_FEATURE_INTERLACED
195 | RCAR_DU_FEATURE_TVM_SYNC,
196 .channels_mask = BIT(3) | BIT(1) | BIT(0),
197 .routes = {
198 /*
199 * R8A774E1 has one RGB output, one LVDS output and one HDMI
200 * output.
201 */
202 [RCAR_DU_OUTPUT_DPAD0] = {
203 .possible_crtcs = BIT(2),
204 .port = 0,
205 },
206 [RCAR_DU_OUTPUT_HDMI0] = {
207 .possible_crtcs = BIT(1),
208 .port = 1,
209 },
210 [RCAR_DU_OUTPUT_LVDS0] = {
211 .possible_crtcs = BIT(0),
212 .port = 2,
213 },
214 },
215 .num_lvds = 1,
216 .dpll_mask = BIT(1),
217};
218
219static const struct rcar_du_device_info rcar_du_r8a7779_info = {
220 .gen = 1,
221 .features = RCAR_DU_FEATURE_INTERLACED
222 | RCAR_DU_FEATURE_TVM_SYNC,
223 .channels_mask = BIT(1) | BIT(0),
224 .routes = {
225 /*
226 * R8A7779 has two RGB outputs and one (currently unsupported)
227 * TCON output.
228 */
229 [RCAR_DU_OUTPUT_DPAD0] = {
230 .possible_crtcs = BIT(0),
231 .port = 0,
232 },
233 [RCAR_DU_OUTPUT_DPAD1] = {
234 .possible_crtcs = BIT(1) | BIT(0),
235 .port = 1,
236 },
237 },
238};
239
240static const struct rcar_du_device_info rcar_du_r8a7790_info = {
241 .gen = 2,
242 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
243 | RCAR_DU_FEATURE_INTERLACED
244 | RCAR_DU_FEATURE_TVM_SYNC,
245 .quirks = RCAR_DU_QUIRK_ALIGN_128B,
246 .channels_mask = BIT(2) | BIT(1) | BIT(0),
247 .routes = {
248 /*
249 * R8A7742 and R8A7790 each have one RGB output and two LVDS
250 * outputs. Additionally R8A7790 supports one TCON output
251 * (currently unsupported by the driver).
252 */
253 [RCAR_DU_OUTPUT_DPAD0] = {
254 .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
255 .port = 0,
256 },
257 [RCAR_DU_OUTPUT_LVDS0] = {
258 .possible_crtcs = BIT(0),
259 .port = 1,
260 },
261 [RCAR_DU_OUTPUT_LVDS1] = {
262 .possible_crtcs = BIT(2) | BIT(1),
263 .port = 2,
264 },
265 },
266 .num_lvds = 2,
267};
268
269/* M2-W (r8a7791) and M2-N (r8a7793) are identical */
270static const struct rcar_du_device_info rcar_du_r8a7791_info = {
271 .gen = 2,
272 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
273 | RCAR_DU_FEATURE_INTERLACED
274 | RCAR_DU_FEATURE_TVM_SYNC,
275 .channels_mask = BIT(1) | BIT(0),
276 .routes = {
277 /*
278 * R8A779[13] has one RGB output, one LVDS output and one
279 * (currently unsupported) TCON output.
280 */
281 [RCAR_DU_OUTPUT_DPAD0] = {
282 .possible_crtcs = BIT(1) | BIT(0),
283 .port = 0,
284 },
285 [RCAR_DU_OUTPUT_LVDS0] = {
286 .possible_crtcs = BIT(0),
287 .port = 1,
288 },
289 },
290 .num_lvds = 1,
291};
292
293static const struct rcar_du_device_info rcar_du_r8a7792_info = {
294 .gen = 2,
295 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
296 | RCAR_DU_FEATURE_INTERLACED
297 | RCAR_DU_FEATURE_TVM_SYNC,
298 .channels_mask = BIT(1) | BIT(0),
299 .routes = {
300 /* R8A7792 has two RGB outputs. */
301 [RCAR_DU_OUTPUT_DPAD0] = {
302 .possible_crtcs = BIT(0),
303 .port = 0,
304 },
305 [RCAR_DU_OUTPUT_DPAD1] = {
306 .possible_crtcs = BIT(1),
307 .port = 1,
308 },
309 },
310};
311
312static const struct rcar_du_device_info rcar_du_r8a7794_info = {
313 .gen = 2,
314 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
315 | RCAR_DU_FEATURE_INTERLACED
316 | RCAR_DU_FEATURE_TVM_SYNC,
317 .channels_mask = BIT(1) | BIT(0),
318 .routes = {
319 /*
320 * R8A7794 has two RGB outputs and one (currently unsupported)
321 * TCON output.
322 */
323 [RCAR_DU_OUTPUT_DPAD0] = {
324 .possible_crtcs = BIT(0),
325 .port = 0,
326 },
327 [RCAR_DU_OUTPUT_DPAD1] = {
328 .possible_crtcs = BIT(1),
329 .port = 1,
330 },
331 },
332};
333
334static const struct rcar_du_device_info rcar_du_r8a7795_info = {
335 .gen = 3,
336 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
337 | RCAR_DU_FEATURE_VSP1_SOURCE
338 | RCAR_DU_FEATURE_INTERLACED
339 | RCAR_DU_FEATURE_TVM_SYNC,
340 .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
341 .routes = {
342 /*
343 * R8A7795 has one RGB output, two HDMI outputs and one
344 * LVDS output.
345 */
346 [RCAR_DU_OUTPUT_DPAD0] = {
347 .possible_crtcs = BIT(3),
348 .port = 0,
349 },
350 [RCAR_DU_OUTPUT_HDMI0] = {
351 .possible_crtcs = BIT(1),
352 .port = 1,
353 },
354 [RCAR_DU_OUTPUT_HDMI1] = {
355 .possible_crtcs = BIT(2),
356 .port = 2,
357 },
358 [RCAR_DU_OUTPUT_LVDS0] = {
359 .possible_crtcs = BIT(0),
360 .port = 3,
361 },
362 },
363 .num_lvds = 1,
364 .dpll_mask = BIT(2) | BIT(1),
365};
366
367static const struct rcar_du_device_info rcar_du_r8a7796_info = {
368 .gen = 3,
369 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
370 | RCAR_DU_FEATURE_VSP1_SOURCE
371 | RCAR_DU_FEATURE_INTERLACED
372 | RCAR_DU_FEATURE_TVM_SYNC,
373 .channels_mask = BIT(2) | BIT(1) | BIT(0),
374 .routes = {
375 /*
376 * R8A7796 has one RGB output, one LVDS output and one HDMI
377 * output.
378 */
379 [RCAR_DU_OUTPUT_DPAD0] = {
380 .possible_crtcs = BIT(2),
381 .port = 0,
382 },
383 [RCAR_DU_OUTPUT_HDMI0] = {
384 .possible_crtcs = BIT(1),
385 .port = 1,
386 },
387 [RCAR_DU_OUTPUT_LVDS0] = {
388 .possible_crtcs = BIT(0),
389 .port = 2,
390 },
391 },
392 .num_lvds = 1,
393 .dpll_mask = BIT(1),
394};
395
396static const struct rcar_du_device_info rcar_du_r8a77965_info = {
397 .gen = 3,
398 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
399 | RCAR_DU_FEATURE_VSP1_SOURCE
400 | RCAR_DU_FEATURE_INTERLACED
401 | RCAR_DU_FEATURE_TVM_SYNC,
402 .channels_mask = BIT(3) | BIT(1) | BIT(0),
403 .routes = {
404 /*
405 * R8A77965 has one RGB output, one LVDS output and one HDMI
406 * output.
407 */
408 [RCAR_DU_OUTPUT_DPAD0] = {
409 .possible_crtcs = BIT(2),
410 .port = 0,
411 },
412 [RCAR_DU_OUTPUT_HDMI0] = {
413 .possible_crtcs = BIT(1),
414 .port = 1,
415 },
416 [RCAR_DU_OUTPUT_LVDS0] = {
417 .possible_crtcs = BIT(0),
418 .port = 2,
419 },
420 },
421 .num_lvds = 1,
422 .dpll_mask = BIT(1),
423};
424
425static const struct rcar_du_device_info rcar_du_r8a77970_info = {
426 .gen = 3,
427 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
428 | RCAR_DU_FEATURE_VSP1_SOURCE
429 | RCAR_DU_FEATURE_INTERLACED
430 | RCAR_DU_FEATURE_TVM_SYNC,
431 .channels_mask = BIT(0),
432 .routes = {
433 /*
434 * R8A77970 and R8A77980 have one RGB output and one LVDS
435 * output.
436 */
437 [RCAR_DU_OUTPUT_DPAD0] = {
438 .possible_crtcs = BIT(0),
439 .port = 0,
440 },
441 [RCAR_DU_OUTPUT_LVDS0] = {
442 .possible_crtcs = BIT(0),
443 .port = 1,
444 },
445 },
446 .num_lvds = 1,
447};
448
449static const struct rcar_du_device_info rcar_du_r8a7799x_info = {
450 .gen = 3,
451 .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
452 | RCAR_DU_FEATURE_VSP1_SOURCE,
453 .channels_mask = BIT(1) | BIT(0),
454 .routes = {
455 /*
456 * R8A77990 and R8A77995 have one RGB output and two LVDS
457 * outputs.
458 */
459 [RCAR_DU_OUTPUT_DPAD0] = {
460 .possible_crtcs = BIT(0) | BIT(1),
461 .port = 0,
462 },
463 [RCAR_DU_OUTPUT_LVDS0] = {
464 .possible_crtcs = BIT(0),
465 .port = 1,
466 },
467 [RCAR_DU_OUTPUT_LVDS1] = {
468 .possible_crtcs = BIT(1),
469 .port = 2,
470 },
471 },
472 .num_lvds = 2,
473 .lvds_clk_mask = BIT(1) | BIT(0),
474};
475
476static const struct of_device_id rcar_du_of_table[] = {
477 { .compatible = "renesas,du-r8a7742", .data = &rcar_du_r8a7790_info },
478 { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
479 { .compatible = "renesas,du-r8a7744", .data = &rzg1_du_r8a7743_info },
480 { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
481 { .compatible = "renesas,du-r8a77470", .data = &rzg1_du_r8a77470_info },
482 { .compatible = "renesas,du-r8a774a1", .data = &rcar_du_r8a774a1_info },
483 { .compatible = "renesas,du-r8a774b1", .data = &rcar_du_r8a774b1_info },
484 { .compatible = "renesas,du-r8a774c0", .data = &rcar_du_r8a774c0_info },
485 { .compatible = "renesas,du-r8a774e1", .data = &rcar_du_r8a774e1_info },
486 { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
487 { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
488 { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
489 { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
490 { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
491 { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
492 { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
493 { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
494 { .compatible = "renesas,du-r8a77961", .data = &rcar_du_r8a7796_info },
495 { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
496 { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
497 { .compatible = "renesas,du-r8a77980", .data = &rcar_du_r8a77970_info },
498 { .compatible = "renesas,du-r8a77990", .data = &rcar_du_r8a7799x_info },
499 { .compatible = "renesas,du-r8a77995", .data = &rcar_du_r8a7799x_info },
500 { }
501};
502
503MODULE_DEVICE_TABLE(of, rcar_du_of_table);
504
505/* -----------------------------------------------------------------------------
506 * DRM operations
507 */
508
509DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
510
511static const struct drm_driver rcar_du_driver = {
512 .driver_features = DRIVER_GEM | DRIVER_MODESET | DRIVER_ATOMIC,
513 DRM_GEM_CMA_DRIVER_OPS_WITH_DUMB_CREATE(rcar_du_dumb_create),
514 .fops = &rcar_du_fops,
515 .name = "rcar-du",
516 .desc = "Renesas R-Car Display Unit",
517 .date = "20130110",
518 .major = 1,
519 .minor = 0,
520};
521
522/* -----------------------------------------------------------------------------
523 * Power management
524 */
525
526#ifdef CONFIG_PM_SLEEP
527static int rcar_du_pm_suspend(struct device *dev)
528{
529 struct rcar_du_device *rcdu = dev_get_drvdata(dev);
530
531 return drm_mode_config_helper_suspend(&rcdu->ddev);
532}
533
534static int rcar_du_pm_resume(struct device *dev)
535{
536 struct rcar_du_device *rcdu = dev_get_drvdata(dev);
537
538 return drm_mode_config_helper_resume(&rcdu->ddev);
539}
540#endif
541
542static const struct dev_pm_ops rcar_du_pm_ops = {
543 SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume)
544};
545
546/* -----------------------------------------------------------------------------
547 * Platform driver
548 */
549
550static int rcar_du_remove(struct platform_device *pdev)
551{
552 struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
553 struct drm_device *ddev = &rcdu->ddev;
554
555 drm_dev_unregister(ddev);
556
557 drm_kms_helper_poll_fini(ddev);
558
559 return 0;
560}
561
562static void rcar_du_shutdown(struct platform_device *pdev)
563{
564 struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
565
566 drm_atomic_helper_shutdown(&rcdu->ddev);
567}
568
569static int rcar_du_probe(struct platform_device *pdev)
570{
571 struct rcar_du_device *rcdu;
572 struct resource *mem;
573 int ret;
574
575 /* Allocate and initialize the R-Car device structure. */
576 rcdu = devm_drm_dev_alloc(&pdev->dev, &rcar_du_driver,
577 struct rcar_du_device, ddev);
578 if (IS_ERR(rcdu))
579 return PTR_ERR(rcdu);
580
581 rcdu->dev = &pdev->dev;
582 rcdu->info = of_device_get_match_data(rcdu->dev);
583
584 platform_set_drvdata(pdev, rcdu);
585
586 /* I/O resources */
587 mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
588 rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
589 if (IS_ERR(rcdu->mmio))
590 return PTR_ERR(rcdu->mmio);
591
592 /* DRM/KMS objects */
593 ret = rcar_du_modeset_init(rcdu);
594 if (ret < 0) {
595 if (ret != -EPROBE_DEFER)
596 dev_err(&pdev->dev,
597 "failed to initialize DRM/KMS (%d)\n", ret);
598 goto error;
599 }
600
601 rcdu->ddev.irq_enabled = 1;
602
603 /*
604 * Register the DRM device with the core and the connectors with
605 * sysfs.
606 */
607 ret = drm_dev_register(&rcdu->ddev, 0);
608 if (ret)
609 goto error;
610
611 DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
612
613 drm_fbdev_generic_setup(&rcdu->ddev, 32);
614
615 return 0;
616
617error:
618 drm_kms_helper_poll_fini(&rcdu->ddev);
619 return ret;
620}
621
622static struct platform_driver rcar_du_platform_driver = {
623 .probe = rcar_du_probe,
624 .remove = rcar_du_remove,
625 .shutdown = rcar_du_shutdown,
626 .driver = {
627 .name = "rcar-du",
628 .pm = &rcar_du_pm_ops,
629 .of_match_table = rcar_du_of_table,
630 },
631};
632
633static int __init rcar_du_init(void)
634{
635 rcar_du_of_init(rcar_du_of_table);
636
637 return platform_driver_register(&rcar_du_platform_driver);
638}
639module_init(rcar_du_init);
640
641static void __exit rcar_du_exit(void)
642{
643 platform_driver_unregister(&rcar_du_platform_driver);
644}
645module_exit(rcar_du_exit);
646
647MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
648MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver");
649MODULE_LICENSE("GPL");