Skip to contentSkip to conversation

drm/msm: YUV suppport addition for MDP4 & MDP5

PATCH New Stephane Viau 1 participant 5 messages Dec 8, 2014

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover drm/msm: YUV suppport addition for MDP4 & MDP5

Hi,

So this set of patches adds YUV support for MDP4 and MDP5. This only concerns the public planes (using ViG pipes).

The fun part was to rebase things on top of atomic but things worked out fine. I was able to test this for MDP5 on a 8084 target. I cannot say the same for MDP4 for which I don't have a build based on atomic yet. The change is pretty similar to MDP5 though.

Rgds,
Stephane.

Beeresh Gopal (1):
drm/msm/mdp4: add YUV format support

Stephane Viau (3):
drm/msm/mdp: add register description for YUV support drm/msm/mdp: add common YUV information for MDP4/MDP5 drm/msm/mdp5: add NV12 support for MDP5

 drivers/gpu/drm/msm/hdmi/hdmi.c           | 149 ++++++++++++++-------
 drivers/gpu/drm/msm/hdmi/hdmi.h           |   8 +-
 drivers/gpu/drm/msm/hdmi/hdmi_connector.c |   1 -
 drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h   |  44 ++++++
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h   |  19 ++-
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 104 +++++++++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h   | 153 +++++++++++++++++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |  19 ++-
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 215 +++++++++++++++++++++++++++---
 drivers/gpu/drm/msm/mdp/mdp_common.xml.h  |  30 +++--
 drivers/gpu/drm/msm/mdp/mdp_format.c      | 108 +++++++++++++--
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |  24 +++-
 drivers/gpu/drm/msm/msm_fb.c              |   4 +-
 drivers/gpu/drm/msm/msm_kms.h             |   2 +
 14 files changed, 754 insertions(+), 126 deletions(-)
Signature · 8 lines
Qualcomm Innovation Center, Inc.

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

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#1 lore raw

PATCH 1/4 drm/msm/mdp: add register description for YUV support

YUV support addition implies that sub-modules of the ViG pipes need to be configured: Color Space Converter (CSC) and Scaler are the main components used to convert YUV to RGB data. Note that the output of a pipe has to be in RGB888 format since only this format is understood by the (layer) mixers.

Generated headers are kept in a separate change to ease the actual driver's code review.

---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h  |  44 +++++++++
 drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h  | 153 +++++++++++++++++++++++++++++--
 drivers/gpu/drm/msm/mdp/mdp_common.xml.h |  30 +++---
 3 files changed, 205 insertions(+), 22 deletions(-)
drivers/gpu/drm/msm/mdp/mdp4/mdp4.xml.h +44 -0
index a4a7f8c..b815c9c 100644
@@ -72,6 +72,18 @@ enum mdp4_cursor_format {
 	CURSOR_XRGB = 2,
 };
 
+enum mdp4_frame_format {
+	FRAME_LINEAR = 0,
+	FRAME_TILE_ARGB_4X4 = 1,
+	FRAME_TILE_YCBCR_420 = 2,
+};
+
+enum mdp4_scale_unit {
+	SCALE_FIR = 0,
+	SCALE_MN_PHASE = 1,
+	SCALE_PIXEL_RPT = 2,
+};
+
 enum mdp4_dma {
 	DMA_P = 0,
 	DMA_S = 1,
@@ -637,6 +649,8 @@ static inline uint32_t REG_MDP4_PIPE_SRCP1_BASE(enum mdp4_pipe i0) { return 0x00
 
 static inline uint32_t REG_MDP4_PIPE_SRCP2_BASE(enum mdp4_pipe i0) { return 0x00020018 + 0x10000*i0; }
 
+static inline uint32_t REG_MDP4_PIPE_SRCP3_BASE(enum mdp4_pipe i0) { return 0x0002001c + 0x10000*i0; }
+
 static inline uint32_t REG_MDP4_PIPE_SRC_STRIDE_A(enum mdp4_pipe i0) { return 0x00020040 + 0x10000*i0; }
 #define MDP4_PIPE_SRC_STRIDE_A_P0__MASK				0x0000ffff
 #define MDP4_PIPE_SRC_STRIDE_A_P0__SHIFT			0
@@ -720,7 +734,25 @@ static inline uint32_t MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(uint32_t val)
 }
 #define MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT			0x00020000
 #define MDP4_PIPE_SRC_FORMAT_UNPACK_ALIGN_MSB			0x00040000
+#define MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__MASK			0x00180000
+#define MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__SHIFT		19
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(uint32_t val)
+{
+	return ((val) << MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__SHIFT) & MDP4_PIPE_SRC_FORMAT_FETCH_PLANES__MASK;
+}
 #define MDP4_PIPE_SRC_FORMAT_SOLID_FILL				0x00400000
+#define MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK			0x0c000000
+#define MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT			26
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(enum mdp_chroma_samp_type val)
+{
+	return ((val) << MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__SHIFT) & MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP__MASK;
+}
+#define MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__MASK			0x60000000
+#define MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__SHIFT		29
+static inline uint32_t MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT(enum mdp4_frame_format val)
+{
+	return ((val) << MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__SHIFT) & MDP4_PIPE_SRC_FORMAT_FRAME_FORMAT__MASK;
+}
 
 static inline uint32_t REG_MDP4_PIPE_SRC_UNPACK(enum mdp4_pipe i0) { return 0x00020054 + 0x10000*i0; }
 #define MDP4_PIPE_SRC_UNPACK_ELEM0__MASK			0x000000ff
@@ -751,6 +783,18 @@ static inline uint32_t MDP4_PIPE_SRC_UNPACK_ELEM3(uint32_t val)
 static inline uint32_t REG_MDP4_PIPE_OP_MODE(enum mdp4_pipe i0) { return 0x00020058 + 0x10000*i0; }
 #define MDP4_PIPE_OP_MODE_SCALEX_EN				0x00000001
 #define MDP4_PIPE_OP_MODE_SCALEY_EN				0x00000002
+#define MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__MASK			0x0000000c
+#define MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__SHIFT		2
+static inline uint32_t MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(enum mdp4_scale_unit val)
+{
+	return ((val) << MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__SHIFT) & MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL__MASK;
+}
+#define MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__MASK			0x00000030
+#define MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__SHIFT		4
+static inline uint32_t MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(enum mdp4_scale_unit val)
+{
+	return ((val) << MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__SHIFT) & MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL__MASK;
+}
 #define MDP4_PIPE_OP_MODE_SRC_YCBCR				0x00000200
 #define MDP4_PIPE_OP_MODE_DST_YCBCR				0x00000400
 #define MDP4_PIPE_OP_MODE_CSC_EN				0x00000800
drivers/gpu/drm/msm/mdp/mdp5/mdp5.xml.h +143 -10

195 lines not on this page · raw message

drivers/gpu/drm/msm/mdp/mdp_common.xml.h +18 -12
index 64c1afd..39602bb 100644
@@ -8,18 +8,11 @@ http://github.com/freedreno/envytools/
 git clone https://github.com/freedreno/envytools.git
 
 The rules-ng-ng source files this header was generated from are:
-- /home/robclark/src/freedreno/envytools/rnndb/msm.xml                 (    647 bytes, from 2013-11-30 14:45:35)
-- /home/robclark/src/freedreno/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2013-03-31 16:51:27)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp4.xml            (  17996 bytes, from 2013-12-01 19:10:31)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp_common.xml      (   1615 bytes, from 2013-11-30 15:00:52)
-- /home/robclark/src/freedreno/envytools/rnndb/mdp/mdp5.xml            (  22517 bytes, from 2014-06-25 12:55:02)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/dsi.xml             (  11712 bytes, from 2013-08-17 17:13:43)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/sfpb.xml            (    344 bytes, from 2013-08-11 19:26:32)
-- /home/robclark/src/freedreno/envytools/rnndb/dsi/mmss_cc.xml         (   1544 bytes, from 2013-08-16 19:17:05)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/qfprom.xml         (    600 bytes, from 2013-07-05 19:21:12)
-- /home/robclark/src/freedreno/envytools/rnndb/hdmi/hdmi.xml           (  23613 bytes, from 2014-06-25 12:53:44)
-
-Copyright (C) 2013 by the following authors:
+- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp5.xml            (  27208 bytes, from 2014-10-28 19:05:31)
+- /local/mnt2/workspace2/sviau/envytools/rnndb/freedreno_copyright.xml (   1453 bytes, from 2014-06-02 18:31:15)
+- /local/mnt2/workspace2/sviau/envytools/rnndb/mdp/mdp_common.xml      (   2357 bytes, from 2014-10-07 21:41:04)
+
+Copyright (C) 2013-2014 by the following authors:
 - Rob Clark <[email protected]> (robclark)
 
 Permission is hereby granted, free of charge, to any person obtaining
@@ -44,6 +37,19 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 */
 
 
+enum mdp_chroma_samp_type {
+	CHROMA_RGB = 0,
+	CHROMA_H2V1 = 1,
+	CHROMA_H1V2 = 2,
+	CHROMA_420 = 3,
+};
+
+enum mdp_sspp_fetch_type {
+	MDP_PLANE_INTERLEAVED = 0,
+	MDP_PLANE_PLANAR = 1,
+	MDP_PLANE_PSEUDO_PLANAR = 2,
+};
+
 enum mdp_mixer_stage_id {
 	STAGE_UNUSED = 0,
 	STAGE_BASE = 1,
Signature · 8 lines
Qualcomm Innovation Center, Inc.

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

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#2 lore raw

PATCH 2/4 drm/msm/mdp: add common YUV information for MDP4/MDP5

In reply to Stephane Viau

Both MDP4 and MDP5 share some code as far as YUV support is concerned. This change adds this information and will be followed by the actual MDP4 and MDP5 YUV support patches.

---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h   |  19 ++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h   |  19 ++++--
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c |   2 -
 drivers/gpu/drm/msm/mdp/mdp_format.c      | 108 +++++++++++++++++++++++++++---
 drivers/gpu/drm/msm/mdp/mdp_kms.h         |  24 ++++++-
 drivers/gpu/drm/msm/msm_fb.c              |   2 +-
 drivers/gpu/drm/msm/msm_kms.h             |   2 +
 7 files changed, 154 insertions(+), 22 deletions(-)
drivers/gpu/drm/msm/mdp/mdp4/mdp4_kms.h +15 -4
index cbd77bc..0a5c58b 100644
@@ -175,14 +175,25 @@ irqreturn_t mdp4_irq(struct msm_kms *kms);
 int mdp4_enable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 void mdp4_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 
+static inline bool pipe_supports_yuv(enum mdp4_pipe pipe)
+{
+	switch (pipe) {
+	case VG1:
+	case VG2:
+	case VG3:
+	case VG4:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static inline
 uint32_t mdp4_get_formats(enum mdp4_pipe pipe_id, uint32_t *pixel_formats,
 		uint32_t max_formats)
 {
-	/* TODO when we have YUV, we need to filter supported formats
-	 * based on pipe_id..
-	 */
-	return mdp_get_formats(pixel_formats, max_formats);
+	return mdp_get_formats(pixel_formats, max_formats,
+				!pipe_supports_yuv(pipe_id));
 }
 
 void mdp4_plane_install_properties(struct drm_plane *plane,
drivers/gpu/drm/msm/mdp/mdp5/mdp5_kms.h +15 -4
index dd69c77..49d011e 100644
@@ -165,14 +165,25 @@ void mdp5_disable_vblank(struct msm_kms *kms, struct drm_crtc *crtc);
 int mdp5_irq_domain_init(struct mdp5_kms *mdp5_kms);
 void mdp5_irq_domain_fini(struct mdp5_kms *mdp5_kms);
 
+static inline bool pipe_supports_yuv(enum mdp5_pipe pipe)
+{
+	switch (pipe) {
+	case SSPP_VIG0:
+	case SSPP_VIG1:
+	case SSPP_VIG2:
+	case SSPP_VIG3:
+		return true;
+	default:
+		return false;
+	}
+}
+
 static inline
 uint32_t mdp5_get_formats(enum mdp5_pipe pipe, uint32_t *pixel_formats,
 		uint32_t max_formats)
 {
-	/* TODO when we have YUV, we need to filter supported formats
-	 * based on pipe id..
-	 */
-	return mdp_get_formats(pixel_formats, max_formats);
+	return mdp_get_formats(pixel_formats, max_formats,
+				!pipe_supports_yuv(pipe));
 }
 
 void mdp5_plane_install_properties(struct drm_plane *plane,
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +0 -2
index 533df7c..9a57e87 100644
@@ -18,8 +18,6 @@
 
 #include "mdp5_kms.h"
 
-#define MAX_PLANE	4
-
 struct mdp5_plane {
 	struct drm_plane base;
 	const char *name;
drivers/gpu/drm/msm/mdp/mdp_format.c +98 -10

139 lines not on this page · raw message

drivers/gpu/drm/msm/mdp/mdp_kms.h +23 -1
index 99557b5..64c83a9 100644
@@ -88,10 +88,32 @@ struct mdp_format {
 	uint8_t unpack[4];
 	bool alpha_enable, unpack_tight;
 	uint8_t cpp, unpack_count;
+	enum mdp_sspp_fetch_type fetch_type;
+	enum mdp_chroma_samp_type chroma_sample;
 };
 #define to_mdp_format(x) container_of(x, struct mdp_format, base)
+#define MDP_FORMAT_IS_YUV(mdp_format) ((mdp_format)->chroma_sample > CHROMA_RGB)
 
-uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats);
+uint32_t mdp_get_formats(uint32_t *formats, uint32_t max_formats, bool rgb_only);
 const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
 
+enum csc_type {
+	CSC_RGB2RGB = 0,
+	CSC_YUV2RGB,
+	CSC_RGB2YUV,
+	CSC_YUV2YUV,
+	CSC_MAX
+};
+
+struct csc_cfg {
+	enum csc_type type;
+	uint32_t matrix[9];
+	uint32_t pre_bias[3];
+	uint32_t post_bias[3];
+	uint32_t pre_clamp[6];
+	uint32_t post_clamp[6];
+};
+
+struct csc_cfg *mdp_get_default_csc_cfg(enum csc_type);
+
 #endif /* __MDP_KMS_H__ */
drivers/gpu/drm/msm/msm_fb.c +1 -1
index 84dec16..d1a7a45 100644
@@ -24,7 +24,7 @@
 struct msm_framebuffer {
 	struct drm_framebuffer base;
 	const struct msm_format *format;
-	struct drm_gem_object *planes[3];
+	struct drm_gem_object *planes[MAX_PLANE];
 };
 #define to_msm_framebuffer(x) container_of(x, struct msm_framebuffer, base)
 
drivers/gpu/drm/msm/msm_kms.h +2 -0
index 7fb4876..6a28835 100644
@@ -23,6 +23,8 @@
 
 #include "msm_drv.h"
 
+#define MAX_PLANE	4
+
 /* As there are different display controller blocks depending on the
  * snapdragon version, the kms support is split out and the appropriate
  * implementation is loaded at runtime.  The kms module is responsible
Signature · 8 lines
Qualcomm Innovation Center, Inc.

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

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#3 lore raw

PATCH 3/4 drm/msm/mdp5: add NV12 support for MDP5

In reply to Stephane Viau

This change adds the NV12 format support for public planes.

---
 drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c | 213 +++++++++++++++++++++++++++---
 drivers/gpu/drm/msm/msm_fb.c              |   2 +-
 2 files changed, 194 insertions(+), 21 deletions(-)
drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c +193 -20
index 9a57e87..263a16b 100644
@@ -274,6 +274,155 @@ static void set_scanout_locked(struct drm_plane *plane,
 	plane->fb = fb;
 }
 
+/* Note: mdp5_plane->pipe_lock must be locked */
+static void csc_disable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe)
+{
+	uint32_t value = mdp5_read(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe)) &
+			 ~MDP5_PIPE_OP_MODE_CSC_1_EN;
+
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), value);
+}
+
+/* Note: mdp5_plane->pipe_lock must be locked */
+static void csc_enable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
+		struct csc_cfg *csc)
+{
+	uint32_t  i, mode = 0; /* RGB, no CSC */
+	uint32_t *matrix;
+
+	if (unlikely(!csc))
+		return;
+
+	if ((csc->type == CSC_YUV2RGB) || (CSC_YUV2YUV == csc->type))
+		mode |= MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT(DATA_FORMAT_YUV);
+	if ((csc->type == CSC_RGB2YUV) || (CSC_YUV2YUV == csc->type))
+		mode |= MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT(DATA_FORMAT_YUV);
+	mode |= MDP5_PIPE_OP_MODE_CSC_1_EN;
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), mode);
+
+	matrix = csc->matrix;
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_0(pipe),
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11(matrix[0]) |
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12(matrix[1]));
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_1(pipe),
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13(matrix[2]) |
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21(matrix[3]));
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_2(pipe),
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22(matrix[4]) |
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23(matrix[5]));
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_3(pipe),
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31(matrix[6]) |
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32(matrix[7]));
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_4(pipe),
+			MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33(matrix[8]));
+
+	for (i = 0; i < ARRAY_SIZE(csc->pre_bias); i++) {
+		uint32_t *pre_clamp = csc->pre_clamp;
+		uint32_t *post_clamp = csc->post_clamp;
+
+		mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_CLAMP(pipe, i),
+			MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH(pre_clamp[2*i+1]) |
+			MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW(pre_clamp[2*i]));
+
+		mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_CLAMP(pipe, i),
+			MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH(post_clamp[2*i+1]) |
+			MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW(post_clamp[2*i]));
+
+		mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_BIAS(pipe, i),
+			MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE(csc->pre_bias[i]));
+
+		mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_BIAS(pipe, i),
+			MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE(csc->post_bias[i]));
+	}
+}
+
+#define PHASE_STEP_SHIFT	21
+#define DOWN_SCALE_RATIO_MAX	32	/* 2^(26-21) */
+
+static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
+{
+	uint32_t unit;
+
+	if (src == 0 || dst == 0)
+		return -EINVAL;
+
+	/*
+	 * PHASE_STEP_X/Y is coded on 26 bits (25:0),
+	 * where 2^21 represents the unity "1" in fixed-point hardware design.
+	 * This leaves 5 bits for the integer part (downscale case):
+	 *	-> maximum downscale ratio = 0b1_1111 = 31
+	 */
+	if (src > (dst * DOWN_SCALE_RATIO_MAX))
+		return -EOVERFLOW;
+
+	unit = 1 << PHASE_STEP_SHIFT;
+	*out_phase = mult_frac(unit, src, dst);
+
+	return 0;
+}
+
+static int calc_scalex_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
+		uint32_t phasex_steps[2])
+{
+	uint32_t phasex_step;
+	unsigned int hsub;
+	int ret;
+
+	ret = calc_phase_step(src, dest, &phasex_step);
+	if (ret)
+		return ret;
+
+	hsub = drm_format_horz_chroma_subsampling(pixel_format);
+
+	phasex_steps[0] = phasex_step;
+	phasex_steps[1] = phasex_step / hsub;
+
+	return 0;
+}
+
+static int calc_scaley_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
+		uint32_t phasey_steps[2])
+{
+	uint32_t phasey_step;
+	unsigned int vsub;
+	int ret;
+
+	ret = calc_phase_step(src, dest, &phasey_step);
+	if (ret)
+		return ret;
+
+	vsub = drm_format_vert_chroma_subsampling(pixel_format);
+
+	phasey_steps[0] = phasey_step;
+	phasey_steps[1] = phasey_step / vsub;
+
+	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_MIN_FILTER(filter) |
+		MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(filter)  |
+		MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(filter);
+}
+
+static uint32_t get_scaley_config(uint32_t src, uint32_t dest)
+{
+	uint32_t filter;
+
+	filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
+
+	return  MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
+		MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(filter) |
+		MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(filter)  |
+		MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(filter);
+}
+
 static int mdp5_plane_mode_set(struct drm_plane *plane,
 		struct drm_crtc *crtc, struct drm_framebuffer *fb,
 		int crtc_x, int crtc_y,
@@ -283,11 +432,14 @@ 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;
-	uint32_t phasex_step = 0, phasey_step = 0;
+	/* below array -> index 0: comp 0/3 ; index 1: comp 1/2 */
+	uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
 	uint32_t hdecm = 0, vdecm = 0;
+	uint32_t pix_format;
 	unsigned long flags;
 	int ret;
 
@@ -297,6 +449,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	if (WARN_ON(nplanes > pipe2nclients(pipe)))
 		return -EINVAL;
 
+	format = to_mdp_format(msm_framebuffer_format(fb));
+	pix_format = format->base.pixel_format;
+
 	/* src values are in Q16 fixed point, convert to integer: */
 	src_x = src_x >> 16;
 	src_y = src_y >> 16;
@@ -321,14 +476,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	 */
 	mdp5_smp_configure(mdp5_kms->smp, pipe);
 
-	if (src_w != crtc_w) {
-		config |= MDP5_PIPE_SCALE_CONFIG_SCALEX_EN;
-		/* TODO calc phasex_step, hdecm */
+	/* SCALE is used to both scale and up-sample chroma components */
+
+	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);
 	}
 
-	if (src_h != crtc_h) {
-		config |= MDP5_PIPE_SCALE_CONFIG_SCALEY_EN;
-		/* TODO calc phasey_step, vdecm */
+	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);
 	}
 
 	spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
@@ -353,8 +522,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 			MDP5_PIPE_OUT_XY_X(crtc_x) |
 			MDP5_PIPE_OUT_XY_Y(crtc_y));
 
-	format = to_mdp_format(msm_framebuffer_format(fb));
-
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe),
 			MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
 			MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
@@ -364,8 +531,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 			MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
 			MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
 			COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) |
-			MDP5_PIPE_SRC_FORMAT_NUM_PLANES(nplanes - 1) |
-			MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(CHROMA_RGB));
+			MDP5_PIPE_SRC_FORMAT_NUM_PLANES(format->fetch_type) |
+			MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample));
 
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe),
 			MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
@@ -379,18 +546,24 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
 	/* not using secure mode: */
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
 
-	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), phasex_step);
-	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasey_step);
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
+			phasex_step[0]);
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
+			phasey_step[0]);
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
+			phasex_step[1]);
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
+			phasey_step[1]);
 	mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
 			MDP5_PIPE_DECIMATION_VERT(vdecm) |
 			MDP5_PIPE_DECIMATION_HORZ(hdecm));
-	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe),
-			MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(SCALE_FILTER_NEAREST) |
-			MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(SCALE_FILTER_NEAREST) |
-			MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(SCALE_FILTER_NEAREST) |
-			MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(SCALE_FILTER_NEAREST) |
-			MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(SCALE_FILTER_NEAREST) |
-			MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(SCALE_FILTER_NEAREST));
+	mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
+
+	if (MDP_FORMAT_IS_YUV(format))
+		csc_enable(mdp5_kms, pipe,
+				mdp_get_default_csc_cfg(CSC_YUV2RGB));
+	else
+		csc_disable(mdp5_kms, pipe);
 
 	set_scanout_locked(plane, fb);
 
drivers/gpu/drm/msm/msm_fb.c +1 -1
index d1a7a45..6b573e6 100644
@@ -122,7 +122,7 @@ uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane)
 	struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
 	if (!msm_fb->planes[plane])
 		return 0;
-	return msm_gem_iova(msm_fb->planes[plane], id);
+	return msm_gem_iova(msm_fb->planes[plane], id) + fb->offsets[plane];
 }
 
 struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane)
Signature · 8 lines
Qualcomm Innovation Center, Inc.

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

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel
#4 lore raw

PATCH 4/4 drm/msm/mdp4: add YUV format support

In reply to Stephane Viau

From: Beeresh Gopal <[email protected]>

The patch add support for YUV frame format
for MDP4 platform.

---
 drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 104 +++++++++++++++++++++++++++---
 1 file changed, 95 insertions(+), 9 deletions(-)
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +95 -9
index 76d0a40..6e3c1ef 100644
@@ -17,6 +17,8 @@
 
 #include "mdp4_kms.h"
 
+#define DOWN_SCALE_MAX	8
+#define UP_SCALE_MAX	8
 
 struct mdp4_plane {
 	struct drm_plane base;
@@ -135,10 +137,6 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
 	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
 	struct mdp4_kms *mdp4_kms = get_kms(plane);
 	enum mdp4_pipe pipe = mdp4_plane->pipe;
-	uint32_t iova = msm_framebuffer_iova(fb, mdp4_kms->id, 0);
-
-	DBG("%s: set_scanout: %08x (%u)", mdp4_plane->name,
-			iova, fb->pitches[0]);
 
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe),
 			MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) |
@@ -148,11 +146,45 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane,
 			MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) |
 			MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3]));
 
-	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova);
+	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe),
+			msm_framebuffer_iova(fb, mdp4_kms->id, 0));
+	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe),
+			msm_framebuffer_iova(fb, mdp4_kms->id, 1));
+	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe),
+			msm_framebuffer_iova(fb, mdp4_kms->id, 2));
+	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe),
+			msm_framebuffer_iova(fb, mdp4_kms->id, 3));
 
 	plane->fb = fb;
 }
 
+static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms,
+		enum mdp4_pipe pipe, struct csc_cfg *csc)
+{
+	int i;
+
+	for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) {
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i),
+				csc->matrix[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) {
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i),
+				csc->pre_bias[i]);
+
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i),
+				csc->post_bias[i]);
+	}
+
+	for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) {
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i),
+				csc->pre_clamp[i]);
+
+		mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i),
+				csc->post_clamp[i]);
+	}
+}
+
 #define MDP4_VG_PHASE_STEP_DEFAULT	0x20000000
 
 static int mdp4_plane_mode_set(struct drm_plane *plane,
@@ -162,6 +194,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 		uint32_t src_x, uint32_t src_y,
 		uint32_t src_w, uint32_t src_h)
 {
+	struct drm_device *dev = plane->dev;
 	struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane);
 	struct mdp4_kms *mdp4_kms = get_kms(plane);
 	enum mdp4_pipe pipe = mdp4_plane->pipe;
@@ -185,14 +218,59 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 			fb->base.id, src_x, src_y, src_w, src_h,
 			crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h);
 
+	format = to_mdp_format(msm_framebuffer_format(fb));
+
+	if (src_w > (crtc_w * DOWN_SCALE_MAX)) {
+		dev_err(dev->dev, "Width down scaling exceeds limits!\n");
+		return -ERANGE;
+	}
+
+	if (src_h > (crtc_h * DOWN_SCALE_MAX)) {
+		dev_err(dev->dev, "Height down scaling exceeds limits!\n");
+		return -ERANGE;
+	}
+
+	if (crtc_w > (src_w * UP_SCALE_MAX)) {
+		dev_err(dev->dev, "Width up scaling exceeds limits!\n");
+		return -ERANGE;
+	}
+
+	if (crtc_h > (src_h * UP_SCALE_MAX)) {
+		dev_err(dev->dev, "Height up scaling exceeds limits!\n");
+		return -ERANGE;
+	}
+
 	if (src_w != crtc_w) {
+		uint32_t sel_unit = SCALE_FIR;
 		op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN;
-		/* TODO calc phasex_step */
+
+		if (MDP_FORMAT_IS_YUV(format)) {
+			if (crtc_w > src_w)
+				sel_unit = SCALE_PIXEL_RPT;
+			else if (crtc_w <= (src_w / 4))
+				sel_unit = SCALE_MN_PHASE;
+
+			op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit);
+			phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
+					src_w, crtc_w);
+		}
 	}
 
 	if (src_h != crtc_h) {
+		uint32_t sel_unit = SCALE_FIR;
 		op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN;
-		/* TODO calc phasey_step */
+
+		if (MDP_FORMAT_IS_YUV(format)) {
+
+			if (crtc_h > src_h)
+				sel_unit = SCALE_PIXEL_RPT;
+			else if (crtc_h <= (src_h / 4))
+				sel_unit = SCALE_MN_PHASE;
+
+			op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit);
+			phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT,
+					src_h, crtc_h);
+		}
 	}
 
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe),
@@ -213,8 +291,6 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 
 	mdp4_plane_set_scanout(plane, fb);
 
-	format = to_mdp_format(msm_framebuffer_format(fb));
-
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe),
 			MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
 			MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
@@ -223,6 +299,8 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 			COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) |
 			MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
 			MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
+			MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) |
+			MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) |
 			COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT));
 
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe),
@@ -231,6 +309,14 @@ static int mdp4_plane_mode_set(struct drm_plane *plane,
 			MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) |
 			MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3]));
 
+	if (MDP_FORMAT_IS_YUV(format)) {
+		struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB);
+
+		op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR;
+		op_mode |= MDP4_PIPE_OP_MODE_CSC_EN;
+		mdp4_write_csc_config(mdp4_kms, pipe, csc);
+	}
+
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode);
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);
 	mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step);
Signature · 8 lines
Qualcomm Innovation Center, Inc.

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

_______________________________________________
dri-devel mailing list
[email protected]
http://lists.freedesktop.org/mailman/listinfo/dri-devel