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 
rcar_du_output_name(enum rcar_du_output output)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
rcar_du_pm_suspend(struct device * dev)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 
rcar_du_pm_resume(struct device * dev)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 
rcar_du_remove(struct platform_device * pdev)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 
rcar_du_shutdown(struct platform_device * pdev)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 
rcar_du_probe(struct platform_device * pdev)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");
709