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