aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/rcar-du/Makefile1
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.c92
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_crtc.h5
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.c46
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_drv.h10
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.c127
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_group.h47
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_kms.c11
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.c155
-rw-r--r--drivers/gpu/drm/rcar-du/rcar_du_plane.h8
10 files changed, 299 insertions, 203 deletions
diff --git a/drivers/gpu/drm/rcar-du/Makefile b/drivers/gpu/drm/rcar-du/Makefile
index 57b0fe1fa66e..b9b5e666fbba 100644
--- a/drivers/gpu/drm/rcar-du/Makefile
+++ b/drivers/gpu/drm/rcar-du/Makefile
@@ -1,6 +1,7 @@
1rcar-du-drm-y := rcar_du_crtc.o \ 1rcar-du-drm-y := rcar_du_crtc.o \
2 rcar_du_drv.o \ 2 rcar_du_drv.o \
3 rcar_du_encoder.o \ 3 rcar_du_encoder.o \
4 rcar_du_group.o \
4 rcar_du_kms.o \ 5 rcar_du_kms.o \
5 rcar_du_lvdscon.o \ 6 rcar_du_lvdscon.o \
6 rcar_du_plane.o \ 7 rcar_du_plane.o \
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
index 03dd7018dde8..7784a3ba7854 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.c
@@ -30,21 +30,21 @@
30 30
31static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) 31static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
32{ 32{
33 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 33 struct rcar_du_device *rcdu = rcrtc->group->dev;
34 34
35 return rcar_du_read(rcdu, rcrtc->mmio_offset + reg); 35 return rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
36} 36}
37 37
38static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data) 38static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data)
39{ 39{
40 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 40 struct rcar_du_device *rcdu = rcrtc->group->dev;
41 41
42 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data); 42 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data);
43} 43}
44 44
45static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr) 45static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
46{ 46{
47 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 47 struct rcar_du_device *rcdu = rcrtc->group->dev;
48 48
49 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, 49 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
50 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr); 50 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) & ~clr);
@@ -52,7 +52,7 @@ static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr)
52 52
53static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set) 53static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
54{ 54{
55 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 55 struct rcar_du_device *rcdu = rcrtc->group->dev;
56 56
57 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, 57 rcar_du_write(rcdu, rcrtc->mmio_offset + reg,
58 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set); 58 rcar_du_read(rcdu, rcrtc->mmio_offset + reg) | set);
@@ -61,7 +61,7 @@ static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set)
61static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg, 61static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
62 u32 clr, u32 set) 62 u32 clr, u32 set)
63{ 63{
64 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 64 struct rcar_du_device *rcdu = rcrtc->group->dev;
65 u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg); 65 u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg);
66 66
67 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set); 67 rcar_du_write(rcdu, rcrtc->mmio_offset + reg, (value & ~clr) | set);
@@ -69,14 +69,13 @@ static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg,
69 69
70static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc) 70static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
71{ 71{
72 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private;
73 int ret; 72 int ret;
74 73
75 ret = clk_prepare_enable(rcrtc->clock); 74 ret = clk_prepare_enable(rcrtc->clock);
76 if (ret < 0) 75 if (ret < 0)
77 return ret; 76 return ret;
78 77
79 ret = rcar_du_get(rcdu); 78 ret = rcar_du_group_get(rcrtc->group);
80 if (ret < 0) 79 if (ret < 0)
81 clk_disable_unprepare(rcrtc->clock); 80 clk_disable_unprepare(rcrtc->clock);
82 81
@@ -85,17 +84,14 @@ static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc)
85 84
86static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) 85static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc)
87{ 86{
88 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 87 rcar_du_group_put(rcrtc->group);
89
90 rcar_du_put(rcdu);
91 clk_disable_unprepare(rcrtc->clock); 88 clk_disable_unprepare(rcrtc->clock);
92} 89}
93 90
94static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) 91static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
95{ 92{
96 struct drm_crtc *crtc = &rcrtc->crtc; 93 const struct drm_display_mode *mode = &rcrtc->crtc.mode;
97 struct rcar_du_device *rcdu = crtc->dev->dev_private; 94 struct rcar_du_device *rcdu = rcrtc->group->dev;
98 const struct drm_display_mode *mode = &crtc->mode;
99 unsigned long clk; 95 unsigned long clk;
100 u32 value; 96 u32 value;
101 u32 div; 97 u32 div;
@@ -136,7 +132,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc)
136 132
137static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc) 133static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc)
138{ 134{
139 struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; 135 struct rcar_du_device *rcdu = rcrtc->group->dev;
140 u32 dorcr = rcar_du_read(rcdu, DORCR); 136 u32 dorcr = rcar_du_read(rcdu, DORCR);
141 137
142 dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK); 138 dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK);
@@ -153,36 +149,6 @@ static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc)
153 rcar_du_write(rcdu, DORCR, dorcr); 149 rcar_du_write(rcdu, DORCR, dorcr);
154} 150}
155 151
156static void __rcar_du_start_stop(struct rcar_du_device *rcdu, bool start)
157{
158 rcar_du_write(rcdu, DSYSR,
159 (rcar_du_read(rcdu, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
160 (start ? DSYSR_DEN : DSYSR_DRES));
161}
162
163static void rcar_du_start_stop(struct rcar_du_device *rcdu, bool start)
164{
165 /* Many of the configuration bits are only updated when the display
166 * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some
167 * of those bits could be pre-configured, but others (especially the
168 * bits related to plane assignment to display timing controllers) need
169 * to be modified at runtime.
170 *
171 * Restart the display controller if a start is requested. Sorry for the
172 * flicker. It should be possible to move most of the "DRES-update" bits
173 * setup to driver initialization time and minimize the number of cases
174 * when the display controller will have to be restarted.
175 */
176 if (start) {
177 if (rcdu->used_crtcs++ != 0)
178 __rcar_du_start_stop(rcdu, false);
179 __rcar_du_start_stop(rcdu, true);
180 } else {
181 if (--rcdu->used_crtcs == 0)
182 __rcar_du_start_stop(rcdu, false);
183 }
184}
185
186void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output) 152void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output)
187{ 153{
188 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 154 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
@@ -195,8 +161,8 @@ void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output)
195 161
196void rcar_du_crtc_update_planes(struct drm_crtc *crtc) 162void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
197{ 163{
198 struct rcar_du_device *rcdu = crtc->dev->dev_private;
199 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 164 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
165 struct rcar_du_device *rcdu = rcrtc->group->dev;
200 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; 166 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
201 unsigned int num_planes = 0; 167 unsigned int num_planes = 0;
202 unsigned int prio = 0; 168 unsigned int prio = 0;
@@ -204,8 +170,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
204 u32 dptsr = 0; 170 u32 dptsr = 0;
205 u32 dspr = 0; 171 u32 dspr = 0;
206 172
207 for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { 173 for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
208 struct rcar_du_plane *plane = &rcdu->planes.planes[i]; 174 struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
209 unsigned int j; 175 unsigned int j;
210 176
211 if (plane->crtc != &rcrtc->crtc || !plane->enabled) 177 if (plane->crtc != &rcrtc->crtc || !plane->enabled)
@@ -254,10 +220,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
254 */ 220 */
255 if (value != dptsr) { 221 if (value != dptsr) {
256 rcar_du_write(rcdu, DPTSR, dptsr); 222 rcar_du_write(rcdu, DPTSR, dptsr);
257 if (rcdu->used_crtcs) { 223 if (rcrtc->group->used_crtcs)
258 __rcar_du_start_stop(rcdu, false); 224 rcar_du_group_restart(rcrtc->group);
259 __rcar_du_start_stop(rcdu, true);
260 }
261 } 225 }
262 } 226 }
263 227
@@ -267,7 +231,6 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc)
267static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) 231static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
268{ 232{
269 struct drm_crtc *crtc = &rcrtc->crtc; 233 struct drm_crtc *crtc = &rcrtc->crtc;
270 struct rcar_du_device *rcdu = crtc->dev->dev_private;
271 unsigned int i; 234 unsigned int i;
272 235
273 if (rcrtc->started) 236 if (rcrtc->started)
@@ -284,14 +247,14 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
284 rcar_du_crtc_set_display_timing(rcrtc); 247 rcar_du_crtc_set_display_timing(rcrtc);
285 rcar_du_crtc_set_routing(rcrtc); 248 rcar_du_crtc_set_routing(rcrtc);
286 249
287 mutex_lock(&rcdu->planes.lock); 250 mutex_lock(&rcrtc->group->planes.lock);
288 rcrtc->plane->enabled = true; 251 rcrtc->plane->enabled = true;
289 rcar_du_crtc_update_planes(crtc); 252 rcar_du_crtc_update_planes(crtc);
290 mutex_unlock(&rcdu->planes.lock); 253 mutex_unlock(&rcrtc->group->planes.lock);
291 254
292 /* Setup planes. */ 255 /* Setup planes. */
293 for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { 256 for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) {
294 struct rcar_du_plane *plane = &rcdu->planes.planes[i]; 257 struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i];
295 258
296 if (plane->crtc != crtc || !plane->enabled) 259 if (plane->crtc != crtc || !plane->enabled)
297 continue; 260 continue;
@@ -305,7 +268,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
305 */ 268 */
306 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER); 269 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER);
307 270
308 rcar_du_start_stop(rcdu, true); 271 rcar_du_group_start_stop(rcrtc->group, true);
309 272
310 rcrtc->started = true; 273 rcrtc->started = true;
311} 274}
@@ -313,22 +276,21 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)
313static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) 276static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
314{ 277{
315 struct drm_crtc *crtc = &rcrtc->crtc; 278 struct drm_crtc *crtc = &rcrtc->crtc;
316 struct rcar_du_device *rcdu = crtc->dev->dev_private;
317 279
318 if (!rcrtc->started) 280 if (!rcrtc->started)
319 return; 281 return;
320 282
321 mutex_lock(&rcdu->planes.lock); 283 mutex_lock(&rcrtc->group->planes.lock);
322 rcrtc->plane->enabled = false; 284 rcrtc->plane->enabled = false;
323 rcar_du_crtc_update_planes(crtc); 285 rcar_du_crtc_update_planes(crtc);
324 mutex_unlock(&rcdu->planes.lock); 286 mutex_unlock(&rcrtc->group->planes.lock);
325 287
326 /* Select switch sync mode. This stops display operation and configures 288 /* Select switch sync mode. This stops display operation and configures
327 * the HSYNC and VSYNC signals as inputs. 289 * the HSYNC and VSYNC signals as inputs.
328 */ 290 */
329 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH); 291 rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH);
330 292
331 rcar_du_start_stop(rcdu, false); 293 rcar_du_group_start_stop(rcrtc->group, false);
332 294
333 rcrtc->started = false; 295 rcrtc->started = false;
334} 296}
@@ -406,8 +368,8 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc,
406 int x, int y, 368 int x, int y,
407 struct drm_framebuffer *old_fb) 369 struct drm_framebuffer *old_fb)
408{ 370{
409 struct rcar_du_device *rcdu = crtc->dev->dev_private;
410 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 371 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);
372 struct rcar_du_device *rcdu = rcrtc->group->dev;
411 const struct rcar_du_format_info *format; 373 const struct rcar_du_format_info *format;
412 int ret; 374 int ret;
413 375
@@ -583,8 +545,9 @@ static const struct drm_crtc_funcs crtc_funcs = {
583 .page_flip = rcar_du_crtc_page_flip, 545 .page_flip = rcar_du_crtc_page_flip,
584}; 546};
585 547
586int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index) 548int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
587{ 549{
550 struct rcar_du_device *rcdu = rgrp->dev;
588 struct platform_device *pdev = to_platform_device(rcdu->dev); 551 struct platform_device *pdev = to_platform_device(rcdu->dev);
589 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; 552 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
590 struct drm_crtc *crtc = &rcrtc->crtc; 553 struct drm_crtc *crtc = &rcrtc->crtc;
@@ -608,10 +571,11 @@ int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index)
608 return PTR_ERR(rcrtc->clock); 571 return PTR_ERR(rcrtc->clock);
609 } 572 }
610 573
574 rcrtc->group = rgrp;
611 rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0; 575 rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0;
612 rcrtc->index = index; 576 rcrtc->index = index;
613 rcrtc->dpms = DRM_MODE_DPMS_OFF; 577 rcrtc->dpms = DRM_MODE_DPMS_OFF;
614 rcrtc->plane = &rcdu->planes.planes[index]; 578 rcrtc->plane = &rgrp->planes.planes[index];
615 579
616 rcrtc->plane->crtc = crtc; 580 rcrtc->plane->crtc = crtc;
617 581
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
index 5b69e98a3b92..542a7feceb20 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_crtc.h
@@ -19,7 +19,7 @@
19#include <drm/drmP.h> 19#include <drm/drmP.h>
20#include <drm/drm_crtc.h> 20#include <drm/drm_crtc.h>
21 21
22struct rcar_du_device; 22struct rcar_du_group;
23struct rcar_du_plane; 23struct rcar_du_plane;
24 24
25struct rcar_du_crtc { 25struct rcar_du_crtc {
@@ -34,10 +34,11 @@ struct rcar_du_crtc {
34 unsigned int outputs; 34 unsigned int outputs;
35 int dpms; 35 int dpms;
36 36
37 struct rcar_du_group *group;
37 struct rcar_du_plane *plane; 38 struct rcar_du_plane *plane;
38}; 39};
39 40
40int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index); 41int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index);
41void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable); 42void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable);
42void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc, 43void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc,
43 struct drm_file *file); 44 struct drm_file *file);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.c b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
index 5f82e046f83e..cdc363b6cd37 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.c
@@ -29,52 +29,6 @@
29#include "rcar_du_regs.h" 29#include "rcar_du_regs.h"
30 30
31/* ----------------------------------------------------------------------------- 31/* -----------------------------------------------------------------------------
32 * Core device operations
33 */
34
35/*
36 * rcar_du_get - Acquire a reference to the DU
37 *
38 * Acquiring the first reference setups core registers. A reference must be
39 * held before accessing any hardware registers.
40 *
41 * This function must be called with the DRM mode_config lock held.
42 *
43 * Return 0 in case of success or a negative error code otherwise.
44 */
45int rcar_du_get(struct rcar_du_device *rcdu)
46{
47 if (rcdu->use_count)
48 goto done;
49
50 /* Enable extended features */
51 rcar_du_write(rcdu, DEFR, DEFR_CODE | DEFR_DEFE);
52 rcar_du_write(rcdu, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
53 rcar_du_write(rcdu, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
54 rcar_du_write(rcdu, DEFR4, DEFR4_CODE);
55 rcar_du_write(rcdu, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
56
57 /* Use DS1PR and DS2PR to configure planes priorities and connects the
58 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
59 */
60 rcar_du_write(rcdu, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS);
61
62done:
63 rcdu->use_count++;
64 return 0;
65}
66
67/*
68 * rcar_du_put - Release a reference to the DU
69 *
70 * This function must be called with the DRM mode_config lock held.
71 */
72void rcar_du_put(struct rcar_du_device *rcdu)
73{
74 --rcdu->use_count;
75}
76
77/* -----------------------------------------------------------------------------
78 * DRM operations 32 * DRM operations
79 */ 33 */
80 34
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_drv.h b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
index 0305c21d71f3..5b57a2f9b52a 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_drv.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_drv.h
@@ -18,11 +18,12 @@
18#include <linux/platform_data/rcar-du.h> 18#include <linux/platform_data/rcar-du.h>
19 19
20#include "rcar_du_crtc.h" 20#include "rcar_du_crtc.h"
21#include "rcar_du_plane.h" 21#include "rcar_du_group.h"
22 22
23struct clk; 23struct clk;
24struct device; 24struct device;
25struct drm_device; 25struct drm_device;
26struct rcar_du_device;
26 27
27#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ 28#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
28 29
@@ -40,15 +41,13 @@ struct rcar_du_device {
40 const struct rcar_du_device_info *info; 41 const struct rcar_du_device_info *info;
41 42
42 void __iomem *mmio; 43 void __iomem *mmio;
43 unsigned int use_count;
44 44
45 struct drm_device *ddev; 45 struct drm_device *ddev;
46 46
47 struct rcar_du_crtc crtcs[2]; 47 struct rcar_du_crtc crtcs[2];
48 unsigned int used_crtcs;
49 unsigned int num_crtcs; 48 unsigned int num_crtcs;
50 49
51 struct rcar_du_planes planes; 50 struct rcar_du_group group;
52}; 51};
53 52
54static inline bool rcar_du_has(struct rcar_du_device *rcdu, 53static inline bool rcar_du_has(struct rcar_du_device *rcdu,
@@ -57,9 +56,6 @@ static inline bool rcar_du_has(struct rcar_du_device *rcdu,
57 return rcdu->info->features & feature; 56 return rcdu->info->features & feature;
58} 57}
59 58
60int rcar_du_get(struct rcar_du_device *rcdu);
61void rcar_du_put(struct rcar_du_device *rcdu);
62
63static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg) 59static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg)
64{ 60{
65 return ioread32(rcdu->mmio + reg); 61 return ioread32(rcdu->mmio + reg);
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.c b/drivers/gpu/drm/rcar-du/rcar_du_group.c
new file mode 100644
index 000000000000..625b9f446965
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.c
@@ -0,0 +1,127 @@
1/*
2 * rcar_du_group.c -- R-Car Display Unit Channels Pair
3 *
4 * Copyright (C) 2013 Renesas 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/*
15 * The R8A7779 DU is split in per-CRTC resources (scan-out engine, blending
16 * unit, timings generator, ...) and device-global resources (start/stop
17 * control, planes, ...) shared between the two CRTCs.
18 *
19 * The R8A7790 introduced a third CRTC with its own set of global resources.
20 * This would be modeled as two separate DU device instances if it wasn't for
21 * a handful or resources that are shared between the three CRTCs (mostly
22 * related to input and output routing). For this reason the R8A7790 DU must be
23 * modeled as a single device with three CRTCs, two sets of "semi-global"
24 * resources, and a few device-global resources.
25 *
26 * The rcar_du_group object is a driver specific object, without any real
27 * counterpart in the DU documentation, that models those semi-global resources.
28 */
29
30#include <linux/io.h>
31
32#include "rcar_du_drv.h"
33#include "rcar_du_group.h"
34#include "rcar_du_regs.h"
35
36static u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg)
37{
38 return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg);
39}
40
41static void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data)
42{
43 rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data);
44}
45
46static void rcar_du_group_setup(struct rcar_du_group *rgrp)
47{
48 /* Enable extended features */
49 rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE);
50 rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G);
51 rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3);
52 rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE);
53 rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5);
54
55 /* Use DS1PR and DS2PR to configure planes priorities and connects the
56 * superposition 0 to DU0 pins. DU1 pins will be configured dynamically.
57 */
58 rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS);
59}
60
61/*
62 * rcar_du_group_get - Acquire a reference to the DU channels group
63 *
64 * Acquiring the first reference setups core registers. A reference must be held
65 * before accessing any hardware registers.
66 *
67 * This function must be called with the DRM mode_config lock held.
68 *
69 * Return 0 in case of success or a negative error code otherwise.
70 */
71int rcar_du_group_get(struct rcar_du_group *rgrp)
72{
73 if (rgrp->use_count)
74 goto done;
75
76 rcar_du_group_setup(rgrp);
77
78done:
79 rgrp->use_count++;
80 return 0;
81}
82
83/*
84 * rcar_du_group_put - Release a reference to the DU
85 *
86 * This function must be called with the DRM mode_config lock held.
87 */
88void rcar_du_group_put(struct rcar_du_group *rgrp)
89{
90 --rgrp->use_count;
91}
92
93static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
94{
95 rcar_du_group_write(rgrp, DSYSR,
96 (rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) |
97 (start ? DSYSR_DEN : DSYSR_DRES));
98}
99
100void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start)
101{
102 /* Many of the configuration bits are only updated when the display
103 * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some
104 * of those bits could be pre-configured, but others (especially the
105 * bits related to plane assignment to display timing controllers) need
106 * to be modified at runtime.
107 *
108 * Restart the display controller if a start is requested. Sorry for the
109 * flicker. It should be possible to move most of the "DRES-update" bits
110 * setup to driver initialization time and minimize the number of cases
111 * when the display controller will have to be restarted.
112 */
113 if (start) {
114 if (rgrp->used_crtcs++ != 0)
115 __rcar_du_group_start_stop(rgrp, false);
116 __rcar_du_group_start_stop(rgrp, true);
117 } else {
118 if (--rgrp->used_crtcs == 0)
119 __rcar_du_group_start_stop(rgrp, false);
120 }
121}
122
123void rcar_du_group_restart(struct rcar_du_group *rgrp)
124{
125 __rcar_du_group_start_stop(rgrp, false);
126 __rcar_du_group_start_stop(rgrp, true);
127}
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_group.h b/drivers/gpu/drm/rcar-du/rcar_du_group.h
new file mode 100644
index 000000000000..748331bbb8fe
--- /dev/null
+++ b/drivers/gpu/drm/rcar-du/rcar_du_group.h
@@ -0,0 +1,47 @@
1/*
2 * rcar_du_group.c -- R-Car Display Unit Planes and CRTCs Group
3 *
4 * Copyright (C) 2013 Renesas 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#ifndef __RCAR_DU_GROUP_H__
15#define __RCAR_DU_GROUP_H__
16
17#include "rcar_du_plane.h"
18
19struct rcar_du_device;
20
21/*
22 * struct rcar_du_group - CRTCs and planes group
23 * @dev: the DU device
24 * @mmio_offset: registers offset in the device memory map
25 * @index: group index
26 * @use_count: number of users of the group (rcar_du_group_(get|put))
27 * @used_crtcs: number of CRTCs currently in use
28 * @planes: planes handled by the group
29 */
30struct rcar_du_group {
31 struct rcar_du_device *dev;
32 unsigned int mmio_offset;
33 unsigned int index;
34
35 unsigned int use_count;
36 unsigned int used_crtcs;
37
38 struct rcar_du_planes planes;
39};
40
41int rcar_du_group_get(struct rcar_du_group *rgrp);
42void rcar_du_group_put(struct rcar_du_group *rgrp);
43void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
44void rcar_du_group_restart(struct rcar_du_group *rgrp);
45
46
47#endif /* __RCAR_DU_GROUP_H__ */
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_kms.c b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
index a1343fbde57a..c32e0f9d4823 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_kms.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_kms.c
@@ -174,17 +174,20 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
174 rcdu->ddev->mode_config.max_height = 2047; 174 rcdu->ddev->mode_config.max_height = 2047;
175 rcdu->ddev->mode_config.funcs = &rcar_du_mode_config_funcs; 175 rcdu->ddev->mode_config.funcs = &rcar_du_mode_config_funcs;
176 176
177 ret = rcar_du_planes_init(rcdu); 177 rcdu->group.dev = rcdu;
178 rcdu->group.index = 0;
179 rcdu->group.used_crtcs = 0;
180
181 ret = rcar_du_planes_init(&rcdu->group);
178 if (ret < 0) 182 if (ret < 0)
179 return ret; 183 return ret;
180 184
181 for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i) { 185 for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i) {
182 ret = rcar_du_crtc_create(rcdu, i); 186 ret = rcar_du_crtc_create(&rcdu->group, i);
183 if (ret < 0) 187 if (ret < 0)
184 return ret; 188 return ret;
185 } 189 }
186 190
187 rcdu->used_crtcs = 0;
188 rcdu->num_crtcs = i; 191 rcdu->num_crtcs = i;
189 192
190 for (i = 0; i < rcdu->pdata->num_encoders; ++i) { 193 for (i = 0; i < rcdu->pdata->num_encoders; ++i) {
@@ -215,7 +218,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
215 encoder->possible_clones = 1 << 0; 218 encoder->possible_clones = 1 << 0;
216 } 219 }
217 220
218 ret = rcar_du_planes_register(rcdu); 221 ret = rcar_du_planes_register(&rcdu->group);
219 if (ret < 0) 222 if (ret < 0)
220 return ret; 223 return ret;
221 224
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.c b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
index 29f21477ef0e..1e9cf7c92f8e 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.c
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.c
@@ -36,71 +36,73 @@ static inline struct rcar_du_plane *to_rcar_plane(struct drm_plane *plane)
36 return container_of(plane, struct rcar_du_kms_plane, plane)->hwplane; 36 return container_of(plane, struct rcar_du_kms_plane, plane)->hwplane;
37} 37}
38 38
39static u32 rcar_du_plane_read(struct rcar_du_device *rcdu, 39static u32 rcar_du_plane_read(struct rcar_du_group *rgrp,
40 unsigned int index, u32 reg) 40 unsigned int index, u32 reg)
41{ 41{
42 return rcar_du_read(rcdu, index * PLANE_OFF + reg); 42 return rcar_du_read(rgrp->dev,
43 rgrp->mmio_offset + index * PLANE_OFF + reg);
43} 44}
44 45
45static void rcar_du_plane_write(struct rcar_du_device *rcdu, 46static void rcar_du_plane_write(struct rcar_du_group *rgrp,
46 unsigned int index, u32 reg, u32 data) 47 unsigned int index, u32 reg, u32 data)
47{ 48{
48 rcar_du_write(rcdu, index * PLANE_OFF + reg, data); 49 rcar_du_write(rgrp->dev, rgrp->mmio_offset + index * PLANE_OFF + reg,
50 data);
49} 51}
50 52
51int rcar_du_plane_reserve(struct rcar_du_plane *plane, 53int rcar_du_plane_reserve(struct rcar_du_plane *plane,
52 const struct rcar_du_format_info *format) 54 const struct rcar_du_format_info *format)
53{ 55{
54 struct rcar_du_device *rcdu = plane->dev; 56 struct rcar_du_group *rgrp = plane->group;
55 unsigned int i; 57 unsigned int i;
56 int ret = -EBUSY; 58 int ret = -EBUSY;
57 59
58 mutex_lock(&rcdu->planes.lock); 60 mutex_lock(&rgrp->planes.lock);
59 61
60 for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { 62 for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) {
61 if (!(rcdu->planes.free & (1 << i))) 63 if (!(rgrp->planes.free & (1 << i)))
62 continue; 64 continue;
63 65
64 if (format->planes == 1 || 66 if (format->planes == 1 ||
65 rcdu->planes.free & (1 << ((i + 1) % 8))) 67 rgrp->planes.free & (1 << ((i + 1) % 8)))
66 break; 68 break;
67 } 69 }
68 70
69 if (i == ARRAY_SIZE(rcdu->planes.planes)) 71 if (i == ARRAY_SIZE(rgrp->planes.planes))
70 goto done; 72 goto done;
71 73
72 rcdu->planes.free &= ~(1 << i); 74 rgrp->planes.free &= ~(1 << i);
73 if (format->planes == 2) 75 if (format->planes == 2)
74 rcdu->planes.free &= ~(1 << ((i + 1) % 8)); 76 rgrp->planes.free &= ~(1 << ((i + 1) % 8));
75 77
76 plane->hwindex = i; 78 plane->hwindex = i;
77 79
78 ret = 0; 80 ret = 0;
79 81
80done: 82done:
81 mutex_unlock(&rcdu->planes.lock); 83 mutex_unlock(&rgrp->planes.lock);
82 return ret; 84 return ret;
83} 85}
84 86
85void rcar_du_plane_release(struct rcar_du_plane *plane) 87void rcar_du_plane_release(struct rcar_du_plane *plane)
86{ 88{
87 struct rcar_du_device *rcdu = plane->dev; 89 struct rcar_du_group *rgrp = plane->group;
88 90
89 if (plane->hwindex == -1) 91 if (plane->hwindex == -1)
90 return; 92 return;
91 93
92 mutex_lock(&rcdu->planes.lock); 94 mutex_lock(&rgrp->planes.lock);
93 rcdu->planes.free |= 1 << plane->hwindex; 95 rgrp->planes.free |= 1 << plane->hwindex;
94 if (plane->format->planes == 2) 96 if (plane->format->planes == 2)
95 rcdu->planes.free |= 1 << ((plane->hwindex + 1) % 8); 97 rgrp->planes.free |= 1 << ((plane->hwindex + 1) % 8);
96 mutex_unlock(&rcdu->planes.lock); 98 mutex_unlock(&rgrp->planes.lock);
97 99
98 plane->hwindex = -1; 100 plane->hwindex = -1;
99} 101}
100 102
101void rcar_du_plane_update_base(struct rcar_du_plane *plane) 103void rcar_du_plane_update_base(struct rcar_du_plane *plane)
102{ 104{
103 struct rcar_du_device *rcdu = plane->dev; 105 struct rcar_du_group *rgrp = plane->group;
104 unsigned int index = plane->hwindex; 106 unsigned int index = plane->hwindex;
105 107
106 /* The Y position is expressed in raster line units and must be doubled 108 /* The Y position is expressed in raster line units and must be doubled
@@ -111,18 +113,18 @@ void rcar_du_plane_update_base(struct rcar_du_plane *plane)
111 * Similarly, for the second plane, NV12 and NV21 formats seem to 113 * Similarly, for the second plane, NV12 and NV21 formats seem to
112 * require a halved Y position value. 114 * require a halved Y position value.
113 */ 115 */
114 rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x); 116 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
115 rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y * 117 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
116 (plane->format->bpp == 32 ? 2 : 1)); 118 (plane->format->bpp == 32 ? 2 : 1));
117 rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[0]); 119 rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]);
118 120
119 if (plane->format->planes == 2) { 121 if (plane->format->planes == 2) {
120 index = (index + 1) % 8; 122 index = (index + 1) % 8;
121 123
122 rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x); 124 rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x);
123 rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y * 125 rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y *
124 (plane->format->bpp == 16 ? 2 : 1) / 2); 126 (plane->format->bpp == 16 ? 2 : 1) / 2);
125 rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[1]); 127 rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[1]);
126 } 128 }
127} 129}
128 130
@@ -143,7 +145,7 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane,
143static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, 145static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
144 unsigned int index) 146 unsigned int index)
145{ 147{
146 struct rcar_du_device *rcdu = plane->dev; 148 struct rcar_du_group *rgrp = plane->group;
147 u32 colorkey; 149 u32 colorkey;
148 u32 pnmr; 150 u32 pnmr;
149 151
@@ -157,9 +159,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
157 * enable alpha-blending regardless of the X bit value. 159 * enable alpha-blending regardless of the X bit value.
158 */ 160 */
159 if (plane->format->fourcc != DRM_FORMAT_XRGB1555) 161 if (plane->format->fourcc != DRM_FORMAT_XRGB1555)
160 rcar_du_plane_write(rcdu, index, PnALPHAR, PnALPHAR_ABIT_0); 162 rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
161 else 163 else
162 rcar_du_plane_write(rcdu, index, PnALPHAR, 164 rcar_du_plane_write(rgrp, index, PnALPHAR,
163 PnALPHAR_ABIT_X | plane->alpha); 165 PnALPHAR_ABIT_X | plane->alpha);
164 166
165 pnmr = PnMR_BM_MD | plane->format->pnmr; 167 pnmr = PnMR_BM_MD | plane->format->pnmr;
@@ -175,14 +177,14 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
175 if (plane->format->fourcc == DRM_FORMAT_YUYV) 177 if (plane->format->fourcc == DRM_FORMAT_YUYV)
176 pnmr |= PnMR_YCDF_YUYV; 178 pnmr |= PnMR_YCDF_YUYV;
177 179
178 rcar_du_plane_write(rcdu, index, PnMR, pnmr); 180 rcar_du_plane_write(rgrp, index, PnMR, pnmr);
179 181
180 switch (plane->format->fourcc) { 182 switch (plane->format->fourcc) {
181 case DRM_FORMAT_RGB565: 183 case DRM_FORMAT_RGB565:
182 colorkey = ((plane->colorkey & 0xf80000) >> 8) 184 colorkey = ((plane->colorkey & 0xf80000) >> 8)
183 | ((plane->colorkey & 0x00fc00) >> 5) 185 | ((plane->colorkey & 0x00fc00) >> 5)
184 | ((plane->colorkey & 0x0000f8) >> 3); 186 | ((plane->colorkey & 0x0000f8) >> 3);
185 rcar_du_plane_write(rcdu, index, PnTC2R, colorkey); 187 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
186 break; 188 break;
187 189
188 case DRM_FORMAT_ARGB1555: 190 case DRM_FORMAT_ARGB1555:
@@ -190,12 +192,12 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
190 colorkey = ((plane->colorkey & 0xf80000) >> 9) 192 colorkey = ((plane->colorkey & 0xf80000) >> 9)
191 | ((plane->colorkey & 0x00f800) >> 6) 193 | ((plane->colorkey & 0x00f800) >> 6)
192 | ((plane->colorkey & 0x0000f8) >> 3); 194 | ((plane->colorkey & 0x0000f8) >> 3);
193 rcar_du_plane_write(rcdu, index, PnTC2R, colorkey); 195 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
194 break; 196 break;
195 197
196 case DRM_FORMAT_XRGB8888: 198 case DRM_FORMAT_XRGB8888:
197 case DRM_FORMAT_ARGB8888: 199 case DRM_FORMAT_ARGB8888:
198 rcar_du_plane_write(rcdu, index, PnTC3R, 200 rcar_du_plane_write(rgrp, index, PnTC3R,
199 PnTC3R_CODE | (plane->colorkey & 0xffffff)); 201 PnTC3R_CODE | (plane->colorkey & 0xffffff));
200 break; 202 break;
201 } 203 }
@@ -204,7 +206,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
204static void __rcar_du_plane_setup(struct rcar_du_plane *plane, 206static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
205 unsigned int index) 207 unsigned int index)
206{ 208{
207 struct rcar_du_device *rcdu = plane->dev; 209 struct rcar_du_group *rgrp = plane->group;
208 u32 ddcr2 = PnDDCR2_CODE; 210 u32 ddcr2 = PnDDCR2_CODE;
209 u32 ddcr4; 211 u32 ddcr4;
210 u32 mwr; 212 u32 mwr;
@@ -214,7 +216,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
214 * The data format is selected by the DDDF field in PnMR and the EDF 216 * The data format is selected by the DDDF field in PnMR and the EDF
215 * field in DDCR4. 217 * field in DDCR4.
216 */ 218 */
217 ddcr4 = rcar_du_plane_read(rcdu, index, PnDDCR4); 219 ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4);
218 ddcr4 &= ~PnDDCR4_EDF_MASK; 220 ddcr4 &= ~PnDDCR4_EDF_MASK;
219 ddcr4 |= plane->format->edf | PnDDCR4_CODE; 221 ddcr4 |= plane->format->edf | PnDDCR4_CODE;
220 222
@@ -235,8 +237,8 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
235 } 237 }
236 } 238 }
237 239
238 rcar_du_plane_write(rcdu, index, PnDDCR2, ddcr2); 240 rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
239 rcar_du_plane_write(rcdu, index, PnDDCR4, ddcr4); 241 rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
240 242
241 /* Memory pitch (expressed in pixels) */ 243 /* Memory pitch (expressed in pixels) */
242 if (plane->format->planes == 2) 244 if (plane->format->planes == 2)
@@ -244,19 +246,19 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
244 else 246 else
245 mwr = plane->pitch * 8 / plane->format->bpp; 247 mwr = plane->pitch * 8 / plane->format->bpp;
246 248
247 rcar_du_plane_write(rcdu, index, PnMWR, mwr); 249 rcar_du_plane_write(rgrp, index, PnMWR, mwr);
248 250
249 /* Destination position and size */ 251 /* Destination position and size */
250 rcar_du_plane_write(rcdu, index, PnDSXR, plane->width); 252 rcar_du_plane_write(rgrp, index, PnDSXR, plane->width);
251 rcar_du_plane_write(rcdu, index, PnDSYR, plane->height); 253 rcar_du_plane_write(rgrp, index, PnDSYR, plane->height);
252 rcar_du_plane_write(rcdu, index, PnDPXR, plane->dst_x); 254 rcar_du_plane_write(rgrp, index, PnDPXR, plane->dst_x);
253 rcar_du_plane_write(rcdu, index, PnDPYR, plane->dst_y); 255 rcar_du_plane_write(rgrp, index, PnDPYR, plane->dst_y);
254 256
255 /* Wrap-around and blinking, disabled */ 257 /* Wrap-around and blinking, disabled */
256 rcar_du_plane_write(rcdu, index, PnWASPR, 0); 258 rcar_du_plane_write(rgrp, index, PnWASPR, 0);
257 rcar_du_plane_write(rcdu, index, PnWAMWR, 4095); 259 rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
258 rcar_du_plane_write(rcdu, index, PnBTR, 0); 260 rcar_du_plane_write(rgrp, index, PnBTR, 0);
259 rcar_du_plane_write(rcdu, index, PnMLR, 0); 261 rcar_du_plane_write(rgrp, index, PnMLR, 0);
260} 262}
261 263
262void rcar_du_plane_setup(struct rcar_du_plane *plane) 264void rcar_du_plane_setup(struct rcar_du_plane *plane)
@@ -276,7 +278,7 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
276 uint32_t src_w, uint32_t src_h) 278 uint32_t src_w, uint32_t src_h)
277{ 279{
278 struct rcar_du_plane *rplane = to_rcar_plane(plane); 280 struct rcar_du_plane *rplane = to_rcar_plane(plane);
279 struct rcar_du_device *rcdu = plane->dev->dev_private; 281 struct rcar_du_device *rcdu = rplane->group->dev;
280 const struct rcar_du_format_info *format; 282 const struct rcar_du_format_info *format;
281 unsigned int nplanes; 283 unsigned int nplanes;
282 int ret; 284 int ret;
@@ -319,26 +321,25 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc,
319 rcar_du_plane_compute_base(rplane, fb); 321 rcar_du_plane_compute_base(rplane, fb);
320 rcar_du_plane_setup(rplane); 322 rcar_du_plane_setup(rplane);
321 323
322 mutex_lock(&rcdu->planes.lock); 324 mutex_lock(&rplane->group->planes.lock);
323 rplane->enabled = true; 325 rplane->enabled = true;
324 rcar_du_crtc_update_planes(rplane->crtc); 326 rcar_du_crtc_update_planes(rplane->crtc);
325 mutex_unlock(&rcdu->planes.lock); 327 mutex_unlock(&rplane->group->planes.lock);
326 328
327 return 0; 329 return 0;
328} 330}
329 331
330static int rcar_du_plane_disable(struct drm_plane *plane) 332static int rcar_du_plane_disable(struct drm_plane *plane)
331{ 333{
332 struct rcar_du_device *rcdu = plane->dev->dev_private;
333 struct rcar_du_plane *rplane = to_rcar_plane(plane); 334 struct rcar_du_plane *rplane = to_rcar_plane(plane);
334 335
335 if (!rplane->enabled) 336 if (!rplane->enabled)
336 return 0; 337 return 0;
337 338
338 mutex_lock(&rcdu->planes.lock); 339 mutex_lock(&rplane->group->planes.lock);
339 rplane->enabled = false; 340 rplane->enabled = false;
340 rcar_du_crtc_update_planes(rplane->crtc); 341 rcar_du_crtc_update_planes(rplane->crtc);
341 mutex_unlock(&rcdu->planes.lock); 342 mutex_unlock(&rplane->group->planes.lock);
342 343
343 rcar_du_plane_release(rplane); 344 rcar_du_plane_release(rplane);
344 345
@@ -380,9 +381,7 @@ static void rcar_du_plane_set_colorkey(struct rcar_du_plane *plane,
380static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane, 381static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane,
381 unsigned int zpos) 382 unsigned int zpos)
382{ 383{
383 struct rcar_du_device *rcdu = plane->dev; 384 mutex_lock(&plane->group->planes.lock);
384
385 mutex_lock(&rcdu->planes.lock);
386 if (plane->zpos == zpos) 385 if (plane->zpos == zpos)
387 goto done; 386 goto done;
388 387
@@ -393,21 +392,21 @@ static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane,
393 rcar_du_crtc_update_planes(plane->crtc); 392 rcar_du_crtc_update_planes(plane->crtc);
394 393
395done: 394done:
396 mutex_unlock(&rcdu->planes.lock); 395 mutex_unlock(&plane->group->planes.lock);
397} 396}
398 397
399static int rcar_du_plane_set_property(struct drm_plane *plane, 398static int rcar_du_plane_set_property(struct drm_plane *plane,
400 struct drm_property *property, 399 struct drm_property *property,
401 uint64_t value) 400 uint64_t value)
402{ 401{
403 struct rcar_du_device *rcdu = plane->dev->dev_private;
404 struct rcar_du_plane *rplane = to_rcar_plane(plane); 402 struct rcar_du_plane *rplane = to_rcar_plane(plane);
403 struct rcar_du_group *rgrp = rplane->group;
405 404
406 if (property == rcdu->planes.alpha) 405 if (property == rgrp->planes.alpha)
407 rcar_du_plane_set_alpha(rplane, value); 406 rcar_du_plane_set_alpha(rplane, value);
408 else if (property == rcdu->planes.colorkey) 407 else if (property == rgrp->planes.colorkey)
409 rcar_du_plane_set_colorkey(rplane, value); 408 rcar_du_plane_set_colorkey(rplane, value);
410 else if (property == rcdu->planes.zpos) 409 else if (property == rgrp->planes.zpos)
411 rcar_du_plane_set_zpos(rplane, value); 410 rcar_du_plane_set_zpos(rplane, value);
412 else 411 else
413 return -EINVAL; 412 return -EINVAL;
@@ -435,37 +434,39 @@ static const uint32_t formats[] = {
435 DRM_FORMAT_NV16, 434 DRM_FORMAT_NV16,
436}; 435};
437 436
438int rcar_du_planes_init(struct rcar_du_device *rcdu) 437int rcar_du_planes_init(struct rcar_du_group *rgrp)
439{ 438{
439 struct rcar_du_planes *planes = &rgrp->planes;
440 struct rcar_du_device *rcdu = rgrp->dev;
440 unsigned int i; 441 unsigned int i;
441 442
442 mutex_init(&rcdu->planes.lock); 443 mutex_init(&planes->lock);
443 rcdu->planes.free = 0xff; 444 planes->free = 0xff;
444 445
445 rcdu->planes.alpha = 446 planes->alpha =
446 drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255); 447 drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255);
447 if (rcdu->planes.alpha == NULL) 448 if (planes->alpha == NULL)
448 return -ENOMEM; 449 return -ENOMEM;
449 450
450 /* The color key is expressed as an RGB888 triplet stored in a 32-bit 451 /* The color key is expressed as an RGB888 triplet stored in a 32-bit
451 * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0) 452 * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0)
452 * or enable source color keying (1). 453 * or enable source color keying (1).
453 */ 454 */
454 rcdu->planes.colorkey = 455 planes->colorkey =
455 drm_property_create_range(rcdu->ddev, 0, "colorkey", 456 drm_property_create_range(rcdu->ddev, 0, "colorkey",
456 0, 0x01ffffff); 457 0, 0x01ffffff);
457 if (rcdu->planes.colorkey == NULL) 458 if (planes->colorkey == NULL)
458 return -ENOMEM; 459 return -ENOMEM;
459 460
460 rcdu->planes.zpos = 461 planes->zpos =
461 drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7); 462 drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7);
462 if (rcdu->planes.zpos == NULL) 463 if (planes->zpos == NULL)
463 return -ENOMEM; 464 return -ENOMEM;
464 465
465 for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { 466 for (i = 0; i < ARRAY_SIZE(planes->planes); ++i) {
466 struct rcar_du_plane *plane = &rcdu->planes.planes[i]; 467 struct rcar_du_plane *plane = &planes->planes[i];
467 468
468 plane->dev = rcdu; 469 plane->group = rgrp;
469 plane->hwindex = -1; 470 plane->hwindex = -1;
470 plane->alpha = 255; 471 plane->alpha = 255;
471 plane->colorkey = RCAR_DU_COLORKEY_NONE; 472 plane->colorkey = RCAR_DU_COLORKEY_NONE;
@@ -475,8 +476,10 @@ int rcar_du_planes_init(struct rcar_du_device *rcdu)
475 return 0; 476 return 0;
476} 477}
477 478
478int rcar_du_planes_register(struct rcar_du_device *rcdu) 479int rcar_du_planes_register(struct rcar_du_group *rgrp)
479{ 480{
481 struct rcar_du_planes *planes = &rgrp->planes;
482 struct rcar_du_device *rcdu = rgrp->dev;
480 unsigned int i; 483 unsigned int i;
481 int ret; 484 int ret;
482 485
@@ -487,7 +490,7 @@ int rcar_du_planes_register(struct rcar_du_device *rcdu)
487 if (plane == NULL) 490 if (plane == NULL)
488 return -ENOMEM; 491 return -ENOMEM;
489 492
490 plane->hwplane = &rcdu->planes.planes[i + 2]; 493 plane->hwplane = &planes->planes[i + 2];
491 plane->hwplane->zpos = 1; 494 plane->hwplane->zpos = 1;
492 495
493 ret = drm_plane_init(rcdu->ddev, &plane->plane, 496 ret = drm_plane_init(rcdu->ddev, &plane->plane,
@@ -498,12 +501,12 @@ int rcar_du_planes_register(struct rcar_du_device *rcdu)
498 return ret; 501 return ret;
499 502
500 drm_object_attach_property(&plane->plane.base, 503 drm_object_attach_property(&plane->plane.base,
501 rcdu->planes.alpha, 255); 504 planes->alpha, 255);
502 drm_object_attach_property(&plane->plane.base, 505 drm_object_attach_property(&plane->plane.base,
503 rcdu->planes.colorkey, 506 planes->colorkey,
504 RCAR_DU_COLORKEY_NONE); 507 RCAR_DU_COLORKEY_NONE);
505 drm_object_attach_property(&plane->plane.base, 508 drm_object_attach_property(&plane->plane.base,
506 rcdu->planes.zpos, 1); 509 planes->zpos, 1);
507 } 510 }
508 511
509 return 0; 512 return 0;
diff --git a/drivers/gpu/drm/rcar-du/rcar_du_plane.h b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
index bcf6f76f56a0..f94f9ce84998 100644
--- a/drivers/gpu/drm/rcar-du/rcar_du_plane.h
+++ b/drivers/gpu/drm/rcar-du/rcar_du_plane.h
@@ -19,8 +19,8 @@
19#include <drm/drmP.h> 19#include <drm/drmP.h>
20#include <drm/drm_crtc.h> 20#include <drm/drm_crtc.h>
21 21
22struct rcar_du_device;
23struct rcar_du_format_info; 22struct rcar_du_format_info;
23struct rcar_du_group;
24 24
25/* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As 25/* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As
26 * using KMS planes requires at least one of the CRTCs being enabled, no more 26 * using KMS planes requires at least one of the CRTCs being enabled, no more
@@ -33,7 +33,7 @@ struct rcar_du_format_info;
33#define RCAR_DU_NUM_SW_PLANES 9 33#define RCAR_DU_NUM_SW_PLANES 9
34 34
35struct rcar_du_plane { 35struct rcar_du_plane {
36 struct rcar_du_device *dev; 36 struct rcar_du_group *group;
37 struct drm_crtc *crtc; 37 struct drm_crtc *crtc;
38 38
39 bool enabled; 39 bool enabled;
@@ -67,8 +67,8 @@ struct rcar_du_planes {
67 struct drm_property *zpos; 67 struct drm_property *zpos;
68}; 68};
69 69
70int rcar_du_planes_init(struct rcar_du_device *rcdu); 70int rcar_du_planes_init(struct rcar_du_group *rgrp);
71int rcar_du_planes_register(struct rcar_du_device *rcdu); 71int rcar_du_planes_register(struct rcar_du_group *rgrp);
72 72
73void rcar_du_plane_setup(struct rcar_du_plane *plane); 73void rcar_du_plane_setup(struct rcar_du_plane *plane);
74void rcar_du_plane_update_base(struct rcar_du_plane *plane); 74void rcar_du_plane_update_base(struct rcar_du_plane *plane);