blob: aa02c375ab7f2379b592ef43a31c13c6a54109a6 [file] [log] [blame]
Laurent Pinchart4bf8e192013-06-19 13:54:11 +02001/*
2 * rcar_du_plane.c -- R-Car Display Unit Planes
3 *
Laurent Pinchart36d50462014-02-06 18:13:52 +01004 * Copyright (C) 2013-2014 Renesas Electronics Corporation
Laurent Pinchart4bf8e192013-06-19 13:54:11 +02005 *
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#include <drm/drmP.h>
Laurent Pinchart3e8da872015-02-20 11:30:59 +020015#include <drm/drm_atomic_helper.h>
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020016#include <drm/drm_crtc.h>
17#include <drm/drm_crtc_helper.h>
18#include <drm/drm_fb_cma_helper.h>
19#include <drm/drm_gem_cma_helper.h>
Laurent Pinchart920888a2015-02-18 12:18:05 +020020#include <drm/drm_plane_helper.h>
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020021
22#include "rcar_du_drv.h"
23#include "rcar_du_kms.h"
24#include "rcar_du_plane.h"
25#include "rcar_du_regs.h"
26
27#define RCAR_DU_COLORKEY_NONE (0 << 24)
28#define RCAR_DU_COLORKEY_SOURCE (1 << 24)
29#define RCAR_DU_COLORKEY_MASK (1 << 24)
30
Laurent Pinchartcb2025d2013-06-16 21:01:02 +020031static void rcar_du_plane_write(struct rcar_du_group *rgrp,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020032 unsigned int index, u32 reg, u32 data)
33{
Laurent Pinchartcb2025d2013-06-16 21:01:02 +020034 rcar_du_write(rgrp->dev, rgrp->mmio_offset + index * PLANE_OFF + reg,
35 data);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020036}
37
Laurent Pinchartf398f342015-02-23 01:25:19 +020038static void rcar_du_plane_setup_fb(struct rcar_du_plane *plane)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020039{
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020040 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +030041 to_rcar_plane_state(plane->plane.state);
Laurent Pinchartf398f342015-02-23 01:25:19 +020042 struct drm_framebuffer *fb = plane->plane.state->fb;
Laurent Pinchartcb2025d2013-06-16 21:01:02 +020043 struct rcar_du_group *rgrp = plane->group;
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020044 unsigned int src_x = state->state.src_x >> 16;
45 unsigned int src_y = state->state.src_y >> 16;
Laurent Pinchart5ee5a812015-02-25 18:27:19 +020046 unsigned int index = state->hwindex;
Laurent Pinchartf398f342015-02-23 01:25:19 +020047 struct drm_gem_cma_object *gem;
Laurent Pinchart906eff72014-12-09 19:11:18 +020048 bool interlaced;
Laurent Pincharteb863012013-11-13 14:26:01 +010049 u32 mwr;
50
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020051 interlaced = state->state.crtc->state->adjusted_mode.flags
Laurent Pinchart47094192015-02-22 19:24:59 +020052 & DRM_MODE_FLAG_INTERLACE;
Laurent Pinchart906eff72014-12-09 19:11:18 +020053
54 /* Memory pitch (expressed in pixels). Must be doubled for interlaced
55 * operation with 32bpp formats.
56 */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020057 if (state->format->planes == 2)
Laurent Pinchartf398f342015-02-23 01:25:19 +020058 mwr = fb->pitches[0];
Laurent Pincharteb863012013-11-13 14:26:01 +010059 else
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020060 mwr = fb->pitches[0] * 8 / state->format->bpp;
Laurent Pincharteb863012013-11-13 14:26:01 +010061
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020062 if (interlaced && state->format->bpp == 32)
Laurent Pinchart906eff72014-12-09 19:11:18 +020063 mwr *= 2;
64
Laurent Pincharteb863012013-11-13 14:26:01 +010065 rcar_du_plane_write(rgrp, index, PnMWR, mwr);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020066
Laurent Pinchart9e7db062013-06-14 20:54:16 +020067 /* The Y position is expressed in raster line units and must be doubled
68 * for 32bpp formats, according to the R8A7790 datasheet. No mention of
69 * doubling the Y position is found in the R8A7779 datasheet, but the
70 * rule seems to apply there as well.
71 *
Laurent Pinchart906eff72014-12-09 19:11:18 +020072 * Despite not being documented, doubling seem not to be needed when
73 * operating in interlaced mode.
74 *
Laurent Pinchart9e7db062013-06-14 20:54:16 +020075 * Similarly, for the second plane, NV12 and NV21 formats seem to
Laurent Pinchart906eff72014-12-09 19:11:18 +020076 * require a halved Y position value, in both progressive and interlaced
77 * modes.
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020078 */
Laurent Pinchart287bdf02015-02-20 15:58:38 +020079 rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
80 rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020081 (!interlaced && state->format->bpp == 32 ? 2 : 1));
Laurent Pinchartf398f342015-02-23 01:25:19 +020082
83 gem = drm_fb_cma_get_gem_obj(fb, 0);
84 rcar_du_plane_write(rgrp, index, PnDSA0R, gem->paddr + fb->offsets[0]);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020085
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020086 if (state->format->planes == 2) {
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020087 index = (index + 1) % 8;
88
Laurent Pinchartf398f342015-02-23 01:25:19 +020089 rcar_du_plane_write(rgrp, index, PnMWR, fb->pitches[0]);
Laurent Pinchart49785e22014-12-09 22:45:11 +020090
Laurent Pinchart287bdf02015-02-20 15:58:38 +020091 rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
92 rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020093 (state->format->bpp == 16 ? 2 : 1) / 2);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020094
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020095 gem = drm_fb_cma_get_gem_obj(fb, 1);
Laurent Pinchartf398f342015-02-23 01:25:19 +020096 rcar_du_plane_write(rgrp, index, PnDSA0R,
97 gem->paddr + fb->offsets[1]);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020098 }
99}
100
101static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
102 unsigned int index)
103{
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200104 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300105 to_rcar_plane_state(plane->plane.state);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200106 struct rcar_du_group *rgrp = plane->group;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200107 u32 colorkey;
108 u32 pnmr;
109
110 /* The PnALPHAR register controls alpha-blending in 16bpp formats
111 * (ARGB1555 and XRGB1555).
112 *
113 * For ARGB, set the alpha value to 0, and enable alpha-blending when
114 * the A bit is 0. This maps A=0 to alpha=0 and A=1 to alpha=255.
115 *
116 * For XRGB, set the alpha value to the plane-wide alpha value and
117 * enable alpha-blending regardless of the X bit value.
118 */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200119 if (state->format->fourcc != DRM_FORMAT_XRGB1555)
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200120 rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200121 else
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200122 rcar_du_plane_write(rgrp, index, PnALPHAR,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200123 PnALPHAR_ABIT_X | state->alpha);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200124
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200125 pnmr = PnMR_BM_MD | state->format->pnmr;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200126
127 /* Disable color keying when requested. YUV formats have the
128 * PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying
129 * automatically.
130 */
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200131 if ((state->colorkey & RCAR_DU_COLORKEY_MASK) == RCAR_DU_COLORKEY_NONE)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200132 pnmr |= PnMR_SPIM_TP_OFF;
133
134 /* For packed YUV formats we need to select the U/V order. */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200135 if (state->format->fourcc == DRM_FORMAT_YUYV)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200136 pnmr |= PnMR_YCDF_YUYV;
137
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200138 rcar_du_plane_write(rgrp, index, PnMR, pnmr);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200139
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200140 switch (state->format->fourcc) {
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200141 case DRM_FORMAT_RGB565:
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200142 colorkey = ((state->colorkey & 0xf80000) >> 8)
143 | ((state->colorkey & 0x00fc00) >> 5)
144 | ((state->colorkey & 0x0000f8) >> 3);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200145 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200146 break;
147
148 case DRM_FORMAT_ARGB1555:
149 case DRM_FORMAT_XRGB1555:
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200150 colorkey = ((state->colorkey & 0xf80000) >> 9)
151 | ((state->colorkey & 0x00f800) >> 6)
152 | ((state->colorkey & 0x0000f8) >> 3);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200153 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200154 break;
155
156 case DRM_FORMAT_XRGB8888:
157 case DRM_FORMAT_ARGB8888:
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200158 rcar_du_plane_write(rgrp, index, PnTC3R,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200159 PnTC3R_CODE | (state->colorkey & 0xffffff));
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200160 break;
161 }
162}
163
164static void __rcar_du_plane_setup(struct rcar_du_plane *plane,
165 unsigned int index)
166{
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200167 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300168 to_rcar_plane_state(plane->plane.state);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200169 struct rcar_du_group *rgrp = plane->group;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200170 u32 ddcr2 = PnDDCR2_CODE;
171 u32 ddcr4;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200172
173 /* Data format
174 *
175 * The data format is selected by the DDDF field in PnMR and the EDF
176 * field in DDCR4.
177 */
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200178
179 rcar_du_plane_setup_mode(plane, index);
180
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200181 if (state->format->planes == 2) {
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200182 if (state->hwindex != index) {
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200183 if (state->format->fourcc == DRM_FORMAT_NV12 ||
184 state->format->fourcc == DRM_FORMAT_NV21)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200185 ddcr2 |= PnDDCR2_Y420;
186
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200187 if (state->format->fourcc == DRM_FORMAT_NV21)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200188 ddcr2 |= PnDDCR2_NV21;
189
190 ddcr2 |= PnDDCR2_DIVU;
191 } else {
192 ddcr2 |= PnDDCR2_DIVY;
193 }
194 }
195
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200196 rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
Laurent Pinchartff967362015-07-27 12:46:44 +0300197
198 ddcr4 = state->format->edf | PnDDCR4_CODE;
199
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200200 rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200201
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200202 /* Destination position and size */
Laurent Pinchart287bdf02015-02-20 15:58:38 +0200203 rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
204 rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
205 rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
206 rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200207
208 /* Wrap-around and blinking, disabled */
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200209 rcar_du_plane_write(rgrp, index, PnWASPR, 0);
210 rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
211 rcar_du_plane_write(rgrp, index, PnBTR, 0);
212 rcar_du_plane_write(rgrp, index, PnMLR, 0);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200213}
214
215void rcar_du_plane_setup(struct rcar_du_plane *plane)
216{
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200217 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300218 to_rcar_plane_state(plane->plane.state);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200219
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200220 __rcar_du_plane_setup(plane, state->hwindex);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200221 if (state->format->planes == 2)
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200222 __rcar_du_plane_setup(plane, (state->hwindex + 1) % 8);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200223
Laurent Pinchartf398f342015-02-23 01:25:19 +0200224 rcar_du_plane_setup_fb(plane);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200225}
226
Laurent Pinchart920888a2015-02-18 12:18:05 +0200227static int rcar_du_plane_atomic_check(struct drm_plane *plane,
228 struct drm_plane_state *state)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200229{
Laurent Pinchartec69a402015-04-29 00:48:17 +0300230 struct rcar_du_plane_state *rstate = to_rcar_plane_state(state);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200231 struct rcar_du_plane *rplane = to_rcar_plane(plane);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200232 struct rcar_du_device *rcdu = rplane->group->dev;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200233
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200234 if (!state->fb || !state->crtc) {
235 rstate->format = NULL;
Laurent Pinchart920888a2015-02-18 12:18:05 +0200236 return 0;
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200237 }
Laurent Pinchart917de182015-02-17 18:34:17 +0200238
Laurent Pinchart920888a2015-02-18 12:18:05 +0200239 if (state->src_w >> 16 != state->crtc_w ||
240 state->src_h >> 16 != state->crtc_h) {
241 dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200242 return -EINVAL;
243 }
244
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200245 rstate->format = rcar_du_format_info(state->fb->pixel_format);
246 if (rstate->format == NULL) {
Laurent Pinchart920888a2015-02-18 12:18:05 +0200247 dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
248 state->fb->pixel_format);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200249 return -EINVAL;
250 }
251
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200252 return 0;
253}
254
Laurent Pinchart920888a2015-02-18 12:18:05 +0200255static void rcar_du_plane_atomic_update(struct drm_plane *plane,
256 struct drm_plane_state *old_state)
257{
258 struct rcar_du_plane *rplane = to_rcar_plane(plane);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200259
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200260 if (plane->state->crtc)
261 rcar_du_plane_setup(rplane);
Laurent Pinchart920888a2015-02-18 12:18:05 +0200262}
263
264static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
265 .atomic_check = rcar_du_plane_atomic_check,
266 .atomic_update = rcar_du_plane_atomic_update,
267};
268
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200269static struct drm_plane_state *
270rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200271{
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200272 struct rcar_du_plane_state *state;
273 struct rcar_du_plane_state *copy;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200274
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300275 if (WARN_ON(!plane->state))
276 return NULL;
277
Laurent Pinchartec69a402015-04-29 00:48:17 +0300278 state = to_rcar_plane_state(plane->state);
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200279 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
280 if (copy == NULL)
281 return NULL;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200282
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300283 __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200284
285 return &copy->state;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200286}
287
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200288static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
289 struct drm_plane_state *state)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200290{
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300291 __drm_atomic_helper_plane_destroy_state(plane, state);
Laurent Pinchartec69a402015-04-29 00:48:17 +0300292 kfree(to_rcar_plane_state(state));
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200293}
294
Laurent Pincharta32a3c82015-07-27 11:42:54 +0300295static void rcar_du_plane_reset(struct drm_plane *plane)
296{
297 struct rcar_du_plane_state *state;
298
299 if (plane->state) {
300 rcar_du_plane_atomic_destroy_state(plane, plane->state);
301 plane->state = NULL;
302 }
303
304 state = kzalloc(sizeof(*state), GFP_KERNEL);
305 if (state == NULL)
306 return;
307
308 state->hwindex = -1;
309 state->alpha = 255;
310 state->colorkey = RCAR_DU_COLORKEY_NONE;
311 state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
312
313 plane->state = &state->state;
314 plane->state->plane = plane;
315}
316
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200317static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
318 struct drm_plane_state *state,
319 struct drm_property *property,
320 uint64_t val)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200321{
Laurent Pinchartec69a402015-04-29 00:48:17 +0300322 struct rcar_du_plane_state *rstate = to_rcar_plane_state(state);
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300323 struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200324
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300325 if (property == rcdu->props.alpha)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200326 rstate->alpha = val;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300327 else if (property == rcdu->props.colorkey)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200328 rstate->colorkey = val;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300329 else if (property == rcdu->props.zpos)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200330 rstate->zpos = val;
331 else
332 return -EINVAL;
333
334 return 0;
335}
336
337static int rcar_du_plane_atomic_get_property(struct drm_plane *plane,
338 const struct drm_plane_state *state, struct drm_property *property,
339 uint64_t *val)
340{
341 const struct rcar_du_plane_state *rstate =
342 container_of(state, const struct rcar_du_plane_state, state);
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300343 struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev;
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200344
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300345 if (property == rcdu->props.alpha)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200346 *val = rstate->alpha;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300347 else if (property == rcdu->props.colorkey)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200348 *val = rstate->colorkey;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300349 else if (property == rcdu->props.zpos)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200350 *val = rstate->zpos;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200351 else
352 return -EINVAL;
353
354 return 0;
355}
356
357static const struct drm_plane_funcs rcar_du_plane_funcs = {
Laurent Pinchart336d04a2015-02-20 13:18:56 +0200358 .update_plane = drm_atomic_helper_update_plane,
359 .disable_plane = drm_atomic_helper_disable_plane,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200360 .reset = rcar_du_plane_reset,
361 .set_property = drm_atomic_helper_plane_set_property,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200362 .destroy = drm_plane_cleanup,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200363 .atomic_duplicate_state = rcar_du_plane_atomic_duplicate_state,
364 .atomic_destroy_state = rcar_du_plane_atomic_destroy_state,
365 .atomic_set_property = rcar_du_plane_atomic_set_property,
366 .atomic_get_property = rcar_du_plane_atomic_get_property,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200367};
368
369static const uint32_t formats[] = {
370 DRM_FORMAT_RGB565,
371 DRM_FORMAT_ARGB1555,
372 DRM_FORMAT_XRGB1555,
373 DRM_FORMAT_XRGB8888,
374 DRM_FORMAT_ARGB8888,
375 DRM_FORMAT_UYVY,
376 DRM_FORMAT_YUYV,
377 DRM_FORMAT_NV12,
378 DRM_FORMAT_NV21,
379 DRM_FORMAT_NV16,
380};
381
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200382int rcar_du_planes_init(struct rcar_du_group *rgrp)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200383{
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200384 struct rcar_du_device *rcdu = rgrp->dev;
Laurent Pinchart917de182015-02-17 18:34:17 +0200385 unsigned int crtcs;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200386 unsigned int i;
Laurent Pinchart917de182015-02-17 18:34:17 +0200387 int ret;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200388
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300389 /* Create one primary plane per CRTC in this group and seven overlay
Laurent Pinchart917de182015-02-17 18:34:17 +0200390 * planes.
391 */
Laurent Pinchartd6aed572015-05-25 16:32:45 +0300392 rgrp->num_planes = rgrp->num_crtcs + 7;
Laurent Pinchart917de182015-02-17 18:34:17 +0200393
394 crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
395
Laurent Pinchartd6aed572015-05-25 16:32:45 +0300396 for (i = 0; i < rgrp->num_planes; ++i) {
Laurent Pinchartfe6fbe92015-04-28 17:36:33 +0300397 enum drm_plane_type type = i < rgrp->num_crtcs
Laurent Pinchart917de182015-02-17 18:34:17 +0200398 ? DRM_PLANE_TYPE_PRIMARY
399 : DRM_PLANE_TYPE_OVERLAY;
Laurent Pinchart99caede2015-04-29 00:05:56 +0300400 struct rcar_du_plane *plane = &rgrp->planes[i];
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200401
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200402 plane->group = rgrp;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200403
Laurent Pinchart917de182015-02-17 18:34:17 +0200404 ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
405 &rcar_du_plane_funcs, formats,
Ville Syrjäläb0b3b792015-12-09 16:19:55 +0200406 ARRAY_SIZE(formats), type,
407 NULL);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200408 if (ret < 0)
409 return ret;
410
Laurent Pinchart920888a2015-02-18 12:18:05 +0200411 drm_plane_helper_add(&plane->plane,
412 &rcar_du_plane_helper_funcs);
413
Laurent Pinchart917de182015-02-17 18:34:17 +0200414 if (type == DRM_PLANE_TYPE_PRIMARY)
415 continue;
416
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200417 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300418 rcdu->props.alpha, 255);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200419 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300420 rcdu->props.colorkey,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200421 RCAR_DU_COLORKEY_NONE);
422 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300423 rcdu->props.zpos, 1);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200424 }
425
426 return 0;
427}