aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStephane Viau <sviau@codeaurora.org>2014-12-08 10:48:58 -0500
committerRob Clark <robdclark@gmail.com>2015-02-01 15:30:35 -0500
commitf8d9b5156e966e701cb17c623ffd6ebe35cc3157 (patch)
tree0e33d69578018f8eb3fbda70d8e8b50ff94f05b6
parent7ca12718b393a6b71fc62782a64737b5c9dc6d3c (diff)
drm/msm/mdp5: add NV12 support for MDP5
This change adds the NV12 format support for public planes. Signed-off-by: Stephane Viau <sviau@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c213
-rw-r--r--drivers/gpu/drm/msm/msm_fb.c2
2 files changed, 194 insertions, 21 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 0b2416e77d27..05cf9ab2a876 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -276,6 +276,155 @@ static void set_scanout_locked(struct drm_plane *plane,
276 plane->fb = fb; 276 plane->fb = fb;
277} 277}
278 278
279/* Note: mdp5_plane->pipe_lock must be locked */
280static void csc_disable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe)
281{
282 uint32_t value = mdp5_read(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe)) &
283 ~MDP5_PIPE_OP_MODE_CSC_1_EN;
284
285 mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), value);
286}
287
288/* Note: mdp5_plane->pipe_lock must be locked */
289static void csc_enable(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
290 struct csc_cfg *csc)
291{
292 uint32_t i, mode = 0; /* RGB, no CSC */
293 uint32_t *matrix;
294
295 if (unlikely(!csc))
296 return;
297
298 if ((csc->type == CSC_YUV2RGB) || (CSC_YUV2YUV == csc->type))
299 mode |= MDP5_PIPE_OP_MODE_CSC_SRC_DATA_FORMAT(DATA_FORMAT_YUV);
300 if ((csc->type == CSC_RGB2YUV) || (CSC_YUV2YUV == csc->type))
301 mode |= MDP5_PIPE_OP_MODE_CSC_DST_DATA_FORMAT(DATA_FORMAT_YUV);
302 mode |= MDP5_PIPE_OP_MODE_CSC_1_EN;
303 mdp5_write(mdp5_kms, REG_MDP5_PIPE_OP_MODE(pipe), mode);
304
305 matrix = csc->matrix;
306 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_0(pipe),
307 MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_11(matrix[0]) |
308 MDP5_PIPE_CSC_1_MATRIX_COEFF_0_COEFF_12(matrix[1]));
309 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_1(pipe),
310 MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_13(matrix[2]) |
311 MDP5_PIPE_CSC_1_MATRIX_COEFF_1_COEFF_21(matrix[3]));
312 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_2(pipe),
313 MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_22(matrix[4]) |
314 MDP5_PIPE_CSC_1_MATRIX_COEFF_2_COEFF_23(matrix[5]));
315 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_3(pipe),
316 MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_31(matrix[6]) |
317 MDP5_PIPE_CSC_1_MATRIX_COEFF_3_COEFF_32(matrix[7]));
318 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_MATRIX_COEFF_4(pipe),
319 MDP5_PIPE_CSC_1_MATRIX_COEFF_4_COEFF_33(matrix[8]));
320
321 for (i = 0; i < ARRAY_SIZE(csc->pre_bias); i++) {
322 uint32_t *pre_clamp = csc->pre_clamp;
323 uint32_t *post_clamp = csc->post_clamp;
324
325 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_CLAMP(pipe, i),
326 MDP5_PIPE_CSC_1_PRE_CLAMP_REG_HIGH(pre_clamp[2*i+1]) |
327 MDP5_PIPE_CSC_1_PRE_CLAMP_REG_LOW(pre_clamp[2*i]));
328
329 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_CLAMP(pipe, i),
330 MDP5_PIPE_CSC_1_POST_CLAMP_REG_HIGH(post_clamp[2*i+1]) |
331 MDP5_PIPE_CSC_1_POST_CLAMP_REG_LOW(post_clamp[2*i]));
332
333 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_PRE_BIAS(pipe, i),
334 MDP5_PIPE_CSC_1_PRE_BIAS_REG_VALUE(csc->pre_bias[i]));
335
336 mdp5_write(mdp5_kms, REG_MDP5_PIPE_CSC_1_POST_BIAS(pipe, i),
337 MDP5_PIPE_CSC_1_POST_BIAS_REG_VALUE(csc->post_bias[i]));
338 }
339}
340
341#define PHASE_STEP_SHIFT 21
342#define DOWN_SCALE_RATIO_MAX 32 /* 2^(26-21) */
343
344static int calc_phase_step(uint32_t src, uint32_t dst, uint32_t *out_phase)
345{
346 uint32_t unit;
347
348 if (src == 0 || dst == 0)
349 return -EINVAL;
350
351 /*
352 * PHASE_STEP_X/Y is coded on 26 bits (25:0),
353 * where 2^21 represents the unity "1" in fixed-point hardware design.
354 * This leaves 5 bits for the integer part (downscale case):
355 * -> maximum downscale ratio = 0b1_1111 = 31
356 */
357 if (src > (dst * DOWN_SCALE_RATIO_MAX))
358 return -EOVERFLOW;
359
360 unit = 1 << PHASE_STEP_SHIFT;
361 *out_phase = mult_frac(unit, src, dst);
362
363 return 0;
364}
365
366static int calc_scalex_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
367 uint32_t phasex_steps[2])
368{
369 uint32_t phasex_step;
370 unsigned int hsub;
371 int ret;
372
373 ret = calc_phase_step(src, dest, &phasex_step);
374 if (ret)
375 return ret;
376
377 hsub = drm_format_horz_chroma_subsampling(pixel_format);
378
379 phasex_steps[0] = phasex_step;
380 phasex_steps[1] = phasex_step / hsub;
381
382 return 0;
383}
384
385static int calc_scaley_steps(uint32_t pixel_format, uint32_t src, uint32_t dest,
386 uint32_t phasey_steps[2])
387{
388 uint32_t phasey_step;
389 unsigned int vsub;
390 int ret;
391
392 ret = calc_phase_step(src, dest, &phasey_step);
393 if (ret)
394 return ret;
395
396 vsub = drm_format_vert_chroma_subsampling(pixel_format);
397
398 phasey_steps[0] = phasey_step;
399 phasey_steps[1] = phasey_step / vsub;
400
401 return 0;
402}
403
404static uint32_t get_scalex_config(uint32_t src, uint32_t dest)
405{
406 uint32_t filter;
407
408 filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
409
410 return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
411 MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(filter) |
412 MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(filter) |
413 MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(filter);
414}
415
416static uint32_t get_scaley_config(uint32_t src, uint32_t dest)
417{
418 uint32_t filter;
419
420 filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
421
422 return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
423 MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(filter) |
424 MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(filter) |
425 MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(filter);
426}
427
279static int mdp5_plane_mode_set(struct drm_plane *plane, 428static int mdp5_plane_mode_set(struct drm_plane *plane,
280 struct drm_crtc *crtc, struct drm_framebuffer *fb, 429 struct drm_crtc *crtc, struct drm_framebuffer *fb,
281 int crtc_x, int crtc_y, 430 int crtc_x, int crtc_y,
@@ -285,11 +434,14 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
285{ 434{
286 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane); 435 struct mdp5_plane *mdp5_plane = to_mdp5_plane(plane);
287 struct mdp5_kms *mdp5_kms = get_kms(plane); 436 struct mdp5_kms *mdp5_kms = get_kms(plane);
437 struct device *dev = mdp5_kms->dev->dev;
288 enum mdp5_pipe pipe = mdp5_plane->pipe; 438 enum mdp5_pipe pipe = mdp5_plane->pipe;
289 const struct mdp_format *format; 439 const struct mdp_format *format;
290 uint32_t nplanes, config = 0; 440 uint32_t nplanes, config = 0;
291 uint32_t phasex_step = 0, phasey_step = 0; 441 /* below array -> index 0: comp 0/3 ; index 1: comp 1/2 */
442 uint32_t phasex_step[2] = {0,}, phasey_step[2] = {0,};
292 uint32_t hdecm = 0, vdecm = 0; 443 uint32_t hdecm = 0, vdecm = 0;
444 uint32_t pix_format;
293 unsigned long flags; 445 unsigned long flags;
294 int ret; 446 int ret;
295 447
@@ -299,6 +451,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
299 if (WARN_ON(nplanes > pipe2nclients(pipe))) 451 if (WARN_ON(nplanes > pipe2nclients(pipe)))
300 return -EINVAL; 452 return -EINVAL;
301 453
454 format = to_mdp_format(msm_framebuffer_format(fb));
455 pix_format = format->base.pixel_format;
456
302 /* src values are in Q16 fixed point, convert to integer: */ 457 /* src values are in Q16 fixed point, convert to integer: */
303 src_x = src_x >> 16; 458 src_x = src_x >> 16;
304 src_y = src_y >> 16; 459 src_y = src_y >> 16;
@@ -323,14 +478,28 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
323 */ 478 */
324 mdp5_smp_configure(mdp5_kms->smp, pipe); 479 mdp5_smp_configure(mdp5_kms->smp, pipe);
325 480
326 if (src_w != crtc_w) { 481 /* SCALE is used to both scale and up-sample chroma components */
327 config |= MDP5_PIPE_SCALE_CONFIG_SCALEX_EN; 482
328 /* TODO calc phasex_step, hdecm */ 483 if ((src_w != crtc_w) || MDP_FORMAT_IS_YUV(format)) {
484 /* TODO calc hdecm */
485 ret = calc_scalex_steps(pix_format, src_w, crtc_w, phasex_step);
486 if (ret) {
487 dev_err(dev, "X scaling (%d -> %d) failed: %d\n",
488 src_w, crtc_w, ret);
489 return ret;
490 }
491 config |= get_scalex_config(src_w, crtc_w);
329 } 492 }
330 493
331 if (src_h != crtc_h) { 494 if ((src_h != crtc_h) || MDP_FORMAT_IS_YUV(format)) {
332 config |= MDP5_PIPE_SCALE_CONFIG_SCALEY_EN; 495 /* TODO calc vdecm */
333 /* TODO calc phasey_step, vdecm */ 496 ret = calc_scaley_steps(pix_format, src_h, crtc_h, phasey_step);
497 if (ret) {
498 dev_err(dev, "Y scaling (%d -> %d) failed: %d\n",
499 src_h, crtc_h, ret);
500 return ret;
501 }
502 config |= get_scaley_config(src_h, crtc_h);
334 } 503 }
335 504
336 spin_lock_irqsave(&mdp5_plane->pipe_lock, flags); 505 spin_lock_irqsave(&mdp5_plane->pipe_lock, flags);
@@ -355,8 +524,6 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
355 MDP5_PIPE_OUT_XY_X(crtc_x) | 524 MDP5_PIPE_OUT_XY_X(crtc_x) |
356 MDP5_PIPE_OUT_XY_Y(crtc_y)); 525 MDP5_PIPE_OUT_XY_Y(crtc_y));
357 526
358 format = to_mdp_format(msm_framebuffer_format(fb));
359
360 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe), 527 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_FORMAT(pipe),
361 MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) | 528 MDP5_PIPE_SRC_FORMAT_A_BPC(format->bpc_a) |
362 MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) | 529 MDP5_PIPE_SRC_FORMAT_R_BPC(format->bpc_r) |
@@ -366,8 +533,8 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
366 MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) | 533 MDP5_PIPE_SRC_FORMAT_CPP(format->cpp - 1) |
367 MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) | 534 MDP5_PIPE_SRC_FORMAT_UNPACK_COUNT(format->unpack_count - 1) |
368 COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) | 535 COND(format->unpack_tight, MDP5_PIPE_SRC_FORMAT_UNPACK_TIGHT) |
369 MDP5_PIPE_SRC_FORMAT_NUM_PLANES(nplanes - 1) | 536 MDP5_PIPE_SRC_FORMAT_NUM_PLANES(format->fetch_type) |
370 MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(CHROMA_RGB)); 537 MDP5_PIPE_SRC_FORMAT_CHROMA_SAMP(format->chroma_sample));
371 538
372 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe), 539 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_UNPACK(pipe),
373 MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) | 540 MDP5_PIPE_SRC_UNPACK_ELEM0(format->unpack[0]) |
@@ -381,18 +548,24 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
381 /* not using secure mode: */ 548 /* not using secure mode: */
382 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0); 549 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
383 550
384 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), phasex_step); 551 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
385 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe), phasey_step); 552 phasex_step[0]);
553 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_Y(pipe),
554 phasey_step[0]);
555 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_X(pipe),
556 phasex_step[1]);
557 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CR_PHASE_STEP_Y(pipe),
558 phasey_step[1]);
386 mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe), 559 mdp5_write(mdp5_kms, REG_MDP5_PIPE_DECIMATION(pipe),
387 MDP5_PIPE_DECIMATION_VERT(vdecm) | 560 MDP5_PIPE_DECIMATION_VERT(vdecm) |
388 MDP5_PIPE_DECIMATION_HORZ(hdecm)); 561 MDP5_PIPE_DECIMATION_HORZ(hdecm));
389 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), 562 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_CONFIG(pipe), config);
390 MDP5_PIPE_SCALE_CONFIG_SCALEX_MIN_FILTER(SCALE_FILTER_NEAREST) | 563
391 MDP5_PIPE_SCALE_CONFIG_SCALEY_MIN_FILTER(SCALE_FILTER_NEAREST) | 564 if (MDP_FORMAT_IS_YUV(format))
392 MDP5_PIPE_SCALE_CONFIG_SCALEX_CR_FILTER(SCALE_FILTER_NEAREST) | 565 csc_enable(mdp5_kms, pipe,
393 MDP5_PIPE_SCALE_CONFIG_SCALEY_CR_FILTER(SCALE_FILTER_NEAREST) | 566 mdp_get_default_csc_cfg(CSC_YUV2RGB));
394 MDP5_PIPE_SCALE_CONFIG_SCALEX_MAX_FILTER(SCALE_FILTER_NEAREST) | 567 else
395 MDP5_PIPE_SCALE_CONFIG_SCALEY_MAX_FILTER(SCALE_FILTER_NEAREST)); 568 csc_disable(mdp5_kms, pipe);
396 569
397 set_scanout_locked(plane, fb); 570 set_scanout_locked(plane, fb);
398 571
diff --git a/drivers/gpu/drm/msm/msm_fb.c b/drivers/gpu/drm/msm/msm_fb.c
index d1a7a45091df..6b573e612f27 100644
--- a/drivers/gpu/drm/msm/msm_fb.c
+++ b/drivers/gpu/drm/msm/msm_fb.c
@@ -122,7 +122,7 @@ uint32_t msm_framebuffer_iova(struct drm_framebuffer *fb, int id, int plane)
122 struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb); 122 struct msm_framebuffer *msm_fb = to_msm_framebuffer(fb);
123 if (!msm_fb->planes[plane]) 123 if (!msm_fb->planes[plane])
124 return 0; 124 return 0;
125 return msm_gem_iova(msm_fb->planes[plane], id); 125 return msm_gem_iova(msm_fb->planes[plane], id) + fb->offsets[plane];
126} 126}
127 127
128struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane) 128struct drm_gem_object *msm_framebuffer_bo(struct drm_framebuffer *fb, int plane)