[PATCH 6/6] drm/msm/mdp5: add more YUV formats for MDP5

From: Stephane Viau
Date: Mon Jul 06 2015 - 16:36:20 EST


Add packed YUV422 and planar YUV420 formats to MDP supported
formats.

Signed-off-by: Stephane Viau <sviau@xxxxxxxxxxxxxx>
---
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 105 +++++++++++++++++-------------
drivers/gpu/drm/msm/mdp/mdp_format.c | 19 ++++++
2 files changed, 77 insertions(+), 47 deletions(-)

diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 7fb526d..3d63e21 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2014 The Linux Foundation. All rights reserved.
+ * Copyright (C) 2014-2015 The Linux Foundation. All rights reserved.
* Copyright (C) 2013 Red Hat
* Author: Rob Clark <robdclark@xxxxxxxxx>
*
@@ -40,6 +40,7 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
unsigned int crtc_w, unsigned int crtc_h,
uint32_t src_x, uint32_t src_y,
uint32_t src_w, uint32_t src_h);
+
static void set_scanout_locked(struct drm_plane *plane,
struct drm_framebuffer *fb);

@@ -346,16 +347,21 @@ static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
return 0;
}

-static int calc_scalex_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
+static int calc_scalex_steps(struct drm_plane *plane,
+ uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasex_steps[2])
{
+ struct mdp5_kms *mdp5_kms = get_kms(plane);
+ struct device *dev = mdp5_kms->dev->dev;
uint32_t phasex_step;
unsigned int hsub;
int ret;

ret = calc_phase_step(src, dest, &phasex_step);
- if (ret)
+ if (ret) {
+ dev_err(dev, "X scaling (%d->%d) failed: %d\n", src, dest, ret);
return ret;
+ }

hsub = drm_format_horz_chroma_subsampling(pixel_format);

@@ -365,16 +371,21 @@ static int calc_scalex_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
return 0;
}

-static int calc_scaley_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
+static int calc_scaley_steps(struct drm_plane *plane,
+ uint32_t pixel_format, uint32_t src, uint32_t dest,
uint32_t phasey_steps[2])
{
+ struct mdp5_kms *mdp5_kms = get_kms(plane);
+ struct device *dev = mdp5_kms->dev->dev;
uint32_t phasey_step;
unsigned int vsub;
int ret;

ret = calc_phase_step(src, dest, &phasey_step);
- if (ret)
+ if (ret) {
+ dev_err(dev, "Y scaling (%d->%d) failed: %d\n", src, dest, ret);
return ret;
+ }

vsub = drm_format_vert_chroma_subsampling(pixel_format);

@@ -384,28 +395,38 @@ static int calc_scaley_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
return 0;
}

-static uint32_t get_scalex_config(uint32_t src, uint32_t dest)
-{
- uint32_t filter;
-
- filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
-
- return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(filter);
-}
-
-static uint32_t get_scaley_config(uint32_t src, uint32_t dest)
+static uint32_t get_scale_config(enum mdp_chroma_samp_type chroma_sample,
+ uint32_t src, uint32_t dest, bool hor)
{
- uint32_t filter;
-
- filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
+ uint32_t y_filter = (src <= dest) ? SCALE_FILTER_CA : SCALE_FILTER_PCMN;
+ uint32_t y_a_filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
+ uint32_t uv_filter = ((src / 2) <= dest) ? /* 2x upsample */
+ SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
+ uint32_t value = 0;
+
+ if (chroma_sample == CHROMA_420 || chroma_sample == CHROMA_H2V1) {
+ if (hor)
+ value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter);
+ else
+ value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter);
+ } else if (src != dest) {
+ if (hor)
+ value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_a_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter);
+ else
+ value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_a_filter) |
+ MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter);
+ }

- return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(filter) |
- MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(filter);
+ return value;
}

static int mdp5_plane_mode_set(struct drm_plane *plane,
@@ -417,7 +438,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
{
struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
struct mdp5_kms *mdp5_kms = get_kms(plane);
- struct device *dev = mdp5_kms->dev->dev;
enum mdp5_pipe pipe = mdp5_plane->pipe;
const struct mdp_format *format;
uint32_t nplanes, config = 0;
@@ -461,29 +481,20 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
*/
mdp5_smp_configure(mdp5_kms->smp, pipe);

- /* SCALE is used to both scale and up-sample chroma components */
+ ret = calc_scalex_steps(plane, pix_format, src_w, crtc_w, phasex_step);
+ if (ret)
+ return ret;

- if ((src_w != crtc_w) || MDP_FORMAT_IS_YUV(format)) {
- /* TODO calc hdecm */
- ret = calc_scalex_steps(pix_format, src_w, crtc_w, phasex_step);
- if (ret) {
- dev_err(dev, "X scaling (%d -> %d) failed: %d\n",
- src_w, crtc_w, ret);
- return ret;
- }
- config |= get_scalex_config(src_w, crtc_w);
- }
+ ret = calc_scaley_steps(plane, pix_format, src_h, crtc_h, phasey_step);
+ if (ret)
+ return ret;

- if ((src_h != crtc_h) || MDP_FORMAT_IS_YUV(format)) {
- /* TODO calc vdecm */
- ret = calc_scaley_steps(pix_format, src_h, crtc_h, phasey_step);
- if (ret) {
- dev_err(dev, "Y scaling (%d -> %d) failed: %d\n",
- src_h, crtc_h, ret);
- return ret;
- }
- config |= get_scaley_config(src_h, crtc_h);
- }
+ /* TODO calc hdecm, vdecm */
+
+ /* SCALE is used to both scale and up-sample chroma components */
+ config |= get_scale_config(format->chroma_sample, src_w, crtc_w, true);
+ config |= get_scale_config(format->chroma_sample, src_h, crtc_h, false);
+ DBG("scale config = %x", config);

spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);

diff --git a/drivers/gpu/drm/msm/mdp/mdp_format.c b/drivers/gpu/drm/msm/mdp/mdp_format.c
index fd803c5..1c2caff 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_format.c
+++ b/drivers/gpu/drm/msm/mdp/mdp_format.c
@@ -116,10 +116,29 @@ static const struct mdp_format formats[] = {

/* --- RGB formats above / YUV formats below this line --- */

+ /* 2 plane YUV */
FMT(NV12, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2,
MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true),
FMT(NV21, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2,
MDP_PLANE_PSEUDO_PLANAR, CHROMA_420, true),
+ FMT(NV16, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 2, 2,
+ MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true),
+ FMT(NV61, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 2, 2,
+ MDP_PLANE_PSEUDO_PLANAR, CHROMA_H2V1, true),
+ /* 1 plane YUV */
+ FMT(VYUY, 0, 8, 8, 8, 2, 0, 1, 0, false, true, 2, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true),
+ FMT(UYVY, 0, 8, 8, 8, 1, 0, 2, 0, false, true, 2, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true),
+ FMT(YUYV, 0, 8, 8, 8, 0, 1, 0, 2, false, true, 2, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true),
+ FMT(YVYU, 0, 8, 8, 8, 0, 2, 0, 1, false, true, 2, 4,
+ MDP_PLANE_INTERLEAVED, CHROMA_H2V1, true),
+ /* 3 plane YUV */
+ FMT(YUV420, 0, 8, 8, 8, 2, 1, 0, 0, false, true, 1, 1,
+ MDP_PLANE_PLANAR, CHROMA_420, true),
+ FMT(YVU420, 0, 8, 8, 8, 1, 2, 0, 0, false, true, 1, 1,
+ MDP_PLANE_PLANAR, CHROMA_420, true),
};

/*
--
Qualcomm Innovation Center, Inc.

The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum, a Linux Foundation Collaborative Project

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/