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