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