drm: rcar-du: Add tri-planar memory formats support

Those formats are supported on Gen3 only.

Signed-off-by: Laurent Pinchart <laurent.pinchart+renesas@ideasonboard.com>
This commit is contained in:
Laurent Pinchart 2015-11-12 02:03:47 +02:00
parent fee8abc3bc
commit 7863ac504b
2 changed files with 52 additions and 10 deletions

View file

@ -90,13 +90,44 @@ static const struct rcar_du_format_info rcar_du_format_infos[] = {
.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
.edf = PnDDCR4_EDF_NONE, .edf = PnDDCR4_EDF_NONE,
}, { }, {
/* In YUV 4:2:2, only NV16 is supported (NV61 isn't) */
.fourcc = DRM_FORMAT_NV16, .fourcc = DRM_FORMAT_NV16,
.bpp = 16, .bpp = 16,
.planes = 2, .planes = 2,
.pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC, .pnmr = PnMR_SPIM_TP_OFF | PnMR_DDDF_YC,
.edf = PnDDCR4_EDF_NONE, .edf = PnDDCR4_EDF_NONE,
}, },
/* The following formats are not supported on Gen2 and thus have no
* associated .pnmr or .edf settings.
*/
{
.fourcc = DRM_FORMAT_NV61,
.bpp = 16,
.planes = 2,
}, {
.fourcc = DRM_FORMAT_YUV420,
.bpp = 12,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU420,
.bpp = 12,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YUV422,
.bpp = 16,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU422,
.bpp = 16,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YUV444,
.bpp = 24,
.planes = 3,
}, {
.fourcc = DRM_FORMAT_YVU444,
.bpp = 24,
.planes = 3,
},
}; };
const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc) const struct rcar_du_format_info *rcar_du_format_info(u32 fourcc)
@ -144,6 +175,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
unsigned int max_pitch; unsigned int max_pitch;
unsigned int align; unsigned int align;
unsigned int bpp; unsigned int bpp;
unsigned int i;
format = rcar_du_format_info(mode_cmd->pixel_format); format = rcar_du_format_info(mode_cmd->pixel_format);
if (format == NULL) { if (format == NULL) {
@ -156,7 +188,7 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
* The pitch and alignment constraints are expressed in pixels on the * The pitch and alignment constraints are expressed in pixels on the
* hardware side and in bytes in the DRM API. * hardware side and in bytes in the DRM API.
*/ */
bpp = format->planes == 2 ? 1 : format->bpp / 8; bpp = format->planes == 1 ? format->bpp / 8 : 1;
max_pitch = 4096 * bpp; max_pitch = 4096 * bpp;
if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B)) if (rcar_du_needs(rcdu, RCAR_DU_QUIRK_ALIGN_128B))
@ -171,8 +203,8 @@ rcar_du_fb_create(struct drm_device *dev, struct drm_file *file_priv,
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);
} }
if (format->planes == 2) { for (i = 1; i < format->planes; ++i) {
if (mode_cmd->pitches[1] != mode_cmd->pitches[0]) { if (mode_cmd->pitches[i] != mode_cmd->pitches[0]) {
dev_dbg(dev->dev, dev_dbg(dev->dev,
"luma and chroma pitches do not match\n"); "luma and chroma pitches do not match\n");
return ERR_PTR(-EINVAL); return ERR_PTR(-EINVAL);

View file

@ -106,6 +106,12 @@ static const u32 formats_kms[] = {
DRM_FORMAT_NV21, DRM_FORMAT_NV21,
DRM_FORMAT_NV16, DRM_FORMAT_NV16,
DRM_FORMAT_NV61, DRM_FORMAT_NV61,
DRM_FORMAT_YUV420,
DRM_FORMAT_YVU420,
DRM_FORMAT_YUV422,
DRM_FORMAT_YVU422,
DRM_FORMAT_YUV444,
DRM_FORMAT_YVU444,
}; };
static const u32 formats_v4l2[] = { static const u32 formats_v4l2[] = {
@ -129,6 +135,12 @@ static const u32 formats_v4l2[] = {
V4L2_PIX_FMT_NV21M, V4L2_PIX_FMT_NV21M,
V4L2_PIX_FMT_NV16M, V4L2_PIX_FMT_NV16M,
V4L2_PIX_FMT_NV61M, V4L2_PIX_FMT_NV61M,
V4L2_PIX_FMT_YUV420M,
V4L2_PIX_FMT_YVU420M,
V4L2_PIX_FMT_YUV422M,
V4L2_PIX_FMT_YVU422M,
V4L2_PIX_FMT_YUV444M,
V4L2_PIX_FMT_YVU444M,
}; };
static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane) static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
@ -136,7 +148,6 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
struct rcar_du_vsp_plane_state *state = struct rcar_du_vsp_plane_state *state =
to_rcar_vsp_plane_state(plane->plane.state); to_rcar_vsp_plane_state(plane->plane.state);
struct drm_framebuffer *fb = plane->plane.state->fb; struct drm_framebuffer *fb = plane->plane.state->fb;
struct drm_gem_cma_object *gem;
struct v4l2_rect src; struct v4l2_rect src;
struct v4l2_rect dst; struct v4l2_rect dst;
dma_addr_t paddr[2] = { 0, }; dma_addr_t paddr[2] = { 0, };
@ -153,12 +164,11 @@ static void rcar_du_vsp_plane_setup(struct rcar_du_vsp_plane *plane)
dst.width = state->state.crtc_w; dst.width = state->state.crtc_w;
dst.height = state->state.crtc_h; dst.height = state->state.crtc_h;
gem = drm_fb_cma_get_gem_obj(fb, 0); for (i = 0; i < state->format->planes; ++i) {
paddr[0] = gem->paddr + fb->offsets[0]; struct drm_gem_cma_object *gem;
if (state->format->planes == 2) { gem = drm_fb_cma_get_gem_obj(fb, i);
gem = drm_fb_cma_get_gem_obj(fb, 1); paddr[i] = gem->paddr + fb->offsets[i];
paddr[1] = gem->paddr + fb->offsets[1];
} }
for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) { for (i = 0; i < ARRAY_SIZE(formats_kms); ++i) {