Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm: rcar-du: Expose the VSP1 compositor through KMS planes

On R-Car Gen3 SoCs the DU lost its ability to access memory directly and
needs to work in conjunction with the VSP to do so. This commit handles
the VSP internally to hide it from the user.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>

+539 -16
+7
drivers/gpu/drm/rcar-du/Kconfig
··· 25 25 help 26 26 Enable support for the R-Car Display Unit embedded LVDS encoders 27 27 (currently only on R8A7790 and R8A7791). 28 + 29 + config DRM_RCAR_VSP 30 + bool "R-Car DU VSP Compositor Support" 31 + depends on DRM_RCAR_DU 32 + depends on VIDEO_RENESAS_VSP1 33 + help 34 + Enable support to expose the R-Car VSP Compositor as KMS planes.
+2
drivers/gpu/drm/rcar-du/Makefile
··· 11 11 rcar_du_hdmienc.o 12 12 rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o 13 13 14 + rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o 15 + 14 16 obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
+41 -7
drivers/gpu/drm/rcar-du/rcar_du_crtc.c
··· 28 28 #include "rcar_du_kms.h" 29 29 #include "rcar_du_plane.h" 30 30 #include "rcar_du_regs.h" 31 + #include "rcar_du_vsp.h" 31 32 32 33 static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) 33 34 { ··· 208 207 static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc) 209 208 { 210 209 struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; 210 + struct rcar_du_device *rcdu = rcrtc->group->dev; 211 211 unsigned int num_planes = 0; 212 212 unsigned int dptsr_planes; 213 213 unsigned int hwplanes = 0; ··· 250 248 dspr |= (index + 1) << prio; 251 249 hwplanes |= 1 << index; 252 250 } 251 + } 252 + 253 + /* If VSP+DU integration is enabled the plane assignment is fixed. */ 254 + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) { 255 + dspr = (rcrtc->index % 2) + 1; 256 + hwplanes = 1 << (rcrtc->index % 2); 253 257 } 254 258 255 259 /* Update the planes to display timing and dot clock generator ··· 377 369 378 370 rcar_du_group_start_stop(rcrtc->group, true); 379 371 372 + /* Enable the VSP compositor. */ 373 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 374 + rcar_du_vsp_enable(rcrtc); 375 + 380 376 /* Turn vertical blanking interrupt reporting back on. */ 381 377 drm_crtc_vblank_on(crtc); 382 378 ··· 414 402 rcar_du_crtc_wait_page_flip(rcrtc); 415 403 drm_crtc_vblank_off(crtc); 416 404 405 + /* Disable the VSP compositor. */ 406 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 407 + rcar_du_vsp_disable(rcrtc); 408 + 417 409 /* Select switch sync mode. This stops display operation and configures 418 410 * the HSYNC and VSYNC signals as inputs. 419 411 */ ··· 430 414 431 415 void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc) 432 416 { 417 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 418 + rcar_du_vsp_disable(rcrtc); 419 + 433 420 rcar_du_crtc_stop(rcrtc); 434 421 rcar_du_crtc_put(rcrtc); 435 422 } ··· 448 429 rcar_du_crtc_start(rcrtc); 449 430 450 431 /* Commit the planes state. */ 451 - for (i = 0; i < rcrtc->group->num_planes; ++i) { 452 - struct rcar_du_plane *plane = &rcrtc->group->planes[i]; 432 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) { 433 + rcar_du_vsp_enable(rcrtc); 434 + } else { 435 + for (i = 0; i < rcrtc->group->num_planes; ++i) { 436 + struct rcar_du_plane *plane = &rcrtc->group->planes[i]; 453 437 454 - if (plane->plane.state->crtc != &rcrtc->crtc) 455 - continue; 438 + if (plane->plane.state->crtc != &rcrtc->crtc) 439 + continue; 456 440 457 - rcar_du_plane_setup(plane); 441 + rcar_du_plane_setup(plane); 442 + } 458 443 } 459 444 460 445 rcar_du_crtc_update_planes(rcrtc); ··· 509 486 rcrtc->event = event; 510 487 spin_unlock_irqrestore(&dev->event_lock, flags); 511 488 } 489 + 490 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 491 + rcar_du_vsp_atomic_begin(rcrtc); 512 492 } 513 493 514 494 static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc, ··· 520 494 struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); 521 495 522 496 rcar_du_crtc_update_planes(rcrtc); 497 + 498 + if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) 499 + rcar_du_vsp_atomic_flush(rcrtc); 523 500 } 524 501 525 502 static const struct drm_crtc_helper_funcs crtc_helper_funcs = { ··· 578 549 struct platform_device *pdev = to_platform_device(rcdu->dev); 579 550 struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; 580 551 struct drm_crtc *crtc = &rcrtc->crtc; 552 + struct drm_plane *primary; 581 553 unsigned int irqflags; 582 554 struct clk *clk; 583 555 char clk_name[9]; ··· 615 585 rcrtc->mmio_offset = mmio_offsets[index]; 616 586 rcrtc->index = index; 617 587 618 - ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, 619 - &rgrp->planes[index % 2].plane, 588 + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) 589 + primary = &rcrtc->vsp->planes[0].plane; 590 + else 591 + primary = &rgrp->planes[index % 2].plane; 592 + 593 + ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary, 620 594 NULL, &crtc_funcs, NULL); 621 595 if (ret < 0) 622 596 return ret;
+2
drivers/gpu/drm/rcar-du/rcar_du_crtc.h
··· 21 21 #include <drm/drm_crtc.h> 22 22 23 23 struct rcar_du_group; 24 + struct rcar_du_vsp; 24 25 25 26 /** 26 27 * struct rcar_du_crtc - the CRTC, representing a DU superposition processor ··· 51 50 unsigned int outputs; 52 51 53 52 struct rcar_du_group *group; 53 + struct rcar_du_vsp *vsp; 54 54 }; 55 55 56 56 #define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
+4
drivers/gpu/drm/rcar-du/rcar_du_drv.h
··· 19 19 20 20 #include "rcar_du_crtc.h" 21 21 #include "rcar_du_group.h" 22 + #include "rcar_du_vsp.h" 22 23 23 24 struct clk; 24 25 struct device; ··· 30 29 31 30 #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ 32 31 #define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */ 32 + #define RCAR_DU_FEATURE_VSP1_SOURCE (1 << 2) /* Has inputs from VSP1 */ 33 33 34 34 #define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */ 35 35 #define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */ ··· 70 68 #define RCAR_DU_MAX_CRTCS 3 71 69 #define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2) 72 70 #define RCAR_DU_MAX_LVDS 2 71 + #define RCAR_DU_MAX_VSPS 4 73 72 74 73 struct rcar_du_device { 75 74 struct device *dev; ··· 85 82 unsigned int num_crtcs; 86 83 87 84 struct rcar_du_group groups[RCAR_DU_MAX_GROUPS]; 85 + struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS]; 88 86 89 87 struct { 90 88 struct drm_property *alpha;
+25 -3
drivers/gpu/drm/rcar-du/rcar_du_kms.c
··· 28 28 #include "rcar_du_kms.h" 29 29 #include "rcar_du_lvdsenc.h" 30 30 #include "rcar_du_regs.h" 31 + #include "rcar_du_vsp.h" 31 32 32 33 /* ----------------------------------------------------------------------------- 33 34 * Format helpers ··· 196 195 static int rcar_du_atomic_check(struct drm_device *dev, 197 196 struct drm_atomic_state *state) 198 197 { 198 + struct rcar_du_device *rcdu = dev->dev_private; 199 199 int ret; 200 200 201 201 ret = drm_atomic_helper_check(dev, state); 202 202 if (ret < 0) 203 203 return ret; 204 + 205 + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) 206 + return 0; 204 207 205 208 return rcar_du_atomic_check_planes(dev, state); 206 209 } ··· 549 544 */ 550 545 rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0; 551 546 552 - ret = rcar_du_planes_init(rgrp); 553 - if (ret < 0) 554 - return ret; 547 + if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) { 548 + ret = rcar_du_planes_init(rgrp); 549 + if (ret < 0) 550 + return ret; 551 + } 552 + } 553 + 554 + /* Initialize the compositors. */ 555 + if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) { 556 + for (i = 0; i < rcdu->num_crtcs; ++i) { 557 + struct rcar_du_vsp *vsp = &rcdu->vsps[i]; 558 + 559 + vsp->index = i; 560 + vsp->dev = rcdu; 561 + rcdu->crtcs[i].vsp = vsp; 562 + 563 + ret = rcar_du_vsp_init(vsp); 564 + if (ret < 0) 565 + return ret; 566 + } 555 567 } 556 568 557 569 /* Create the CRTCs. */
+2 -5
drivers/gpu/drm/rcar-du/rcar_du_plane.c
··· 505 505 rcar_du_plane_write(rgrp, index, PnMLR, 0); 506 506 } 507 507 508 - void rcar_du_plane_setup(struct rcar_du_plane *plane) 508 + void __rcar_du_plane_setup(struct rcar_du_group *rgrp, 509 + const struct rcar_du_plane_state *state) 509 510 { 510 - struct rcar_du_plane_state *state = 511 - to_rcar_plane_state(plane->plane.state); 512 - struct rcar_du_group *rgrp = plane->group; 513 - 514 511 rcar_du_plane_setup_format(rgrp, state->hwindex, state); 515 512 if (state->format->planes == 2) 516 513 rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
+10 -1
drivers/gpu/drm/rcar-du/rcar_du_plane.h
··· 76 76 77 77 int rcar_du_planes_init(struct rcar_du_group *rgrp); 78 78 79 - void rcar_du_plane_setup(struct rcar_du_plane *plane); 79 + void __rcar_du_plane_setup(struct rcar_du_group *rgrp, 80 + const struct rcar_du_plane_state *state); 81 + 82 + static inline void rcar_du_plane_setup(struct rcar_du_plane *plane) 83 + { 84 + struct rcar_du_plane_state *state = 85 + to_rcar_plane_state(plane->plane.state); 86 + 87 + return __rcar_du_plane_setup(plane->group, state); 88 + } 80 89 81 90 #endif /* __RCAR_DU_PLANE_H__ */
+370
drivers/gpu/drm/rcar-du/rcar_du_vsp.c
··· 1 + /* 2 + * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor 3 + * 4 + * Copyright (C) 2015 Renesas Electronics 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 + #include <drm/drmP.h> 15 + #include <drm/drm_atomic_helper.h> 16 + #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> 20 + #include <drm/drm_plane_helper.h> 21 + 22 + #include <linux/of_platform.h> 23 + #include <linux/videodev2.h> 24 + 25 + #include <media/vsp1.h> 26 + 27 + #include "rcar_du_drv.h" 28 + #include "rcar_du_kms.h" 29 + #include "rcar_du_vsp.h" 30 + 31 + void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) 32 + { 33 + const struct drm_display_mode *mode = &crtc->crtc.state->adjusted_mode; 34 + struct rcar_du_plane_state state = { 35 + .state = { 36 + .crtc = &crtc->crtc, 37 + .crtc_x = 0, 38 + .crtc_y = 0, 39 + .crtc_w = mode->hdisplay, 40 + .crtc_h = mode->vdisplay, 41 + .src_x = 0, 42 + .src_y = 0, 43 + .src_w = mode->hdisplay << 16, 44 + .src_h = mode->vdisplay << 16, 45 + }, 46 + .format = rcar_du_format_info(DRM_FORMAT_ARGB8888), 47 + .hwindex = crtc->index % 2, 48 + .source = RCAR_DU_PLANE_VSPD1, 49 + .alpha = 255, 50 + .colorkey = 0, 51 + .zpos = 0, 52 + }; 53 + 54 + __rcar_du_plane_setup(crtc->group, &state); 55 + 56 + /* Ensure that the plane source configuration takes effect by requesting 57 + * a restart of the group. See rcar_du_plane_atomic_update() for a more 58 + * detailed explanation. 59 + * 60 + * TODO: Check whether this is still needed on Gen3. 61 + */ 62 + crtc->group->need_restart = true; 63 + 64 + vsp1_du_setup_lif(crtc->vsp->vsp, mode->hdisplay, mode->vdisplay); 65 + } 66 + 67 + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) 68 + { 69 + vsp1_du_setup_lif(crtc->vsp->vsp, 0, 0); 70 + } 71 + 72 + void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) 73 + { 74 + vsp1_du_atomic_begin(crtc->vsp->vsp); 75 + } 76 + 77 + void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) 78 + { 79 + vsp1_du_atomic_flush(crtc->vsp->vsp); 80 + } 81 + 82 + /* Keep the two tables in sync. */ 83 + static const u32 formats_kms[] = { 84 + DRM_FORMAT_RGB332, 85 + DRM_FORMAT_ARGB4444, 86 + DRM_FORMAT_XRGB4444, 87 + DRM_FORMAT_ARGB1555, 88 + DRM_FORMAT_XRGB1555, 89 + DRM_FORMAT_RGB565, 90 + DRM_FORMAT_BGR888, 91 + DRM_FORMAT_RGB888, 92 + DRM_FORMAT_BGRA8888, 93 + DRM_FORMAT_BGRX8888, 94 + DRM_FORMAT_ARGB8888, 95 + DRM_FORMAT_XRGB8888, 96 + DRM_FORMAT_UYVY, 97 + DRM_FORMAT_VYUY, 98 + DRM_FORMAT_YUYV, 99 + DRM_FORMAT_YVYU, 100 + DRM_FORMAT_NV12, 101 + DRM_FORMAT_NV21, 102 + DRM_FORMAT_NV16, 103 + DRM_FORMAT_NV61, 104 + }; 105 + 106 + static const u32 formats_v4l2[] = { 107 + V4L2_PIX_FMT_RGB332, 108 + V4L2_PIX_FMT_ARGB444, 109 + V4L2_PIX_FMT_XRGB444, 110 + V4L2_PIX_FMT_ARGB555, 111 + V4L2_PIX_FMT_XRGB555, 112 + V4L2_PIX_FMT_RGB565, 113 + V4L2_PIX_FMT_RGB24, 114 + V4L2_PIX_FMT_BGR24, 115 + V4L2_PIX_FMT_ARGB32, 116 + V4L2_PIX_FMT_XRGB32, 117 + V4L2_PIX_FMT_ABGR32, 118 + V4L2_PIX_FMT_XBGR32, 119 + V4L2_PIX_FMT_UYVY, 120 + V4L2_PIX_FMT_VYUY, 121 + V4L2_PIX_FMT_YUYV, 122 + V4L2_PIX_FMT_YVYU, 123 + V4L2_PIX_FMT_NV12M, 124 + V4L2_PIX_FMT_NV21M, 125 + V4L2_PIX_FMT_NV16M, 126 + V4L2_PIX_FMT_NV61M, 127 + }; 128 + 129 + static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) 130 + { 131 + struct rcar_du_vsp_plane_state *state = 132 + to_rcar_vsp_plane_state(plane->plane.state); 133 + struct drm_framebuffer *fb = plane->plane.state->fb; 134 + struct drm_gem_cma_object *gem; 135 + struct v4l2_rect src; 136 + struct v4l2_rect dst; 137 + dma_addr_t paddr[2] = { 0, }; 138 + u32 pixelformat = 0; 139 + unsigned int i; 140 + 141 + src.left = state->state.src_x >> 16; 142 + src.top = state->state.src_y >> 16; 143 + src.width = state->state.src_w >> 16; 144 + src.height = state->state.src_h >> 16; 145 + 146 + dst.left = state->state.crtc_x; 147 + dst.top = state->state.crtc_y; 148 + dst.width = state->state.crtc_w; 149 + dst.height = state->state.crtc_h; 150 + 151 + gem = drm_fb_cma_get_gem_obj(fb, 0); 152 + paddr[0] = gem->paddr + fb->offsets[0]; 153 + 154 + if (state->format->planes == 2) { 155 + gem = drm_fb_cma_get_gem_obj(fb, 1); 156 + paddr[1] = gem->paddr + fb->offsets[1]; 157 + } 158 + 159 + for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) { 160 + if (formats_kms[i] == state->format->fourcc) { 161 + pixelformat = formats_v4l2[i]; 162 + break; 163 + } 164 + } 165 + 166 + WARN_ON(!pixelformat); 167 + 168 + vsp1_du_atomic_update(plane->vsp->vsp, plane->index, pixelformat, 169 + fb->pitches[0], paddr, &src, &dst); 170 + } 171 + 172 + static int rcar_du_vsp_plane_atomic_check(struct drm_plane *plane, 173 + struct drm_plane_state *state) 174 + { 175 + struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); 176 + struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane); 177 + struct rcar_du_device *rcdu = rplane->vsp->dev; 178 + 179 + if (!state->fb || !state->crtc) { 180 + rstate->format = NULL; 181 + return 0; 182 + } 183 + 184 + if (state->src_w >> 16 != state->crtc_w || 185 + state->src_h >> 16 != state->crtc_h) { 186 + dev_dbg(rcdu->dev, "%s: scaling not supported\n", __func__); 187 + return -EINVAL; 188 + } 189 + 190 + rstate->format = rcar_du_format_info(state->fb->pixel_format); 191 + if (rstate->format == NULL) { 192 + dev_dbg(rcdu->dev, "%s: unsupported format %08x\n", __func__, 193 + state->fb->pixel_format); 194 + return -EINVAL; 195 + } 196 + 197 + return 0; 198 + } 199 + 200 + static void rcar_du_vsp_plane_atomic_update(struct drm_plane *plane, 201 + struct drm_plane_state *old_state) 202 + { 203 + struct rcar_du_vsp_plane *rplane = to_rcar_vsp_plane(plane); 204 + 205 + if (plane->state->crtc) 206 + rcar_du_vsp_plane_setup(rplane); 207 + else 208 + vsp1_du_atomic_update(rplane->vsp->vsp, rplane->index, 0, 0, 0, 209 + NULL, NULL); 210 + } 211 + 212 + static const struct drm_plane_helper_funcs rcar_du_vsp_plane_helper_funcs = { 213 + .atomic_check = rcar_du_vsp_plane_atomic_check, 214 + .atomic_update = rcar_du_vsp_plane_atomic_update, 215 + }; 216 + 217 + static struct drm_plane_state * 218 + rcar_du_vsp_plane_atomic_duplicate_state(struct drm_plane *plane) 219 + { 220 + struct rcar_du_vsp_plane_state *state; 221 + struct rcar_du_vsp_plane_state *copy; 222 + 223 + if (WARN_ON(!plane->state)) 224 + return NULL; 225 + 226 + state = to_rcar_vsp_plane_state(plane->state); 227 + copy = kmemdup(state, sizeof(*state), GFP_KERNEL); 228 + if (copy == NULL) 229 + return NULL; 230 + 231 + __drm_atomic_helper_plane_duplicate_state(plane, &copy->state); 232 + 233 + return &copy->state; 234 + } 235 + 236 + static void rcar_du_vsp_plane_atomic_destroy_state(struct drm_plane *plane, 237 + struct drm_plane_state *state) 238 + { 239 + __drm_atomic_helper_plane_destroy_state(plane, state); 240 + kfree(to_rcar_vsp_plane_state(state)); 241 + } 242 + 243 + static void rcar_du_vsp_plane_reset(struct drm_plane *plane) 244 + { 245 + struct rcar_du_vsp_plane_state *state; 246 + 247 + if (plane->state) { 248 + rcar_du_vsp_plane_atomic_destroy_state(plane, plane->state); 249 + plane->state = NULL; 250 + } 251 + 252 + state = kzalloc(sizeof(*state), GFP_KERNEL); 253 + if (state == NULL) 254 + return; 255 + 256 + state->alpha = 255; 257 + 258 + plane->state = &state->state; 259 + plane->state->plane = plane; 260 + } 261 + 262 + static int rcar_du_vsp_plane_atomic_set_property(struct drm_plane *plane, 263 + struct drm_plane_state *state, struct drm_property *property, 264 + uint64_t val) 265 + { 266 + struct rcar_du_vsp_plane_state *rstate = to_rcar_vsp_plane_state(state); 267 + struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev; 268 + 269 + if (property == rcdu->props.alpha) 270 + rstate->alpha = val; 271 + else 272 + return -EINVAL; 273 + 274 + return 0; 275 + } 276 + 277 + static int rcar_du_vsp_plane_atomic_get_property(struct drm_plane *plane, 278 + const struct drm_plane_state *state, struct drm_property *property, 279 + uint64_t *val) 280 + { 281 + const struct rcar_du_vsp_plane_state *rstate = 282 + container_of(state, const struct rcar_du_vsp_plane_state, state); 283 + struct rcar_du_device *rcdu = to_rcar_vsp_plane(plane)->vsp->dev; 284 + 285 + if (property == rcdu->props.alpha) 286 + *val = rstate->alpha; 287 + else 288 + return -EINVAL; 289 + 290 + return 0; 291 + } 292 + 293 + static const struct drm_plane_funcs rcar_du_vsp_plane_funcs = { 294 + .update_plane = drm_atomic_helper_update_plane, 295 + .disable_plane = drm_atomic_helper_disable_plane, 296 + .reset = rcar_du_vsp_plane_reset, 297 + .set_property = drm_atomic_helper_plane_set_property, 298 + .destroy = drm_plane_cleanup, 299 + .atomic_duplicate_state = rcar_du_vsp_plane_atomic_duplicate_state, 300 + .atomic_destroy_state = rcar_du_vsp_plane_atomic_destroy_state, 301 + .atomic_set_property = rcar_du_vsp_plane_atomic_set_property, 302 + .atomic_get_property = rcar_du_vsp_plane_atomic_get_property, 303 + }; 304 + 305 + int rcar_du_vsp_init(struct rcar_du_vsp *vsp) 306 + { 307 + struct rcar_du_device *rcdu = vsp->dev; 308 + struct platform_device *pdev; 309 + struct device_node *np; 310 + unsigned int i; 311 + int ret; 312 + 313 + /* Find the VSP device and initialize it. */ 314 + np = of_parse_phandle(rcdu->dev->of_node, "vsps", vsp->index); 315 + if (!np) { 316 + dev_err(rcdu->dev, "vsps node not found\n"); 317 + return -ENXIO; 318 + } 319 + 320 + pdev = of_find_device_by_node(np); 321 + of_node_put(np); 322 + if (!pdev) 323 + return -ENXIO; 324 + 325 + vsp->vsp = &pdev->dev; 326 + 327 + ret = vsp1_du_init(vsp->vsp); 328 + if (ret < 0) 329 + return ret; 330 + 331 + /* The VSP2D (Gen3) has 5 RPFs, but the VSP1D (Gen2) is limited to 332 + * 4 RPFs. Hardcode the number of planes to 4 as Gen3 isn't supported 333 + * yet. 334 + */ 335 + vsp->num_planes = 4; 336 + 337 + vsp->planes = devm_kcalloc(rcdu->dev, vsp->num_planes, 338 + sizeof(*vsp->planes), GFP_KERNEL); 339 + if (!vsp->planes) 340 + return -ENOMEM; 341 + 342 + for (i = 0; i < vsp->num_planes; ++i) { 343 + enum drm_plane_type type = i ? DRM_PLANE_TYPE_OVERLAY 344 + : DRM_PLANE_TYPE_PRIMARY; 345 + struct rcar_du_vsp_plane *plane = &vsp->planes[i]; 346 + 347 + plane->vsp = vsp; 348 + plane->index = i; 349 + 350 + ret = drm_universal_plane_init(rcdu->ddev, &plane->plane, 351 + 1 << vsp->index, 352 + &rcar_du_vsp_plane_funcs, 353 + formats_kms, 354 + ARRAY_SIZE(formats_kms), type, 355 + NULL); 356 + if (ret < 0) 357 + return ret; 358 + 359 + drm_plane_helper_add(&plane->plane, 360 + &rcar_du_vsp_plane_helper_funcs); 361 + 362 + if (type == DRM_PLANE_TYPE_PRIMARY) 363 + continue; 364 + 365 + drm_object_attach_property(&plane->plane.base, 366 + rcdu->props.alpha, 255); 367 + } 368 + 369 + return 0; 370 + }
+76
drivers/gpu/drm/rcar-du/rcar_du_vsp.h
··· 1 + /* 2 + * rcar_du_vsp.h -- R-Car Display Unit VSP-Based Compositor 3 + * 4 + * Copyright (C) 2015 Renesas Electronics 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_VSP_H__ 15 + #define __RCAR_DU_VSP_H__ 16 + 17 + #include <drm/drmP.h> 18 + #include <drm/drm_crtc.h> 19 + 20 + struct rcar_du_format_info; 21 + struct rcar_du_vsp; 22 + 23 + struct rcar_du_vsp_plane { 24 + struct drm_plane plane; 25 + struct rcar_du_vsp *vsp; 26 + unsigned int index; 27 + }; 28 + 29 + struct rcar_du_vsp { 30 + unsigned int index; 31 + struct device *vsp; 32 + struct rcar_du_device *dev; 33 + struct rcar_du_vsp_plane *planes; 34 + unsigned int num_planes; 35 + }; 36 + 37 + static inline struct rcar_du_vsp_plane *to_rcar_vsp_plane(struct drm_plane *p) 38 + { 39 + return container_of(p, struct rcar_du_vsp_plane, plane); 40 + } 41 + 42 + /** 43 + * struct rcar_du_vsp_plane_state - Driver-specific plane state 44 + * @state: base DRM plane state 45 + * @format: information about the pixel format used by the plane 46 + * @alpha: value of the plane alpha property 47 + */ 48 + struct rcar_du_vsp_plane_state { 49 + struct drm_plane_state state; 50 + 51 + const struct rcar_du_format_info *format; 52 + 53 + unsigned int alpha; 54 + }; 55 + 56 + static inline struct rcar_du_vsp_plane_state * 57 + to_rcar_vsp_plane_state(struct drm_plane_state *state) 58 + { 59 + return container_of(state, struct rcar_du_vsp_plane_state, state); 60 + } 61 + 62 + #ifdef CONFIG_DRM_RCAR_VSP 63 + int rcar_du_vsp_init(struct rcar_du_vsp *vsp); 64 + void rcar_du_vsp_enable(struct rcar_du_crtc *crtc); 65 + void rcar_du_vsp_disable(struct rcar_du_crtc *crtc); 66 + void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc); 67 + void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc); 68 + #else 69 + static inline int rcar_du_vsp_init(struct rcar_du_vsp *vsp) { return 0; }; 70 + static inline void rcar_du_vsp_enable(struct rcar_du_crtc *crtc) { }; 71 + static inline void rcar_du_vsp_disable(struct rcar_du_crtc *crtc) { }; 72 + static inline void rcar_du_vsp_atomic_begin(struct rcar_du_crtc *crtc) { }; 73 + static inline void rcar_du_vsp_atomic_flush(struct rcar_du_crtc *crtc) { }; 74 + #endif 75 + 76 + #endif /* __RCAR_DU_VSP_H__ */