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