| From 62db4469a68f3aa96132071ada5e265987c7900a Mon Sep 17 00:00:00 2001 |
| From: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| Date: Sun, 16 Jun 2013 21:01:02 +0200 |
| Subject: drm/rcar-du: Introduce CRTCs groups |
| |
| The R8A7779 DU is split in per-CRTC resources (scan-out engine, blending |
| unit, timings generator, ...) and device-global resources (start/stop |
| control, planes, ...) shared between the two CRTCs. |
| |
| The R8A7790 introduced a third CRTC with its own set of global resources |
| This would be modeled as two separate DU device instances if it wasn't |
| for a handful or resources that are shared between the three CRTCs |
| (mostly related to input and output routing). For this reason the |
| R8A7790 DU must be modeled as a single device with three CRTCs, two sets |
| of "semi-global" resources, and a few device-global resources. |
| |
| Introduce a new rcar_du_group driver-specific object, without any real |
| counterpart in the DU documentation, that models those semi-global |
| resources. |
| |
| Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com> |
| (cherry picked from commit cb2025d2509ffab1c426509fd9de3d83e40398b9) |
| Signed-off-by: Simon Horman <horms+renesas@verge.net.au> |
| --- |
| drivers/gpu/drm/rcar-du/Makefile | 1 + |
| drivers/gpu/drm/rcar-du/rcar_du_crtc.c | 92 ++++++------------- |
| drivers/gpu/drm/rcar-du/rcar_du_crtc.h | 5 +- |
| drivers/gpu/drm/rcar-du/rcar_du_drv.c | 46 ---------- |
| drivers/gpu/drm/rcar-du/rcar_du_drv.h | 10 +-- |
| drivers/gpu/drm/rcar-du/rcar_du_group.c | 127 ++++++++++++++++++++++++++ |
| drivers/gpu/drm/rcar-du/rcar_du_group.h | 47 ++++++++++ |
| drivers/gpu/drm/rcar-du/rcar_du_kms.c | 11 ++- |
| drivers/gpu/drm/rcar-du/rcar_du_plane.c | 155 ++++++++++++++++---------------- |
| drivers/gpu/drm/rcar-du/rcar_du_plane.h | 8 +- |
| 10 files changed, 299 insertions(+), 203 deletions(-) |
| create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_group.c |
| create mode 100644 drivers/gpu/drm/rcar-du/rcar_du_group.h |
| |
| 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 @@ |
| rcar-du-drm-y := rcar_du_crtc.o \ |
| rcar_du_drv.o \ |
| rcar_du_encoder.o \ |
| + rcar_du_group.o \ |
| rcar_du_kms.o \ |
| rcar_du_lvdscon.o \ |
| 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 @@ |
| |
| static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| |
| return rcar_du_read(rcdu, rcrtc->mmio_offset + reg); |
| } |
| |
| static void rcar_du_crtc_write(struct rcar_du_crtc *rcrtc, u32 reg, u32 data) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| |
| rcar_du_write(rcdu, rcrtc->mmio_offset + reg, data); |
| } |
| |
| static void rcar_du_crtc_clr(struct rcar_du_crtc *rcrtc, u32 reg, u32 clr) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| |
| rcar_du_write(rcdu, rcrtc->mmio_offset + reg, |
| 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) |
| |
| static void rcar_du_crtc_set(struct rcar_du_crtc *rcrtc, u32 reg, u32 set) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| |
| rcar_du_write(rcdu, rcrtc->mmio_offset + reg, |
| 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) |
| static void rcar_du_crtc_clr_set(struct rcar_du_crtc *rcrtc, u32 reg, |
| u32 clr, u32 set) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| u32 value = rcar_du_read(rcdu, rcrtc->mmio_offset + reg); |
| |
| 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, |
| |
| static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| int ret; |
| |
| ret = clk_prepare_enable(rcrtc->clock); |
| if (ret < 0) |
| return ret; |
| |
| - ret = rcar_du_get(rcdu); |
| + ret = rcar_du_group_get(rcrtc->group); |
| if (ret < 0) |
| clk_disable_unprepare(rcrtc->clock); |
| |
| @@ -85,17 +84,14 @@ static int rcar_du_crtc_get(struct rcar_du_crtc *rcrtc) |
| |
| static void rcar_du_crtc_put(struct rcar_du_crtc *rcrtc) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| - |
| - rcar_du_put(rcdu); |
| + rcar_du_group_put(rcrtc->group); |
| clk_disable_unprepare(rcrtc->clock); |
| } |
| |
| static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) |
| { |
| - struct drm_crtc *crtc = &rcrtc->crtc; |
| - struct rcar_du_device *rcdu = crtc->dev->dev_private; |
| - const struct drm_display_mode *mode = &crtc->mode; |
| + const struct drm_display_mode *mode = &rcrtc->crtc.mode; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| unsigned long clk; |
| u32 value; |
| u32 div; |
| @@ -136,7 +132,7 @@ static void rcar_du_crtc_set_display_timing(struct rcar_du_crtc *rcrtc) |
| |
| static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc) |
| { |
| - struct rcar_du_device *rcdu = rcrtc->crtc.dev->dev_private; |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| u32 dorcr = rcar_du_read(rcdu, DORCR); |
| |
| dorcr &= ~(DORCR_PG2T | DORCR_DK2S | DORCR_PG2D_MASK); |
| @@ -153,36 +149,6 @@ static void rcar_du_crtc_set_routing(struct rcar_du_crtc *rcrtc) |
| rcar_du_write(rcdu, DORCR, dorcr); |
| } |
| |
| -static void __rcar_du_start_stop(struct rcar_du_device *rcdu, bool start) |
| -{ |
| - rcar_du_write(rcdu, DSYSR, |
| - (rcar_du_read(rcdu, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) | |
| - (start ? DSYSR_DEN : DSYSR_DRES)); |
| -} |
| - |
| -static void rcar_du_start_stop(struct rcar_du_device *rcdu, bool start) |
| -{ |
| - /* Many of the configuration bits are only updated when the display |
| - * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some |
| - * of those bits could be pre-configured, but others (especially the |
| - * bits related to plane assignment to display timing controllers) need |
| - * to be modified at runtime. |
| - * |
| - * Restart the display controller if a start is requested. Sorry for the |
| - * flicker. It should be possible to move most of the "DRES-update" bits |
| - * setup to driver initialization time and minimize the number of cases |
| - * when the display controller will have to be restarted. |
| - */ |
| - if (start) { |
| - if (rcdu->used_crtcs++ != 0) |
| - __rcar_du_start_stop(rcdu, false); |
| - __rcar_du_start_stop(rcdu, true); |
| - } else { |
| - if (--rcdu->used_crtcs == 0) |
| - __rcar_du_start_stop(rcdu, false); |
| - } |
| -} |
| - |
| void rcar_du_crtc_route_output(struct drm_crtc *crtc, unsigned int output) |
| { |
| 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) |
| |
| void rcar_du_crtc_update_planes(struct drm_crtc *crtc) |
| { |
| - struct rcar_du_device *rcdu = crtc->dev->dev_private; |
| struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES]; |
| unsigned int num_planes = 0; |
| unsigned int prio = 0; |
| @@ -204,8 +170,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc) |
| u32 dptsr = 0; |
| u32 dspr = 0; |
| |
| - for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { |
| - struct rcar_du_plane *plane = &rcdu->planes.planes[i]; |
| + for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { |
| + struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; |
| unsigned int j; |
| |
| if (plane->crtc != &rcrtc->crtc || !plane->enabled) |
| @@ -254,10 +220,8 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc) |
| */ |
| if (value != dptsr) { |
| rcar_du_write(rcdu, DPTSR, dptsr); |
| - if (rcdu->used_crtcs) { |
| - __rcar_du_start_stop(rcdu, false); |
| - __rcar_du_start_stop(rcdu, true); |
| - } |
| + if (rcrtc->group->used_crtcs) |
| + rcar_du_group_restart(rcrtc->group); |
| } |
| } |
| |
| @@ -267,7 +231,6 @@ void rcar_du_crtc_update_planes(struct drm_crtc *crtc) |
| static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) |
| { |
| struct drm_crtc *crtc = &rcrtc->crtc; |
| - struct rcar_du_device *rcdu = crtc->dev->dev_private; |
| unsigned int i; |
| |
| if (rcrtc->started) |
| @@ -284,14 +247,14 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) |
| rcar_du_crtc_set_display_timing(rcrtc); |
| rcar_du_crtc_set_routing(rcrtc); |
| |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&rcrtc->group->planes.lock); |
| rcrtc->plane->enabled = true; |
| rcar_du_crtc_update_planes(crtc); |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&rcrtc->group->planes.lock); |
| |
| /* Setup planes. */ |
| - for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { |
| - struct rcar_du_plane *plane = &rcdu->planes.planes[i]; |
| + for (i = 0; i < ARRAY_SIZE(rcrtc->group->planes.planes); ++i) { |
| + struct rcar_du_plane *plane = &rcrtc->group->planes.planes[i]; |
| |
| if (plane->crtc != crtc || !plane->enabled) |
| continue; |
| @@ -305,7 +268,7 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) |
| */ |
| rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_MASTER); |
| |
| - rcar_du_start_stop(rcdu, true); |
| + rcar_du_group_start_stop(rcrtc->group, true); |
| |
| rcrtc->started = true; |
| } |
| @@ -313,22 +276,21 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc) |
| static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc) |
| { |
| struct drm_crtc *crtc = &rcrtc->crtc; |
| - struct rcar_du_device *rcdu = crtc->dev->dev_private; |
| |
| if (!rcrtc->started) |
| return; |
| |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&rcrtc->group->planes.lock); |
| rcrtc->plane->enabled = false; |
| rcar_du_crtc_update_planes(crtc); |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&rcrtc->group->planes.lock); |
| |
| /* Select switch sync mode. This stops display operation and configures |
| * the HSYNC and VSYNC signals as inputs. |
| */ |
| rcar_du_crtc_clr_set(rcrtc, DSYSR, DSYSR_TVM_MASK, DSYSR_TVM_SWITCH); |
| |
| - rcar_du_start_stop(rcdu, false); |
| + rcar_du_group_start_stop(rcrtc->group, false); |
| |
| rcrtc->started = false; |
| } |
| @@ -406,8 +368,8 @@ static int rcar_du_crtc_mode_set(struct drm_crtc *crtc, |
| int x, int y, |
| struct drm_framebuffer *old_fb) |
| { |
| - struct rcar_du_device *rcdu = crtc->dev->dev_private; |
| struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc); |
| + struct rcar_du_device *rcdu = rcrtc->group->dev; |
| const struct rcar_du_format_info *format; |
| int ret; |
| |
| @@ -583,8 +545,9 @@ static const struct drm_crtc_funcs crtc_funcs = { |
| .page_flip = rcar_du_crtc_page_flip, |
| }; |
| |
| -int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index) |
| +int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index) |
| { |
| + struct rcar_du_device *rcdu = rgrp->dev; |
| struct platform_device *pdev = to_platform_device(rcdu->dev); |
| struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index]; |
| struct drm_crtc *crtc = &rcrtc->crtc; |
| @@ -608,10 +571,11 @@ int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index) |
| return PTR_ERR(rcrtc->clock); |
| } |
| |
| + rcrtc->group = rgrp; |
| rcrtc->mmio_offset = index ? DISP2_REG_OFFSET : 0; |
| rcrtc->index = index; |
| rcrtc->dpms = DRM_MODE_DPMS_OFF; |
| - rcrtc->plane = &rcdu->planes.planes[index]; |
| + rcrtc->plane = &rgrp->planes.planes[index]; |
| |
| rcrtc->plane->crtc = crtc; |
| |
| 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 @@ |
| #include <drm/drmP.h> |
| #include <drm/drm_crtc.h> |
| |
| -struct rcar_du_device; |
| +struct rcar_du_group; |
| struct rcar_du_plane; |
| |
| struct rcar_du_crtc { |
| @@ -34,10 +34,11 @@ struct rcar_du_crtc { |
| unsigned int outputs; |
| int dpms; |
| |
| + struct rcar_du_group *group; |
| struct rcar_du_plane *plane; |
| }; |
| |
| -int rcar_du_crtc_create(struct rcar_du_device *rcdu, unsigned int index); |
| +int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index); |
| void rcar_du_crtc_enable_vblank(struct rcar_du_crtc *rcrtc, bool enable); |
| void rcar_du_crtc_cancel_page_flip(struct rcar_du_crtc *rcrtc, |
| 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 9b89dbf3fb32..8600b2b6aea4 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 @@ |
| #include "rcar_du_regs.h" |
| |
| /* ----------------------------------------------------------------------------- |
| - * Core device operations |
| - */ |
| - |
| -/* |
| - * rcar_du_get - Acquire a reference to the DU |
| - * |
| - * Acquiring the first reference setups core registers. A reference must be |
| - * held before accessing any hardware registers. |
| - * |
| - * This function must be called with the DRM mode_config lock held. |
| - * |
| - * Return 0 in case of success or a negative error code otherwise. |
| - */ |
| -int rcar_du_get(struct rcar_du_device *rcdu) |
| -{ |
| - if (rcdu->use_count) |
| - goto done; |
| - |
| - /* Enable extended features */ |
| - rcar_du_write(rcdu, DEFR, DEFR_CODE | DEFR_DEFE); |
| - rcar_du_write(rcdu, DEFR2, DEFR2_CODE | DEFR2_DEFE2G); |
| - rcar_du_write(rcdu, DEFR3, DEFR3_CODE | DEFR3_DEFE3); |
| - rcar_du_write(rcdu, DEFR4, DEFR4_CODE); |
| - rcar_du_write(rcdu, DEFR5, DEFR5_CODE | DEFR5_DEFE5); |
| - |
| - /* Use DS1PR and DS2PR to configure planes priorities and connects the |
| - * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. |
| - */ |
| - rcar_du_write(rcdu, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS); |
| - |
| -done: |
| - rcdu->use_count++; |
| - return 0; |
| -} |
| - |
| -/* |
| - * rcar_du_put - Release a reference to the DU |
| - * |
| - * This function must be called with the DRM mode_config lock held. |
| - */ |
| -void rcar_du_put(struct rcar_du_device *rcdu) |
| -{ |
| - --rcdu->use_count; |
| -} |
| - |
| -/* ----------------------------------------------------------------------------- |
| * DRM operations |
| */ |
| |
| 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 @@ |
| #include <linux/platform_data/rcar-du.h> |
| |
| #include "rcar_du_crtc.h" |
| -#include "rcar_du_plane.h" |
| +#include "rcar_du_group.h" |
| |
| struct clk; |
| struct device; |
| struct drm_device; |
| +struct rcar_du_device; |
| |
| #define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */ |
| |
| @@ -40,15 +41,13 @@ struct rcar_du_device { |
| const struct rcar_du_device_info *info; |
| |
| void __iomem *mmio; |
| - unsigned int use_count; |
| |
| struct drm_device *ddev; |
| |
| struct rcar_du_crtc crtcs[2]; |
| - unsigned int used_crtcs; |
| unsigned int num_crtcs; |
| |
| - struct rcar_du_planes planes; |
| + struct rcar_du_group group; |
| }; |
| |
| static 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, |
| return rcdu->info->features & feature; |
| } |
| |
| -int rcar_du_get(struct rcar_du_device *rcdu); |
| -void rcar_du_put(struct rcar_du_device *rcdu); |
| - |
| static inline u32 rcar_du_read(struct rcar_du_device *rcdu, u32 reg) |
| { |
| 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 @@ |
| +/* |
| + * rcar_du_group.c -- R-Car Display Unit Channels Pair |
| + * |
| + * Copyright (C) 2013 Renesas Corporation |
| + * |
| + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + */ |
| + |
| +/* |
| + * The R8A7779 DU is split in per-CRTC resources (scan-out engine, blending |
| + * unit, timings generator, ...) and device-global resources (start/stop |
| + * control, planes, ...) shared between the two CRTCs. |
| + * |
| + * The R8A7790 introduced a third CRTC with its own set of global resources. |
| + * This would be modeled as two separate DU device instances if it wasn't for |
| + * a handful or resources that are shared between the three CRTCs (mostly |
| + * related to input and output routing). For this reason the R8A7790 DU must be |
| + * modeled as a single device with three CRTCs, two sets of "semi-global" |
| + * resources, and a few device-global resources. |
| + * |
| + * The rcar_du_group object is a driver specific object, without any real |
| + * counterpart in the DU documentation, that models those semi-global resources. |
| + */ |
| + |
| +#include <linux/io.h> |
| + |
| +#include "rcar_du_drv.h" |
| +#include "rcar_du_group.h" |
| +#include "rcar_du_regs.h" |
| + |
| +static u32 rcar_du_group_read(struct rcar_du_group *rgrp, u32 reg) |
| +{ |
| + return rcar_du_read(rgrp->dev, rgrp->mmio_offset + reg); |
| +} |
| + |
| +static void rcar_du_group_write(struct rcar_du_group *rgrp, u32 reg, u32 data) |
| +{ |
| + rcar_du_write(rgrp->dev, rgrp->mmio_offset + reg, data); |
| +} |
| + |
| +static void rcar_du_group_setup(struct rcar_du_group *rgrp) |
| +{ |
| + /* Enable extended features */ |
| + rcar_du_group_write(rgrp, DEFR, DEFR_CODE | DEFR_DEFE); |
| + rcar_du_group_write(rgrp, DEFR2, DEFR2_CODE | DEFR2_DEFE2G); |
| + rcar_du_group_write(rgrp, DEFR3, DEFR3_CODE | DEFR3_DEFE3); |
| + rcar_du_group_write(rgrp, DEFR4, DEFR4_CODE); |
| + rcar_du_group_write(rgrp, DEFR5, DEFR5_CODE | DEFR5_DEFE5); |
| + |
| + /* Use DS1PR and DS2PR to configure planes priorities and connects the |
| + * superposition 0 to DU0 pins. DU1 pins will be configured dynamically. |
| + */ |
| + rcar_du_group_write(rgrp, DORCR, DORCR_PG1D_DS1 | DORCR_DPRS); |
| +} |
| + |
| +/* |
| + * rcar_du_group_get - Acquire a reference to the DU channels group |
| + * |
| + * Acquiring the first reference setups core registers. A reference must be held |
| + * before accessing any hardware registers. |
| + * |
| + * This function must be called with the DRM mode_config lock held. |
| + * |
| + * Return 0 in case of success or a negative error code otherwise. |
| + */ |
| +int rcar_du_group_get(struct rcar_du_group *rgrp) |
| +{ |
| + if (rgrp->use_count) |
| + goto done; |
| + |
| + rcar_du_group_setup(rgrp); |
| + |
| +done: |
| + rgrp->use_count++; |
| + return 0; |
| +} |
| + |
| +/* |
| + * rcar_du_group_put - Release a reference to the DU |
| + * |
| + * This function must be called with the DRM mode_config lock held. |
| + */ |
| +void rcar_du_group_put(struct rcar_du_group *rgrp) |
| +{ |
| + --rgrp->use_count; |
| +} |
| + |
| +static void __rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) |
| +{ |
| + rcar_du_group_write(rgrp, DSYSR, |
| + (rcar_du_group_read(rgrp, DSYSR) & ~(DSYSR_DRES | DSYSR_DEN)) | |
| + (start ? DSYSR_DEN : DSYSR_DRES)); |
| +} |
| + |
| +void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start) |
| +{ |
| + /* Many of the configuration bits are only updated when the display |
| + * reset (DRES) bit in DSYSR is set to 1, disabling *both* CRTCs. Some |
| + * of those bits could be pre-configured, but others (especially the |
| + * bits related to plane assignment to display timing controllers) need |
| + * to be modified at runtime. |
| + * |
| + * Restart the display controller if a start is requested. Sorry for the |
| + * flicker. It should be possible to move most of the "DRES-update" bits |
| + * setup to driver initialization time and minimize the number of cases |
| + * when the display controller will have to be restarted. |
| + */ |
| + if (start) { |
| + if (rgrp->used_crtcs++ != 0) |
| + __rcar_du_group_start_stop(rgrp, false); |
| + __rcar_du_group_start_stop(rgrp, true); |
| + } else { |
| + if (--rgrp->used_crtcs == 0) |
| + __rcar_du_group_start_stop(rgrp, false); |
| + } |
| +} |
| + |
| +void rcar_du_group_restart(struct rcar_du_group *rgrp) |
| +{ |
| + __rcar_du_group_start_stop(rgrp, false); |
| + __rcar_du_group_start_stop(rgrp, true); |
| +} |
| 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 @@ |
| +/* |
| + * rcar_du_group.c -- R-Car Display Unit Planes and CRTCs Group |
| + * |
| + * Copyright (C) 2013 Renesas Corporation |
| + * |
| + * Contact: Laurent Pinchart (laurent.pinchart@ideasonboard.com) |
| + * |
| + * This program is free software; you can redistribute it and/or modify |
| + * it under the terms of the GNU General Public License as published by |
| + * the Free Software Foundation; either version 2 of the License, or |
| + * (at your option) any later version. |
| + */ |
| + |
| +#ifndef __RCAR_DU_GROUP_H__ |
| +#define __RCAR_DU_GROUP_H__ |
| + |
| +#include "rcar_du_plane.h" |
| + |
| +struct rcar_du_device; |
| + |
| +/* |
| + * struct rcar_du_group - CRTCs and planes group |
| + * @dev: the DU device |
| + * @mmio_offset: registers offset in the device memory map |
| + * @index: group index |
| + * @use_count: number of users of the group (rcar_du_group_(get|put)) |
| + * @used_crtcs: number of CRTCs currently in use |
| + * @planes: planes handled by the group |
| + */ |
| +struct rcar_du_group { |
| + struct rcar_du_device *dev; |
| + unsigned int mmio_offset; |
| + unsigned int index; |
| + |
| + unsigned int use_count; |
| + unsigned int used_crtcs; |
| + |
| + struct rcar_du_planes planes; |
| +}; |
| + |
| +int rcar_du_group_get(struct rcar_du_group *rgrp); |
| +void rcar_du_group_put(struct rcar_du_group *rgrp); |
| +void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start); |
| +void rcar_du_group_restart(struct rcar_du_group *rgrp); |
| + |
| + |
| +#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) |
| rcdu->ddev->mode_config.max_height = 2047; |
| rcdu->ddev->mode_config.funcs = &rcar_du_mode_config_funcs; |
| |
| - ret = rcar_du_planes_init(rcdu); |
| + rcdu->group.dev = rcdu; |
| + rcdu->group.index = 0; |
| + rcdu->group.used_crtcs = 0; |
| + |
| + ret = rcar_du_planes_init(&rcdu->group); |
| if (ret < 0) |
| return ret; |
| |
| for (i = 0; i < ARRAY_SIZE(rcdu->crtcs); ++i) { |
| - ret = rcar_du_crtc_create(rcdu, i); |
| + ret = rcar_du_crtc_create(&rcdu->group, i); |
| if (ret < 0) |
| return ret; |
| } |
| |
| - rcdu->used_crtcs = 0; |
| rcdu->num_crtcs = i; |
| |
| for (i = 0; i < rcdu->pdata->num_encoders; ++i) { |
| @@ -215,7 +218,7 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu) |
| encoder->possible_clones = 1 << 0; |
| } |
| |
| - ret = rcar_du_planes_register(rcdu); |
| + ret = rcar_du_planes_register(&rcdu->group); |
| if (ret < 0) |
| return ret; |
| |
| 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) |
| return container_of(plane, struct rcar_du_kms_plane, plane)->hwplane; |
| } |
| |
| -static u32 rcar_du_plane_read(struct rcar_du_device *rcdu, |
| +static u32 rcar_du_plane_read(struct rcar_du_group *rgrp, |
| unsigned int index, u32 reg) |
| { |
| - return rcar_du_read(rcdu, index * PLANE_OFF + reg); |
| + return rcar_du_read(rgrp->dev, |
| + rgrp->mmio_offset + index * PLANE_OFF + reg); |
| } |
| |
| -static void rcar_du_plane_write(struct rcar_du_device *rcdu, |
| +static void rcar_du_plane_write(struct rcar_du_group *rgrp, |
| unsigned int index, u32 reg, u32 data) |
| { |
| - rcar_du_write(rcdu, index * PLANE_OFF + reg, data); |
| + rcar_du_write(rgrp->dev, rgrp->mmio_offset + index * PLANE_OFF + reg, |
| + data); |
| } |
| |
| int rcar_du_plane_reserve(struct rcar_du_plane *plane, |
| const struct rcar_du_format_info *format) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| + struct rcar_du_group *rgrp = plane->group; |
| unsigned int i; |
| int ret = -EBUSY; |
| |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&rgrp->planes.lock); |
| |
| - for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { |
| - if (!(rcdu->planes.free & (1 << i))) |
| + for (i = 0; i < ARRAY_SIZE(rgrp->planes.planes); ++i) { |
| + if (!(rgrp->planes.free & (1 << i))) |
| continue; |
| |
| if (format->planes == 1 || |
| - rcdu->planes.free & (1 << ((i + 1) % 8))) |
| + rgrp->planes.free & (1 << ((i + 1) % 8))) |
| break; |
| } |
| |
| - if (i == ARRAY_SIZE(rcdu->planes.planes)) |
| + if (i == ARRAY_SIZE(rgrp->planes.planes)) |
| goto done; |
| |
| - rcdu->planes.free &= ~(1 << i); |
| + rgrp->planes.free &= ~(1 << i); |
| if (format->planes == 2) |
| - rcdu->planes.free &= ~(1 << ((i + 1) % 8)); |
| + rgrp->planes.free &= ~(1 << ((i + 1) % 8)); |
| |
| plane->hwindex = i; |
| |
| ret = 0; |
| |
| done: |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&rgrp->planes.lock); |
| return ret; |
| } |
| |
| void rcar_du_plane_release(struct rcar_du_plane *plane) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| + struct rcar_du_group *rgrp = plane->group; |
| |
| if (plane->hwindex == -1) |
| return; |
| |
| - mutex_lock(&rcdu->planes.lock); |
| - rcdu->planes.free |= 1 << plane->hwindex; |
| + mutex_lock(&rgrp->planes.lock); |
| + rgrp->planes.free |= 1 << plane->hwindex; |
| if (plane->format->planes == 2) |
| - rcdu->planes.free |= 1 << ((plane->hwindex + 1) % 8); |
| - mutex_unlock(&rcdu->planes.lock); |
| + rgrp->planes.free |= 1 << ((plane->hwindex + 1) % 8); |
| + mutex_unlock(&rgrp->planes.lock); |
| |
| plane->hwindex = -1; |
| } |
| |
| void rcar_du_plane_update_base(struct rcar_du_plane *plane) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| + struct rcar_du_group *rgrp = plane->group; |
| unsigned int index = plane->hwindex; |
| |
| /* 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) |
| * Similarly, for the second plane, NV12 and NV21 formats seem to |
| * require a halved Y position value. |
| */ |
| - rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x); |
| - rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y * |
| + rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); |
| + rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * |
| (plane->format->bpp == 32 ? 2 : 1)); |
| - rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[0]); |
| + rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[0]); |
| |
| if (plane->format->planes == 2) { |
| index = (index + 1) % 8; |
| |
| - rcar_du_plane_write(rcdu, index, PnSPXR, plane->src_x); |
| - rcar_du_plane_write(rcdu, index, PnSPYR, plane->src_y * |
| + rcar_du_plane_write(rgrp, index, PnSPXR, plane->src_x); |
| + rcar_du_plane_write(rgrp, index, PnSPYR, plane->src_y * |
| (plane->format->bpp == 16 ? 2 : 1) / 2); |
| - rcar_du_plane_write(rcdu, index, PnDSA0R, plane->dma[1]); |
| + rcar_du_plane_write(rgrp, index, PnDSA0R, plane->dma[1]); |
| } |
| } |
| |
| @@ -143,7 +145,7 @@ void rcar_du_plane_compute_base(struct rcar_du_plane *plane, |
| static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
| unsigned int index) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| + struct rcar_du_group *rgrp = plane->group; |
| u32 colorkey; |
| u32 pnmr; |
| |
| @@ -157,9 +159,9 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
| * enable alpha-blending regardless of the X bit value. |
| */ |
| if (plane->format->fourcc != DRM_FORMAT_XRGB1555) |
| - rcar_du_plane_write(rcdu, index, PnALPHAR, PnALPHAR_ABIT_0); |
| + rcar_du_plane_write(rgrp, index, PnALPHAR, PnALPHAR_ABIT_0); |
| else |
| - rcar_du_plane_write(rcdu, index, PnALPHAR, |
| + rcar_du_plane_write(rgrp, index, PnALPHAR, |
| PnALPHAR_ABIT_X | plane->alpha); |
| |
| pnmr = PnMR_BM_MD | plane->format->pnmr; |
| @@ -175,14 +177,14 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
| if (plane->format->fourcc == DRM_FORMAT_YUYV) |
| pnmr |= PnMR_YCDF_YUYV; |
| |
| - rcar_du_plane_write(rcdu, index, PnMR, pnmr); |
| + rcar_du_plane_write(rgrp, index, PnMR, pnmr); |
| |
| switch (plane->format->fourcc) { |
| case DRM_FORMAT_RGB565: |
| colorkey = ((plane->colorkey & 0xf80000) >> 8) |
| | ((plane->colorkey & 0x00fc00) >> 5) |
| | ((plane->colorkey & 0x0000f8) >> 3); |
| - rcar_du_plane_write(rcdu, index, PnTC2R, colorkey); |
| + rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); |
| break; |
| |
| case DRM_FORMAT_ARGB1555: |
| @@ -190,12 +192,12 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
| colorkey = ((plane->colorkey & 0xf80000) >> 9) |
| | ((plane->colorkey & 0x00f800) >> 6) |
| | ((plane->colorkey & 0x0000f8) >> 3); |
| - rcar_du_plane_write(rcdu, index, PnTC2R, colorkey); |
| + rcar_du_plane_write(rgrp, index, PnTC2R, colorkey); |
| break; |
| |
| case DRM_FORMAT_XRGB8888: |
| case DRM_FORMAT_ARGB8888: |
| - rcar_du_plane_write(rcdu, index, PnTC3R, |
| + rcar_du_plane_write(rgrp, index, PnTC3R, |
| PnTC3R_CODE | (plane->colorkey & 0xffffff)); |
| break; |
| } |
| @@ -204,7 +206,7 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane, |
| static void __rcar_du_plane_setup(struct rcar_du_plane *plane, |
| unsigned int index) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| + struct rcar_du_group *rgrp = plane->group; |
| u32 ddcr2 = PnDDCR2_CODE; |
| u32 ddcr4; |
| u32 mwr; |
| @@ -214,7 +216,7 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, |
| * The data format is selected by the DDDF field in PnMR and the EDF |
| * field in DDCR4. |
| */ |
| - ddcr4 = rcar_du_plane_read(rcdu, index, PnDDCR4); |
| + ddcr4 = rcar_du_plane_read(rgrp, index, PnDDCR4); |
| ddcr4 &= ~PnDDCR4_EDF_MASK; |
| ddcr4 |= plane->format->edf | PnDDCR4_CODE; |
| |
| @@ -235,8 +237,8 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, |
| } |
| } |
| |
| - rcar_du_plane_write(rcdu, index, PnDDCR2, ddcr2); |
| - rcar_du_plane_write(rcdu, index, PnDDCR4, ddcr4); |
| + rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2); |
| + rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4); |
| |
| /* Memory pitch (expressed in pixels) */ |
| if (plane->format->planes == 2) |
| @@ -244,19 +246,19 @@ static void __rcar_du_plane_setup(struct rcar_du_plane *plane, |
| else |
| mwr = plane->pitch * 8 / plane->format->bpp; |
| |
| - rcar_du_plane_write(rcdu, index, PnMWR, mwr); |
| + rcar_du_plane_write(rgrp, index, PnMWR, mwr); |
| |
| /* Destination position and size */ |
| - rcar_du_plane_write(rcdu, index, PnDSXR, plane->width); |
| - rcar_du_plane_write(rcdu, index, PnDSYR, plane->height); |
| - rcar_du_plane_write(rcdu, index, PnDPXR, plane->dst_x); |
| - rcar_du_plane_write(rcdu, index, PnDPYR, plane->dst_y); |
| + rcar_du_plane_write(rgrp, index, PnDSXR, plane->width); |
| + rcar_du_plane_write(rgrp, index, PnDSYR, plane->height); |
| + rcar_du_plane_write(rgrp, index, PnDPXR, plane->dst_x); |
| + rcar_du_plane_write(rgrp, index, PnDPYR, plane->dst_y); |
| |
| /* Wrap-around and blinking, disabled */ |
| - rcar_du_plane_write(rcdu, index, PnWASPR, 0); |
| - rcar_du_plane_write(rcdu, index, PnWAMWR, 4095); |
| - rcar_du_plane_write(rcdu, index, PnBTR, 0); |
| - rcar_du_plane_write(rcdu, index, PnMLR, 0); |
| + rcar_du_plane_write(rgrp, index, PnWASPR, 0); |
| + rcar_du_plane_write(rgrp, index, PnWAMWR, 4095); |
| + rcar_du_plane_write(rgrp, index, PnBTR, 0); |
| + rcar_du_plane_write(rgrp, index, PnMLR, 0); |
| } |
| |
| void 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, |
| uint32_t src_w, uint32_t src_h) |
| { |
| struct rcar_du_plane *rplane = to_rcar_plane(plane); |
| - struct rcar_du_device *rcdu = plane->dev->dev_private; |
| + struct rcar_du_device *rcdu = rplane->group->dev; |
| const struct rcar_du_format_info *format; |
| unsigned int nplanes; |
| int ret; |
| @@ -319,26 +321,25 @@ rcar_du_plane_update(struct drm_plane *plane, struct drm_crtc *crtc, |
| rcar_du_plane_compute_base(rplane, fb); |
| rcar_du_plane_setup(rplane); |
| |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&rplane->group->planes.lock); |
| rplane->enabled = true; |
| rcar_du_crtc_update_planes(rplane->crtc); |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&rplane->group->planes.lock); |
| |
| return 0; |
| } |
| |
| static int rcar_du_plane_disable(struct drm_plane *plane) |
| { |
| - struct rcar_du_device *rcdu = plane->dev->dev_private; |
| struct rcar_du_plane *rplane = to_rcar_plane(plane); |
| |
| if (!rplane->enabled) |
| return 0; |
| |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&rplane->group->planes.lock); |
| rplane->enabled = false; |
| rcar_du_crtc_update_planes(rplane->crtc); |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&rplane->group->planes.lock); |
| |
| rcar_du_plane_release(rplane); |
| |
| @@ -380,9 +381,7 @@ static void rcar_du_plane_set_colorkey(struct rcar_du_plane *plane, |
| static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane, |
| unsigned int zpos) |
| { |
| - struct rcar_du_device *rcdu = plane->dev; |
| - |
| - mutex_lock(&rcdu->planes.lock); |
| + mutex_lock(&plane->group->planes.lock); |
| if (plane->zpos == zpos) |
| goto done; |
| |
| @@ -393,21 +392,21 @@ static void rcar_du_plane_set_zpos(struct rcar_du_plane *plane, |
| rcar_du_crtc_update_planes(plane->crtc); |
| |
| done: |
| - mutex_unlock(&rcdu->planes.lock); |
| + mutex_unlock(&plane->group->planes.lock); |
| } |
| |
| static int rcar_du_plane_set_property(struct drm_plane *plane, |
| struct drm_property *property, |
| uint64_t value) |
| { |
| - struct rcar_du_device *rcdu = plane->dev->dev_private; |
| struct rcar_du_plane *rplane = to_rcar_plane(plane); |
| + struct rcar_du_group *rgrp = rplane->group; |
| |
| - if (property == rcdu->planes.alpha) |
| + if (property == rgrp->planes.alpha) |
| rcar_du_plane_set_alpha(rplane, value); |
| - else if (property == rcdu->planes.colorkey) |
| + else if (property == rgrp->planes.colorkey) |
| rcar_du_plane_set_colorkey(rplane, value); |
| - else if (property == rcdu->planes.zpos) |
| + else if (property == rgrp->planes.zpos) |
| rcar_du_plane_set_zpos(rplane, value); |
| else |
| return -EINVAL; |
| @@ -435,37 +434,39 @@ static const uint32_t formats[] = { |
| DRM_FORMAT_NV16, |
| }; |
| |
| -int rcar_du_planes_init(struct rcar_du_device *rcdu) |
| +int rcar_du_planes_init(struct rcar_du_group *rgrp) |
| { |
| + struct rcar_du_planes *planes = &rgrp->planes; |
| + struct rcar_du_device *rcdu = rgrp->dev; |
| unsigned int i; |
| |
| - mutex_init(&rcdu->planes.lock); |
| - rcdu->planes.free = 0xff; |
| + mutex_init(&planes->lock); |
| + planes->free = 0xff; |
| |
| - rcdu->planes.alpha = |
| + planes->alpha = |
| drm_property_create_range(rcdu->ddev, 0, "alpha", 0, 255); |
| - if (rcdu->planes.alpha == NULL) |
| + if (planes->alpha == NULL) |
| return -ENOMEM; |
| |
| /* The color key is expressed as an RGB888 triplet stored in a 32-bit |
| * integer in XRGB8888 format. Bit 24 is used as a flag to disable (0) |
| * or enable source color keying (1). |
| */ |
| - rcdu->planes.colorkey = |
| + planes->colorkey = |
| drm_property_create_range(rcdu->ddev, 0, "colorkey", |
| 0, 0x01ffffff); |
| - if (rcdu->planes.colorkey == NULL) |
| + if (planes->colorkey == NULL) |
| return -ENOMEM; |
| |
| - rcdu->planes.zpos = |
| + planes->zpos = |
| drm_property_create_range(rcdu->ddev, 0, "zpos", 1, 7); |
| - if (rcdu->planes.zpos == NULL) |
| + if (planes->zpos == NULL) |
| return -ENOMEM; |
| |
| - for (i = 0; i < ARRAY_SIZE(rcdu->planes.planes); ++i) { |
| - struct rcar_du_plane *plane = &rcdu->planes.planes[i]; |
| + for (i = 0; i < ARRAY_SIZE(planes->planes); ++i) { |
| + struct rcar_du_plane *plane = &planes->planes[i]; |
| |
| - plane->dev = rcdu; |
| + plane->group = rgrp; |
| plane->hwindex = -1; |
| plane->alpha = 255; |
| plane->colorkey = RCAR_DU_COLORKEY_NONE; |
| @@ -475,8 +476,10 @@ int rcar_du_planes_init(struct rcar_du_device *rcdu) |
| return 0; |
| } |
| |
| -int rcar_du_planes_register(struct rcar_du_device *rcdu) |
| +int rcar_du_planes_register(struct rcar_du_group *rgrp) |
| { |
| + struct rcar_du_planes *planes = &rgrp->planes; |
| + struct rcar_du_device *rcdu = rgrp->dev; |
| unsigned int i; |
| int ret; |
| |
| @@ -487,7 +490,7 @@ int rcar_du_planes_register(struct rcar_du_device *rcdu) |
| if (plane == NULL) |
| return -ENOMEM; |
| |
| - plane->hwplane = &rcdu->planes.planes[i + 2]; |
| + plane->hwplane = &planes->planes[i + 2]; |
| plane->hwplane->zpos = 1; |
| |
| ret = drm_plane_init(rcdu->ddev, &plane->plane, |
| @@ -498,12 +501,12 @@ int rcar_du_planes_register(struct rcar_du_device *rcdu) |
| return ret; |
| |
| drm_object_attach_property(&plane->plane.base, |
| - rcdu->planes.alpha, 255); |
| + planes->alpha, 255); |
| drm_object_attach_property(&plane->plane.base, |
| - rcdu->planes.colorkey, |
| + planes->colorkey, |
| RCAR_DU_COLORKEY_NONE); |
| drm_object_attach_property(&plane->plane.base, |
| - rcdu->planes.zpos, 1); |
| + planes->zpos, 1); |
| } |
| |
| 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 @@ |
| #include <drm/drmP.h> |
| #include <drm/drm_crtc.h> |
| |
| -struct rcar_du_device; |
| struct rcar_du_format_info; |
| +struct rcar_du_group; |
| |
| /* The RCAR DU has 8 hardware planes, shared between KMS planes and CRTCs. As |
| * using KMS planes requires at least one of the CRTCs being enabled, no more |
| @@ -33,7 +33,7 @@ struct rcar_du_format_info; |
| #define RCAR_DU_NUM_SW_PLANES 9 |
| |
| struct rcar_du_plane { |
| - struct rcar_du_device *dev; |
| + struct rcar_du_group *group; |
| struct drm_crtc *crtc; |
| |
| bool enabled; |
| @@ -67,8 +67,8 @@ struct rcar_du_planes { |
| struct drm_property *zpos; |
| }; |
| |
| -int rcar_du_planes_init(struct rcar_du_device *rcdu); |
| -int rcar_du_planes_register(struct rcar_du_device *rcdu); |
| +int rcar_du_planes_init(struct rcar_du_group *rgrp); |
| +int rcar_du_planes_register(struct rcar_du_group *rgrp); |
| |
| void rcar_du_plane_setup(struct rcar_du_plane *plane); |
| void rcar_du_plane_update_base(struct rcar_du_plane *plane); |
| -- |
| 1.8.5.rc3 |
| |