Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

drm/msm/mdp4: add YUV format support

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

Signed-off-by: Beeresh Gopal <gbeeresh@codeaurora.org>
Signed-off-by: Stephane Viau <sviau@codeaurora.org>
Signed-off-by: Rob Clark <robdclark@gmail.com>

authored by

Beeresh Gopal and committed by
Rob Clark
b1b1c74e f8d9b515

+95 -9
+95 -9
drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c
··· 17 17 18 18 #include "mdp4_kms.h" 19 19 20 + #define DOWN_SCALE_MAX 8 21 + #define UP_SCALE_MAX 8 20 22 21 23 struct mdp4_plane { 22 24 struct drm_plane base; ··· 138 136 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); 139 137 struct mdp4_kms *mdp4_kms = get_kms(plane); 140 138 enum mdp4_pipe pipe = mdp4_plane->pipe; 141 - uint32_t iova = msm_framebuffer_iova(fb, mdp4_kms->id, 0); 142 - 143 - DBG("%s: set_scanout: %08x (%u)", mdp4_plane->name, 144 - iova, fb->pitches[0]); 145 139 146 140 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe), 147 141 MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) | ··· 147 149 MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) | 148 150 MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); 149 151 150 - mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova); 152 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), 153 + msm_framebuffer_iova(fb, mdp4_kms->id, 0)); 154 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe), 155 + msm_framebuffer_iova(fb, mdp4_kms->id, 1)); 156 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe), 157 + msm_framebuffer_iova(fb, mdp4_kms->id, 2)); 158 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe), 159 + msm_framebuffer_iova(fb, mdp4_kms->id, 3)); 151 160 152 161 plane->fb = fb; 162 + } 163 + 164 + static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms, 165 + enum mdp4_pipe pipe, struct csc_cfg *csc) 166 + { 167 + int i; 168 + 169 + for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) { 170 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i), 171 + csc->matrix[i]); 172 + } 173 + 174 + for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) { 175 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i), 176 + csc->pre_bias[i]); 177 + 178 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i), 179 + csc->post_bias[i]); 180 + } 181 + 182 + for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) { 183 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i), 184 + csc->pre_clamp[i]); 185 + 186 + mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i), 187 + csc->post_clamp[i]); 188 + } 153 189 } 154 190 155 191 #define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 ··· 195 163 uint32_t src_x, uint32_t src_y, 196 164 uint32_t src_w, uint32_t src_h) 197 165 { 166 + struct drm_device *dev = plane->dev; 198 167 struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); 199 168 struct mdp4_kms *mdp4_kms = get_kms(plane); 200 169 enum mdp4_pipe pipe = mdp4_plane->pipe; ··· 219 186 fb->base.id, src_x, src_y, src_w, src_h, 220 187 crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h); 221 188 189 + format = to_mdp_format(msm_framebuffer_format(fb)); 190 + 191 + if (src_w > (crtc_w * DOWN_SCALE_MAX)) { 192 + dev_err(dev->dev, "Width down scaling exceeds limits!\n"); 193 + return -ERANGE; 194 + } 195 + 196 + if (src_h > (crtc_h * DOWN_SCALE_MAX)) { 197 + dev_err(dev->dev, "Height down scaling exceeds limits!\n"); 198 + return -ERANGE; 199 + } 200 + 201 + if (crtc_w > (src_w * UP_SCALE_MAX)) { 202 + dev_err(dev->dev, "Width up scaling exceeds limits!\n"); 203 + return -ERANGE; 204 + } 205 + 206 + if (crtc_h > (src_h * UP_SCALE_MAX)) { 207 + dev_err(dev->dev, "Height up scaling exceeds limits!\n"); 208 + return -ERANGE; 209 + } 210 + 222 211 if (src_w != crtc_w) { 212 + uint32_t sel_unit = SCALE_FIR; 223 213 op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN; 224 - /* TODO calc phasex_step */ 214 + 215 + if (MDP_FORMAT_IS_YUV(format)) { 216 + if (crtc_w > src_w) 217 + sel_unit = SCALE_PIXEL_RPT; 218 + else if (crtc_w <= (src_w / 4)) 219 + sel_unit = SCALE_MN_PHASE; 220 + 221 + op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit); 222 + phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT, 223 + src_w, crtc_w); 224 + } 225 225 } 226 226 227 227 if (src_h != crtc_h) { 228 + uint32_t sel_unit = SCALE_FIR; 228 229 op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN; 229 - /* TODO calc phasey_step */ 230 + 231 + if (MDP_FORMAT_IS_YUV(format)) { 232 + 233 + if (crtc_h > src_h) 234 + sel_unit = SCALE_PIXEL_RPT; 235 + else if (crtc_h <= (src_h / 4)) 236 + sel_unit = SCALE_MN_PHASE; 237 + 238 + op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit); 239 + phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT, 240 + src_h, crtc_h); 241 + } 230 242 } 231 243 232 244 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe), ··· 292 214 293 215 mdp4_plane_set_scanout(plane, fb); 294 216 295 - format = to_mdp_format(msm_framebuffer_format(fb)); 296 - 297 217 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe), 298 218 MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | 299 219 MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | ··· 300 224 COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) | 301 225 MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | 302 226 MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | 227 + MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) | 228 + MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) | 303 229 COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT)); 304 230 305 231 mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe), ··· 309 231 MDP4_PIPE_SRC_UNPACK_ELEM1(format->unpack[1]) | 310 232 MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) | 311 233 MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3])); 234 + 235 + if (MDP_FORMAT_IS_YUV(format)) { 236 + struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB); 237 + 238 + op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR; 239 + op_mode |= MDP4_PIPE_OP_MODE_CSC_EN; 240 + mdp4_write_csc_config(mdp4_kms, pipe, csc); 241 + } 312 242 313 243 mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode); 314 244 mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step);