lkml.org 
[lkml]   [2011]   [Mar]   [18]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 20/20] video: msm: Add support for MDP 3.1 (qsd8k)
    Date
    Includes support for the PPP which does scale, rotate, blend,
    color-convert , etc.

    Authors:
    Dima Zavin <dima@android.com>
    Rebecca Schultz Zavin <rebecca@android.com>
    Colin Cross <ccross@android.com>

    Signed-off-by: Carl Vanderlip <carlv@codeaurora.org>
    ---
    arch/arm/mach-msm/Kconfig | 7 +-
    drivers/video/msm/Makefile | 1 +
    drivers/video/msm/mdp.c | 114 ++++++++++---
    drivers/video/msm/mdp_csc_table.h | 68 ++++++++
    drivers/video/msm/mdp_hw.h | 140 ++++++++++++----
    drivers/video/msm/mdp_ppp.c | 117 ++++++++++++-
    drivers/video/msm/mdp_ppp.h | 20 +++
    drivers/video/msm/mdp_ppp31.c | 335 +++++++++++++++++++++++++++++++++++++
    8 files changed, 731 insertions(+), 71 deletions(-)
    create mode 100644 drivers/video/msm/mdp_ppp31.c

    diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
    index d6e75c3..83c4838 100644
    --- a/arch/arm/mach-msm/Kconfig
    +++ b/arch/arm/mach-msm/Kconfig
    @@ -13,6 +13,7 @@ config ARCH_MSM7X00A
    select CPU_V6
    select MSM_PROC_COMM
    select HAS_MSM_DEBUG_UART_PHYS
    + select MSM_MDP22

    config ARCH_MSM7X30
    bool "MSM7x30"
    @@ -35,6 +36,7 @@ config ARCH_QSD8X50
    select MSM_GPIOMUX
    select MSM_PROC_COMM
    select HAS_MSM_DEBUG_UART_PHYS
    + select MSM_MDP31

    config ARCH_MSM8X60
    bool "MSM8X60"
    @@ -78,8 +80,9 @@ config MSM_VIC

    config MSM_MDP22
    bool
    - depends on ARCH_MSM7X00A
    - default y
    +
    +config MSM_MDP31
    + bool

    menu "Qualcomm MSM Board Type"

    diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
    index 0666aef..b0a07d1 100644
    --- a/drivers/video/msm/Makefile
    +++ b/drivers/video/msm/Makefile
    @@ -8,6 +8,7 @@ obj-y := msm_fb.o
    obj-y += mdp.o mdp_ppp.o

    obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
    +obj-$(CONFIG_MSM_MDP31) += mdp_ppp31.o

    # MDDI interface
    #
    diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
    index 49d956a..057b6fa 100644
    --- a/drivers/video/msm/mdp.c
    +++ b/drivers/video/msm/mdp.c
    @@ -240,15 +240,16 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,

    dma2_cfg |= DMA_DITHER_EN;

    + /* 666 18BPP */
    + dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
    +
    +#ifdef CONFIG_MSM_MDP22
    /* setup size, address, and stride */
    mdp_writel(mdp, (height << 16) | (width),
    MDP_CMD_DEBUG_ACCESS_BASE + 0x0184);
    mdp_writel(mdp, addr, MDP_CMD_DEBUG_ACCESS_BASE + 0x0188);
    mdp_writel(mdp, stride, MDP_CMD_DEBUG_ACCESS_BASE + 0x018C);

    - /* 666 18BPP */
    - dma2_cfg |= DMA_DSTC0G_6BITS | DMA_DSTC1B_6BITS | DMA_DSTC2R_6BITS;
    -
    /* set y & x offset and MDDI transaction parameters */
    mdp_writel(mdp, (y << 16) | (x), MDP_CMD_DEBUG_ACCESS_BASE + 0x0194);
    mdp_writel(mdp, ld_param, MDP_CMD_DEBUG_ACCESS_BASE + 0x01a0);
    @@ -259,6 +260,21 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,

    /* start DMA2 */
    mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0044);
    +#else
    + /* setup size, address, and stride */
    + mdp_writel(mdp, (height << 16) | (width), MDP_DMA_P_SIZE);
    + mdp_writel(mdp, addr, MDP_DMA_P_IBUF_ADDR);
    + mdp_writel(mdp, stride, MDP_DMA_P_IBUF_Y_STRIDE);
    +
    + /* set y & x offset and MDDI transaction parameters */
    + mdp_writel(mdp, (y << 16) | (x), MDP_DMA_P_OUT_XY);
    + mdp_writel(mdp, ld_param, MDP_MDDI_PARAM_WR_SEL);
    + mdp_writel(mdp, (MDDI_VDO_PACKET_DESC << 16) | MDDI_VDO_PACKET_PRIM,
    + MDP_MDDI_PARAM);
    +
    + mdp_writel(mdp, dma2_cfg, MDP_DMA_P_CONFIG);
    + mdp_writel(mdp, 0, MDP_DMA_P_START);
    +#endif
    }

    void mdp_dma(struct mdp_device *mdp_dev, uint32_t addr, uint32_t stride,
    @@ -353,10 +369,21 @@ int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
    format = DMA_IBUF_FORMAT_RGB565;
    pack_pattern = DMA_PACK_PATTERN_RGB;
    break;
    +#ifdef CONFIG_MSM_MDP22
    case 24:
    case 32:
    format = DMA_IBUF_FORMAT_RGB888_OR_ARGB8888;
    break;
    +#else
    + case 24:
    + format = DMA_IBUF_FORMAT_RGB888;
    + pack_pattern = DMA_PACK_PATTERN_BGR;
    + break;
    + case 32:
    + format = DMA_IBUF_FORMAT_XRGB8888;
    + pack_pattern = DMA_PACK_PATTERN_BGR;
    + break;
    +#endif
    default:
    return -EINVAL;
    }
    @@ -392,6 +419,51 @@ int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
    return 0;
    }

    +#ifndef CONFIG_MSM_MDP31
    +static int mdp_blit_tiles(struct mdp_device *mdp_dev, struct mdp_blit_req *req,
    + struct file *src_file, struct file *dst_file)
    +{
    + int ret;
    + if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
    + req->alpha != MDP_ALPHA_NOP ||
    + HAS_ALPHA(req->src.format)) &&
    + (req->flags & MDP_ROT_90 &&
    + req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
    + int i;
    + struct mdp_info *mdp = container_of(mdp_dev,
    + struct mdp_info, mdp_dev);
    + unsigned long src_start = 0, src_len = 0;
    + unsigned long dst_start = 0, dst_len = 0;
    + unsigned int tiles = req->dst_rect.h / 16;
    + unsigned int remainder = req->dst_rect.h % 16;
    + req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
    + req->dst_rect.h = 16;
    + for (i = 0; i < tiles; i++) {
    + ret = mdp_blit_and_wait(mdp, req,
    + src_file, src_start, src_len,
    + dst_file, dst_start, dst_len);
    + if (ret)
    + return 1;
    + req->dst_rect.y += 16;
    + req->src_rect.x += req->src_rect.w;
    + }
    + if (!remainder)
    + return 1;
    + req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
    + req->dst_rect.h = remainder;
    + }
    + return 0;
    +
    +}
    +#else
    +static int mdp_blit_tiles(struct mdp_device *mdp_dev, struct mdp_blit_req *req,
    + struct file *src_file, struct file *dst_file)
    +{
    + return 0;
    +}
    +#endif
    +
    +
    int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
    struct mdp_blit_req *req)
    {
    @@ -427,30 +499,12 @@ int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,

    /* transp_masking unimplemented */
    req->transp_mask = MDP_TRANSP_NOP;
    - if (unlikely((req->transp_mask != MDP_TRANSP_NOP ||
    - req->alpha != MDP_ALPHA_NOP ||
    - HAS_ALPHA(req->src.format)) &&
    - (req->flags & MDP_ROT_90 &&
    - req->dst_rect.w <= 16 && req->dst_rect.h >= 16))) {
    - int i;
    - unsigned int tiles = req->dst_rect.h / 16;
    - unsigned int remainder = req->dst_rect.h % 16;
    - req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
    - req->dst_rect.h = 16;
    - for (i = 0; i < tiles; i++) {
    - ret = mdp_blit_and_wait(mdp, req,
    - src_file, src_start, src_len,
    - dst_file, dst_start, dst_len);
    - if (ret)
    - goto end;
    - req->dst_rect.y += 16;
    - req->src_rect.x += req->src_rect.w;
    - }
    - if (!remainder)
    - goto end;
    - req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
    - req->dst_rect.h = remainder;
    +
    + if (mdp_blit_tiles(mdp_dev, req, src_file, dst_file)) {
    + ret = 1;
    + goto end;
    }
    +
    ret = mdp_blit_and_wait(mdp, req,
    src_file, src_start, src_len,
    dst_file, dst_start, dst_len);
    @@ -564,12 +618,14 @@ void mdp_hw_init(struct mdp_info *mdp)
    mdp_writel(mdp, 1, 0x60);
    mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);

    +#ifndef CONFIG_MSM_MDP22
    /* disable lcdc */
    mdp_writel(mdp, 0, MDP_LCDC_CTL);
    /* enable auto clock gating for all blocks by default */
    mdp_writel(mdp, 0xffffffff, MDP_CGC_EN);
    /* reset color/gamma correct parms */
    mdp_writel(mdp, 0, MDP_DMA_P_COLOR_CORRECT_CONFIG);
    +#endif

    mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
    mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
    @@ -607,9 +663,13 @@ void mdp_hw_init(struct mdp_info *mdp)
    for (n = 0; n < ARRAY_SIZE(csc_matrix_config_table); n++)
    mdp_writel(mdp, csc_matrix_config_table[n].val,
    csc_matrix_config_table[n].reg);
    -#ifdef CONFIG_MSM_MDP22
    +#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP22)
    mdp_ppp_init_scale(mdp);
    #endif
    +
    +#ifndef CONFIG_MSM_MDP31
    + mdp_writel(mdp, 0x04000400, MDP_COMMAND_CONFIG);
    +#endif
    }

    int mdp_probe(struct platform_device *pdev)
    diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
    index 6eb0fc3..81abc5d 100644
    --- a/drivers/video/msm/mdp_csc_table.h
    +++ b/drivers/video/msm/mdp_csc_table.h
    @@ -39,6 +39,7 @@ static struct {
    { MDP_CSC_PRMVn(7), 0x409 },
    { MDP_CSC_PRMVn(8), 0x0 },

    +#ifndef CONFIG_MSM_MDP31
    /* For MDP 2.2/3.0 */

    /* primary limit vector */
    @@ -52,6 +53,73 @@ static struct {
    { MDP_CSC_PBVn(1), 0x80 },
    { MDP_CSC_PBVn(2), 0x80 },

    +#else /* CONFIG_MSM_MDP31 */
    +
    + /* limit vectors configuration */
    + /* rgb -> yuv (set1) pre-limit vector */
    + { MDP_PPP_CSC_PRE_LV1n(0), 0x10 },
    + { MDP_PPP_CSC_PRE_LV1n(1), 0xeb },
    + { MDP_PPP_CSC_PRE_LV1n(2), 0x10 },
    + { MDP_PPP_CSC_PRE_LV1n(3), 0xf0 },
    + { MDP_PPP_CSC_PRE_LV1n(4), 0x10 },
    + { MDP_PPP_CSC_PRE_LV1n(5), 0xf0 },
    +
    + /* rgb -> yuv (set1) post-limit vector */
    + { MDP_PPP_CSC_POST_LV1n(0), 0x0 },
    + { MDP_PPP_CSC_POST_LV1n(1), 0xff },
    + { MDP_PPP_CSC_POST_LV1n(2), 0x0 },
    + { MDP_PPP_CSC_POST_LV1n(3), 0xff },
    + { MDP_PPP_CSC_POST_LV1n(4), 0x0 },
    + { MDP_PPP_CSC_POST_LV1n(5), 0xff },
    +
    + /* yuv -> rgb (set2) pre-limit vector */
    + { MDP_PPP_CSC_PRE_LV2n(0), 0x0 },
    + { MDP_PPP_CSC_PRE_LV2n(1), 0xff },
    + { MDP_PPP_CSC_PRE_LV2n(2), 0x0 },
    + { MDP_PPP_CSC_PRE_LV2n(3), 0xff },
    + { MDP_PPP_CSC_PRE_LV2n(4), 0x0 },
    + { MDP_PPP_CSC_PRE_LV2n(5), 0xff },
    +
    + /* yuv -> rgb (set2) post-limit vector */
    + { MDP_PPP_CSC_POST_LV2n(0), 0x10 },
    + { MDP_PPP_CSC_POST_LV2n(1), 0xeb },
    + { MDP_PPP_CSC_POST_LV2n(2), 0x10 },
    + { MDP_PPP_CSC_POST_LV2n(3), 0xf0 },
    + { MDP_PPP_CSC_POST_LV2n(4), 0x10 },
    + { MDP_PPP_CSC_POST_LV2n(5), 0xf0 },
    +
    + /* bias vectors configuration */
    +
    + /* XXX: why is set2 used for rgb->yuv, but set1 */
    + /* used for yuv -> rgb??!? Seems to be the reverse of the
    + * other vectors. */
    +
    + /* RGB -> YUV pre-bias vector... */
    + { MDP_PPP_CSC_PRE_BV2n(0), 0 },
    + { MDP_PPP_CSC_PRE_BV2n(1), 0 },
    + { MDP_PPP_CSC_PRE_BV2n(2), 0 },
    +
    + /* RGB -> YUV post-bias vector */
    + { MDP_PPP_CSC_POST_BV2n(0), 0x10 },
    + { MDP_PPP_CSC_POST_BV2n(1), 0x80 },
    + { MDP_PPP_CSC_POST_BV2n(2), 0x80 },
    +
    + /* YUV -> RGB pre-bias vector... */
    + { MDP_PPP_CSC_PRE_BV1n(0), 0x1f0 },
    + { MDP_PPP_CSC_PRE_BV1n(1), 0x180 },
    + { MDP_PPP_CSC_PRE_BV1n(2), 0x180 },
    +
    + /* YUV -> RGB post-bias vector */
    + { MDP_PPP_CSC_POST_BV1n(0), 0 },
    + { MDP_PPP_CSC_POST_BV1n(1), 0 },
    + { MDP_PPP_CSC_POST_BV1n(2), 0 },
    +
    + /* luma filter coefficients */
    + { MDP_PPP_DEINT_COEFFn(0), 0x3e0 },
    + { MDP_PPP_DEINT_COEFFn(1), 0x360 },
    + { MDP_PPP_DEINT_COEFFn(2), 0x120 },
    + { MDP_PPP_DEINT_COEFFn(3), 0x140 },
    +#endif
    };

    static struct {
    diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
    index 7485a9e..d20952c 100644
    --- a/drivers/video/msm/mdp_hw.h
    +++ b/drivers/video/msm/mdp_hw.h
    @@ -85,10 +85,18 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define MDP_DISPLAY_STATUS (0x00038)
    #define MDP_EBI2_LCD0 (0x0003c)
    #define MDP_EBI2_LCD1 (0x00040)
    +#define MDP_EBI2_PORTMAP_MODE (0x0005c)
    +
    +#ifndef CONFIG_MSM_MDP31
    #define MDP_DISPLAY0_ADDR (0x00054)
    #define MDP_DISPLAY1_ADDR (0x00058)
    -#define MDP_EBI2_PORTMAP_MODE (0x0005c)
    #define MDP_PPP_CMD_MODE (0x00060)
    +#else
    +#define MDP_DISPLAY0_ADDR (0x10000)
    +#define MDP_DISPLAY1_ADDR (0x10004)
    +#define MDP_PPP_CMD_MODE (0x10060)
    +#endif
    +
    #define MDP_TV_OUT_STATUS (0x00064)
    #define MDP_HW_VERSION (0x00070)
    #define MDP_SW_RESET (0x00074)
    @@ -98,6 +106,8 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define MDP_SECONDARY_VSYNC_OUT_CTRL (0x00084)
    #define MDP_EXTERNAL_VSYNC_OUT_CTRL (0x00088)
    #define MDP_VSYNC_CTRL (0x0008c)
    +#define MDP_MDDI_PARAM_WR_SEL (0x00090)
    +#define MDP_MDDI_PARAM (0x00094)
    #define MDP_CGC_EN (0x00100)
    #define MDP_CMD_STATUS (0x10008)
    #define MDP_PROFILE_EN (0x10010)
    @@ -144,6 +154,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define MDP_FULL_BYPASS_WORD35 (0x1018c)
    #define MDP_FULL_BYPASS_WORD37 (0x10194)
    #define MDP_FULL_BYPASS_WORD39 (0x1019c)
    +#define MDP_PPP_OUT_XY (0x1019c)
    #define MDP_FULL_BYPASS_WORD40 (0x101a0)
    #define MDP_FULL_BYPASS_WORD41 (0x101a4)
    #define MDP_FULL_BYPASS_WORD43 (0x101ac)
    @@ -166,11 +177,26 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define MDP_FULL_BYPASS_WORD61 (0x101f4)
    #define MDP_FULL_BYPASS_WORD62 (0x101f8)
    #define MDP_FULL_BYPASS_WORD63 (0x101fc)
    +
    +/* used only for MDP 3.1 */
    +#define MDP_PPP_SRC_XY (0x10200)
    +#define MDP_PPP_BG_XY (0x10204)
    +#define MDP_PPP_SRC_IMAGE_SIZE (0x10208)
    +#define MDP_PPP_BG_IMAGE_SIZE (0x1020c)
    +#define MDP_PPP_SCALE_CONFIG (0x10230)
    +#define MDP_PPP_CSC_CONFIG (0x10240)
    +#define MDP_PPP_BLEND_BG_ALPHA_SEL (0x70010)
    +
    #define MDP_TFETCH_TEST_MODE (0x20004)
    #define MDP_TFETCH_STATUS (0x20008)
    #define MDP_TFETCH_TILE_COUNT (0x20010)
    #define MDP_TFETCH_FETCH_COUNT (0x20014)
    #define MDP_TFETCH_CONSTANT_COLOR (0x20040)
    +#define MDP_BGTFETCH_TEST_MODE (0x28004)
    +#define MDP_BGTFETCH_STATUS (0x28008)
    +#define MDP_BGTFETCH_TILE_COUNT (0x28010)
    +#define MDP_BGTFETCH_FETCH_COUNT (0x28014)
    +#define MDP_BGTFETCH_CONSTANT_COLOR (0x28040)
    #define MDP_CSC_BYPASS (0x40004)
    #define MDP_SCALE_COEFF_LSB (0x5fffc)
    #define MDP_TV_OUT_CTL (0xc0000)
    @@ -222,39 +248,22 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define MDP_LCDC_DMA_IBUF_ADDR (0xe1008)
    #define MDP_LCDC_DMA_IBUF_Y_STRIDE (0xe100c)

    +#define MDP_PPP_SCALE_STATUS (0x50000)
    +#define MDP_PPP_BLEND_STATUS (0x70000)

    -#define MDP_DMA2_TERM 0x1
    -#define MDP_DMA3_TERM 0x2
    -#define MDP_PPP_TERM 0x3
    +/* MDP_SW_RESET */
    +#define MDP_PPP_SW_RESET (1<<4)

    /* MDP_INTR_ENABLE */
    -#define DL0_ROI_DONE (1<<0)
    -#define DL1_ROI_DONE (1<<1)
    -#define DL0_DMA2_TERM_DONE (1<<2)
    -#define DL1_DMA2_TERM_DONE (1<<3)
    -#define DL0_PPP_TERM_DONE (1<<4)
    -#define DL1_PPP_TERM_DONE (1<<5)
    -#define TV_OUT_DMA3_DONE (1<<6)
    -#define TV_ENC_UNDERRUN (1<<7)
    -#define DL0_FETCH_DONE (1<<11)
    -#define DL1_FETCH_DONE (1<<12)
    -
    -#define MDP_PPP_BUSY_STATUS (DL0_ROI_DONE| \
    - DL1_ROI_DONE| \
    - DL0_PPP_TERM_DONE| \
    - DL1_PPP_TERM_DONE)
    -
    -#define MDP_ANY_INTR_MASK (DL0_ROI_DONE| \
    - DL1_ROI_DONE| \
    - DL0_DMA2_TERM_DONE| \
    - DL1_DMA2_TERM_DONE| \
    - DL0_PPP_TERM_DONE| \
    - DL1_PPP_TERM_DONE| \
    - DL0_FETCH_DONE| \
    - DL1_FETCH_DONE| \
    - TV_ENC_UNDERRUN)
    +#define DL0_ROI_DONE (1<<0)
    +#define TV_OUT_DMA3_DONE (1<<6)
    +#define TV_ENC_UNDERRUN (1<<7)

    +#ifdef CONFIG_MSM_MDP22
    #define MDP_DMA_P_DONE (1 << 2)
    +#else /* CONFIG_MSM_MDP31 */
    +#define MDP_DMA_P_DONE (1 << 14)
    +#endif

    #define MDP_TOP_LUMA 16
    #define MDP_TOP_CHROMA 0
    @@ -364,7 +373,12 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define PPP_OP_SCALE_X_ON (1<<0)
    #define PPP_OP_SCALE_Y_ON (1<<1)

    +#ifndef CONFIG_MSM_MDP31
    #define PPP_OP_CONVERT_RGB2YCBCR 0
    +#else
    +#define PPP_OP_CONVERT_RGB2YCBCR (1<<30)
    +#endif
    +
    #define PPP_OP_CONVERT_YCBCR2RGB (1<<2)
    #define PPP_OP_CONVERT_ON (1<<3)

    @@ -420,6 +434,13 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define PPP_OP_BG_CHROMA_SITE_COSITE 0
    #define PPP_OP_BG_CHROMA_SITE_OFFSITE (1<<27)

    +#define PPP_BLEND_BG_USE_ALPHA_SEL (1 << 0)
    +#define PPP_BLEND_BG_ALPHA_REVERSE (1 << 3)
    +#define PPP_BLEND_BG_SRCPIXEL_ALPHA (0 << 1)
    +#define PPP_BLEND_BG_DSTPIXEL_ALPHA (1 << 1)
    +#define PPP_BLEND_BG_CONSTANT_ALPHA (2 << 1)
    +#define PPP_BLEND_BG_CONST_ALPHA_VAL(x) ((x) << 24)
    +
    /* MDP_PPP_DESTINATION_CONFIG / MDP_FULL_BYPASS_WORD20 */
    #define PPP_DST_C0G_8BIT ((1<<0)|(1<<1))
    #define PPP_DST_C1B_8BIT ((1<<3)|(1<<2))
    @@ -634,19 +655,53 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    /* pfmv is mv1, prmv is mv2 */
    #define MDP_CSC_PFMVn(n) (0x40400 + (4 * (n)))
    #define MDP_CSC_PRMVn(n) (0x40440 + (4 * (n)))
    +
    +#ifdef CONFIG_MSM_MDP31
    +#define MDP_PPP_CSC_PRE_BV1n(n) (0x40500 + (4 * (n)))
    +#define MDP_PPP_CSC_PRE_BV2n(n) (0x40540 + (4 * (n)))
    +#define MDP_PPP_CSC_POST_BV1n(n) (0x40580 + (4 * (n)))
    +#define MDP_PPP_CSC_POST_BV2n(n) (0x405c0 + (4 * (n)))
    +
    +#define MDP_PPP_CSC_PRE_LV1n(n) (0x40600 + (4 * (n)))
    +#define MDP_PPP_CSC_PRE_LV2n(n) (0x40640 + (4 * (n)))
    +#define MDP_PPP_CSC_POST_LV1n(n) (0x40680 + (4 * (n)))
    +#define MDP_PPP_CSC_POST_LV2n(n) (0x406c0 + (4 * (n)))
    +
    +#define MDP_PPP_SCALE_COEFF_D0_SET (0)
    +#define MDP_PPP_SCALE_COEFF_D1_SET (1)
    +#define MDP_PPP_SCALE_COEFF_D2_SET (2)
    +#define MDP_PPP_SCALE_COEFF_U1_SET (3)
    +#define MDP_PPP_SCALE_COEFF_LSBn(n) (0x50400 + (8 * (n)))
    +#define MDP_PPP_SCALE_COEFF_MSBn(n) (0x50404 + (8 * (n)))
    +
    +#define MDP_PPP_DEINT_COEFFn(n) (0x30010 + (4 * (n)))
    +
    +#define MDP_PPP_SCALER_FIR (0)
    +#define MDP_PPP_SCALER_MN (1)
    +
    +#else /* !defined(CONFIG_MSM_MDP31) */
    #define MDP_CSC_PBVn(n) (0x40500 + (4 * (n)))
    #define MDP_CSC_SBVn(n) (0x40540 + (4 * (n)))
    #define MDP_CSC_PLVn(n) (0x40580 + (4 * (n)))
    #define MDP_CSC_SLVn(n) (0x405c0 + (4 * (n)))

    +#endif
    +
    /* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
    -#define DMA_DSTC0G_6BITS (1<<1)
    -#define DMA_DSTC1B_6BITS (1<<3)
    -#define DMA_DSTC2R_6BITS (1<<5)
    #define DMA_DSTC0G_5BITS (1<<0)
    #define DMA_DSTC1B_5BITS (1<<2)
    #define DMA_DSTC2R_5BITS (1<<4)

    +#define DMA_DSTC0G_6BITS (2<<0)
    +#define DMA_DSTC1B_6BITS (2<<2)
    +#define DMA_DSTC2R_6BITS (2<<4)
    +
    +#define DMA_DSTC0G_8BITS (3<<0)
    +#define DMA_DSTC1B_8BITS (3<<2)
    +#define DMA_DSTC2R_8BITS (3<<4)
    +
    +#define DMA_DST_BITS_MASK 0x3F
    +
    #define DMA_PACK_TIGHT (1<<6)
    #define DMA_PACK_LOOSE 0
    #define DMA_PACK_ALIGN_LSB 0
    @@ -657,23 +712,38 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    #define DMA_PACK_PATTERN_BGR \
    (MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)

    +#ifdef CONFIG_MSM_MDP22
    +
    #define DMA_OUT_SEL_AHB 0
    #define DMA_OUT_SEL_MDDI (1<<14)
    #define DMA_AHBM_LCD_SEL_PRIMARY 0
    #define DMA_AHBM_LCD_SEL_SECONDARY (1<<15)
    #define DMA_IBUF_C3ALPHA_EN (1<<16)
    #define DMA_DITHER_EN (1<<17)
    -
    #define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY 0
    #define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (1<<18)
    #define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (1<<19)
    -
    #define DMA_IBUF_FORMAT_RGB565 (1<<20)
    #define DMA_IBUF_FORMAT_RGB888_OR_ARGB8888 0
    #define DMA_IBUF_FORMAT_MASK (1 << 20)
    -
    #define DMA_IBUF_NONCONTIGUOUS (1<<21)

    +#else /* CONFIG_MSM_MDP31 */
    +
    +#define DMA_OUT_SEL_AHB (0 << 19)
    +#define DMA_OUT_SEL_MDDI (1 << 19)
    +#define DMA_OUT_SEL_LCDC (2 << 19)
    +#define DMA_OUT_SEL_LCDC_MDDI (3 << 19)
    +#define DMA_DITHER_EN (1 << 24)
    +#define DMA_IBUF_FORMAT_RGB888 (0 << 25)
    +#define DMA_IBUF_FORMAT_RGB565 (1 << 25)
    +#define DMA_IBUF_FORMAT_XRGB8888 (2 << 25)
    +#define DMA_IBUF_FORMAT_MASK (3 << 25)
    +#define DMA_IBUF_NONCONTIGUOUS (0)
    +#define DMA_MDDI_DMAOUT_LCD_SEL_PRIMARY (0)
    +#define DMA_MDDI_DMAOUT_LCD_SEL_SECONDARY (0)
    +#define DMA_MDDI_DMAOUT_LCD_SEL_EXTERNAL (0)
    +#endif
    /* MDDI REGISTER ? */
    #define MDDI_VDO_PACKET_DESC 0x5666
    #define MDDI_VDO_PACKET_PRIM 0xC3
    diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
    index 6d14c4f..8261f5a 100644
    --- a/drivers/video/msm/mdp_ppp.c
    +++ b/drivers/video/msm/mdp_ppp.c
    @@ -67,17 +67,62 @@ static uint32_t bg_op_chroma[] = {
    PPP_ARRAY1(CHROMA_SAMP, BG)
    };

    +#ifdef CONFIG_MSM_MDP31
    +static uint32_t get_luma_offset(struct mdp_img *img,
    + struct mdp_rect *rect, uint32_t bpp)
    +{
    + return (rect->x + (rect->y * img->width)) * bpp;
    +}
    +
    +static uint32_t get_chroma_offset(struct mdp_img *img,
    + struct mdp_rect *rect, uint32_t bpp)
    +{
    + uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
    + uint32_t compress_h = 2;
    + uint32_t offset = 0;
    +
    + if (IS_PSEUDOPLNR(img->format)) {
    + offset = (rect->x / compress_h) * compress_h;
    + offset += rect->y == 0 ? 0 :
    + ((rect->y + 1) / compress_v) * img->width;
    + offset *= bpp;
    + }
    + return offset;
    +}
    +
    static void set_src_region(struct mdp_img *img, struct mdp_rect *rect,
    struct ppp_regs *regs)
    {
    regs->src_rect = (rect->h << 16) | (rect->w & 0x1fff);
    -
    + regs->src_xy = (rect->y << 16) | (rect->x & 0x1fff);
    + regs->src_img_sz = (img->height << 16) | (img->width & 0x1fff);
    }

    static inline void set_dst_region(struct mdp_rect *rect, struct ppp_regs *regs)
    {
    regs->dst_rect = (rect->h << 16) | (rect->w & 0xfff);
    + regs->dst_xy = (rect->y << 16) | (rect->x & 0x1fff);
    +}
    +
    +static void set_blend_region(struct mdp_img *img, struct mdp_rect *rect,
    + struct ppp_regs *regs)
    +{
    + uint32_t rect_x = rect->x;
    + uint32_t rect_y = rect->y;
    + uint32_t img_w = img->width;
    + uint32_t img_h = img->height;
    +
    + /* HW bug workaround */
    + if (img->format == MDP_YCRYCB_H2V1) {
    + regs->bg0 += (rect_x + (rect_y * img_w)) * regs->bg_bpp;
    + rect_x = 0;
    + rect_y = 0;
    + img_w = rect->w;
    + img_h = rect->h;
    + }

    + regs->bg_xy = (rect_y << 16) | (rect_x & 0x1fff);
    + regs->bg_img_sz = (img_h << 16) | (img_w & 0x1fff);
    }

    static void rotate_dst_addr_x(struct mdp_blit_req *req,
    @@ -100,6 +145,8 @@ static void rotate_dst_addr_y(struct mdp_blit_req *req,
    regs->dst_ystride;
    }

    +#else
    +
    static uint32_t get_luma_offset(struct mdp_img *img,
    struct mdp_rect *rect, uint32_t bpp)
    {
    @@ -111,6 +158,31 @@ static uint32_t get_chroma_offset(struct mdp_img *img,
    {
    return 0;
    }
    +
    +static void set_src_region(struct mdp_img *img, struct mdp_rect *rect,
    + struct ppp_regs *regs)
    +{
    + regs->src_rect = (rect->h << 16) | (rect->w & 0x1fff);
    +}
    +
    +static inline void set_dst_region(struct mdp_rect *rect, struct ppp_regs *regs)
    +{
    + regs->dst_rect = (rect->h << 16) | (rect->w & 0xfff);
    +}
    +
    +static void set_blend_region(struct mdp_img *img, struct mdp_rect *rect,
    + struct ppp_regs *regs)
    +{}
    +
    +static void rotate_dst_addr_x(struct mdp_blit_req *req,
    + struct ppp_regs *regs)
    +{}
    +
    +static void rotate_dst_addr_y(struct mdp_blit_req *req,
    + struct ppp_regs *regs)
    +{}
    +#endif
    +
    static void blit_rotate(struct mdp_blit_req *req,
    struct ppp_regs *regs)
    {
    @@ -137,10 +209,18 @@ static void blit_convert(struct mdp_blit_req *req, struct ppp_regs *regs)
    return;
    if (IS_RGB(req->src.format) && IS_YCRCB(req->dst.format)) {
    regs->op |= PPP_OP_CONVERT_RGB2YCBCR | PPP_OP_CONVERT_ON;
    +#ifdef CONFIG_MSM_MDP31
    + /* primary really means set1 */
    + regs->op |= PPP_OP_CONVERT_MATRIX_PRIMARY;
    + regs->csc_cfg = 0x1e;
    +#endif
    } else if (IS_YCRCB(req->src.format) && IS_RGB(req->dst.format)) {
    regs->op |= PPP_OP_CONVERT_YCBCR2RGB | PPP_OP_CONVERT_ON;
    - if (req->dst.format == MDP_RGB_565)
    - regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
    +#ifdef CONFIG_MSM_MDP31
    + /* secondary really means set2 */
    + regs->op |= PPP_OP_CONVERT_MATRIX_SECONDARY;
    + regs->csc_cfg = 0;
    +#endif
    }
    }

    @@ -214,6 +294,7 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
    regs->bg_bpp = regs->dst_bpp;
    regs->bg_pack = pack_pattern[req->dst.format];
    regs->bg_ystride = regs->dst_ystride;
    + set_blend_region(&req->dst, &req->dst_rect, regs);
    }

    static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
    @@ -236,7 +317,7 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
    return 0;
    }

    -#ifdef CONFIG_MSM_MDP22
    +#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP22)
    if (mdp_ppp_cfg_scale(mdp, regs, &req->src_rect, &dst_rect,
    req->src.format, req->dst.format)) {
    DLOG("crap, bad scale\n");
    @@ -251,13 +332,13 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
    static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
    struct ppp_regs *regs)
    {
    -#ifdef CONFIG_MSM_MDP22
    +#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP22)
    int ret;
    #endif
    if (!(req->flags & MDP_BLUR))
    return;

    -#ifdef CONFIG_MSM_MDP22
    +#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP22)
    ret = mdp_ppp_load_blur(mdp);
    if (ret)
    return;
    @@ -354,7 +435,17 @@ static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    mdp_writel_dbg(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
    mdp_writel_dbg(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);

    +#ifdef CONFIG_MSM_MDP31
    + mdp_writel_dbg(mdp, regs->scale_cfg, MDP_PPP_SCALE_CONFIG);
    + mdp_writel_dbg(mdp, regs->csc_cfg, MDP_PPP_CSC_CONFIG);
    + mdp_writel_dbg(mdp, regs->src_xy, MDP_PPP_SRC_XY);
    + mdp_writel_dbg(mdp, regs->src_img_sz, MDP_PPP_SRC_IMAGE_SIZE);
    + mdp_writel_dbg(mdp, regs->dst_xy, MDP_PPP_OUT_XY);
    +#else
    + /* no edge conditions to set for MDP 3.1 */
    mdp_writel_dbg(mdp, regs->edge, PPP_ADDR_EDGE);
    +#endif
    +
    mdp_writel_dbg(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
    PPP_ADDR_ALPHA_TRANSP);

    @@ -371,6 +462,12 @@ static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    mdp_writel_dbg(mdp, regs->bg_ystride, PPP_ADDR_BG_YSTRIDE);
    mdp_writel_dbg(mdp, regs->bg_cfg, PPP_ADDR_BG_CFG);
    mdp_writel_dbg(mdp, regs->bg_pack, PPP_ADDR_BG_PACK_PATTERN);
    +#ifdef CONFIG_MSM_MDP31
    + mdp_writel_dbg(mdp, regs->bg_xy, MDP_PPP_BG_XY);
    + mdp_writel_dbg(mdp, regs->bg_img_sz, MDP_PPP_BG_IMAGE_SIZE);
    + mdp_writel_dbg(mdp, regs->bg_alpha_sel,
    + MDP_PPP_BLEND_BG_ALPHA_SEL);
    +#endif
    }
    flush_imgs(req, regs, src_file, dst_file);
    mdp_writel_dbg(mdp, 0x1000, MDP_DISPLAY0_START);
    @@ -436,6 +533,12 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    regs.dst_ystride = req->dst.width * regs.dst_bpp;
    set_dst_region(&req->dst_rect, &regs);

    + /* for simplicity, always write the chroma stride */
    + regs.src_ystride &= 0x3fff;
    + regs.src_ystride |= regs.src_ystride << 16;
    + regs.dst_ystride &= 0x3fff;
    + regs.dst_ystride |= regs.dst_ystride << 16;
    +
    if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
    &regs)) {
    printk(KERN_ERR "mdp_ppp: final src or dst location is "
    @@ -467,7 +570,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
    req->dst_rect.w = req->dst_rect.w & (~0x1);
    }

    -#ifdef CONFIG_MSM_MDP22
    +#if defined(CONFIG_MSM_MDP31) || defined(CONFIG_MSM_MDP22)
    if (mdp_ppp_cfg_edge_cond(req, &regs))
    return -EINVAL;
    #endif
    diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
    index c3cd895..e045643 100644
    --- a/drivers/video/msm/mdp_ppp.h
    +++ b/drivers/video/msm/mdp_ppp.h
    @@ -45,6 +45,18 @@ struct ppp_regs {
    uint32_t bg_bpp;
    uint32_t bg_pack;
    uint32_t bg_ystride;
    +
    +#ifdef CONFIG_MSM_MDP31
    + uint32_t src_xy;
    + uint32_t src_img_sz;
    + uint32_t dst_xy;
    + uint32_t bg_xy;
    + uint32_t bg_img_sz;
    + uint32_t bg_alpha_sel;
    +
    + uint32_t scale_cfg;
    + uint32_t csc_cfg;
    +#endif
    };

    struct mdp_info;
    @@ -57,6 +69,14 @@ int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
    uint32_t src_format, uint32_t dst_format);
    int mdp_ppp_load_blur(const struct mdp_info *mdp);

    +#ifndef CONFIG_MSM_MDP31
    int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
    +#else
    +static inline int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req,
    + struct ppp_regs *regs)
    +{
    + return 0;
    +}
    +#endif

    #endif /* _VIDEO_MSM_MDP_PPP_H_ */
    diff --git a/drivers/video/msm/mdp_ppp31.c b/drivers/video/msm/mdp_ppp31.c
    new file mode 100644
    index 0000000..ad81b00
    --- /dev/null
    +++ b/drivers/video/msm/mdp_ppp31.c
    @@ -0,0 +1,335 @@
    +/* drivers/video/msm/mdp_ppp31.c
    + *
    + * Copyright (C) 2009, 2011 Code Aurora Forum. All rights reserved.
    + * Copyright (C) 2009 Google Incorporated
    + *
    + * This software is licensed under the terms of the GNU General Public
    + * License version 2, as published by the Free Software Foundation, and
    + * may be copied, distributed, and modified under those terms.
    + *
    + * This program is distributed in the hope that it will be useful,
    + * but WITHOUT ANY WARRANTY; without even the implied warranty of
    + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    + * GNU General Public License for more details.
    + */
    +
    +#include <linux/errno.h>
    +#include <linux/kernel.h>
    +#include <linux/io.h>
    +#include <linux/msm_mdp.h>
    +
    +#include "mdp_hw.h"
    +#include "mdp_ppp.h"
    +
    +#define NUM_COEFFS 32
    +
    +struct mdp_scale_coeffs {
    + /*
    + * signed 10-bit coeffs that need to be be 16-bit aligned
    + */
    + uint16_t c[4][NUM_COEFFS];
    +};
    +
    +struct mdp_scale_tbl_info {
    + uint16_t offset;
    + uint32_t set:2;
    + int use_pr;
    + struct mdp_scale_coeffs coeffs;
    +};
    +
    +enum {
    + MDP_SCALE_PT2TOPT4,
    + MDP_SCALE_PT4TOPT6,
    + MDP_SCALE_PT6TOPT8,
    + MDP_SCALE_PT8TO8,
    + MDP_SCALE_MAX,
    +};
    +
    +static struct mdp_scale_coeffs mdp_scale_pr_coeffs = {
    + .c = {
    + [0] = {
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + },
    + [1] = {
    + 511, 511, 511, 511, 511, 511, 511, 511,
    + 511, 511, 511, 511, 511, 511, 511, 511,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + },
    + [2] = {
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 511, 511, 511, 511, 511, 511, 511, 511,
    + 511, 511, 511, 511, 511, 511, 511, 511,
    + },
    + [3] = {
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + 0, 0, 0, 0, 0, 0, 0, 0,
    + },
    + },
    +};
    +
    +static struct mdp_scale_tbl_info mdp_scale_tbl[MDP_SCALE_MAX] = {
    + [MDP_SCALE_PT2TOPT4] = {
    + .offset = 0,
    + .set = MDP_PPP_SCALE_COEFF_D0_SET,
    + .use_pr = -1,
    + .coeffs.c = {
    + [0] = {
    + 131, 131, 130, 129, 128, 127, 127, 126,
    + 125, 125, 124, 123, 123, 121, 120, 119,
    + 119, 118, 117, 117, 116, 115, 115, 114,
    + 113, 112, 111, 110, 109, 109, 108, 107,
    + },
    + [1] = {
    + 141, 140, 140, 140, 140, 139, 138, 138,
    + 138, 137, 137, 137, 136, 137, 137, 137,
    + 136, 136, 136, 135, 135, 135, 134, 134,
    + 134, 134, 134, 133, 133, 132, 132, 132,
    + },
    + [2] = {
    + 132, 132, 132, 133, 133, 134, 134, 134,
    + 134, 134, 135, 135, 135, 136, 136, 136,
    + 137, 137, 137, 136, 137, 137, 137, 138,
    + 138, 138, 139, 140, 140, 140, 140, 141,
    + },
    + [3] = {
    + 107, 108, 109, 109, 110, 111, 112, 113,
    + 114, 115, 115, 116, 117, 117, 118, 119,
    + 119, 120, 121, 123, 123, 124, 125, 125,
    + 126, 127, 127, 128, 129, 130, 131, 131,
    + }
    + },
    + },
    + [MDP_SCALE_PT4TOPT6] = {
    + .offset = 32,
    + .set = MDP_PPP_SCALE_COEFF_D1_SET,
    + .use_pr = -1,
    + .coeffs.c = {
    + [0] = {
    + 136, 132, 128, 123, 119, 115, 111, 107,
    + 103, 98, 95, 91, 87, 84, 80, 76,
    + 73, 69, 66, 62, 59, 57, 54, 50,
    + 47, 44, 41, 39, 36, 33, 32, 29,
    + },
    + [1] = {
    + 206, 205, 204, 204, 201, 200, 199, 197,
    + 196, 194, 191, 191, 189, 185, 184, 182,
    + 180, 178, 176, 173, 170, 168, 165, 162,
    + 160, 157, 155, 152, 148, 146, 142, 140,
    + },
    + [2] = {
    + 140, 142, 146, 148, 152, 155, 157, 160,
    + 162, 165, 168, 170, 173, 176, 178, 180,
    + 182, 184, 185, 189, 191, 191, 194, 196,
    + 197, 199, 200, 201, 204, 204, 205, 206,
    + },
    + [3] = {
    + 29, 32, 33, 36, 39, 41, 44, 47,
    + 50, 54, 57, 59, 62, 66, 69, 73,
    + 76, 80, 84, 87, 91, 95, 98, 103,
    + 107, 111, 115, 119, 123, 128, 132, 136,
    + },
    + },
    + },
    + [MDP_SCALE_PT6TOPT8] = {
    + .offset = 64,
    + .set = MDP_PPP_SCALE_COEFF_D2_SET,
    + .use_pr = -1,
    + .coeffs.c = {
    + [0] = {
    + 104, 96, 89, 82, 75, 68, 61, 55,
    + 49, 43, 38, 33, 28, 24, 20, 16,
    + 12, 9, 6, 4, 2, 0, -2, -4,
    + -5, -6, -7, -7, -8, -8, -8, -8,
    + },
    + [1] = {
    + 303, 303, 302, 300, 298, 296, 293, 289,
    + 286, 281, 276, 270, 265, 258, 252, 245,
    + 238, 230, 223, 214, 206, 197, 189, 180,
    + 172, 163, 154, 145, 137, 128, 120, 112,
    + },
    + [2] = {
    + 112, 120, 128, 137, 145, 154, 163, 172,
    + 180, 189, 197, 206, 214, 223, 230, 238,
    + 245, 252, 258, 265, 270, 276, 281, 286,
    + 289, 293, 296, 298, 300, 302, 303, 303,
    + },
    + [3] = {
    + -8, -8, -8, -8, -7, -7, -6, -5,
    + -4, -2, 0, 2, 4, 6, 9, 12,
    + 16, 20, 24, 28, 33, 38, 43, 49,
    + 55, 61, 68, 75, 82, 89, 96, 104,
    + },
    + },
    + },
    + [MDP_SCALE_PT8TO8] = {
    + .offset = 96,
    + .set = MDP_PPP_SCALE_COEFF_U1_SET,
    + .use_pr = -1,
    + .coeffs.c = {
    + [0] = {
    + 0, -7, -13, -19, -24, -28, -32, -34,
    + -37, -39, -40, -41, -41, -41, -40, -40,
    + -38, -37, -35, -33, -31, -29, -26, -24,
    + -21, -18, -15, -13, -10, -7, -5, -2,
    + },
    + [1] = {
    + 511, 507, 501, 494, 485, 475, 463, 450,
    + 436, 422, 405, 388, 370, 352, 333, 314,
    + 293, 274, 253, 233, 213, 193, 172, 152,
    + 133, 113, 95, 77, 60, 43, 28, 13,
    + },
    + [2] = {
    + 0, 13, 28, 43, 60, 77, 95, 113,
    + 133, 152, 172, 193, 213, 233, 253, 274,
    + 294, 314, 333, 352, 370, 388, 405, 422,
    + 436, 450, 463, 475, 485, 494, 501, 507,
    + },
    + [3] = {
    + 0, -2, -5, -7, -10, -13, -15, -18,
    + -21, -24, -26, -29, -31, -33, -35, -37,
    + -38, -40, -40, -41, -41, -41, -40, -39,
    + -37, -34, -32, -28, -24, -19, -13, -7,
    + },
    + },
    + },
    +};
    +
    +static void load_table(const struct mdp_info *mdp, int scale, int use_pr)
    +{
    + int i;
    + uint32_t val;
    + struct mdp_scale_coeffs *coeffs;
    + struct mdp_scale_tbl_info *tbl = &mdp_scale_tbl[scale];
    +
    + if (use_pr == tbl->use_pr)
    + return;
    +
    + tbl->use_pr = use_pr;
    + if (!use_pr)
    + coeffs = &tbl->coeffs;
    + else
    + coeffs = &mdp_scale_pr_coeffs;
    +
    + for (i = 0; i < NUM_COEFFS; ++i) {
    + val = ((coeffs->c[1][i] & 0x3ff) << 16) |
    + (coeffs->c[0][i] & 0x3ff);
    + mdp_writel(mdp, val, MDP_PPP_SCALE_COEFF_LSBn(tbl->offset + i));
    +
    + val = ((coeffs->c[3][i] & 0x3ff) << 16) |
    + (coeffs->c[2][i] & 0x3ff);
    + mdp_writel(mdp, val, MDP_PPP_SCALE_COEFF_MSBn(tbl->offset + i));
    + }
    +}
    +
    +#define SCALER_PHASE_BITS 29
    +static void scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t scaler,
    + uint32_t *phase_init, uint32_t *phase_step)
    +{
    + uint64_t src = dim_in;
    + uint64_t dst = dim_out;
    + uint64_t numer;
    + uint64_t denom;
    +
    + *phase_init = 0;
    +
    + if (dst == 1) {
    + /* if destination is 1 pixel wide, the value of phase_step
    + * is unimportant. */
    + *phase_step = (uint32_t) (src << SCALER_PHASE_BITS);
    + if (scaler == MDP_PPP_SCALER_FIR)
    + *phase_init =
    + (uint32_t) ((src - 1) << SCALER_PHASE_BITS);
    + return;
    + }
    +
    + if (scaler == MDP_PPP_SCALER_FIR) {
    + numer = (src - 1) << SCALER_PHASE_BITS;
    + denom = dst - 1;
    + /* we want to round up the result*/
    + numer += denom - 1;
    + } else {
    + numer = src << SCALER_PHASE_BITS;
    + denom = dst;
    + }
    +
    + do_div(numer, denom);
    + *phase_step = (uint32_t) numer;
    +}
    +
    +static int scale_idx(int factor)
    +{
    + int idx;
    +
    + if (factor > 80)
    + idx = MDP_SCALE_PT8TO8;
    + else if (factor > 60)
    + idx = MDP_SCALE_PT6TOPT8;
    + else if (factor > 40)
    + idx = MDP_SCALE_PT4TOPT6;
    + else
    + idx = MDP_SCALE_PT2TOPT4;
    +
    + return idx;
    +}
    +
    +int mdp_ppp_cfg_scale(const struct mdp_info *mdp, struct ppp_regs *regs,
    + struct mdp_rect *src_rect, struct mdp_rect *dst_rect,
    + uint32_t src_format, uint32_t dst_format)
    +{
    + uint32_t x_fac;
    + uint32_t y_fac;
    + uint32_t scaler_x = MDP_PPP_SCALER_FIR;
    + uint32_t scaler_y = MDP_PPP_SCALER_FIR;
    + /* Don't use pixel repeat mode, it looks bad */
    + int use_pr = 0;
    + int x_idx;
    + int y_idx;
    +
    + if (unlikely(src_rect->w > 2048 || src_rect->h > 2048))
    + return -ENOTSUPP;
    +
    + x_fac = (dst_rect->w * 100) / src_rect->w;
    + y_fac = (dst_rect->h * 100) / src_rect->h;
    +
    + /* if down-scaling by a factor smaller than 1/4, use M/N */
    + scaler_x = x_fac <= 25 ? MDP_PPP_SCALER_MN : MDP_PPP_SCALER_FIR;
    + scaler_y = y_fac <= 25 ? MDP_PPP_SCALER_MN : MDP_PPP_SCALER_FIR;
    + scale_params(src_rect->w, dst_rect->w, scaler_x, &regs->phasex_init,
    + &regs->phasex_step);
    + scale_params(src_rect->h, dst_rect->h, scaler_y, &regs->phasey_init,
    + &regs->phasey_step);
    +
    + x_idx = scale_idx(x_fac);
    + y_idx = scale_idx(y_fac);
    + load_table(mdp, x_idx, use_pr);
    + load_table(mdp, y_idx, use_pr);
    +
    + regs->scale_cfg = 0;
    + /* Enable SVI when source or destination is YUV */
    + if (!IS_RGB(src_format) && !IS_RGB(dst_format))
    + regs->scale_cfg |= (1 << 6);
    + regs->scale_cfg |= (mdp_scale_tbl[x_idx].set << 2) |
    + (mdp_scale_tbl[x_idx].set << 4);
    + regs->scale_cfg |= (scaler_x << 0) | (scaler_y << 1);
    +
    + return 0;
    +}
    +
    +int mdp_ppp_load_blur(const struct mdp_info *mdp)
    +{
    + return -ENOTSUPP;
    +}
    +
    +void mdp_ppp_init_scale(const struct mdp_info *mdp)
    +{
    + int scale;
    + for (scale = 0; scale < MDP_SCALE_MAX; ++scale)
    + load_table(mdp, scale, 0);
    +}
    --
    Sent by an employee of the Qualcomm Innovation Center, Inc.
    The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


    \
     
     \ /
      Last update: 2011-03-18 23:03    [W:5.033 / U:0.576 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site