diff options
author | Beeresh Gopal <gbeeresh@codeaurora.org> | 2014-12-08 10:48:59 -0500 |
---|---|---|
committer | Rob Clark <robdclark@gmail.com> | 2015-02-01 15:30:35 -0500 |
commit | b1b1c74e36b369dceaa0ea98ac543e8c13c720ee (patch) | |
tree | 6cac5fb6d36934ca02ea0b9c1c8f162ca1d2eeaa | |
parent | f8d9b5156e966e701cb17c623ffd6ebe35cc3157 (diff) |
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>
-rw-r--r-- | drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | 104 |
1 files changed, 95 insertions, 9 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c index 1e5ebe83647d..cde25009203a 100644 --- a/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c +++ b/drivers/gpu/drm/msm/mdp/mdp4/mdp4_plane.c | |||
@@ -17,6 +17,8 @@ | |||
17 | 17 | ||
18 | #include "mdp4_kms.h" | 18 | #include "mdp4_kms.h" |
19 | 19 | ||
20 | #define DOWN_SCALE_MAX 8 | ||
21 | #define UP_SCALE_MAX 8 | ||
20 | 22 | ||
21 | struct mdp4_plane { | 23 | struct mdp4_plane { |
22 | struct drm_plane base; | 24 | struct drm_plane base; |
@@ -136,10 +138,6 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane, | |||
136 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); | 138 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); |
137 | struct mdp4_kms *mdp4_kms = get_kms(plane); | 139 | struct mdp4_kms *mdp4_kms = get_kms(plane); |
138 | enum mdp4_pipe pipe = mdp4_plane->pipe; | 140 | enum mdp4_pipe pipe = mdp4_plane->pipe; |
139 | uint32_t iova = msm_framebuffer_iova(fb, mdp4_kms->id, 0); | ||
140 | |||
141 | DBG("%s: set_scanout: %08x (%u)", mdp4_plane->name, | ||
142 | iova, fb->pitches[0]); | ||
143 | 141 | ||
144 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe), | 142 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_STRIDE_A(pipe), |
145 | MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) | | 143 | MDP4_PIPE_SRC_STRIDE_A_P0(fb->pitches[0]) | |
@@ -149,11 +147,45 @@ static void mdp4_plane_set_scanout(struct drm_plane *plane, | |||
149 | MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) | | 147 | MDP4_PIPE_SRC_STRIDE_B_P2(fb->pitches[2]) | |
150 | MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); | 148 | MDP4_PIPE_SRC_STRIDE_B_P3(fb->pitches[3])); |
151 | 149 | ||
152 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), iova); | 150 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP0_BASE(pipe), |
151 | msm_framebuffer_iova(fb, mdp4_kms->id, 0)); | ||
152 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP1_BASE(pipe), | ||
153 | msm_framebuffer_iova(fb, mdp4_kms->id, 1)); | ||
154 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP2_BASE(pipe), | ||
155 | msm_framebuffer_iova(fb, mdp4_kms->id, 2)); | ||
156 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRCP3_BASE(pipe), | ||
157 | msm_framebuffer_iova(fb, mdp4_kms->id, 3)); | ||
153 | 158 | ||
154 | plane->fb = fb; | 159 | plane->fb = fb; |
155 | } | 160 | } |
156 | 161 | ||
162 | static void mdp4_write_csc_config(struct mdp4_kms *mdp4_kms, | ||
163 | enum mdp4_pipe pipe, struct csc_cfg *csc) | ||
164 | { | ||
165 | int i; | ||
166 | |||
167 | for (i = 0; i < ARRAY_SIZE(csc->matrix); i++) { | ||
168 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_MV(pipe, i), | ||
169 | csc->matrix[i]); | ||
170 | } | ||
171 | |||
172 | for (i = 0; i < ARRAY_SIZE(csc->post_bias) ; i++) { | ||
173 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_BV(pipe, i), | ||
174 | csc->pre_bias[i]); | ||
175 | |||
176 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_BV(pipe, i), | ||
177 | csc->post_bias[i]); | ||
178 | } | ||
179 | |||
180 | for (i = 0; i < ARRAY_SIZE(csc->post_clamp) ; i++) { | ||
181 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_PRE_LV(pipe, i), | ||
182 | csc->pre_clamp[i]); | ||
183 | |||
184 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_CSC_POST_LV(pipe, i), | ||
185 | csc->post_clamp[i]); | ||
186 | } | ||
187 | } | ||
188 | |||
157 | #define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 | 189 | #define MDP4_VG_PHASE_STEP_DEFAULT 0x20000000 |
158 | 190 | ||
159 | static int mdp4_plane_mode_set(struct drm_plane *plane, | 191 | static int mdp4_plane_mode_set(struct drm_plane *plane, |
@@ -163,6 +195,7 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
163 | uint32_t src_x, uint32_t src_y, | 195 | uint32_t src_x, uint32_t src_y, |
164 | uint32_t src_w, uint32_t src_h) | 196 | uint32_t src_w, uint32_t src_h) |
165 | { | 197 | { |
198 | struct drm_device *dev = plane->dev; | ||
166 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); | 199 | struct mdp4_plane *mdp4_plane = to_mdp4_plane(plane); |
167 | struct mdp4_kms *mdp4_kms = get_kms(plane); | 200 | struct mdp4_kms *mdp4_kms = get_kms(plane); |
168 | enum mdp4_pipe pipe = mdp4_plane->pipe; | 201 | enum mdp4_pipe pipe = mdp4_plane->pipe; |
@@ -186,14 +219,59 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
186 | fb->base.id, src_x, src_y, src_w, src_h, | 219 | fb->base.id, src_x, src_y, src_w, src_h, |
187 | crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h); | 220 | crtc->base.id, crtc_x, crtc_y, crtc_w, crtc_h); |
188 | 221 | ||
222 | format = to_mdp_format(msm_framebuffer_format(fb)); | ||
223 | |||
224 | if (src_w > (crtc_w * DOWN_SCALE_MAX)) { | ||
225 | dev_err(dev->dev, "Width down scaling exceeds limits!\n"); | ||
226 | return -ERANGE; | ||
227 | } | ||
228 | |||
229 | if (src_h > (crtc_h * DOWN_SCALE_MAX)) { | ||
230 | dev_err(dev->dev, "Height down scaling exceeds limits!\n"); | ||
231 | return -ERANGE; | ||
232 | } | ||
233 | |||
234 | if (crtc_w > (src_w * UP_SCALE_MAX)) { | ||
235 | dev_err(dev->dev, "Width up scaling exceeds limits!\n"); | ||
236 | return -ERANGE; | ||
237 | } | ||
238 | |||
239 | if (crtc_h > (src_h * UP_SCALE_MAX)) { | ||
240 | dev_err(dev->dev, "Height up scaling exceeds limits!\n"); | ||
241 | return -ERANGE; | ||
242 | } | ||
243 | |||
189 | if (src_w != crtc_w) { | 244 | if (src_w != crtc_w) { |
245 | uint32_t sel_unit = SCALE_FIR; | ||
190 | op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN; | 246 | op_mode |= MDP4_PIPE_OP_MODE_SCALEX_EN; |
191 | /* TODO calc phasex_step */ | 247 | |
248 | if (MDP_FORMAT_IS_YUV(format)) { | ||
249 | if (crtc_w > src_w) | ||
250 | sel_unit = SCALE_PIXEL_RPT; | ||
251 | else if (crtc_w <= (src_w / 4)) | ||
252 | sel_unit = SCALE_MN_PHASE; | ||
253 | |||
254 | op_mode |= MDP4_PIPE_OP_MODE_SCALEX_UNIT_SEL(sel_unit); | ||
255 | phasex_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT, | ||
256 | src_w, crtc_w); | ||
257 | } | ||
192 | } | 258 | } |
193 | 259 | ||
194 | if (src_h != crtc_h) { | 260 | if (src_h != crtc_h) { |
261 | uint32_t sel_unit = SCALE_FIR; | ||
195 | op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN; | 262 | op_mode |= MDP4_PIPE_OP_MODE_SCALEY_EN; |
196 | /* TODO calc phasey_step */ | 263 | |
264 | if (MDP_FORMAT_IS_YUV(format)) { | ||
265 | |||
266 | if (crtc_h > src_h) | ||
267 | sel_unit = SCALE_PIXEL_RPT; | ||
268 | else if (crtc_h <= (src_h / 4)) | ||
269 | sel_unit = SCALE_MN_PHASE; | ||
270 | |||
271 | op_mode |= MDP4_PIPE_OP_MODE_SCALEY_UNIT_SEL(sel_unit); | ||
272 | phasey_step = mult_frac(MDP4_VG_PHASE_STEP_DEFAULT, | ||
273 | src_h, crtc_h); | ||
274 | } | ||
197 | } | 275 | } |
198 | 276 | ||
199 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe), | 277 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_SIZE(pipe), |
@@ -214,8 +292,6 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
214 | 292 | ||
215 | mdp4_plane_set_scanout(plane, fb); | 293 | mdp4_plane_set_scanout(plane, fb); |
216 | 294 | ||
217 | format = to_mdp_format(msm_framebuffer_format(fb)); | ||
218 | |||
219 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe), | 295 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_FORMAT(pipe), |
220 | MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | | 296 | MDP4_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | |
221 | MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | | 297 | MDP4_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | |
@@ -224,6 +300,8 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
224 | COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) | | 300 | COND(format->alpha_enable, MDP4_PIPE_SRC_FORMAT_ALPHA_ENABLE) | |
225 | MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | | 301 | MDP4_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | |
226 | MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | | 302 | MDP4_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | |
303 | MDP4_PIPE_SRC_FORMAT_FETCH_PLANES(format->fetch_type) | | ||
304 | MDP4_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample) | | ||
227 | COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT)); | 305 | COND(format->unpack_tight, MDP4_PIPE_SRC_FORMAT_UNPACK_TIGHT)); |
228 | 306 | ||
229 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe), | 307 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_SRC_UNPACK(pipe), |
@@ -232,6 +310,14 @@ static int mdp4_plane_mode_set(struct drm_plane *plane, | |||
232 | MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) | | 310 | MDP4_PIPE_SRC_UNPACK_ELEM2(format->unpack[2]) | |
233 | MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3])); | 311 | MDP4_PIPE_SRC_UNPACK_ELEM3(format->unpack[3])); |
234 | 312 | ||
313 | if (MDP_FORMAT_IS_YUV(format)) { | ||
314 | struct csc_cfg *csc = mdp_get_default_csc_cfg(CSC_YUV2RGB); | ||
315 | |||
316 | op_mode |= MDP4_PIPE_OP_MODE_SRC_YCBCR; | ||
317 | op_mode |= MDP4_PIPE_OP_MODE_CSC_EN; | ||
318 | mdp4_write_csc_config(mdp4_kms, pipe, csc); | ||
319 | } | ||
320 | |||
235 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode); | 321 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_OP_MODE(pipe), op_mode); |
236 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step); | 322 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEX_STEP(pipe), phasex_step); |
237 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step); | 323 | mdp4_write(mdp4_kms, REG_MDP4_PIPE_PHASEY_STEP(pipe), phasey_step); |