GNU Linux-libre 4.19.211-gnu1
[releases.git] / drivers / gpu / drm / rcar-du / rcar_du_drv.c
1 /*
2  * rcar_du_drv.c  --  R-Car Display Unit DRM driver
3  *
4  * Copyright (C) 2013-2015 Renesas Electronics Corporation
5  *
6  * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com)
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License as published by
10  * the Free Software Foundation; either version 2 of the License, or
11  * (at your option) any later version.
12  */
13
14 #include <linux/clk.h>
15 #include <linux/io.h>
16 #include <linux/mm.h>
17 #include <linux/module.h>
18 #include <linux/of_device.h>
19 #include <linux/platform_device.h>
20 #include <linux/pm.h>
21 #include <linux/slab.h>
22 #include <linux/wait.h>
23
24 #include <drm/drmP.h>
25 #include <drm/drm_atomic_helper.h>
26 #include <drm/drm_crtc_helper.h>
27 #include <drm/drm_fb_cma_helper.h>
28 #include <drm/drm_gem_cma_helper.h>
29
30 #include "rcar_du_drv.h"
31 #include "rcar_du_kms.h"
32 #include "rcar_du_of.h"
33 #include "rcar_du_regs.h"
34
35 /* -----------------------------------------------------------------------------
36  * Device Information
37  */
38
39 static const struct rcar_du_device_info rzg1_du_r8a7743_info = {
40         .gen = 2,
41         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
42                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
43         .channels_mask = BIT(1) | BIT(0),
44         .routes = {
45                 /*
46                  * R8A7743 has one RGB output and one LVDS output
47                  */
48                 [RCAR_DU_OUTPUT_DPAD0] = {
49                         .possible_crtcs = BIT(1) | BIT(0),
50                         .port = 0,
51                 },
52                 [RCAR_DU_OUTPUT_LVDS0] = {
53                         .possible_crtcs = BIT(0),
54                         .port = 1,
55                 },
56         },
57         .num_lvds = 1,
58 };
59
60 static const struct rcar_du_device_info rzg1_du_r8a7745_info = {
61         .gen = 2,
62         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
63                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
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
80 static const struct rcar_du_device_info rcar_du_r8a7779_info = {
81         .gen = 2,
82         .features = 0,
83         .channels_mask = BIT(1) | BIT(0),
84         .routes = {
85                 /*
86                  * R8A7779 has two RGB outputs and one (currently unsupported)
87                  * TCON output.
88                  */
89                 [RCAR_DU_OUTPUT_DPAD0] = {
90                         .possible_crtcs = BIT(0),
91                         .port = 0,
92                 },
93                 [RCAR_DU_OUTPUT_DPAD1] = {
94                         .possible_crtcs = BIT(1) | BIT(0),
95                         .port = 1,
96                 },
97         },
98 };
99
100 static const struct rcar_du_device_info rcar_du_r8a7790_info = {
101         .gen = 2,
102         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
103                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
104         .quirks = RCAR_DU_QUIRK_ALIGN_128B,
105         .channels_mask = BIT(2) | BIT(1) | BIT(0),
106         .routes = {
107                 /*
108                  * R8A7790 has one RGB output, two LVDS outputs and one
109                  * (currently unsupported) TCON output.
110                  */
111                 [RCAR_DU_OUTPUT_DPAD0] = {
112                         .possible_crtcs = BIT(2) | BIT(1) | BIT(0),
113                         .port = 0,
114                 },
115                 [RCAR_DU_OUTPUT_LVDS0] = {
116                         .possible_crtcs = BIT(0),
117                         .port = 1,
118                 },
119                 [RCAR_DU_OUTPUT_LVDS1] = {
120                         .possible_crtcs = BIT(2) | BIT(1),
121                         .port = 2,
122                 },
123         },
124         .num_lvds = 2,
125 };
126
127 /* M2-W (r8a7791) and M2-N (r8a7793) are identical */
128 static const struct rcar_du_device_info rcar_du_r8a7791_info = {
129         .gen = 2,
130         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
131                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
132         .channels_mask = BIT(1) | BIT(0),
133         .routes = {
134                 /*
135                  * R8A779[13] has one RGB output, one LVDS output and one
136                  * (currently unsupported) TCON output.
137                  */
138                 [RCAR_DU_OUTPUT_DPAD0] = {
139                         .possible_crtcs = BIT(1) | BIT(0),
140                         .port = 0,
141                 },
142                 [RCAR_DU_OUTPUT_LVDS0] = {
143                         .possible_crtcs = BIT(0),
144                         .port = 1,
145                 },
146         },
147         .num_lvds = 1,
148 };
149
150 static const struct rcar_du_device_info rcar_du_r8a7792_info = {
151         .gen = 2,
152         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
153                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
154         .channels_mask = BIT(1) | BIT(0),
155         .routes = {
156                 /* R8A7792 has two RGB outputs. */
157                 [RCAR_DU_OUTPUT_DPAD0] = {
158                         .possible_crtcs = BIT(0),
159                         .port = 0,
160                 },
161                 [RCAR_DU_OUTPUT_DPAD1] = {
162                         .possible_crtcs = BIT(1),
163                         .port = 1,
164                 },
165         },
166 };
167
168 static const struct rcar_du_device_info rcar_du_r8a7794_info = {
169         .gen = 2,
170         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
171                   | RCAR_DU_FEATURE_EXT_CTRL_REGS,
172         .channels_mask = BIT(1) | BIT(0),
173         .routes = {
174                 /*
175                  * R8A7794 has two RGB outputs and one (currently unsupported)
176                  * TCON output.
177                  */
178                 [RCAR_DU_OUTPUT_DPAD0] = {
179                         .possible_crtcs = BIT(0),
180                         .port = 0,
181                 },
182                 [RCAR_DU_OUTPUT_DPAD1] = {
183                         .possible_crtcs = BIT(1),
184                         .port = 1,
185                 },
186         },
187 };
188
189 static const struct rcar_du_device_info rcar_du_r8a7795_info = {
190         .gen = 3,
191         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
192                   | RCAR_DU_FEATURE_EXT_CTRL_REGS
193                   | RCAR_DU_FEATURE_VSP1_SOURCE,
194         .channels_mask = BIT(3) | BIT(2) | BIT(1) | BIT(0),
195         .routes = {
196                 /*
197                  * R8A7795 has one RGB output, two HDMI outputs and one
198                  * LVDS output.
199                  */
200                 [RCAR_DU_OUTPUT_DPAD0] = {
201                         .possible_crtcs = BIT(3),
202                         .port = 0,
203                 },
204                 [RCAR_DU_OUTPUT_HDMI0] = {
205                         .possible_crtcs = BIT(1),
206                         .port = 1,
207                 },
208                 [RCAR_DU_OUTPUT_HDMI1] = {
209                         .possible_crtcs = BIT(2),
210                         .port = 2,
211                 },
212                 [RCAR_DU_OUTPUT_LVDS0] = {
213                         .possible_crtcs = BIT(0),
214                         .port = 3,
215                 },
216         },
217         .num_lvds = 1,
218         .dpll_ch =  BIT(2) | BIT(1),
219 };
220
221 static const struct rcar_du_device_info rcar_du_r8a7796_info = {
222         .gen = 3,
223         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
224                   | RCAR_DU_FEATURE_EXT_CTRL_REGS
225                   | RCAR_DU_FEATURE_VSP1_SOURCE,
226         .channels_mask = BIT(2) | BIT(1) | BIT(0),
227         .routes = {
228                 /*
229                  * R8A7796 has one RGB output, one LVDS output and one HDMI
230                  * output.
231                  */
232                 [RCAR_DU_OUTPUT_DPAD0] = {
233                         .possible_crtcs = BIT(2),
234                         .port = 0,
235                 },
236                 [RCAR_DU_OUTPUT_HDMI0] = {
237                         .possible_crtcs = BIT(1),
238                         .port = 1,
239                 },
240                 [RCAR_DU_OUTPUT_LVDS0] = {
241                         .possible_crtcs = BIT(0),
242                         .port = 2,
243                 },
244         },
245         .num_lvds = 1,
246         .dpll_ch =  BIT(1),
247 };
248
249 static const struct rcar_du_device_info rcar_du_r8a77965_info = {
250         .gen = 3,
251         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
252                   | RCAR_DU_FEATURE_EXT_CTRL_REGS
253                   | RCAR_DU_FEATURE_VSP1_SOURCE,
254         .channels_mask = BIT(3) | BIT(1) | BIT(0),
255         .routes = {
256                 /*
257                  * R8A77965 has one RGB output, one LVDS output and one HDMI
258                  * output.
259                  */
260                 [RCAR_DU_OUTPUT_DPAD0] = {
261                         .possible_crtcs = BIT(2),
262                         .port = 0,
263                 },
264                 [RCAR_DU_OUTPUT_HDMI0] = {
265                         .possible_crtcs = BIT(1),
266                         .port = 1,
267                 },
268                 [RCAR_DU_OUTPUT_LVDS0] = {
269                         .possible_crtcs = BIT(0),
270                         .port = 2,
271                 },
272         },
273         .num_lvds = 1,
274         .dpll_ch =  BIT(1),
275 };
276
277 static const struct rcar_du_device_info rcar_du_r8a77970_info = {
278         .gen = 3,
279         .features = RCAR_DU_FEATURE_CRTC_IRQ_CLOCK
280                   | RCAR_DU_FEATURE_EXT_CTRL_REGS
281                   | RCAR_DU_FEATURE_VSP1_SOURCE,
282         .channels_mask = BIT(0),
283         .routes = {
284                 /* R8A77970 has one RGB output and one LVDS output. */
285                 [RCAR_DU_OUTPUT_DPAD0] = {
286                         .possible_crtcs = BIT(0),
287                         .port = 0,
288                 },
289                 [RCAR_DU_OUTPUT_LVDS0] = {
290                         .possible_crtcs = BIT(0),
291                         .port = 1,
292                 },
293         },
294         .num_lvds = 1,
295 };
296
297 static const struct of_device_id rcar_du_of_table[] = {
298         { .compatible = "renesas,du-r8a7743", .data = &rzg1_du_r8a7743_info },
299         { .compatible = "renesas,du-r8a7745", .data = &rzg1_du_r8a7745_info },
300         { .compatible = "renesas,du-r8a7779", .data = &rcar_du_r8a7779_info },
301         { .compatible = "renesas,du-r8a7790", .data = &rcar_du_r8a7790_info },
302         { .compatible = "renesas,du-r8a7791", .data = &rcar_du_r8a7791_info },
303         { .compatible = "renesas,du-r8a7792", .data = &rcar_du_r8a7792_info },
304         { .compatible = "renesas,du-r8a7793", .data = &rcar_du_r8a7791_info },
305         { .compatible = "renesas,du-r8a7794", .data = &rcar_du_r8a7794_info },
306         { .compatible = "renesas,du-r8a7795", .data = &rcar_du_r8a7795_info },
307         { .compatible = "renesas,du-r8a7796", .data = &rcar_du_r8a7796_info },
308         { .compatible = "renesas,du-r8a77965", .data = &rcar_du_r8a77965_info },
309         { .compatible = "renesas,du-r8a77970", .data = &rcar_du_r8a77970_info },
310         { }
311 };
312
313 MODULE_DEVICE_TABLE(of, rcar_du_of_table);
314
315 /* -----------------------------------------------------------------------------
316  * DRM operations
317  */
318
319 static void rcar_du_lastclose(struct drm_device *dev)
320 {
321         struct rcar_du_device *rcdu = dev->dev_private;
322
323         drm_fbdev_cma_restore_mode(rcdu->fbdev);
324 }
325
326 DEFINE_DRM_GEM_CMA_FOPS(rcar_du_fops);
327
328 static struct drm_driver rcar_du_driver = {
329         .driver_features        = DRIVER_GEM | DRIVER_MODESET | DRIVER_PRIME
330                                 | DRIVER_ATOMIC,
331         .lastclose              = rcar_du_lastclose,
332         .gem_free_object_unlocked = drm_gem_cma_free_object,
333         .gem_vm_ops             = &drm_gem_cma_vm_ops,
334         .prime_handle_to_fd     = drm_gem_prime_handle_to_fd,
335         .prime_fd_to_handle     = drm_gem_prime_fd_to_handle,
336         .gem_prime_import       = drm_gem_prime_import,
337         .gem_prime_export       = drm_gem_prime_export,
338         .gem_prime_get_sg_table = drm_gem_cma_prime_get_sg_table,
339         .gem_prime_import_sg_table = drm_gem_cma_prime_import_sg_table,
340         .gem_prime_vmap         = drm_gem_cma_prime_vmap,
341         .gem_prime_vunmap       = drm_gem_cma_prime_vunmap,
342         .gem_prime_mmap         = drm_gem_cma_prime_mmap,
343         .dumb_create            = rcar_du_dumb_create,
344         .fops                   = &rcar_du_fops,
345         .name                   = "rcar-du",
346         .desc                   = "Renesas R-Car Display Unit",
347         .date                   = "20130110",
348         .major                  = 1,
349         .minor                  = 0,
350 };
351
352 /* -----------------------------------------------------------------------------
353  * Power management
354  */
355
356 #ifdef CONFIG_PM_SLEEP
357 static int rcar_du_pm_suspend(struct device *dev)
358 {
359         struct rcar_du_device *rcdu = dev_get_drvdata(dev);
360         struct drm_atomic_state *state;
361
362         drm_kms_helper_poll_disable(rcdu->ddev);
363         drm_fbdev_cma_set_suspend_unlocked(rcdu->fbdev, true);
364
365         state = drm_atomic_helper_suspend(rcdu->ddev);
366         if (IS_ERR(state)) {
367                 drm_fbdev_cma_set_suspend_unlocked(rcdu->fbdev, false);
368                 drm_kms_helper_poll_enable(rcdu->ddev);
369                 return PTR_ERR(state);
370         }
371
372         rcdu->suspend_state = state;
373
374         return 0;
375 }
376
377 static int rcar_du_pm_resume(struct device *dev)
378 {
379         struct rcar_du_device *rcdu = dev_get_drvdata(dev);
380
381         drm_atomic_helper_resume(rcdu->ddev, rcdu->suspend_state);
382         drm_fbdev_cma_set_suspend_unlocked(rcdu->fbdev, false);
383         drm_kms_helper_poll_enable(rcdu->ddev);
384
385         return 0;
386 }
387 #endif
388
389 static const struct dev_pm_ops rcar_du_pm_ops = {
390         SET_SYSTEM_SLEEP_PM_OPS(rcar_du_pm_suspend, rcar_du_pm_resume)
391 };
392
393 /* -----------------------------------------------------------------------------
394  * Platform driver
395  */
396
397 static int rcar_du_remove(struct platform_device *pdev)
398 {
399         struct rcar_du_device *rcdu = platform_get_drvdata(pdev);
400         struct drm_device *ddev = rcdu->ddev;
401
402         drm_dev_unregister(ddev);
403
404         if (rcdu->fbdev)
405                 drm_fbdev_cma_fini(rcdu->fbdev);
406
407         drm_kms_helper_poll_fini(ddev);
408         drm_mode_config_cleanup(ddev);
409
410         drm_dev_unref(ddev);
411
412         return 0;
413 }
414
415 static int rcar_du_probe(struct platform_device *pdev)
416 {
417         struct rcar_du_device *rcdu;
418         struct drm_device *ddev;
419         struct resource *mem;
420         int ret;
421
422         /* Allocate and initialize the R-Car device structure. */
423         rcdu = devm_kzalloc(&pdev->dev, sizeof(*rcdu), GFP_KERNEL);
424         if (rcdu == NULL)
425                 return -ENOMEM;
426
427         rcdu->dev = &pdev->dev;
428         rcdu->info = of_device_get_match_data(rcdu->dev);
429
430         platform_set_drvdata(pdev, rcdu);
431
432         /* I/O resources */
433         mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
434         rcdu->mmio = devm_ioremap_resource(&pdev->dev, mem);
435         if (IS_ERR(rcdu->mmio))
436                 return PTR_ERR(rcdu->mmio);
437
438         /* DRM/KMS objects */
439         ddev = drm_dev_alloc(&rcar_du_driver, &pdev->dev);
440         if (IS_ERR(ddev))
441                 return PTR_ERR(ddev);
442
443         rcdu->ddev = ddev;
444         ddev->dev_private = rcdu;
445
446         ret = rcar_du_modeset_init(rcdu);
447         if (ret < 0) {
448                 if (ret != -EPROBE_DEFER)
449                         dev_err(&pdev->dev,
450                                 "failed to initialize DRM/KMS (%d)\n", ret);
451                 goto error;
452         }
453
454         ddev->irq_enabled = 1;
455
456         /*
457          * Register the DRM device with the core and the connectors with
458          * sysfs.
459          */
460         ret = drm_dev_register(ddev, 0);
461         if (ret)
462                 goto error;
463
464         DRM_INFO("Device %s probed\n", dev_name(&pdev->dev));
465
466         return 0;
467
468 error:
469         rcar_du_remove(pdev);
470
471         return ret;
472 }
473
474 static struct platform_driver rcar_du_platform_driver = {
475         .probe          = rcar_du_probe,
476         .remove         = rcar_du_remove,
477         .driver         = {
478                 .name   = "rcar-du",
479                 .pm     = &rcar_du_pm_ops,
480                 .of_match_table = rcar_du_of_table,
481         },
482 };
483
484 static int __init rcar_du_init(void)
485 {
486         rcar_du_of_init(rcar_du_of_table);
487
488         return platform_driver_register(&rcar_du_platform_driver);
489 }
490 module_init(rcar_du_init);
491
492 static void __exit rcar_du_exit(void)
493 {
494         platform_driver_unregister(&rcar_du_platform_driver);
495 }
496 module_exit(rcar_du_exit);
497
498 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
499 MODULE_DESCRIPTION("Renesas R-Car Display Unit DRM Driver");
500 MODULE_LICENSE("GPL");