Skip to content

Commit

Permalink
drm: rcar-du: Expose the VSP1 compositor through KMS planes
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
Laurent Pinchart committed Feb 23, 2016
1 parent ab334e1 commit 6d62ef3
Show file tree
Hide file tree
Showing 10 changed files with 539 additions and 16 deletions.
7 changes: 7 additions & 0 deletions drivers/gpu/drm/rcar-du/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -25,3 +25,10 @@ config DRM_RCAR_LVDS
help
Enable support for the R-Car Display Unit embedded LVDS encoders
(currently only on R8A7790 and R8A7791).

config DRM_RCAR_VSP
bool "R-Car DU VSP Compositor Support"
depends on DRM_RCAR_DU
depends on VIDEO_RENESAS_VSP1
help
Enable support to expose the R-Car VSP Compositor as KMS planes.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/rcar-du/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -11,4 +11,6 @@ rcar-du-drm-$(CONFIG_DRM_RCAR_HDMI) += rcar_du_hdmicon.o \
rcar_du_hdmienc.o
rcar-du-drm-$(CONFIG_DRM_RCAR_LVDS) += rcar_du_lvdsenc.o

rcar-du-drm-$(CONFIG_DRM_RCAR_VSP) += rcar_du_vsp.o

obj-$(CONFIG_DRM_RCAR_DU) += rcar-du-drm.o
48 changes: 41 additions & 7 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
#include "rcar_du_vsp.h"

static u32 rcar_du_crtc_read(struct rcar_du_crtc *rcrtc, u32 reg)
{
Expand Down Expand Up @@ -207,6 +208,7 @@ plane_format(struct rcar_du_plane *plane)
static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
{
struct rcar_du_plane *planes[RCAR_DU_NUM_HW_PLANES];
struct rcar_du_device *rcdu = rcrtc->group->dev;
unsigned int num_planes = 0;
unsigned int dptsr_planes;
unsigned int hwplanes = 0;
Expand Down Expand Up @@ -250,6 +252,12 @@ static void rcar_du_crtc_update_planes(struct rcar_du_crtc *rcrtc)
}
}

/* If VSP+DU integration is enabled the plane assignment is fixed. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
dspr = (rcrtc->index % 2) + 1;
hwplanes = 1 << (rcrtc->index % 2);
}

/* Update the planes to display timing and dot clock generator
* associations.
*
Expand Down Expand Up @@ -369,6 +377,10 @@ static void rcar_du_crtc_start(struct rcar_du_crtc *rcrtc)

rcar_du_group_start_stop(rcrtc->group, true);

/* Enable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_enable(rcrtc);

/* Turn vertical blanking interrupt reporting back on. */
drm_crtc_vblank_on(crtc);

Expand Down Expand Up @@ -402,6 +414,10 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_wait_page_flip(rcrtc);
drm_crtc_vblank_off(crtc);

/* Disable the VSP compositor. */
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);

/* Select switch sync mode. This stops display operation and configures
* the HSYNC and VSYNC signals as inputs.
*/
Expand All @@ -414,6 +430,9 @@ static void rcar_du_crtc_stop(struct rcar_du_crtc *rcrtc)

void rcar_du_crtc_suspend(struct rcar_du_crtc *rcrtc)
{
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_disable(rcrtc);

rcar_du_crtc_stop(rcrtc);
rcar_du_crtc_put(rcrtc);
}
Expand All @@ -429,13 +448,17 @@ void rcar_du_crtc_resume(struct rcar_du_crtc *rcrtc)
rcar_du_crtc_start(rcrtc);

/* Commit the planes state. */
for (i = 0; i < rcrtc->group->num_planes; ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes[i];
if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE)) {
rcar_du_vsp_enable(rcrtc);
} else {
for (i = 0; i < rcrtc->group->num_planes; ++i) {
struct rcar_du_plane *plane = &rcrtc->group->planes[i];

if (plane->plane.state->crtc != &rcrtc->crtc)
continue;
if (plane->plane.state->crtc != &rcrtc->crtc)
continue;

rcar_du_plane_setup(plane);
rcar_du_plane_setup(plane);
}
}

rcar_du_crtc_update_planes(rcrtc);
Expand Down Expand Up @@ -486,6 +509,9 @@ static void rcar_du_crtc_atomic_begin(struct drm_crtc *crtc,
rcrtc->event = event;
spin_unlock_irqrestore(&dev->event_lock, flags);
}

if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_begin(rcrtc);
}

static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
Expand All @@ -494,6 +520,9 @@ static void rcar_du_crtc_atomic_flush(struct drm_crtc *crtc,
struct rcar_du_crtc *rcrtc = to_rcar_crtc(crtc);

rcar_du_crtc_update_planes(rcrtc);

if (rcar_du_has(rcrtc->group->dev, RCAR_DU_FEATURE_VSP1_SOURCE))
rcar_du_vsp_atomic_flush(rcrtc);
}

static const struct drm_crtc_helper_funcs crtc_helper_funcs = {
Expand Down Expand Up @@ -549,6 +578,7 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
struct platform_device *pdev = to_platform_device(rcdu->dev);
struct rcar_du_crtc *rcrtc = &rcdu->crtcs[index];
struct drm_crtc *crtc = &rcrtc->crtc;
struct drm_plane *primary;
unsigned int irqflags;
struct clk *clk;
char clk_name[9];
Expand Down Expand Up @@ -585,8 +615,12 @@ int rcar_du_crtc_create(struct rcar_du_group *rgrp, unsigned int index)
rcrtc->mmio_offset = mmio_offsets[index];
rcrtc->index = index;

ret = drm_crtc_init_with_planes(rcdu->ddev, crtc,
&rgrp->planes[index % 2].plane,
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
primary = &rcrtc->vsp->planes[0].plane;
else
primary = &rgrp->planes[index % 2].plane;

ret = drm_crtc_init_with_planes(rcdu->ddev, crtc, primary,
NULL, &crtc_funcs, NULL);
if (ret < 0)
return ret;
Expand Down
2 changes: 2 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_crtc.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
#include <drm/drm_crtc.h>

struct rcar_du_group;
struct rcar_du_vsp;

/**
* struct rcar_du_crtc - the CRTC, representing a DU superposition processor
Expand Down Expand Up @@ -50,6 +51,7 @@ struct rcar_du_crtc {
unsigned int outputs;

struct rcar_du_group *group;
struct rcar_du_vsp *vsp;
};

#define to_rcar_crtc(c) container_of(c, struct rcar_du_crtc, crtc)
Expand Down
4 changes: 4 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@

#include "rcar_du_crtc.h"
#include "rcar_du_group.h"
#include "rcar_du_vsp.h"

struct clk;
struct device;
Expand All @@ -29,6 +30,7 @@ struct rcar_du_lvdsenc;

#define RCAR_DU_FEATURE_CRTC_IRQ_CLOCK (1 << 0) /* Per-CRTC IRQ and clock */
#define RCAR_DU_FEATURE_EXT_CTRL_REGS (1 << 1) /* Has extended control registers */
#define RCAR_DU_FEATURE_VSP1_SOURCE (1 << 2) /* Has inputs from VSP1 */

#define RCAR_DU_QUIRK_ALIGN_128B (1 << 0) /* Align pitches to 128 bytes */
#define RCAR_DU_QUIRK_LVDS_LANES (1 << 1) /* LVDS lanes 1 and 3 inverted */
Expand Down Expand Up @@ -68,6 +70,7 @@ struct rcar_du_device_info {
#define RCAR_DU_MAX_CRTCS 3
#define RCAR_DU_MAX_GROUPS DIV_ROUND_UP(RCAR_DU_MAX_CRTCS, 2)
#define RCAR_DU_MAX_LVDS 2
#define RCAR_DU_MAX_VSPS 4

struct rcar_du_device {
struct device *dev;
Expand All @@ -82,6 +85,7 @@ struct rcar_du_device {
unsigned int num_crtcs;

struct rcar_du_group groups[RCAR_DU_MAX_GROUPS];
struct rcar_du_vsp vsps[RCAR_DU_MAX_VSPS];

struct {
struct drm_property *alpha;
Expand Down
28 changes: 25 additions & 3 deletions drivers/gpu/drm/rcar-du/rcar_du_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
#include "rcar_du_kms.h"
#include "rcar_du_lvdsenc.h"
#include "rcar_du_regs.h"
#include "rcar_du_vsp.h"

/* -----------------------------------------------------------------------------
* Format helpers
Expand Down Expand Up @@ -195,12 +196,16 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
static int rcar_du_atomic_check(struct drm_device *dev,
struct drm_atomic_state *state)
{
struct rcar_du_device *rcdu = dev->dev_private;
int ret;

ret = drm_atomic_helper_check(dev, state);
if (ret < 0)
return ret;

if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE))
return 0;

return rcar_du_atomic_check_planes(dev, state);
}

Expand Down Expand Up @@ -544,9 +549,26 @@ int rcar_du_modeset_init(struct rcar_du_device *rcdu)
*/
rgrp->dptsr_planes = rgrp->num_crtcs > 1 ? 0xf0 : 0;

ret = rcar_du_planes_init(rgrp);
if (ret < 0)
return ret;
if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
ret = rcar_du_planes_init(rgrp);
if (ret < 0)
return ret;
}
}

/* Initialize the compositors. */
if (rcar_du_has(rcdu, RCAR_DU_FEATURE_VSP1_SOURCE)) {
for (i = 0; i < rcdu->num_crtcs; ++i) {
struct rcar_du_vsp *vsp = &rcdu->vsps[i];

vsp->index = i;
vsp->dev = rcdu;
rcdu->crtcs[i].vsp = vsp;

ret = rcar_du_vsp_init(vsp);
if (ret < 0)
return ret;
}
}

/* Create the CRTCs. */
Expand Down
7 changes: 2 additions & 5 deletions drivers/gpu/drm/rcar-du/rcar_du_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -505,12 +505,9 @@ static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
rcar_du_plane_write(rgrp, index, PnMLR, 0);
}

void rcar_du_plane_setup(struct rcar_du_plane *plane)
void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);
struct rcar_du_group *rgrp = plane->group;

rcar_du_plane_setup_format(rgrp, state->hwindex, state);
if (state->format->planes == 2)
rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
Expand Down
11 changes: 10 additions & 1 deletion drivers/gpu/drm/rcar-du/rcar_du_plane.h
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,15 @@ int rcar_du_atomic_check_planes(struct drm_device *dev,

int rcar_du_planes_init(struct rcar_du_group *rgrp);

void rcar_du_plane_setup(struct rcar_du_plane *plane);
void __rcar_du_plane_setup(struct rcar_du_group *rgrp,
const struct rcar_du_plane_state *state);

static inline void rcar_du_plane_setup(struct rcar_du_plane *plane)
{
struct rcar_du_plane_state *state =
to_rcar_plane_state(plane->plane.state);

return __rcar_du_plane_setup(plane->group, state);
}

#endif /* __RCAR_DU_PLANE_H__ */
Loading

0 comments on commit 6d62ef3

Please sign in to comment.