blob: a75bfa8bd9b4ac01b70e814749598273895146ec [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 Pinchart2f13c522015-07-27 13:43:09 +030038static void rcar_du_plane_setup_scanout(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 Pinchart2f13c522015-07-27 13:43:09 +030048 unsigned int pitch;
Laurent Pinchart906eff72014-12-09 19:11:18 +020049 bool interlaced;
Laurent Pinchart2f13c522015-07-27 13:43:09 +030050 unsigned int i;
51 u32 dma[2];
Laurent Pincharteb863012013-11-13 14:26:01 +010052
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020053 interlaced = state->state.crtc->state->adjusted_mode.flags
Laurent Pinchart47094192015-02-22 19:24:59 +020054 & DRM_MODE_FLAG_INTERLACE;
Laurent Pinchart906eff72014-12-09 19:11:18 +020055
56 /* Memory pitch (expressed in pixels). Must be doubled for interlaced
57 * operation with 32bpp formats.
58 */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020059 if (state->format->planes == 2)
Laurent Pinchart2f13c522015-07-27 13:43:09 +030060 pitch = fb->pitches[0];
Laurent Pincharteb863012013-11-13 14:26:01 +010061 else
Laurent Pinchart2f13c522015-07-27 13:43:09 +030062 pitch = fb->pitches[0] * 8 / state->format->bpp;
Laurent Pincharteb863012013-11-13 14:26:01 +010063
Laurent Pinchart2f13c522015-07-27 13:43:09 +030064 for (i = 0; i < state->format->planes; ++i) {
65 gem = drm_fb_cma_get_gem_obj(fb, i);
66 dma[i] = gem->paddr + fb->offsets[i];
67 }
Laurent Pinchart906eff72014-12-09 19:11:18 +020068
Laurent Pinchart2f13c522015-07-27 13:43:09 +030069 rcar_du_plane_write(rgrp, index, PnMWR,
70 (interlaced && state->format->bpp == 32) ?
71 pitch * 2 : pitch);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020072
Laurent Pinchart9e7db062013-06-14 20:54:16 +020073 /* The Y position is expressed in raster line units and must be doubled
74 * for 32bpp formats, according to the R8A7790 datasheet. No mention of
75 * doubling the Y position is found in the R8A7779 datasheet, but the
76 * rule seems to apply there as well.
77 *
Laurent Pinchart906eff72014-12-09 19:11:18 +020078 * Despite not being documented, doubling seem not to be needed when
79 * operating in interlaced mode.
80 *
Laurent Pinchart9e7db062013-06-14 20:54:16 +020081 * Similarly, for the second plane, NV12 and NV21 formats seem to
Laurent Pinchart906eff72014-12-09 19:11:18 +020082 * require a halved Y position value, in both progressive and interlaced
83 * modes.
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020084 */
Laurent Pinchart287bdf02015-02-20 15:58:38 +020085 rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
86 rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020087 (!interlaced && state->format->bpp == 32 ? 2 : 1));
Laurent Pinchartf398f342015-02-23 01:25:19 +020088
Laurent Pinchart2f13c522015-07-27 13:43:09 +030089 rcar_du_plane_write(rgrp, index, PnDSA0R, dma[0]);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020090
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020091 if (state->format->planes == 2) {
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020092 index = (index + 1) % 8;
93
Laurent Pinchart2f13c522015-07-27 13:43:09 +030094 rcar_du_plane_write(rgrp, index, PnMWR, pitch);
Laurent Pinchart49785e22014-12-09 22:45:11 +020095
Laurent Pinchart287bdf02015-02-20 15:58:38 +020096 rcar_du_plane_write(rgrp, index, PnSPXR, src_x);
97 rcar_du_plane_write(rgrp, index, PnSPYR, src_y *
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +020098 (state->format->bpp == 16 ? 2 : 1) / 2);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +020099
Laurent Pinchart2f13c522015-07-27 13:43:09 +0300100 rcar_du_plane_write(rgrp, index, PnDSA0R, dma[1]);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200101 }
102}
103
104static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
105 unsigned int index)
106{
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200107 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300108 to_rcar_plane_state(plane->plane.state);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200109 struct rcar_du_group *rgrp = plane->group;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200110 u32 colorkey;
111 u32 pnmr;
112
113 /* The PnALPHAR register controls alpha-blending in 16bpp formats
114 * (ARGB1555 and XRGB1555).
115 *
116 * For ARGB, set the alpha value to 0, and enable alpha-blending when
117 * the A bit is 0. This maps A=0 to alpha=0 and A=1 to alpha=255.
118 *
119 * For XRGB, set the alpha value to the plane-wide alpha value and
120 * enable alpha-blending regardless of the X bit value.
121 */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200122 if (state->format->fourcc != DRM_FORMAT_XRGB1555)
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200123 rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200124 else
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200125 rcar_du_plane_write(rgrp, index, PnALPHAR,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200126 PnALPHAR_ABIT_X | state->alpha);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200127
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200128 pnmr = PnMR_BM_MD | state->format->pnmr;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200129
130 /* Disable color keying when requested. YUV formats have the
131 * PnMR_SPIM_TP_OFF bit set in their pnmr field, disabling color keying
132 * automatically.
133 */
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200134 if ((state->colorkey & RCAR_DU_COLORKEY_MASK) == RCAR_DU_COLORKEY_NONE)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200135 pnmr |= PnMR_SPIM_TP_OFF;
136
137 /* For packed YUV formats we need to select the U/V order. */
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200138 if (state->format->fourcc == DRM_FORMAT_YUYV)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200139 pnmr |= PnMR_YCDF_YUYV;
140
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200141 rcar_du_plane_write(rgrp, index, PnMR, pnmr);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200142
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200143 switch (state->format->fourcc) {
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200144 case DRM_FORMAT_RGB565:
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200145 colorkey = ((state->colorkey & 0xf80000) >> 8)
146 | ((state->colorkey & 0x00fc00) >> 5)
147 | ((state->colorkey & 0x0000f8) >> 3);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200148 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200149 break;
150
151 case DRM_FORMAT_ARGB1555:
152 case DRM_FORMAT_XRGB1555:
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200153 colorkey = ((state->colorkey & 0xf80000) >> 9)
154 | ((state->colorkey & 0x00f800) >> 6)
155 | ((state->colorkey & 0x0000f8) >> 3);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200156 rcar_du_plane_write(rgrp, index, PnTC2R, colorkey);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200157 break;
158
159 case DRM_FORMAT_XRGB8888:
160 case DRM_FORMAT_ARGB8888:
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200161 rcar_du_plane_write(rgrp, index, PnTC3R,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200162 PnTC3R_CODE | (state->colorkey & 0xffffff));
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200163 break;
164 }
165}
166
Laurent Pinchart2f13c522015-07-27 13:43:09 +0300167static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
168 unsigned int index)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200169{
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200170 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300171 to_rcar_plane_state(plane->plane.state);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200172 struct rcar_du_group *rgrp = plane->group;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200173 u32 ddcr2 = PnDDCR2_CODE;
174 u32 ddcr4;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200175
176 /* Data format
177 *
178 * The data format is selected by the DDDF field in PnMR and the EDF
179 * field in DDCR4.
180 */
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200181
182 rcar_du_plane_setup_mode(plane, index);
183
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200184 if (state->format->planes == 2) {
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200185 if (state->hwindex != index) {
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200186 if (state->format->fourcc == DRM_FORMAT_NV12 ||
187 state->format->fourcc == DRM_FORMAT_NV21)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200188 ddcr2 |= PnDDCR2_Y420;
189
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200190 if (state->format->fourcc == DRM_FORMAT_NV21)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200191 ddcr2 |= PnDDCR2_NV21;
192
193 ddcr2 |= PnDDCR2_DIVU;
194 } else {
195 ddcr2 |= PnDDCR2_DIVY;
196 }
197 }
198
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200199 rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);
Laurent Pinchartff967362015-07-27 12:46:44 +0300200
201 ddcr4 = state->format->edf | PnDDCR4_CODE;
202
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200203 rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200204
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200205 /* Destination position and size */
Laurent Pinchart287bdf02015-02-20 15:58:38 +0200206 rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
207 rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
208 rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
209 rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200210
211 /* Wrap-around and blinking, disabled */
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200212 rcar_du_plane_write(rgrp, index, PnWASPR, 0);
213 rcar_du_plane_write(rgrp, index, PnWAMWR, 4095);
214 rcar_du_plane_write(rgrp, index, PnBTR, 0);
215 rcar_du_plane_write(rgrp, index, PnMLR, 0);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200216}
217
218void rcar_du_plane_setup(struct rcar_du_plane *plane)
219{
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200220 struct rcar_du_plane_state *state =
Laurent Pinchartec69a402015-04-29 00:48:17 +0300221 to_rcar_plane_state(plane->plane.state);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200222
Laurent Pinchart2f13c522015-07-27 13:43:09 +0300223 rcar_du_plane_setup_format(plane, state->hwindex);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200224 if (state->format->planes == 2)
Laurent Pinchart2f13c522015-07-27 13:43:09 +0300225 rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200226
Laurent Pinchart2f13c522015-07-27 13:43:09 +0300227 rcar_du_plane_setup_scanout(plane);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200228}
229
Laurent Pinchart920888a2015-02-18 12:18:05 +0200230static int rcar_du_plane_atomic_check(struct drm_plane *plane,
231 struct drm_plane_state *state)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200232{
Laurent Pinchartec69a402015-04-29 00:48:17 +0300233 struct rcar_du_plane_state *rstate = to_rcar_plane_state(state);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200234 struct rcar_du_plane *rplane = to_rcar_plane(plane);
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200235 struct rcar_du_device *rcdu = rplane->group->dev;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200236
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200237 if (!state->fb || !state->crtc) {
238 rstate->format = NULL;
Laurent Pinchart920888a2015-02-18 12:18:05 +0200239 return 0;
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200240 }
Laurent Pinchart917de182015-02-17 18:34:17 +0200241
Laurent Pinchart920888a2015-02-18 12:18:05 +0200242 if (state->src_w >> 16 != state->crtc_w ||
243 state->src_h >> 16 != state->crtc_h) {
244 dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200245 return -EINVAL;
246 }
247
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200248 rstate->format = rcar_du_format_info(state->fb->pixel_format);
249 if (rstate->format == NULL) {
Laurent Pinchart920888a2015-02-18 12:18:05 +0200250 dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__,
251 state->fb->pixel_format);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200252 return -EINVAL;
253 }
254
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200255 return 0;
256}
257
Laurent Pinchart920888a2015-02-18 12:18:05 +0200258static void rcar_du_plane_atomic_update(struct drm_plane *plane,
259 struct drm_plane_state *old_state)
260{
261 struct rcar_du_plane *rplane = to_rcar_plane(plane);
Laurent Pinchart5bfcbce2015-02-23 02:59:35 +0200262
Laurent Pinchart5ee5a812015-02-25 18:27:19 +0200263 if (plane->state->crtc)
264 rcar_du_plane_setup(rplane);
Laurent Pinchart920888a2015-02-18 12:18:05 +0200265}
266
267static const struct drm_plane_helper_funcs rcar_du_plane_helper_funcs = {
268 .atomic_check = rcar_du_plane_atomic_check,
269 .atomic_update = rcar_du_plane_atomic_update,
270};
271
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200272static struct drm_plane_state *
273rcar_du_plane_atomic_duplicate_state(struct drm_plane *plane)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200274{
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200275 struct rcar_du_plane_state *state;
276 struct rcar_du_plane_state *copy;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200277
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300278 if (WARN_ON(!plane->state))
279 return NULL;
280
Laurent Pinchartec69a402015-04-29 00:48:17 +0300281 state = to_rcar_plane_state(plane->state);
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200282 copy = kmemdup(state, sizeof(*state), GFP_KERNEL);
283 if (copy == NULL)
284 return NULL;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200285
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300286 __drm_atomic_helper_plane_duplicate_state(plane, &copy->state);
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200287
288 return &copy->state;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200289}
290
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200291static void rcar_du_plane_atomic_destroy_state(struct drm_plane *plane,
292 struct drm_plane_state *state)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200293{
Laurent Pinchart263b39f2015-05-27 16:36:29 +0300294 __drm_atomic_helper_plane_destroy_state(plane, state);
Laurent Pinchartec69a402015-04-29 00:48:17 +0300295 kfree(to_rcar_plane_state(state));
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200296}
297
Laurent Pincharta32a3c82015-07-27 11:42:54 +0300298static void rcar_du_plane_reset(struct drm_plane *plane)
299{
300 struct rcar_du_plane_state *state;
301
302 if (plane->state) {
303 rcar_du_plane_atomic_destroy_state(plane, plane->state);
304 plane->state = NULL;
305 }
306
307 state = kzalloc(sizeof(*state), GFP_KERNEL);
308 if (state == NULL)
309 return;
310
311 state->hwindex = -1;
Laurent Pinchartaf8ad962013-06-21 17:36:15 +0200312 state->source = RCAR_DU_PLANE_MEMORY;
Laurent Pincharta32a3c82015-07-27 11:42:54 +0300313 state->alpha = 255;
314 state->colorkey = RCAR_DU_COLORKEY_NONE;
315 state->zpos = plane->type == DRM_PLANE_TYPE_PRIMARY ? 0 : 1;
316
317 plane->state = &state->state;
318 plane->state->plane = plane;
319}
320
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200321static int rcar_du_plane_atomic_set_property(struct drm_plane *plane,
322 struct drm_plane_state *state,
323 struct drm_property *property,
324 uint64_t val)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200325{
Laurent Pinchartec69a402015-04-29 00:48:17 +0300326 struct rcar_du_plane_state *rstate = to_rcar_plane_state(state);
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300327 struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200328
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300329 if (property == rcdu->props.alpha)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200330 rstate->alpha = val;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300331 else if (property == rcdu->props.colorkey)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200332 rstate->colorkey = val;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300333 else if (property == rcdu->props.zpos)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200334 rstate->zpos = val;
335 else
336 return -EINVAL;
337
338 return 0;
339}
340
341static int rcar_du_plane_atomic_get_property(struct drm_plane *plane,
342 const struct drm_plane_state *state, struct drm_property *property,
343 uint64_t *val)
344{
345 const struct rcar_du_plane_state *rstate =
346 container_of(state, const struct rcar_du_plane_state, state);
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300347 struct rcar_du_device *rcdu = to_rcar_plane(plane)->group->dev;
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200348
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300349 if (property == rcdu->props.alpha)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200350 *val = rstate->alpha;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300351 else if (property == rcdu->props.colorkey)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200352 *val = rstate->colorkey;
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300353 else if (property == rcdu->props.zpos)
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200354 *val = rstate->zpos;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200355 else
356 return -EINVAL;
357
358 return 0;
359}
360
361static const struct drm_plane_funcs rcar_du_plane_funcs = {
Laurent Pinchart336d04a2015-02-20 13:18:56 +0200362 .update_plane = drm_atomic_helper_update_plane,
363 .disable_plane = drm_atomic_helper_disable_plane,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200364 .reset = rcar_du_plane_reset,
365 .set_property = drm_atomic_helper_plane_set_property,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200366 .destroy = drm_plane_cleanup,
Laurent Pinchart4407cc02015-02-23 02:36:31 +0200367 .atomic_duplicate_state = rcar_du_plane_atomic_duplicate_state,
368 .atomic_destroy_state = rcar_du_plane_atomic_destroy_state,
369 .atomic_set_property = rcar_du_plane_atomic_set_property,
370 .atomic_get_property = rcar_du_plane_atomic_get_property,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200371};
372
373static const uint32_t formats[] = {
374 DRM_FORMAT_RGB565,
375 DRM_FORMAT_ARGB1555,
376 DRM_FORMAT_XRGB1555,
377 DRM_FORMAT_XRGB8888,
378 DRM_FORMAT_ARGB8888,
379 DRM_FORMAT_UYVY,
380 DRM_FORMAT_YUYV,
381 DRM_FORMAT_NV12,
382 DRM_FORMAT_NV21,
383 DRM_FORMAT_NV16,
384};
385
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200386int rcar_du_planes_init(struct rcar_du_group *rgrp)
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200387{
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200388 struct rcar_du_device *rcdu = rgrp->dev;
Laurent Pinchart917de182015-02-17 18:34:17 +0200389 unsigned int crtcs;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200390 unsigned int i;
Laurent Pinchart917de182015-02-17 18:34:17 +0200391 int ret;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200392
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300393 /* Create one primary plane per CRTC in this group and seven overlay
Laurent Pinchart917de182015-02-17 18:34:17 +0200394 * planes.
395 */
Laurent Pinchartd6aed572015-05-25 16:32:45 +0300396 rgrp->num_planes = rgrp->num_crtcs + 7;
Laurent Pinchart917de182015-02-17 18:34:17 +0200397
398 crtcs = ((1 << rcdu->num_crtcs) - 1) & (3 << (2 * rgrp->index));
399
Laurent Pinchartd6aed572015-05-25 16:32:45 +0300400 for (i = 0; i < rgrp->num_planes; ++i) {
Laurent Pinchartfe6fbe92015-04-28 17:36:33 +0300401 enum drm_plane_type type = i < rgrp->num_crtcs
Laurent Pinchart917de182015-02-17 18:34:17 +0200402 ? DRM_PLANE_TYPE_PRIMARY
403 : DRM_PLANE_TYPE_OVERLAY;
Laurent Pinchart99caede2015-04-29 00:05:56 +0300404 struct rcar_du_plane *plane = &rgrp->planes[i];
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200405
Laurent Pinchartcb2025d2013-06-16 21:01:02 +0200406 plane->group = rgrp;
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200407
Laurent Pinchart917de182015-02-17 18:34:17 +0200408 ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, crtcs,
409 &rcar_du_plane_funcs, formats,
Ville Syrjäläb0b3b792015-12-09 16:19:55 +0200410 ARRAY_SIZE(formats), type,
411 NULL);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200412 if (ret < 0)
413 return ret;
414
Laurent Pinchart920888a2015-02-18 12:18:05 +0200415 drm_plane_helper_add(&plane->plane,
416 &rcar_du_plane_helper_funcs);
417
Laurent Pinchart917de182015-02-17 18:34:17 +0200418 if (type == DRM_PLANE_TYPE_PRIMARY)
419 continue;
420
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200421 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300422 rcdu->props.alpha, 255);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200423 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300424 rcdu->props.colorkey,
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200425 RCAR_DU_COLORKEY_NONE);
426 drm_object_attach_property(&plane->plane.base,
Laurent Pinchart9f6aee92015-04-28 23:59:29 +0300427 rcdu->props.zpos, 1);
Laurent Pinchart4bf8e192013-06-19 13:54:11 +0200428 }
429
430 return 0;
431}