Skip to content

Commit

Permalink
drm: rcar-du: Add VSP1 compositor support
Browse files Browse the repository at this point in the history
Configure the plane source at plane setup time to source frames from
memory or from the VSP1.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
  • Loading branch information
Laurent Pinchart committed Feb 20, 2016
1 parent af8ad96 commit 34a04f2
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 49 deletions.
2 changes: 2 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,8 @@ struct rcar_du_device {
} props;

unsigned int dpad0_source;
unsigned int vspd1_sink;

struct rcar_du_lvdsenc *lvds[RCAR_DU_MAX_LVDS];

struct {
Expand Down
24 changes: 14 additions & 10 deletions drivers/gpu/drm/rcar-du/rcar_du_group.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,11 +49,15 @@ static void rcar_du_group_setup_defr8(struct rcar_du_group *rgrp)
u32 defr8 = DEFR8_CODE | DEFR8_DEFE8;

/* The DEFR8 register for the first group also controls RGB output
* routing to DPAD0 for DU instances that support it.
* routing to DPAD0 and VSPD1 routing to DU0/1/2 for DU instances that
* support it.
*/
if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1 &&
rgrp->index == 0)
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
if (rgrp->index == 0) {
if (rgrp->dev->info->routes[RCAR_DU_OUTPUT_DPAD0].possible_crtcs > 1)
defr8 |= DEFR8_DRGBS_DU(rgrp->dev->dpad0_source);
if (rgrp->dev->vspd1_sink == 2)
defr8 |= DEFR8_VSCS;
}

rcar_du_group_write(rgrp, DEFR8, defr8);
}
Expand Down Expand Up @@ -162,17 +166,17 @@ void rcar_du_group_restart(struct rcar_du_group *rgrp)
__rcar_du_group_start_stop(rgrp, true);
}

static int rcar_du_set_dpad0_routing(struct rcar_du_device *rcdu)
int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu)
{
int ret;

if (!rcar_du_has(rcdu, RCAR_DU_FEATURE_EXT_CTRL_REGS))
return 0;

/* RGB output routing to DPAD0 is configured in the DEFR8 register of
* the first group. As this function can be called with the DU0 and DU1
* CRTCs disabled, we need to enable the first group clock before
* accessing the register.
/* RGB output routing to DPAD0 and VSP1D routing to DU0/1/2 are
* configured in the DEFR8 register of the first group. As this function
* can be called with the DU0 and DU1 CRTCs disabled, we need to enable
* the first group clock before accessing the register.
*/
ret = clk_prepare_enable(rcdu->crtcs[0].clock);
if (ret < 0)
Expand Down Expand Up @@ -203,5 +207,5 @@ int rcar_du_group_set_routing(struct rcar_du_group *rgrp)

rcar_du_group_write(rgrp, DORCR, dorcr);

return rcar_du_set_dpad0_routing(rgrp->dev);
return rcar_du_set_dpad0_vsp1_routing(rgrp->dev);
}
2 changes: 2 additions & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_group.h
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,6 @@ void rcar_du_group_start_stop(struct rcar_du_group *rgrp, bool start);
void rcar_du_group_restart(struct rcar_du_group *rgrp);
int rcar_du_group_set_routing(struct rcar_du_group *rgrp);

int rcar_du_set_dpad0_vsp1_routing(struct rcar_du_device *rcdu);

#endif /* __RCAR_DU_GROUP_H__ */
16 changes: 12 additions & 4 deletions drivers/gpu/drm/rcar-du/rcar_du_kms.c
Original file line number Diff line number Diff line change
Expand Up @@ -217,17 +217,25 @@ static void rcar_du_output_poll_changed(struct drm_device *dev)
*/

static bool rcar_du_plane_needs_realloc(struct rcar_du_plane *plane,
struct rcar_du_plane_state *state)
struct rcar_du_plane_state *new_state)
{
const struct rcar_du_format_info *cur_format;
struct rcar_du_plane_state *cur_state;

cur_format = to_rcar_plane_state(plane->plane.state)->format;
cur_state = to_rcar_plane_state(plane->plane.state);

/* Lowering the number of planes doesn't strictly require reallocation
* as the extra hardware plane will be freed when committing, but doing
* so could lead to more fragmentation.
*/
return !cur_format || cur_format->planes != state->format->planes;
if (!cur_state->format ||
cur_state->format->planes != new_state->format->planes)
return true;

/* Reallocate hardware planes if the source has changed. */
if (cur_state->source != new_state->source)
return true;

return false;
}

static unsigned int rcar_du_plane_hwmask(struct rcar_du_plane_state *state)
Expand Down
86 changes: 51 additions & 35 deletions drivers/gpu/drm/rcar-du/rcar_du_plane.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <drm/drm_plane_helper.h>

#include "rcar_du_drv.h"
#include "rcar_du_group.h"
#include "rcar_du_kms.h"
#include "rcar_du_plane.h"
#include "rcar_du_regs.h"
Expand All @@ -35,37 +36,42 @@ static void rcar_du_plane_write(struct rcar_du_group *rgrp,
data);
}

static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
static void rcar_du_plane_setup_scanout(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 drm_framebuffer *fb = plane->plane.state->fb;
struct rcar_du_group *rgrp = plane->group;
unsigned int src_x = state->state.src_x >> 16;
unsigned int src_y = state->state.src_y >> 16;
unsigned int index = state->hwindex;
struct drm_gem_cma_object *gem;
unsigned int pitch;
bool interlaced;
unsigned int i;
u32 dma[2];

interlaced = state->state.crtc->state->adjusted_mode.flags
& DRM_MODE_FLAG_INTERLACE;

/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
*/
if (state->format->planes == 2)
pitch = fb->pitches[0];
else
pitch = fb->pitches[0] * 8 / state->format->bpp;
if (state->source == RCAR_DU_PLANE_MEMORY) {
struct drm_framebuffer *fb = state->state.fb;
struct drm_gem_cma_object *gem;
unsigned int i;

if (state->format->planes == 2)
pitch = fb->pitches[0];
else
pitch = fb->pitches[0] * 8 / state->format->bpp;

for (i = 0; i < state->format->planes; ++i) {
gem = drm_fb_cma_get_gem_obj(fb, i);
dma[i] = gem->paddr + fb->offsets[i];
for (i = 0; i < state->format->planes; ++i) {
gem = drm_fb_cma_get_gem_obj(fb, i);
dma[i] = gem->paddr + fb->offsets[i];
}
} else {
pitch = state->state.src_w >> 16;
dma[0] = 0;
dma[1] = 0;
}

/* Memory pitch (expressed in pixels). Must be doubled for interlaced
* operation with 32bpp formats.
*/
rcar_du_plane_write(rgrp, index, PnMWR,
(interlaced && state->format->bpp == 32) ?
pitch * 2 : pitch);
Expand Down Expand Up @@ -101,12 +107,10 @@ static void rcar_du_plane_setup_scanout(struct rcar_du_plane *plane)
}
}

static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
unsigned int index)
static void rcar_du_plane_setup_mode(struct rcar_du_group *rgrp,
unsigned int index,
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;
u32 colorkey;
u32 pnmr;

Expand Down Expand Up @@ -164,12 +168,10 @@ static void rcar_du_plane_setup_mode(struct rcar_du_plane *plane,
}
}

static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
unsigned int index)
static void rcar_du_plane_setup_format(struct rcar_du_group *rgrp,
unsigned int index,
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;
u32 ddcr2 = PnDDCR2_CODE;
u32 ddcr4;

Expand All @@ -179,7 +181,7 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
* field in DDCR4.
*/

rcar_du_plane_setup_mode(plane, index);
rcar_du_plane_setup_mode(rgrp, index, state);

if (state->format->planes == 2) {
if (state->hwindex != index) {
Expand All @@ -199,14 +201,16 @@ static void rcar_du_plane_setup_format(struct rcar_du_plane *plane,
rcar_du_plane_write(rgrp, index, PnDDCR2, ddcr2);

ddcr4 = state->format->edf | PnDDCR4_CODE;
if (state->source != RCAR_DU_PLANE_MEMORY)
ddcr4 |= PnDDCR4_VSPS;

rcar_du_plane_write(rgrp, index, PnDDCR4, ddcr4);

/* Destination position and size */
rcar_du_plane_write(rgrp, index, PnDSXR, plane->plane.state->crtc_w);
rcar_du_plane_write(rgrp, index, PnDSYR, plane->plane.state->crtc_h);
rcar_du_plane_write(rgrp, index, PnDPXR, plane->plane.state->crtc_x);
rcar_du_plane_write(rgrp, index, PnDPYR, plane->plane.state->crtc_y);
rcar_du_plane_write(rgrp, index, PnDSXR, state->state.crtc_w);
rcar_du_plane_write(rgrp, index, PnDSYR, state->state.crtc_h);
rcar_du_plane_write(rgrp, index, PnDPXR, state->state.crtc_x);
rcar_du_plane_write(rgrp, index, PnDPYR, state->state.crtc_y);

/* Wrap-around and blinking, disabled */
rcar_du_plane_write(rgrp, index, PnWASPR, 0);
Expand All @@ -219,12 +223,24 @@ void rcar_du_plane_setup(struct rcar_du_plane *plane)
{
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(plane, state->hwindex);
rcar_du_plane_setup_format(rgrp, state->hwindex, state);
if (state->format->planes == 2)
rcar_du_plane_setup_format(plane, (state->hwindex + 1) % 8);
rcar_du_plane_setup_format(rgrp, (state->hwindex + 1) % 8,
state);

rcar_du_plane_setup_scanout(rgrp, state);

rcar_du_plane_setup_scanout(plane);
if (state->source == RCAR_DU_PLANE_VSPD1) {
unsigned int vspd1_sink = rgrp->index ? 2 : 0;
struct rcar_du_device *rcdu = rgrp->dev;

if (rcdu->vspd1_sink != vspd1_sink) {
rcdu->vspd1_sink = vspd1_sink;
rcar_du_set_dpad0_vsp1_routing(rcdu);
}
}
}

static int rcar_du_plane_atomic_check(struct drm_plane *plane,
Expand Down
1 change: 1 addition & 0 deletions drivers/gpu/drm/rcar-du/rcar_du_regs.h
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,7 @@

#define PnDDCR4 0x00190
#define PnDDCR4_CODE (0x7766 << 16)
#define PnDDCR4_VSPS (1 << 13)
#define PnDDCR4_SDFS_RGB (0 << 4)
#define PnDDCR4_SDFS_YC (5 << 4)
#define PnDDCR4_SDFS_MASK (7 << 4)
Expand Down

0 comments on commit 34a04f2

Please sign in to comment.