aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm/msm
diff options
context:
space:
mode:
authorStephane Viau <sviau@codeaurora.org>2015-09-15 08:41:52 -0400
committerRob Clark <robdclark@gmail.com>2015-10-22 15:39:56 -0400
commit8e2930c6cfb45acc00da9bd6779f5fdd6ec4cb03 (patch)
treec158da4a58de9859079f768b0f37af029956e072 /drivers/gpu/drm/msm
parent95651cd926bfa37036d7011a65421ab0db1b4959 (diff)
drm/msm/mdp: Add Software Pixel Extension support
In order to produce an image, the scalar needs to be fed extra pixels. These top/bottom/left/right values depend on a various of factors, including resolution, scaling type, phase step and initial phase. Pixel Extension are programmed by hardware in most targets - and can be overwritten by software. For some targets (e.g.: msm8996), software *must* program those registers. In order to ease this computation, let's always use bilinear filters, which are easier to program from kernel. Eventually, all of these values will come down from user space for better quality. Signed-off-by: Stephane Viau <sviau@codeaurora.org> Signed-off-by: Rob Clark <robdclark@gmail.com>
Diffstat (limited to 'drivers/gpu/drm/msm')
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c158
-rw-r--r--drivers/gpu/drm/msm/mdp/mdp_kms.h1
2 files changed, 128 insertions, 31 deletions
diff --git a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
index 5a11fc41b394..d93185e6f18a 100644
--- a/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
+++ b/drivers/gpu/drm/msm/mdp/mdp5/mdp5_plane.c
@@ -548,40 +548,120 @@ static int calc_scaley_steps(struct drm_plane *plane,
548 return 0; 548 return 0;
549} 549}
550 550
551static uint32_t get_scale_config(enum mdp_chroma_samp_type chroma_sample, 551static uint32_t get_scale_config(const struct mdp_format *format,
552 uint32_t src, uint32_t dest, bool hor) 552 uint32_t src, uint32_t dst, bool horz)
553{ 553{
554 uint32_t y_filter = (src <= dest) ? SCALE_FILTER_CA : SCALE_FILTER_PCMN; 554 bool scaling = format->is_yuv ? true : (src != dst);
555 uint32_t y_a_filter = (src <= dest) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN; 555 uint32_t sub, pix_fmt = format->base.pixel_format;
556 uint32_t uv_filter = ((src / 2) <= dest) ? /* 2x upsample */ 556 uint32_t ya_filter, uv_filter;
557 SCALE_FILTER_BIL : SCALE_FILTER_PCMN; 557 bool yuv = format->is_yuv;
558 uint32_t value = 0; 558
559 559 if (!scaling)
560 if (chroma_sample == CHROMA_420 || chroma_sample == CHROMA_H2V1) { 560 return 0;
561 if (hor) 561
562 value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN | 562 if (yuv) {
563 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_filter) | 563 sub = horz ? drm_format_horz_chroma_subsampling(pix_fmt) :
564 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter) | 564 drm_format_vert_chroma_subsampling(pix_fmt);
565 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter); 565 uv_filter = ((src / sub) <= dst) ?
566 else 566 SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
567 value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN | 567 }
568 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_filter) | 568 ya_filter = (src <= dst) ? SCALE_FILTER_BIL : SCALE_FILTER_PCMN;
569 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter) | 569
570 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter); 570 if (horz)
571 } else if (src != dest) { 571 return MDP5_PIPE_SCALE_CONFIG_SCALEX_EN |
572 if (hor) 572 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(ya_filter) |
573 value = MDP5_PIPE_SCALE_CONFIG_SCALEX_EN | 573 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(ya_filter) |
574 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_0(y_a_filter) | 574 COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_1_2(uv_filter));
575 MDP5_PIPE_SCALE_CONFIG_SCALEX_FILTER_COMP_3(y_a_filter); 575 else
576 else 576 return MDP5_PIPE_SCALE_CONFIG_SCALEY_EN |
577 value = MDP5_PIPE_SCALE_CONFIG_SCALEY_EN | 577 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(ya_filter) |
578 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_0(y_a_filter) | 578 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(ya_filter) |
579 MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_3(y_a_filter); 579 COND(yuv, MDP5_PIPE_SCALE_CONFIG_SCALEY_FILTER_COMP_1_2(uv_filter));
580}
581
582static void calc_pixel_ext(const struct mdp_format *format,
583 uint32_t src, uint32_t dst, uint32_t phase_step[2],
584 int pix_ext_edge1[COMP_MAX], int pix_ext_edge2[COMP_MAX],
585 bool horz)
586{
587 bool scaling = format->is_yuv ? true : (src != dst);
588 int i;
589
590 /*
591 * Note:
592 * We assume here that:
593 * 1. PCMN filter is used for downscale
594 * 2. bilinear filter is used for upscale
595 * 3. we are in a single pipe configuration
596 */
597
598 for (i = 0; i < COMP_MAX; i++) {
599 pix_ext_edge1[i] = 0;
600 pix_ext_edge2[i] = scaling ? 1 : 0;
580 } 601 }
602}
581 603
582 return value; 604static void mdp5_write_pixel_ext(struct mdp5_kms *mdp5_kms, enum mdp5_pipe pipe,
605 const struct mdp_format *format,
606 uint32_t src_w, int pe_left[COMP_MAX], int pe_right[COMP_MAX],
607 uint32_t src_h, int pe_top[COMP_MAX], int pe_bottom[COMP_MAX])
608{
609 uint32_t pix_fmt = format->base.pixel_format;
610 uint32_t lr, tb, req;
611 int i;
612
613 for (i = 0; i < COMP_MAX; i++) {
614 uint32_t roi_w = src_w;
615 uint32_t roi_h = src_h;
616
617 if (format->is_yuv && i == COMP_1_2) {
618 roi_w /= drm_format_horz_chroma_subsampling(pix_fmt);
619 roi_h /= drm_format_vert_chroma_subsampling(pix_fmt);
620 }
621
622 lr = (pe_left[i] >= 0) ?
623 MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT(pe_left[i]) :
624 MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF(pe_left[i]);
625
626 lr |= (pe_right[i] >= 0) ?
627 MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT(pe_right[i]) :
628 MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF(pe_right[i]);
629
630 tb = (pe_top[i] >= 0) ?
631 MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT(pe_top[i]) :
632 MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF(pe_top[i]);
633
634 tb |= (pe_bottom[i] >= 0) ?
635 MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT(pe_bottom[i]) :
636 MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF(pe_bottom[i]);
637
638 req = MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT(roi_w +
639 pe_left[i] + pe_right[i]);
640
641 req |= MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM(roi_h +
642 pe_top[i] + pe_bottom[i]);
643
644 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_LR(pipe, i), lr);
645 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_TB(pipe, i), tb);
646 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS(pipe, i), req);
647
648 DBG("comp-%d (L/R): rpt=%d/%d, ovf=%d/%d, req=%d", i,
649 FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_RPT),
650 FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_RPT),
651 FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_LEFT_OVF),
652 FIELD(lr, MDP5_PIPE_SW_PIX_EXT_LR_RIGHT_OVF),
653 FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_LEFT_RIGHT));
654
655 DBG("comp-%d (T/B): rpt=%d/%d, ovf=%d/%d, req=%d", i,
656 FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_RPT),
657 FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_RPT),
658 FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_TOP_OVF),
659 FIELD(tb, MDP5_PIPE_SW_PIX_EXT_TB_BOTTOM_OVF),
660 FIELD(req, MDP5_PIPE_SW_PIX_EXT_REQ_PIXELS_TOP_BOTTOM));
661 }
583} 662}
584 663
664
585static int mdp5_plane_mode_set(struct drm_plane *plane, 665static int mdp5_plane_mode_set(struct drm_plane *plane,
586 struct drm_crtc *crtc, struct drm_framebuffer *fb, 666 struct drm_crtc *crtc, struct drm_framebuffer *fb,
587 int crtc_x, int crtc_y, 667 int crtc_x, int crtc_y,
@@ -596,6 +676,9 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
596 const struct mdp_format *format; 676 const struct mdp_format *format;
597 uint32_t nplanes, config = 0; 677 uint32_t nplanes, config = 0;
598 uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,}; 678 uint32_t phasex_step[COMP_MAX] = {0,}, phasey_step[COMP_MAX] = {0,};
679 bool pe = mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT;
680 int pe_left[COMP_MAX], pe_right[COMP_MAX];
681 int pe_top[COMP_MAX], pe_bottom[COMP_MAX];
599 uint32_t hdecm = 0, vdecm = 0; 682 uint32_t hdecm = 0, vdecm = 0;
600 uint32_t pix_format; 683 uint32_t pix_format;
601 bool vflip, hflip; 684 bool vflip, hflip;
@@ -643,11 +726,18 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
643 if (ret) 726 if (ret)
644 return ret; 727 return ret;
645 728
729 if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT) {
730 calc_pixel_ext(format, src_w, crtc_w, phasex_step,
731 pe_left, pe_right, true);
732 calc_pixel_ext(format, src_h, crtc_h, phasey_step,
733 pe_top, pe_bottom, false);
734 }
735
646 /* TODO calc hdecm, vdecm */ 736 /* TODO calc hdecm, vdecm */
647 737
648 /* SCALE is used to both scale and up-sample chroma components */ 738 /* SCALE is used to both scale and up-sample chroma components */
649 config |= get_scale_config(format->chroma_sample, src_w, crtc_w, true); 739 config |= get_scale_config(format, src_w, crtc_w, true);
650 config |= get_scale_config(format->chroma_sample, src_h, crtc_h, false); 740 config |= get_scale_config(format, src_h, crtc_h, false);
651 DBG("scale config = %x", config); 741 DBG("scale config = %x", config);
652 742
653 hflip = !!(pstate->rotation & BIT(DRM_REFLECT_X)); 743 hflip = !!(pstate->rotation & BIT(DRM_REFLECT_X));
@@ -696,11 +786,17 @@ static int mdp5_plane_mode_set(struct drm_plane *plane,
696 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe), 786 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_OP_MODE(pipe),
697 (hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) | 787 (hflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_LR : 0) |
698 (vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) | 788 (vflip ? MDP5_PIPE_SRC_OP_MODE_FLIP_UD : 0) |
789 COND(pe, MDP5_PIPE_SRC_OP_MODE_SW_PIX_EXT_OVERRIDE) |
699 MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS)); 790 MDP5_PIPE_SRC_OP_MODE_BWC(BWC_LOSSLESS));
700 791
701 /* not using secure mode: */ 792 /* not using secure mode: */
702 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0); 793 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SRC_ADDR_SW_STATUS(pipe), 0);
703 794
795 if (mdp5_plane->caps & MDP_PIPE_CAP_SW_PIX_EXT)
796 mdp5_write_pixel_ext(mdp5_kms, pipe, format,
797 src_w, pe_left, pe_right,
798 src_h, pe_top, pe_bottom);
799
704 if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) { 800 if (mdp5_plane->caps & MDP_PIPE_CAP_SCALE) {
705 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe), 801 mdp5_write(mdp5_kms, REG_MDP5_PIPE_SCALE_PHASE_STEP_X(pipe),
706 phasex_step[COMP_0]); 802 phasex_step[COMP_0]);
diff --git a/drivers/gpu/drm/msm/mdp/mdp_kms.h b/drivers/gpu/drm/msm/mdp/mdp_kms.h
index 46a94e7d50e2..0af2a541171d 100644
--- a/drivers/gpu/drm/msm/mdp/mdp_kms.h
+++ b/drivers/gpu/drm/msm/mdp/mdp_kms.h
@@ -106,6 +106,7 @@ const struct msm_format *mdp_get_format(struct msm_kms *kms, uint32_t format);
106#define MDP_PIPE_CAP_SCALE BIT(2) 106#define MDP_PIPE_CAP_SCALE BIT(2)
107#define MDP_PIPE_CAP_CSC BIT(3) 107#define MDP_PIPE_CAP_CSC BIT(3)
108#define MDP_PIPE_CAP_DECIMATION BIT(4) 108#define MDP_PIPE_CAP_DECIMATION BIT(4)
109#define MDP_PIPE_CAP_SW_PIX_EXT BIT(5)
109 110
110static inline bool pipe_supports_yuv(uint32_t pipe_caps) 111static inline bool pipe_supports_yuv(uint32_t pipe_caps)
111{ 112{