Linux Framebuffer Layer development
 help / color / mirror / Atom feed
* RE: [PATCH 09/20] video: msm: Split out MDP2.2 HW specific code.
From: Janorkar, Mayuresh @ 2011-03-21  5:27 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300485423-27281-1-git-send-email-carlv@codeaurora.org>



> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-
> owner@vger.kernel.org] On Behalf Of Carl Vanderlip
> Sent: Saturday, March 19, 2011 3:27 AM
> To: Russell King; David Brown; Daniel Walker; Bryan Huntsman
> Cc: Brian Swetland; Dima Zavin; Rebecca Schultz Zavin; Colin Cross; linux-
> fbdev@vger.kernel.org; Carl Vanderlip; linux-arm-
> kernel@lists.infradead.org; linux-arm-msm@vger.kernel.org; linux-
> kernel@vger.kernel.org
> Subject: [PATCH 09/20] video: msm: Split out MDP2.2 HW specific code.
>
> Moving MDP2.2 HW specific code allows for reuse of PPP code
> when adding other MDP HW versions. Splitting also begins
> simplification of mdp_probe function.
>
> 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                          |    5 +
>  drivers/video/msm/Makefile                         |    4 +-
>  drivers/video/msm/mdp.c                            |   14 +-
>  drivers/video/msm/mdp_ppp.c                        |  358 ++++-----------
> -----
>  drivers/video/msm/mdp_ppp.h                        |   12 +
>  .../video/msm/{mdp_scale_tables.c => mdp_ppp22.c}  |  333
> ++++++++++++++++++-
>  drivers/video/msm/mdp_scale_tables.h               |   38 --
>  7 files changed, 417 insertions(+), 347 deletions(-)
>  rename drivers/video/msm/{mdp_scale_tables.c => mdp_ppp22.c} (69%)
>  delete mode 100644 drivers/video/msm/mdp_scale_tables.h
>
> diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
> index df9d74e..d6e75c3 100644
> --- a/arch/arm/mach-msm/Kconfig
> +++ b/arch/arm/mach-msm/Kconfig
> @@ -76,6 +76,11 @@ config HAS_MSM_DEBUG_UART_PHYS
>  config  MSM_VIC
>       bool
>
> +config MSM_MDP22
> +     bool
> +     depends on ARCH_MSM7X00A
> +     default y

Please add some help here.

> +
>  menu "Qualcomm MSM Board Type"
>
>  config MACH_HALIBUT
> diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
> index 802d6ae..0666aef 100644
> --- a/drivers/video/msm/Makefile
> +++ b/drivers/video/msm/Makefile
> @@ -5,7 +5,9 @@ obj-y := msm_fb.o
>
>  # MDP DMA/PPP engine
>  #
> -obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
> +obj-y += mdp.o mdp_ppp.o
> +
> +obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
>
>  # MDDI interface
>  #
> diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
> index 765df06..6aa9ed5 100644
> --- a/drivers/video/msm/mdp.c
> +++ b/drivers/video/msm/mdp.c
> @@ -30,6 +30,7 @@
>  #include <linux/platform_device.h>
>
>  #include "mdp_hw.h"
> +#include "mdp_ppp.h"
>
>  struct class *mdp_class;
>
> @@ -453,7 +454,13 @@ int register_mdp_client(struct class_interface *cint)
>  }
>
>  #include "mdp_csc_table.h"
> -#include "mdp_scale_tables.h"
> +
> +void mdp_hw_init(struct mdp_info *mdp)
> +{
> +#ifdef CONFIG_MSM_MDP22
> +     mdp_ppp_init_scale(mdp);
> +#endif
> +}
>
>  int mdp_probe(struct platform_device *pdev)
>  {
> @@ -551,15 +558,12 @@ int mdp_probe(struct platform_device *pdev)
>       mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
>       mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
>
> -     for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
> -             mdp_writel(mdp, mdp_upscale_table[n].val,
> -                    mdp_upscale_table[n].reg);
> -
>       for (n = 0; n < 9; n++)
>               mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
>       mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
>       mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
>       mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
> +     mdp_hw_init(mdp);
>
>       /* register mdp device */
>       mdp->mdp_dev.dev.parent = &pdev->dev;
> diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
> index 05f3e33..3d190b9 100644
> --- a/drivers/video/msm/mdp_ppp.c
> +++ b/drivers/video/msm/mdp_ppp.c
> @@ -20,14 +20,14 @@
>
>  #include "mdp_hw.h"
>  #include "mdp_ppp.h"
> -#include "mdp_scale_tables.h"
>
>  #define DLOG(x...) do {} while (0)
>
> -#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
> -static int downscale_y_table = MDP_DOWNSCALE_MAX;
> -static int downscale_x_table = MDP_DOWNSCALE_MAX;
> +#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
>
> +#define Y_TO_CRCB_RATIO(format) \
> +     ((format = MDP_Y_CBCR_H2V2 || format = MDP_Y_CRCB_H2V2) ?  2 :\
> +      (format = MDP_Y_CBCR_H2V1 || format = MDP_Y_CRCB_H2V1) ?  1 : 1)
>
>  static uint32_t pack_pattern[] = {
>       PPP_ARRAY0(PACK_PATTERN)
> @@ -67,6 +67,19 @@ static uint32_t bg_op_chroma[] = {
>       PPP_ARRAY1(CHROMA_SAMP, BG)
>  };
>
> +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);
> +
[cosmetic comment]: unnecessary extra line?

> +}
> +
> +static inline void set_dst_region(struct mdp_rect *rect, struct ppp_regs
> *regs)
> +{
> +     regs->dst_rect = (rect->h << 16) | (rect->w & 0xfff);
> +
[cosmetic comment]: unnecessary extra line?
> +}
> +
>  static void rotate_dst_addr_x(struct mdp_blit_req *req,
>                             struct ppp_regs *regs)
>  {
> @@ -181,254 +194,30 @@ static void blit_blend(struct mdp_blit_req *req,
> struct ppp_regs *regs)
>       }
>
>       regs->op |= bg_op_chroma[req->dst.format];
> -}
> -
> -#define ONE_HALF     (1LL << 32)
> -#define ONE          (1LL << 33)
> -#define TWO          (2LL << 33)
> -#define THREE                (3LL << 33)
> -#define FRAC_MASK (ONE - 1)
> -#define INT_MASK (~FRAC_MASK)
> -
> -static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t
> origin,
> -                     uint32_t *phase_init, uint32_t *phase_step)
> -{
> -     /* to improve precicsion calculations are done in U31.33 and
> converted
> -      * to U3.29 at the end */
> -     int64_t k1, k2, k3, k4, tmp;
> -     uint64_t n, d, os, os_p, od, od_p, oreq;
> -     unsigned rpa = 0;
> -     int64_t ip64, delta;
> -
> -     if (dim_out % 3 = 0)
> -             rpa = !(dim_in % (dim_out / 3));
> -
> -     n = ((uint64_t)dim_out) << 34;
> -     d = dim_in;
> -     if (!d)
> -             return -1;
> -     do_div(n, d);
> -     k3 = (n + 1) >> 1;
> -     if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
> -             DLOG("crap bad scale\n");
> -             return -1;
> -     }
> -     n = ((uint64_t)dim_in) << 34;
> -     d = (uint64_t)dim_out;
> -     if (!d)
> -             return -1;
> -     do_div(n, d);
> -     k1 = (n + 1) >> 1;
> -     k2 = (k1 - ONE) >> 1;
> -
> -     *phase_init = (int)(k2 >> 4);
> -     k4 = (k3 - ONE) >> 1;
> -
> -     if (rpa) {
> -             os = ((uint64_t)origin << 33) - ONE_HALF;
> -             tmp = (dim_out * os) + ONE_HALF;
> -             if (!dim_in)
> -                     return -1;
> -             do_div(tmp, dim_in);
> -             od = tmp - ONE_HALF;
> -     } else {
> -             os = ((uint64_t)origin << 1) - 1;
> -             od = (((k3 * os) >> 1) + k4);
> -     }
> -
> -     od_p = od & INT_MASK;
> -     if (od_p != od)
> -             od_p += ONE;
> -
> -     if (rpa) {
> -             tmp = (dim_in * od_p) + ONE_HALF;
> -             if (!dim_in)
> -                     return -1;
> -             do_div(tmp, dim_in);
> -             os_p = tmp - ONE_HALF;
> -     } else {
> -             os_p = ((k1 * (od_p >> 33)) + k2);
> -     }
> -
> -     oreq = (os_p & INT_MASK) - ONE;
> -
> -     ip64 = os_p - oreq;
> -     delta = ((int64_t)(origin) << 33) - oreq;
> -     ip64 -= delta;
> -     /* limit to valid range before the left shift */
> -     delta = (ip64 & (1LL << 63)) ? 4 : -4;
> -     delta <<= 33;
> -     while (abs((int)(ip64 >> 33)) > 4)
> -             ip64 += delta;
> -     *phase_init = (int)(ip64 >> 4);
> -     *phase_step = (uint32_t)(k1 >> 4);
> -     return 0;
> -}
> -
> -static void load_scale_table(const struct mdp_info *mdp,
> -                          struct mdp_table_entry *table, int len)
> -{
> -     int i;
> -     for (i = 0; i < len; i++)
> -             mdp_writel(mdp, table[i].val, table[i].reg);
> -}
> -
> -enum {
> -IMG_LEFT,
> -IMG_RIGHT,
> -IMG_TOP,
> -IMG_BOTTOM,
> -};
> -
> -static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
> -                       uint32_t *interp1, uint32_t *interp2,
> -                       uint32_t *repeat1, uint32_t *repeat2) {
> -     if (src > 3 * dst) {
> -             *interp1 = 0;
> -             *interp2 = src - 1;
> -             *repeat1 = 0;
> -             *repeat2 = 0;
> -     } else if (src = 3 * dst) {
> -             *interp1 = 0;
> -             *interp2 = src;
> -             *repeat1 = 0;
> -             *repeat2 = 1;
> -     } else if (src > dst && src < 3 * dst) {
> -             *interp1 = -1;
> -             *interp2 = src;
> -             *repeat1 = 1;
> -             *repeat2 = 1;
> -     } else if (src = dst) {
> -             *interp1 = -1;
> -             *interp2 = src + 1;
> -             *repeat1 = 1;
> -             *repeat2 = 2;
> -     } else {
> -             *interp1 = -2;
> -             *interp2 = src + 1;
> -             *repeat1 = 2;
> -             *repeat2 = 2;
> -     }
> -     *interp1 += src_coord;
> -     *interp2 += src_coord;
> -}
> -
> -static int get_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
> -{
> -     int32_t luma_interp[4];
> -     int32_t luma_repeat[4];
> -     int32_t chroma_interp[4];
> -     int32_t chroma_bound[4];
> -     int32_t chroma_repeat[4];
> -     uint32_t dst_w, dst_h;
> -
> -     memset(&luma_interp, 0, sizeof(int32_t) * 4);
> -     memset(&luma_repeat, 0, sizeof(int32_t) * 4);
> -     memset(&chroma_interp, 0, sizeof(int32_t) * 4);
> -     memset(&chroma_bound, 0, sizeof(int32_t) * 4);
> -     memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
> -     regs->edge = 0;
> -
> -     if (req->flags & MDP_ROT_90) {
> -             dst_w = req->dst_rect.h;
> -             dst_h = req->dst_rect.w;
> -     } else {
> -             dst_w = req->dst_rect.w;
> -             dst_h = req->dst_rect.h;
> -     }
> -
> -     if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
> -             get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
> -                           &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
> -                           &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
> -             get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
> -                           &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
> -                           &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
> -     } else {
> -             luma_interp[IMG_LEFT] = req->src_rect.x;
> -             luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w -
> 1;
> -             luma_interp[IMG_TOP] = req->src_rect.y;
> -             luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h -
> 1;
> -             luma_repeat[IMG_LEFT] = 0;
> -             luma_repeat[IMG_TOP] = 0;
> -             luma_repeat[IMG_RIGHT] = 0;
> -             luma_repeat[IMG_BOTTOM] = 0;
> -     }
> -
> -     chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
> -     chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
> -     chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
> -     chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
> -
> -     chroma_bound[IMG_LEFT] = req->src_rect.x;
> -     chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
> -     chroma_bound[IMG_TOP] = req->src_rect.y;
> -     chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
> -
> -     if (IS_YCRCB(req->src.format)) {
> -             chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
> -             chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >>
> 1;
> -
> -             chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
> -             chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
> -     }
>
> -     if (req->src.format = MDP_Y_CBCR_H2V2 ||
> -         req->src.format = MDP_Y_CRCB_H2V2) {
> -             chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
> -             chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
> -                                         >> 1;
> -             chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
> -             chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
> -     }
> -
> -     chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
> -                               chroma_interp[IMG_LEFT];
> -     chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
> -                               chroma_bound[IMG_RIGHT];
> -     chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
> -                               chroma_interp[IMG_TOP];
> -     chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
> -                               chroma_bound[IMG_BOTTOM];
> -
> -     if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
> -         chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
> -         chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
> -         chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3
> ||
> -         luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
> -         luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
> -         luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
> -         luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
> -             return -1;
> -
> -     regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
> -     regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
> -     regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
> -     regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
> -     regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
> -     regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
> -     regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
> -     regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
> -     return 0;
> +     /* since we always blend src + dst -> dst, copy most of the
> +      * configuration from dest to bg */
> +     regs->bg0 = regs->dst0;
> +     regs->bg1 = regs->dst1;
> +     regs->bg_cfg = src_img_cfg[req->dst.format];
> +     regs->bg_bpp = regs->dst_bpp;
> +     regs->bg_pack = pack_pattern[req->dst.format];
> +     regs->bg_ystride = regs->dst_ystride;
>  }
>
>  static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req
> *req,
>                     struct ppp_regs *regs)
>  {
> -     uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
> -     uint32_t scale_factor_x, scale_factor_y;
> -     uint32_t downscale;
> -     uint32_t dst_w, dst_h;
> +     struct mdp_rect dst_rect;
>
> +     memcpy(&dst_rect, &req->dst_rect, sizeof(dst_rect));
>       if (req->flags & MDP_ROT_90) {
> -             dst_w = req->dst_rect.h;
> -             dst_h = req->dst_rect.w;
> -     } else {
> -             dst_w = req->dst_rect.w;
> -             dst_h = req->dst_rect.h;
> +             dst_rect.w = req->dst_rect.h;
> +             dst_rect.h = req->dst_rect.w;
>       }
> -     if ((req->src_rect.w = dst_w)  && (req->src_rect.h = dst_h) &&
> -         !(req->flags & MDP_BLUR)) {
> +
> +     if ((req->src_rect.w = dst_rect.w) && (req->src_rect.h =
> dst_rect.h)
> +         && !(req->flags & MDP_BLUR)) {
>               regs->phasex_init = 0;
>               regs->phasey_init = 0;
>               regs->phasex_step = 0;
> @@ -436,73 +225,35 @@ static int blit_scale(const struct mdp_info *mdp,
> struct mdp_blit_req *req,
>               return 0;
>       }
>
> -     if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
> -                      &phase_step_x) ||
> -         scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
> -                      &phase_step_y))
> +#ifdef 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");
>               return -1;
> -
> -     scale_factor_x = (dst_w * 10) / req->src_rect.w;
> -     scale_factor_y = (dst_h * 10) / req->src_rect.h;
> -
> -     if (scale_factor_x > 8)
> -             downscale = MDP_DOWNSCALE_PT8TO1;
> -     else if (scale_factor_x > 6)
> -             downscale = MDP_DOWNSCALE_PT6TOPT8;
> -     else if (scale_factor_x > 4)
> -             downscale = MDP_DOWNSCALE_PT4TOPT6;
> -     else
> -             downscale = MDP_DOWNSCALE_PT2TOPT4;
> -     if (downscale != downscale_x_table) {
> -             load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
> -             downscale_x_table = downscale;
>       }
> +#endif
>
> -     if (scale_factor_y > 8)
> -             downscale = MDP_DOWNSCALE_PT8TO1;
> -     else if (scale_factor_y > 6)
> -             downscale = MDP_DOWNSCALE_PT6TOPT8;
> -     else if (scale_factor_y > 4)
> -             downscale = MDP_DOWNSCALE_PT4TOPT6;
> -     else
> -             downscale = MDP_DOWNSCALE_PT2TOPT4;
> -     if (downscale != downscale_y_table) {
> -             load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
> -             downscale_y_table = downscale;
> -     }
> -
> -     regs->phasex_init = phase_init_x;
> -     regs->phasey_init = phase_init_y;
> -     regs->phasex_step = phase_step_x;
> -     regs->phasey_step = phase_step_y;
>       regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
>       return 0;
> -
>  }
>
>  static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req
> *req,
>                     struct ppp_regs *regs)
>  {
> +#ifdef CONFIG_MSM_MDP22
> +     int ret;
> +#endif
>       if (!(req->flags & MDP_BLUR))
>               return;
>
> -     if (!(downscale_x_table = MDP_DOWNSCALE_BLUR &&
> -           downscale_y_table = MDP_DOWNSCALE_BLUR)) {
> -             load_scale_table(mdp, mdp_gaussian_blur_table, 128);
> -             downscale_x_table = MDP_DOWNSCALE_BLUR;
> -             downscale_y_table = MDP_DOWNSCALE_BLUR;
> -     }
> -
> +#ifdef CONFIG_MSM_MDP22
> +     ret = mdp_ppp_load_blur(mdp);
> +     if (ret)
> +             return;
> +#endif
>       regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
>  }
>
> -
> -#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
> -
> -#define Y_TO_CRCB_RATIO(format) \
> -     ((format = MDP_Y_CBCR_H2V2 || format = MDP_Y_CRCB_H2V2) ?  2 :\
> -      (format = MDP_Y_CBCR_H2V1 || format = MDP_Y_CRCB_H2V1) ?  1 : 1)
> -
>  static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t
> bpp,
>                   uint32_t *len0, uint32_t *len1)
>  {
> @@ -555,7 +306,6 @@ static int valid_src_dst(unsigned long src_start,
> unsigned long src_len,
>       return 1;
>  }
>
> -
>  static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
>                      struct file *src_file, struct file *dst_file)
>  {
> @@ -643,22 +393,29 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
>               return -EINVAL;
>       }
>
> +     if (unlikely(req->src_rect.x + req->src_rect.w > req->src.width ||
> +                  req->src_rect.y + req->src_rect.h > req->src.height ||
> +                  req->dst_rect.x + req->dst_rect.w > req->dst.width ||
> +                  req->dst_rect.y + req->dst_rect.h > req->dst.height)) {
> +             printk(KERN_ERR "mdp_ppp: img rect extends outside of
> img!\n");
> +             return -EINVAL;
> +     }
> +
>       /* set the src image configuration */
>       regs.src_cfg = src_img_cfg[req->src.format];
>       regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
>       regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
> -     regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
>       regs.src_pack = pack_pattern[req->src.format];
>
>       /* set the dest image configuration */
>       regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
> -     regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
>       regs.dst_pack = pack_pattern[req->dst.format];
>
>       /* set src, bpp, start pixel and ystride */
>       regs.src_bpp = bytes_per_pixel[req->src.format];
>       regs.src0 = src_start + req->src.offset;
>       regs.src_ystride = req->src.width * regs.src_bpp;
> +     set_src_region(&req->src, &req->src_rect, &regs);
>       get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
>                       regs.src_cfg, &regs.src1, &regs.src_ystride);
>       regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width))
> *
> @@ -668,6 +425,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
>       regs.dst_bpp = bytes_per_pixel[req->dst.format];
>       regs.dst0 = dst_start + req->dst.offset;
>       regs.dst_ystride = req->dst.width * regs.dst_bpp;
> +     set_dst_region(&req->dst_rect, &regs);
>       get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
>                       regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
>       regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width))
> *
> @@ -703,9 +461,11 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
>               req->dst_rect.x = req->dst_rect.x & (~0x1);
>               req->dst_rect.w = req->dst_rect.w & (~0x1);
>       }
> -     if (get_edge_cond(req, &regs))
> -             return -EINVAL;
>
> +#ifdef CONFIG_MSM_MDP22
> +     if (mdp_ppp_cfg_edge_cond(req, &regs))
> +             return -EINVAL;
> +#endif
>       send_blit(mdp, req, &regs, src_file, dst_file);
>       return 0;
>  }
> diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
> index ef3b125..c3cd895 100644
> --- a/drivers/video/msm/mdp_ppp.h
> +++ b/drivers/video/msm/mdp_ppp.h
> @@ -47,4 +47,16 @@ struct ppp_regs {
>       uint32_t bg_ystride;
>  };
>
> +struct mdp_info;
> +struct mdp_rect;
> +struct mdp_blit_req;
> +
> +void mdp_ppp_init_scale(const struct mdp_info *mdp);
> +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);
> +int mdp_ppp_load_blur(const struct mdp_info *mdp);
> +
> +int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs
> *regs);
> +
>  #endif /* _VIDEO_MSM_MDP_PPP_H_ */
> diff --git a/drivers/video/msm/mdp_scale_tables.c
> b/drivers/video/msm/mdp_ppp22.c
> similarity index 69%
> rename from drivers/video/msm/mdp_scale_tables.c
> rename to drivers/video/msm/mdp_ppp22.c
> index 604783b..8cfcff2 100644
> --- a/drivers/video/msm/mdp_scale_tables.c
> +++ b/drivers/video/msm/mdp_ppp22.c
> @@ -1,6 +1,6 @@
> -/* drivers/video/msm_fb/mdp_scale_tables.c
> +/* drivers/video/msm/mdp_ppp22.c
>   *
> - * Copyright (C) 2007 QUALCOMM Incorporated
> + * Copyright (C) 2007, 2011 Code Aurora Forum. All rights reserved.
>   * Copyright (C) 2007 Google Incorporated
>   *
>   * This software is licensed under the terms of the GNU General Public
> @@ -13,10 +13,33 @@
>   * GNU General Public License for more details.
>   */
>
> -#include "mdp_scale_tables.h"
> +#include <linux/kernel.h>
> +#include <linux/io.h>
> +#include <linux/msm_mdp.h>
> +
>  #include "mdp_hw.h"
> +#include "mdp_ppp.h"
> +
> +struct mdp_table_entry {
> +     uint32_t reg;
> +     uint32_t val;
> +};
> +
> +enum {
> +     MDP_DOWNSCALE_PT2TOPT4,
> +     MDP_DOWNSCALE_PT4TOPT6,
> +     MDP_DOWNSCALE_PT6TOPT8,
> +     MDP_DOWNSCALE_PT8TO1,
> +     MDP_DOWNSCALE_MAX,
> +
> +     /* not technically in the downscale table list */
> +     MDP_DOWNSCALE_BLUR,
> +};
>
> -struct mdp_table_entry mdp_upscale_table[] = {
> +static int downscale_x_table;
> +static int downscale_y_table;
> +
> +static struct mdp_table_entry mdp_upscale_table[] = {
>       { 0x5fffc, 0x0 },
>       { 0x50200, 0x7fc00000 },
>       { 0x5fffc, 0xff80000d },
> @@ -764,3 +787,305 @@ struct mdp_table_entry mdp_gaussian_blur_table[] = {
>       { 0x5fffc, 0x20000080 },
>       { 0x5037c, 0x20000080 },
>  };
> +
> +static void load_table(const struct mdp_info *mdp,
> +                    struct mdp_table_entry *table, int len)
> +{
> +     int i;
> +     for (i = 0; i < len; i++)
> +             mdp_writel(mdp, table[i].val, table[i].reg);
> +}
> +
> +enum {
> +     IMG_LEFT,
> +     IMG_RIGHT,
> +     IMG_TOP,
> +     IMG_BOTTOM,
> +};
> +
> +static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
> +                       uint32_t *interp1, uint32_t *interp2,
> +                       uint32_t *repeat1, uint32_t *repeat2) {
> +     if (src > 3 * dst) {
> +             *interp1 = 0;
> +             *interp2 = src - 1;
> +             *repeat1 = 0;
> +             *repeat2 = 0;
> +     } else if (src = 3 * dst) {
> +             *interp1 = 0;
> +             *interp2 = src;
> +             *repeat1 = 0;
> +             *repeat2 = 1;
> +     } else if (src > dst && src < 3 * dst) {
> +             *interp1 = -1;
> +             *interp2 = src;
> +             *repeat1 = 1;
> +             *repeat2 = 1;
> +     } else if (src = dst) {
> +             *interp1 = -1;
> +             *interp2 = src + 1;
> +             *repeat1 = 1;
> +             *repeat2 = 2;
> +     } else {
> +             *interp1 = -2;
> +             *interp2 = src + 1;
> +             *repeat1 = 2;
> +             *repeat2 = 2;
> +     }
> +     *interp1 += src_coord;
> +     *interp2 += src_coord;
> +}
> +
> +int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs
> *regs)
> +{
> +     int32_t luma_interp[4];
> +     int32_t luma_repeat[4];
> +     int32_t chroma_interp[4];
> +     int32_t chroma_bound[4];
> +     int32_t chroma_repeat[4];
> +     uint32_t dst_w, dst_h;
> +
> +     memset(&luma_interp, 0, sizeof(int32_t) * 4);
> +     memset(&luma_repeat, 0, sizeof(int32_t) * 4);
> +     memset(&chroma_interp, 0, sizeof(int32_t) * 4);
> +     memset(&chroma_bound, 0, sizeof(int32_t) * 4);
> +     memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
> +     regs->edge = 0;
> +
> +     if (req->flags & MDP_ROT_90) {
> +             dst_w = req->dst_rect.h;
> +             dst_h = req->dst_rect.w;
> +     } else {
> +             dst_w = req->dst_rect.w;
> +             dst_h = req->dst_rect.h;
> +     }
> +
> +     if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
> +             get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
> +                           &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
> +                           &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
> +             get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
> +                           &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
> +                           &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
> +     } else {
> +             luma_interp[IMG_LEFT] = req->src_rect.x;
> +             luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w -
> 1;
> +             luma_interp[IMG_TOP] = req->src_rect.y;
> +             luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h -
> 1;
> +             luma_repeat[IMG_LEFT] = 0;
> +             luma_repeat[IMG_TOP] = 0;
> +             luma_repeat[IMG_RIGHT] = 0;
> +             luma_repeat[IMG_BOTTOM] = 0;
> +     }
> +
> +     chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
> +     chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
> +     chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
> +     chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
> +
> +     chroma_bound[IMG_LEFT] = req->src_rect.x;
> +     chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
> +     chroma_bound[IMG_TOP] = req->src_rect.y;
> +     chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
> +
> +     if (IS_YCRCB(req->src.format)) {
> +             chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
> +             chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >>
> 1;
> +
> +             chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
> +             chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
> +     }
> +
> +     if (req->src.format = MDP_Y_CBCR_H2V2 ||
> +         req->src.format = MDP_Y_CRCB_H2V2) {
> +             chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
> +             chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
> +                                         >> 1;
> +             chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
> +             chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
> +     }
> +
> +     chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
> +                               chroma_interp[IMG_LEFT];
> +     chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
> +                               chroma_bound[IMG_RIGHT];
> +     chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
> +                               chroma_interp[IMG_TOP];
> +     chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
> +                               chroma_bound[IMG_BOTTOM];
> +
> +     if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
> +         chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
> +         chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
> +         chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3
> ||
> +         luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
> +         luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
> +         luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
> +         luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
> +             return -1;
Please use error codes defined by linux-kernel.
Please refer to:
http://lxr.linux.no/#linux+v2.6.38/include/asm-generic/errno-base.h
Here you can use -EINVAL for invalid value.

> +
> +     regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
> +     regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
> +     regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
> +     regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
> +     regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
> +     regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
> +     regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
> +     regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
> +     return 0;
> +}
> +
> +#define ONE_HALF     (1LL << 32)
> +#define ONE          (1LL << 33)
> +#define TWO          (2LL << 33)
> +#define THREE                (3LL << 33)
> +#define FRAC_MASK (ONE - 1)
> +#define INT_MASK (~FRAC_MASK)
> +
> +static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t
> origin,
> +                     uint32_t *phase_init, uint32_t *phase_step)
> +{
> +     /* to improve precicsion calculations are done in U31.33 and
> converted
> +      * to U3.29 at the end */
[cosmetic comment]: Multiline comments?

> +     int64_t k1, k2, k3, k4, tmp;
> +     uint64_t n, d, os, os_p, od, od_p, oreq;
> +     unsigned rpa = 0;
> +     int64_t ip64, delta;
> +
> +     if (dim_out % 3 = 0)
> +             rpa = !(dim_in % (dim_out / 3));
> +
> +     n = ((uint64_t)dim_out) << 34;
> +     d = dim_in;
> +     if (!d)
> +             return -1;

Please use standard error codes.

> +     do_div(n, d);
> +     k3 = (n + 1) >> 1;
> +     if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31))
> +             return -1;
> +
> +     n = ((uint64_t)dim_in) << 34;
> +     d = (uint64_t)dim_out;
> +     if (!d)
> +             return -1;
Same: Please use standard error codes.


> +     do_div(n, d);
> +     k1 = (n + 1) >> 1;
> +     k2 = (k1 - ONE) >> 1;
> +
> +     *phase_init = (int)(k2 >> 4);
> +     k4 = (k3 - ONE) >> 1;
> +
> +     if (rpa) {
> +             os = ((uint64_t)origin << 33) - ONE_HALF;
> +             tmp = (dim_out * os) + ONE_HALF;
> +             if (!dim_in)
> +                     return -1;
> +             do_div(tmp, dim_in);
> +             od = tmp - ONE_HALF;
> +     } else {
> +             os = ((uint64_t)origin << 1) - 1;
> +             od = (((k3 * os) >> 1) + k4);
> +     }
> +
> +     od_p = od & INT_MASK;
> +     if (od_p != od)
> +             od_p += ONE;
> +
> +     if (rpa) {
> +             tmp = (dim_in * od_p) + ONE_HALF;
> +             if (!dim_in)
> +                     return -1;
> +             do_div(tmp, dim_in);
> +             os_p = tmp - ONE_HALF;
> +     } else {
> +             os_p = ((k1 * (od_p >> 33)) + k2);
> +     }
> +
> +     oreq = (os_p & INT_MASK) - ONE;
> +
> +     ip64 = os_p - oreq;
> +     delta = ((int64_t)(origin) << 33) - oreq;
> +     ip64 -= delta;
> +     /* limit to valid range before the left shift */
> +     delta = (ip64 & (1LL << 63)) ? 4 : -4;
> +     delta <<= 33;
> +     while (abs((int)(ip64 >> 33)) > 4)
> +             ip64 += delta;
> +     *phase_init = (int)(ip64 >> 4);
> +     *phase_step = (uint32_t)(k1 >> 4);
> +     return 0;
> +}
> +
> +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)
> +{
> +     int downscale;
> +     uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
> +     uint32_t scale_factor_x, scale_factor_y;
> +
> +     if (scale_params(src_rect->w, dst_rect->w, 1, &phase_init_x,
> +                      &phase_step_x) ||
> +         scale_params(src_rect->h, dst_rect->h, 1, &phase_init_y,
> +                      &phase_step_y))
> +             return -1;


Error code?

> +
> +     regs->phasex_init = phase_init_x;
> +     regs->phasey_init = phase_init_y;
> +     regs->phasex_step = phase_step_x;
> +     regs->phasey_step = phase_step_y;
> +
> +     scale_factor_x = (dst_rect->w * 10) / src_rect->w;
> +     scale_factor_y = (dst_rect->h * 10) / src_rect->h;
> +
> +     if (scale_factor_x > 8)
> +             downscale = MDP_DOWNSCALE_PT8TO1;
> +     else if (scale_factor_x > 6)
> +             downscale = MDP_DOWNSCALE_PT6TOPT8;
> +     else if (scale_factor_x > 4)
> +             downscale = MDP_DOWNSCALE_PT4TOPT6;
> +     else
> +             downscale = MDP_DOWNSCALE_PT2TOPT4;
> +
> +     if (downscale != downscale_x_table) {
> +             load_table(mdp, mdp_downscale_x_table[downscale], 64);
> +             downscale_x_table = downscale;
> +     }
> +
> +     if (scale_factor_y > 8)
> +             downscale = MDP_DOWNSCALE_PT8TO1;
> +     else if (scale_factor_y > 6)
> +             downscale = MDP_DOWNSCALE_PT6TOPT8;
> +     else if (scale_factor_y > 4)
> +             downscale = MDP_DOWNSCALE_PT4TOPT6;
> +     else
> +             downscale = MDP_DOWNSCALE_PT2TOPT4;
> +
> +     if (downscale != downscale_y_table) {
> +             load_table(mdp, mdp_downscale_y_table[downscale], 64);
> +             downscale_y_table = downscale;
> +     }
> +
> +     return 0;
> +}
> +
> +
[cosmetic comment]: Extra line?

> +int mdp_ppp_load_blur(const struct mdp_info *mdp)
> +{
> +     if (!(downscale_x_table = MDP_DOWNSCALE_BLUR &&
> +             downscale_y_table = MDP_DOWNSCALE_BLUR)) {
> +             load_table(mdp, mdp_gaussian_blur_table, 128);
> +             downscale_x_table = MDP_DOWNSCALE_BLUR;
> +             downscale_y_table = MDP_DOWNSCALE_BLUR;
> +     }
> +
> +     return 0;
> +}
> +
> +void mdp_ppp_init_scale(const struct mdp_info *mdp)
> +{
> +     downscale_x_table = MDP_DOWNSCALE_MAX;
> +     downscale_y_table = MDP_DOWNSCALE_MAX;
> +
> +     load_table(mdp, mdp_upscale_table, ARRAY_SIZE(mdp_upscale_table));
> +}
> diff --git a/drivers/video/msm/mdp_scale_tables.h
> b/drivers/video/msm/mdp_scale_tables.h
> deleted file mode 100644
> index 34077b1..0000000
> --- a/drivers/video/msm/mdp_scale_tables.h
> +++ /dev/null
> @@ -1,38 +0,0 @@
> -/* drivers/video/msm_fb/mdp_scale_tables.h
> - *
> - * Copyright (C) 2007 QUALCOMM Incorporated
> - * Copyright (C) 2007 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.
> - */
> -#ifndef _MDP_SCALE_TABLES_H_
> -#define _MDP_SCALE_TABLES_H_
> -
> -#include <linux/types.h>
> -struct mdp_table_entry {
> -     uint32_t reg;
> -     uint32_t val;
> -};
> -
> -extern struct mdp_table_entry mdp_upscale_table[64];
> -
> -enum {
> -     MDP_DOWNSCALE_PT2TOPT4,
> -     MDP_DOWNSCALE_PT4TOPT6,
> -     MDP_DOWNSCALE_PT6TOPT8,
> -     MDP_DOWNSCALE_PT8TO1,
> -     MDP_DOWNSCALE_MAX,
> -};
> -
> -extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
> -extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
> -extern struct mdp_table_entry mdp_gaussian_blur_table[];
> -
> -#endif
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
>
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH 07/20] video: msm: Allow users to request a larger x and
From: Janorkar, Mayuresh @ 2011-03-21  4:52 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300485381-27201-1-git-send-email-carlv@codeaurora.org>



> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-
> owner@vger.kernel.org] On Behalf Of Carl Vanderlip
> Sent: Saturday, March 19, 2011 3:26 AM
> To: David Brown; Daniel Walker; Bryan Huntsman
> Cc: Brian Swetland; Dima Zavin; Rebecca Schultz Zavin; Colin Cross; linux-
> fbdev@vger.kernel.org; Carl Vanderlip; linux-arm-
> kernel@lists.infradead.org; linux-arm-msm@vger.kernel.org; linux-
> kernel@vger.kernel.org
> Subject: [PATCH 07/20] video: msm: Allow users to request a larger x and y
> virtual fb
> 
> As long as the total size fits inside the memory allocated to the
> framebuffer
> users can request a larger size. This change allows users to request a
> triple
> buffered fb.
> 
> 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>
> ---
>  drivers/video/msm/msm_fb.c |   63 ++++++++++++++++++++++++++++++++++-----
> ----
>  1 files changed, 50 insertions(+), 13 deletions(-)
> 
> diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
> index 04d0067..6af8b41 100644
> --- a/drivers/video/msm/msm_fb.c
> +++ b/drivers/video/msm/msm_fb.c
> @@ -53,6 +53,9 @@ do { \
>  		printk(KERN_INFO "msmfb: "fmt, ##args); \
>  } while (0)
> 
> +#define BITS_PER_PIXEL(info) (info->fb->var.bits_per_pixel)
> +#define BYTES_PER_PIXEL(info) (info->fb->var.bits_per_pixel >> 3)
> +
>  static int msmfb_debug_mask;
>  module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
>  		   S_IRUGO | S_IWUSR | S_IWGRP);
> @@ -161,9 +164,10 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
>  	}
>  	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
> 
> -	addr = ((msmfb->xres * (yoffset + y) + x) * 2);
> +	addr = ((msmfb->xres * (yoffset + y) + x) * BYTES_PER_PIXEL(msmfb));
>  	mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
> -		 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
> +		 msmfb->xres * BYTES_PER_PIXEL(msmfb), w, h, x, y,
> +		 &msmfb->dma_callback,
>  		 panel->interface_type);
>  	return 0;
>  error:
> @@ -323,14 +327,46 @@ error:
> 
>  static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info
> *info)
>  {
> +	u32 size;
> +
>  	if ((var->xres != info->var.xres) ||
>  	    (var->yres != info->var.yres) ||
> -	    (var->xres_virtual != info->var.xres_virtual) ||
> -	    (var->yres_virtual != info->var.yres_virtual) ||
>  	    (var->xoffset != info->var.xoffset) ||
>  	    (var->bits_per_pixel != info->var.bits_per_pixel) ||
>  	    (var->grayscale != info->var.grayscale))
>  		 return -EINVAL;
> +
> +	size = var->xres_virtual * var->yres_virtual *
> +		(var->bits_per_pixel >> 3);

How about defining a new macro BYTES_PER_PIXEL_VAR for fb_var_screeninfo also? That would make code more readable.

> +	if (size > info->fix.smem_len)
> +		return -EINVAL;
> +	return 0;
> +}
> +
> +static int msmfb_set_par(struct fb_info *info)
> +{
> +	struct fb_var_screeninfo *var = &info->var;
> +	struct fb_fix_screeninfo *fix = &info->fix;
> +
> +	/* we only support RGB ordering for now */
> +	if (var->bits_per_pixel = 32 || var->bits_per_pixel = 24) {
> +		var->red.offset = 0;
> +		var->red.length = 8;
> +		var->green.offset = 8;
> +		var->green.length = 8;
> +		var->blue.offset = 16;
> +		var->blue.length = 8;

var->red is a fb_bitfield variable.
It provides offset, length and msb_right.

struct fb_bitfield {
    __u32 offset;                   /* beginning of bitfield        */
    __u32 length;                   /* length of bitfield           */
    __u32 msb_right;                /* != 0 : Most significant bit is */ 
                                    /* right */ 
}
Please don't keep msb_right unassigned.

> +	} else if (var->bits_per_pixel = 16) {
> +		var->red.offset = 11;
> +		var->red.length = 5;
> +		var->green.offset = 5;
> +		var->green.length = 6;
> +		var->blue.offset = 0;
> +		var->blue.length = 5;
> +	} else
> +		return -1;

Please use standard error code provided by Linux kernel -EINVAL
(-22 Invalid argument)

> +	fix->line_length = var->xres * var->bits_per_pixel / 8;
Why to divide by 8? Atleast use >>3, bitwise operations that would take less cpu cycles)
As I stated earlier define a new macro for var also.

> +
>  	return 0;
>  }
> 
> @@ -427,6 +463,7 @@ static struct fb_ops msmfb_ops = {
>  	.fb_open = msmfb_open,
>  	.fb_release = msmfb_release,
>  	.fb_check_var = msmfb_check_var,
> +	.fb_set_par = msmfb_set_par,
>  	.fb_pan_display = msmfb_pan_display,
>  	.fb_fillrect = msmfb_fillrect,
>  	.fb_copyarea = msmfb_copyarea,
> @@ -438,8 +475,6 @@ static unsigned PP[16];
> 
> 
> 
> -#define BITS_PER_PIXEL 16
> -
>  static void setup_fb_info(struct msmfb_info *msmfb)
>  {
>  	struct fb_info *fb_info = msmfb->fb;
> @@ -462,7 +497,7 @@ static void setup_fb_info(struct msmfb_info *msmfb)
>  	fb_info->var.height = msmfb->panel->fb_data->height;
>  	fb_info->var.xres_virtual = msmfb->xres;
>  	fb_info->var.yres_virtual = msmfb->yres * 2;
> -	fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
> +	fb_info->var.bits_per_pixel = 16;
>  	fb_info->var.accel_flags = 0;
> 
>  	fb_info->var.yoffset = 0;
> @@ -497,28 +532,30 @@ static int setup_fbmem(struct msmfb_info *msmfb,
> struct platform_device *pdev)
>  	struct fb_info *fb = msmfb->fb;
>  	struct resource *resource;
>  	unsigned long size = msmfb->xres * msmfb->yres *
> -			     (BITS_PER_PIXEL >> 3) * 2;
> +		BYTES_PER_PIXEL(msmfb) * 2;
> +	unsigned long resource_size;
>  	unsigned char *fbram;
> 
>  	/* board file might have attached a resource describing an fb */
>  	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>  	if (!resource)
>  		return -EINVAL;
> +	resource_size = resource->end - resource->start + 1;
> 
>  	/* check the resource is large enough to fit the fb */
> -	if (resource->end - resource->start < size) {
> -		printk(KERN_ERR "allocated resource is too small for "
> +	if (resource_size < size) {
> +		printk(KERN_ERR "msmfb: allocated resource is too small for "
>  				"fb\n");
>  		return -ENOMEM;
>  	}
>  	fb->fix.smem_start = resource->start;
> -	fb->fix.smem_len = resource->end - resource->start;
> -	fbram = ioremap(resource->start,
> -			resource->end - resource->start);
> +	fb->fix.smem_len = resource_size;
> +	fbram = ioremap(resource->start, resource_size);
>  	if (fbram = 0) {
>  		printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
>  		return -ENOMEM;
>  	}
> +
>  	fb->screen_base = fbram;
>  	return 0;
>  }
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [patch] fbdev: sh_mobile_lcdc: checking NULL instead of
From: Dan Carpenter @ 2011-03-21  4:39 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110319043647.GZ2008@bicker>

On Mon, Mar 21, 2011 at 09:47:50AM +0530, Janorkar, Mayuresh wrote:
> > backlight_device_register() returns an ERR_PTR.  It doesn't return NULL.
> 
> The patch is not applying on the master branch of fbdev tree.
> I could find another branch: 	fbdev/shmobile on the tree.
> It is a good idea to mention this in the description of the patch.
> 

Sorry, I'm working against linux-next so I wasn't aware.

> > 
> > Signed-off-by: Dan Carpenter <error27@gmail.com>
> > 
> > diff --git a/drivers/video/sh_mobile_lcdcfb.c
> > b/drivers/video/sh_mobile_lcdcfb.c
> > index bf2629f..a53abe1 100644
> > --- a/drivers/video/sh_mobile_lcdcfb.c
> > +++ b/drivers/video/sh_mobile_lcdcfb.c
> > @@ -1088,7 +1088,7 @@ static struct backlight_device
> > *sh_mobile_lcdc_bl_probe(struct device *parent,
> > 
> >  	bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch,
> >  				       &sh_mobile_lcdc_bl_ops, NULL);
> > -	if (!bl) {
> > +	if (IS_ERR(bl)) {
> >  		dev_err(parent, "unable to register backlight device\n");
> 
> 
> How about printing the error number here?
> 

Ok.  That's a good idea.

> >  		return NULL;
> 
> Code is not checking for return value where this function is called.
> 
> A code snippet where this function is called:
> /* probe the backlight is there is one defined */
>                  if (ch->cfg.bl_info.max_brightness)
>                        ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);
> 
> If the return value is not checked then whats the use of return value?
> 

It is checked actually.  Look at the places which would dereference
->bl.

> >  	}
> > --
> > To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> > the body of a message to majordomo@vger.kernel.org
> > More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [PATCH 01/20] video: msm: Fix typo 'mpd'->'mdp'
From: Janorkar, Mayuresh @ 2011-03-21  4:36 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300485095-26923-1-git-send-email-carlv@codeaurora.org>



> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-
> owner@vger.kernel.org] On Behalf Of Carl Vanderlip
> Sent: Saturday, March 19, 2011 3:22 AM
> To: Russell King; David Brown; Daniel Walker; Bryan Huntsman
> Cc: Brian Swetland; Dima Zavin; Rebecca Schultz Zavin; Colin Cross; linux-
> fbdev@vger.kernel.org; linux-arm-kernel@lists.infradead.org; linux-arm-
> msm@vger.kernel.org; linux-kernel@vger.kernel.org; Carl Vanderlip
> Subject: [PATCH 01/20] video: msm: Fix typo 'mpd'->'mdp'
> 
> From: Brian Swetland <swetland@google.com>
> 
> Trivial fix

The Subject line states that you are only changing a typo from mpd to mdp.
The description doesn't state anything more.
But the patch is changing Copyright info also.
> 
> 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/include/mach/msm_fb.h |    2 +-
>  drivers/video/msm/mdp.c                 |    8 ++++----
>  drivers/video/msm/mdp_ppp.c             |   10 +++++-----
>  drivers/video/msm/msm_fb.c              |    1 -
>  4 files changed, 10 insertions(+), 11 deletions(-)
> 
> diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-
> msm/include/mach/msm_fb.h
> index 1f4fc81..da11719 100644
> --- a/arch/arm/mach-msm/include/mach/msm_fb.h
> +++ b/arch/arm/mach-msm/include/mach/msm_fb.h
> @@ -114,7 +114,7 @@ struct mdp_blit_req;
>  struct fb_info;
>  struct mdp_device {
>  	struct device dev;
> -	void (*dma)(struct mdp_device *mpd, uint32_t addr,
> +	void (*dma)(struct mdp_device *mdp, uint32_t addr,
>  		    uint32_t stride, uint32_t w, uint32_t h, uint32_t x,
>  		    uint32_t y, struct msmfb_callback *callback, int
> interface);
>  	void (*dma_wait)(struct mdp_device *mdp);
> diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
> index c3636d5..45af97d 100644
> --- a/drivers/video/msm/mdp.c
> +++ b/drivers/video/msm/mdp.c
> @@ -2,7 +2,7 @@
>   *
>   * MSM MDP Interface (used by framebuffer core)
>   *
> - * Copyright (C) 2007 QUALCOMM Incorporated
> + * Copyright (C) 2007, 2011 Code Aurora Forum. All rights reserved.

It is a change from 2007 to 2011 and the company name is being changed.
I think it should be mentioned in the Subject/Description.

>   * Copyright (C) 2007 Google Incorporated
>   *
>   * This software is licensed under the terms of the GNU General Public
> @@ -288,7 +288,7 @@ int mdp_blit(struct mdp_device *mdp_dev, struct
> fb_info *fb,
>  	/* WORKAROUND FOR HARDWARE BUG IN BG TILE FETCH */
>  	if (unlikely(req->src_rect.h = 0 ||
>  		     req->src_rect.w = 0)) {
> -		printk(KERN_ERR "mpd_ppp: src img of zero size!\n");
> +		printk(KERN_ERR "mdp_ppp: src img of zero size!\n");
>  		return -EINVAL;
>  	}
>  	if (unlikely(req->dst_rect.h = 0 ||
> @@ -298,13 +298,13 @@ int mdp_blit(struct mdp_device *mdp_dev, struct
> fb_info *fb,
>  	/* do this first so that if this fails, the caller can always
>  	 * safely call put_img */
>  	if (unlikely(get_img(&req->src, fb, &src_start, &src_len,
> &src_file))) {
> -		printk(KERN_ERR "mpd_ppp: could not retrieve src image from "
> +		printk(KERN_ERR "mdp_ppp: could not retrieve src image from "
>  				"memory\n");
>  		return -EINVAL;
>  	}
> 
>  	if (unlikely(get_img(&req->dst, fb, &dst_start, &dst_len,
> &dst_file))) {
> -		printk(KERN_ERR "mpd_ppp: could not retrieve dst image from "
> +		printk(KERN_ERR "mdp_ppp: could not retrieve dst image from "
>  				"memory\n");
>  		return -EINVAL;
>  	}
> diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
> index 4ff001f..2b04027 100644
> --- a/drivers/video/msm/mdp_ppp.c
> +++ b/drivers/video/msm/mdp_ppp.c
> @@ -1,6 +1,6 @@
>  /* drivers/video/msm/mdp_ppp.c
>   *
> - * Copyright (C) 2007 QUALCOMM Incorporated
> + * Copyright (C) 2007, 2011 Code Aurora Forum. All rights reserved.

Same here.

>   * Copyright (C) 2007 Google Incorporated
>   *
>   * This software is licensed under the terms of the GNU General Public
> @@ -650,7 +650,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
> 
>  	if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
>  		     req->dst.format >= MDP_IMGTYPE_LIMIT)) {
> -		printk(KERN_ERR "mpd_ppp: img is of wrong format\n");
> +		printk(KERN_ERR "mdp_ppp: img is of wrong format\n");
>  		return -EINVAL;
>  	}
> 
> @@ -658,7 +658,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
>  		     req->src_rect.y > req->src.height ||
>  		     req->dst_rect.x > req->dst.width ||
>  		     req->dst_rect.y > req->dst.height)) {
> -		printk(KERN_ERR "mpd_ppp: img rect is outside of img!\n");
> +		printk(KERN_ERR "mdp_ppp: img rect is outside of img!\n");
>  		return -EINVAL;
>  	}
> 
> @@ -694,7 +694,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
> 
>  	if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
>  			   &regs)) {
> -		printk(KERN_ERR "mpd_ppp: final src or dst location is "
> +		printk(KERN_ERR "mdp_ppp: final src or dst location is "
>  			"invalid, are you trying to make an image too large "
>  			"or to place it outside the screen?\n");
>  		return -EINVAL;
> @@ -708,7 +708,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct
> mdp_blit_req *req,
>  		regs.op |= PPP_OP_DITHER_EN;
>  	blit_blend(req, &regs);
>  	if (blit_scale(mdp, req, &regs)) {
> -		printk(KERN_ERR "mpd_ppp: error computing scale for img.\n");
> +		printk(KERN_ERR "mdp_ppp: error computing scale for img.\n");
>  		return -EINVAL;
>  	}
>  	blit_blur(mdp, req, &regs);
> diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
> index 5436aeb..04d0067 100644
> --- a/drivers/video/msm/msm_fb.c
> +++ b/drivers/video/msm/msm_fb.c
> @@ -321,7 +321,6 @@ error:
>  	mutex_unlock(&msmfb->panel_init_lock);
>  }
> 
> -
>  static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info
> *info)
>  {
>  	if ((var->xres != info->var.xres) ||
> --
> Sent by an employee of the Qualcomm Innovation Center, Inc.
> The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* RE: [patch] fbdev: sh_mobile_lcdc: checking NULL instead of IS_ERR()
From: Janorkar, Mayuresh @ 2011-03-21  4:29 UTC (permalink / raw)
  To: linux-fbdev
In-Reply-To: <20110319043647.GZ2008@bicker>



> -----Original Message-----
> From: linux-fbdev-owner@vger.kernel.org [mailto:linux-fbdev-
> owner@vger.kernel.org] On Behalf Of Dan Carpenter
> Sent: Saturday, March 19, 2011 10:07 AM
> To: Paul Mundt
> Cc: Guennadi Liakhovetski; Magnus Damm; linux-fbdev@vger.kernel.org;
> kernel-janitors@vger.kernel.org
> Subject: [patch] fbdev: sh_mobile_lcdc: checking NULL instead of IS_ERR()
> 
> backlight_device_register() returns an ERR_PTR.  It doesn't return NULL.

The patch is not applying on the master branch of fbdev tree.
I could find another branch: 	fbdev/shmobile on the tree.
It is a good idea to mention this in the description of the patch.

> 
> Signed-off-by: Dan Carpenter <error27@gmail.com>
> 
> diff --git a/drivers/video/sh_mobile_lcdcfb.c
> b/drivers/video/sh_mobile_lcdcfb.c
> index bf2629f..a53abe1 100644
> --- a/drivers/video/sh_mobile_lcdcfb.c
> +++ b/drivers/video/sh_mobile_lcdcfb.c
> @@ -1088,7 +1088,7 @@ static struct backlight_device
> *sh_mobile_lcdc_bl_probe(struct device *parent,
> 
>  	bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch,
>  				       &sh_mobile_lcdc_bl_ops, NULL);
> -	if (!bl) {
> +	if (IS_ERR(bl)) {
>  		dev_err(parent, "unable to register backlight device\n");


How about printing the error number here?

>  		return NULL;

Code is not checking for return value where this function is called.

A code snippet where this function is called:
/* probe the backlight is there is one defined */
                 if (ch->cfg.bl_info.max_brightness)
                       ch->bl = sh_mobile_lcdc_bl_probe(&pdev->dev, ch);

If the return value is not checked then whats the use of return value?

>  	}
> --
> To unsubscribe from this list: send the line "unsubscribe linux-fbdev" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html

^ permalink raw reply

* Re: [PATCH 09/20] video: msm: Split out MDP2.2 HW specific code.
From: Russell King - ARM Linux @ 2011-03-20  9:22 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300485423-27281-1-git-send-email-carlv@codeaurora.org>

On Fri, Mar 18, 2011 at 02:57:03PM -0700, Carl Vanderlip wrote:
> +int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
> +{
> +	int32_t luma_interp[4];
> +	int32_t luma_repeat[4];
> +	int32_t chroma_interp[4];
> +	int32_t chroma_bound[4];
> +	int32_t chroma_repeat[4];
> +	uint32_t dst_w, dst_h;
> +
> +	memset(&luma_interp, 0, sizeof(int32_t) * 4);
> +	memset(&luma_repeat, 0, sizeof(int32_t) * 4);
> +	memset(&chroma_interp, 0, sizeof(int32_t) * 4);
> +	memset(&chroma_bound, 0, sizeof(int32_t) * 4);
> +	memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
> +	regs->edge = 0;
> +
> +	if (req->flags & MDP_ROT_90) {
> +		dst_w = req->dst_rect.h;
> +		dst_h = req->dst_rect.w;
> +	} else {
> +		dst_w = req->dst_rect.w;
> +		dst_h = req->dst_rect.h;
> +	}
> +
> +	if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
> +		get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
> +			      &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
> +			      &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
> +		get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
> +			      &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
> +			      &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
> +	} else {
> +		luma_interp[IMG_LEFT] = req->src_rect.x;
> +		luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
> +		luma_interp[IMG_TOP] = req->src_rect.y;
> +		luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
> +		luma_repeat[IMG_LEFT] = 0;
> +		luma_repeat[IMG_TOP] = 0;
> +		luma_repeat[IMG_RIGHT] = 0;
> +		luma_repeat[IMG_BOTTOM] = 0;
> +	}
> +
> +	chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
> +	chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
> +	chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
> +	chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
> +
> +	chroma_bound[IMG_LEFT] = req->src_rect.x;
> +	chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
> +	chroma_bound[IMG_TOP] = req->src_rect.y;
> +	chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
> +
> +	if (IS_YCRCB(req->src.format)) {
> +		chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
> +		chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
> +
> +		chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
> +		chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
> +	}
> +
> +	if (req->src.format = MDP_Y_CBCR_H2V2 ||
> +	    req->src.format = MDP_Y_CRCB_H2V2) {
> +		chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
> +		chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
> +					    >> 1;
> +		chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
> +		chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
> +	}
> +
> +	chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
> +				  chroma_interp[IMG_LEFT];
> +	chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
> +				  chroma_bound[IMG_RIGHT];
> +	chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
> +				  chroma_interp[IMG_TOP];
> +	chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
> +				  chroma_bound[IMG_BOTTOM];
> +
> +	if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
> +	    chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
> +	    chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
> +	    chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
> +	    luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
> +	    luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
> +	    luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
> +	    luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
> +		return -1;

Lazy programming strikes again.  Public functions really should not
return things that look like errno codes, rather they should return
real errno codes.

Secondly, why is this stuff, which looks very driver like, under arch/arm
and not in drivers/ somewhere?

^ permalink raw reply

* Re: Future desktop on dumb frame buffers?
From: Rob Clark @ 2011-03-19 15:45 UTC (permalink / raw)
  To: Geert Uytterhoeven; +Cc: Linux Fbdev development list, dri-devel, wayland-devel
In-Reply-To: <AANLkTimJWpebAskcjA+qQUDWXjiH6aHta4fri9z6OxRN@mail.gmail.com>

On Sat, Mar 19, 2011 at 6:20 AM, Geert Uytterhoeven
<geert@linux-m68k.org> wrote:
> As noone responded to my question in
> http://www.spinics.net/lists/dri-devel/msg08851.html
> (yes, it was a bit hidden in a thread), I'm asking it here again (and
> also on the Wayland
> mailing list).
>
> Basically I'm still puzzled about this KMS thing. If the name "Kernel
> Mode Setting"
> covers it, then how does it compare to plain fbdev? Just additional frame buffer
> memory management?
> Also, some people may remember we did have kernel messages (e.g. oops, panic)
> on graphical consoles with fbdev, until people started not liking them
> showing up
> on their X desktops...

The KMS part of DRM has nothing to do with acceleration.  So it could
be implemented on a dumb framebuffer.  KMS is just about mode-setting,
and configuring framebuffer (memory) that is scanned out to one or
more displays.

BR,
-R

> Furthermore, everybody states that "future desktop" (that's
> http://wayland.freedesktop.org/)
> will require KMS drivers.
> How do/will we handle this on dumb frame buffers? It's not like we can't do
> "advanced" things like compositing using the CPU. Transparency may stretch
> it a bit on lower end CPUs, but you don't always need that.
>
> Thanks for your answers and comments!
>
> Gr{oetje,eeting}s,
>
>                         Geert
>
> --
> Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org
>
> In personal conversations with technical people, I call myself a hacker. But
> when I'm talking to journalists I just say "programmer" or something like that.
>                                 -- Linus Torvalds
> _______________________________________________
> dri-devel mailing list
> dri-devel@lists.freedesktop.org
> http://lists.freedesktop.org/mailman/listinfo/dri-devel
>

^ permalink raw reply

* Xrandr and udlfb
From: Alexander Todorov @ 2011-03-19 14:18 UTC (permalink / raw)
  To: linux-fbdev

Hello folks,
does udlfb support Xrandr? What I need is to be able to rotate the display which 
for some reason I can't. My xorg.conf:

Section "ServerFlags"
         Option "RandR" "on
EndSection

Section "Device"
         Identifier "dl"
         driver     "fbdev"
         Option "ReportDamage" "true"
         Option "fbdev"  "/dev/fb1"
EndSection

Section "Monitor"
         Identifier "monitor"
         Option "Rotate" "left"
         Option "DPMS" "false"
EndSection


I'm using the fbdev DisplayLink Xorg drvier.

When X starts and shows a browser on the screen it is in normal orientation. If 
I decide to use xrandr command I get:

$ xrandr -o left
RANDR failure: 8 (extension base 160)
00060294 000000e2 00000000 00057b2b
00020000 0000003c
X Error of failed request:  BadMatch (invalid parameter attributes)
   Major opcode of failed request:  148 (RANDR)
   Minor opcode of failed request:  2 (RRSetScreenConfig)
   Serial number of failed request:  14
   Current serial number in output stream:  14


Not sure if it is supported or I am missing something.


Regards,
Alexander.

^ permalink raw reply

* Future desktop on dumb frame buffers?
From: Geert Uytterhoeven @ 2011-03-19 11:20 UTC (permalink / raw)
  To: dri-devel, wayland-devel; +Cc: Linux Fbdev development list

As noone responded to my question in
http://www.spinics.net/lists/dri-devel/msg08851.html
(yes, it was a bit hidden in a thread), I'm asking it here again (and
also on the Wayland
mailing list).

Basically I'm still puzzled about this KMS thing. If the name "Kernel
Mode Setting"
covers it, then how does it compare to plain fbdev? Just additional frame buffer
memory management?
Also, some people may remember we did have kernel messages (e.g. oops, panic)
on graphical consoles with fbdev, until people started not liking them
showing up
on their X desktops...

Furthermore, everybody states that "future desktop" (that's
http://wayland.freedesktop.org/)
will require KMS drivers.
How do/will we handle this on dumb frame buffers? It's not like we can't do
"advanced" things like compositing using the CPU. Transparency may stretch
it a bit on lower end CPUs, but you don't always need that.

Thanks for your answers and comments!

Gr{oetje,eeting}s,

                        Geert

--
Geert Uytterhoeven -- There's lots of Linux beyond ia32 -- geert@linux-m68k.org

In personal conversations with technical people, I call myself a hacker. But
when I'm talking to journalists I just say "programmer" or something like that.
                                -- Linus Torvalds

^ permalink raw reply

* [patch] fbdev: sh_mobile_lcdc: checking NULL instead of IS_ERR()
From: Dan Carpenter @ 2011-03-19  4:36 UTC (permalink / raw)
  To: linux-fbdev

backlight_device_register() returns an ERR_PTR.  It doesn't return NULL.

Signed-off-by: Dan Carpenter <error27@gmail.com>

diff --git a/drivers/video/sh_mobile_lcdcfb.c b/drivers/video/sh_mobile_lcdcfb.c
index bf2629f..a53abe1 100644
--- a/drivers/video/sh_mobile_lcdcfb.c
+++ b/drivers/video/sh_mobile_lcdcfb.c
@@ -1088,7 +1088,7 @@ static struct backlight_device *sh_mobile_lcdc_bl_probe(struct device *parent,
 
 	bl = backlight_device_register(ch->cfg.bl_info.name, parent, ch,
 				       &sh_mobile_lcdc_bl_ops, NULL);
-	if (!bl) {
+	if (IS_ERR(bl)) {
 		dev_err(parent, "unable to register backlight device\n");
 		return NULL;
 	}

^ permalink raw reply related

* [PATCH 20/20] video: msm: Add support for MDP 3.1 (qsd8k)
From: Carl Vanderlip @ 2011-03-18 22:00 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

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.


^ permalink raw reply related

* [PATCH 19/20] video: msm: Separate calculation of base and offset
From: Carl Vanderlip @ 2011-03-18 21:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Separating the calculation of base and offset for luma and chroma allows
for easier specialization for HW targets.

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>
---
 drivers/video/msm/mdp_ppp.c |   56 ++++++++++++++++++++++--------------------
 1 files changed, 29 insertions(+), 27 deletions(-)

diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 290c29a..6d14c4f 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -100,6 +100,17 @@ static void rotate_dst_addr_y(struct mdp_blit_req *req,
 		       regs->dst_ystride;
 }
 
+static uint32_t get_luma_offset(struct mdp_img *img,
+				struct mdp_rect *rect, uint32_t bpp)
+{
+	return 0;
+}
+
+static uint32_t get_chroma_offset(struct mdp_img *img,
+				  struct mdp_rect *rect, uint32_t bpp)
+{
+	return 0;
+}
 static void blit_rotate(struct mdp_blit_req *req,
 			struct ppp_regs *regs)
 {
@@ -311,24 +322,14 @@ static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
 {
 }
 
-static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
-			    uint32_t base, uint32_t bpp, uint32_t cfg,
-			    uint32_t *addr, uint32_t *ystride)
+static uint32_t get_chroma_base(struct mdp_img *img, uint32_t base,
+				uint32_t bpp)
 {
-	uint32_t compress_v = Y_TO_CRCB_RATIO(img->format);
-	uint32_t compress_h = 2;
-	uint32_t  offset;
-
-	if (IS_PSEUDOPLNR(img->format)) {
-		offset = (rect->x / compress_h) * compress_h;
-		offset += rect->y = 0 ? 0 :
-			  ((rect->y + 1) / compress_v) * img->width;
-		*addr = base + (img->width * img->height * bpp);
-		*addr += offset * bpp;
-		*ystride |= *ystride << 16;
-	} else {
-		*addr = 0;
-	}
+	uint32_t addr = 0;
+
+	if (IS_PSEUDOPLNR(img->format))
+		addr = base + (img->width * img->height * bpp);
+	return addr;
 }
 
 #define mdp_writel_dbg(mdp, val, reg) mdp_writel((mdp), (val), (reg))
@@ -381,6 +382,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
 {
 	struct ppp_regs regs = {0};
+	uint32_t luma_base;
 
 	if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
 		     req->dst.format >= MDP_IMGTYPE_LIMIT)) {
@@ -416,23 +418,23 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 
 	/* set src, bpp, start pixel and ystride */
 	regs.src_bpp = bytes_per_pixel[req->src.format];
-	regs.src0 = src_start + req->src.offset;
+	luma_base = src_start + req->src.offset;
+	regs.src0 = luma_base +
+		get_luma_offset(&req->src, &req->src_rect, regs.src_bpp);
+	regs.src1 = get_chroma_base(&req->src, luma_base, regs.src_bpp);
+	regs.src1 += get_chroma_offset(&req->src, &req->src_rect, regs.src_bpp);
 	regs.src_ystride = req->src.width * regs.src_bpp;
 	set_src_region(&req->src, &req->src_rect, &regs);
-	get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
-			regs.src_cfg, &regs.src1, &regs.src_ystride);
-	regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
-		      regs.src_bpp;
 
 	/* set dst, bpp, start pixel and ystride */
 	regs.dst_bpp = bytes_per_pixel[req->dst.format];
-	regs.dst0 = dst_start + req->dst.offset;
+	luma_base = dst_start + req->dst.offset;
+	regs.dst0 = luma_base +
+		get_luma_offset(&req->dst, &req->dst_rect, regs.dst_bpp);
+	regs.dst1 = get_chroma_base(&req->dst, luma_base, regs.dst_bpp);
+	regs.dst1 += get_chroma_offset(&req->dst, &req->dst_rect, regs.dst_bpp);
 	regs.dst_ystride = req->dst.width * regs.dst_bpp;
 	set_dst_region(&req->dst_rect, &regs);
-	get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
-			regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
-	regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
-		      regs.dst_bpp;
 
 	if (!valid_src_dst(src_start, src_len, dst_start, dst_len, req,
 			   &regs)) {
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 18/20] video: msm: Prevent DMA lockups when switching bit depths
From: Carl Vanderlip @ 2011-03-18 21:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Forces the lcdc off and waits a frame vsync period to prevent the MDP DMA
engine crashing if the DMA bit depth is changed.  A sleep cannot be used
because lcdc_dma_start is called in irq context.

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>
---
 drivers/video/msm/mdp.c |    7 +++++++
 1 files changed, 7 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index b3f334ad..49d956a 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -564,6 +564,13 @@ void mdp_hw_init(struct mdp_info *mdp)
 	mdp_writel(mdp, 1, 0x60);
 	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
 
+	/* 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);
+
 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
 	mdp_writel(mdp, 1, 0x60);
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 17/20] video: msm: Prevent framebuffer glitch during initialization
From: Carl Vanderlip @ 2011-03-18 21:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Holds a reference to the mdp_clk until lateinit, and moves the frambuffer
initialization to device_init.  The framebuffer lcdc driver will grab a
reference to mdp_clk, which prevents the clock from being disabled by
clock_late_init.

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>
---
 drivers/video/msm/mdp.c |   10 ++++++++++
 1 files changed, 10 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 0bb19fa..b3f334ad 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -38,6 +38,7 @@ struct class *mdp_class;
 
 static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
 static unsigned int mdp_irq_mask;
+struct clk *mdp_clk_to_disable_later;
 DEFINE_MUTEX(mdp_mutex);
 
 static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
@@ -670,6 +671,7 @@ int mdp_probe(struct platform_device *pdev)
 	disable_irq(mdp->irq);
 
 	clk_enable(mdp->clk);
+	mdp_clk_to_disable_later = mdp->clk;
 	mdp_hw_init(mdp);
 
 	/* register mdp device */
@@ -706,6 +708,13 @@ static struct platform_driver msm_mdp_driver = {
 	.driver = {.name = "msm_mdp"},
 };
 
+static int __init mdp_lateinit(void)
+{
+	if (mdp_clk_to_disable_later)
+		clk_disable(mdp_clk_to_disable_later);
+	return 0;
+}
+
 static int __init mdp_init(void)
 {
 	mdp_class = class_create(THIS_MODULE, "msm_mdp");
@@ -717,3 +726,4 @@ static int __init mdp_init(void)
 }
 
 subsys_initcall(mdp_init);
+late_initcall(mdp_lateinit);
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 16/20] video: msm: Set the EBI1 clock to 128MHz when performing blits
From: Carl Vanderlip @ 2011-03-18 21:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

This makes sure that the MDP (locked to AXI) and the AXI/ABI1 run at the
maximum frequency during blit operations.

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>
---
 drivers/video/msm/mdp.c    |   11 +++++++++++
 drivers/video/msm/mdp_hw.h |    1 +
 2 files changed, 12 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index b03204d..0bb19fa 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -52,6 +52,7 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
 	}
 	/* if the mdp irq is not already enabled enable it */
 	if (!mdp_irq_mask) {
+		clk_set_rate(mdp->ebi1_clk, 128000000);
 		clk_enable(mdp->clk);
 		enable_irq(mdp->irq);
 	}
@@ -656,6 +657,13 @@ int mdp_probe(struct platform_device *pdev)
 		goto error_get_mdp_clk;
 	}
 
+	mdp->ebi1_clk = clk_get(NULL, "ebi1_clk");
+	if (IS_ERR(mdp->ebi1_clk)) {
+		pr_err("mdp: failed to get ebi1 clk\n");
+		ret = PTR_ERR(mdp->ebi1_clk);
+		goto error_get_ebi1_clk;
+	}
+
 	ret = request_irq(mdp->irq, mdp_isr, IRQF_DISABLED, "msm_mdp", mdp);
 	if (ret)
 		goto error_request_irq;
@@ -681,6 +689,9 @@ int mdp_probe(struct platform_device *pdev)
 error_device_register:
 	free_irq(mdp->irq, mdp);
 error_request_irq:
+	clk_put(mdp->ebi1_clk);
+error_get_ebi1_clk:
+	clk_put(mdp->clk);
 error_get_mdp_clk:
 error_mddi_pmdh_register:
 	iounmap(mdp->base);
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index fdf9e5e..7485a9e 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -46,6 +46,7 @@ struct mdp_info {
 	char * __iomem base;
 	int irq;
 	struct clk *clk;
+	struct clk *ebi1_clk;
 	struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
 	int format;
 	int pack_pattern;
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 15/20] video: msm: convert printk to pr_*
From: Carl Vanderlip @ 2011-03-18 21:59 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Reword debugging messages to use pr_err and pr_warning

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>
---
 drivers/video/msm/mdp.c |   11 ++++-------
 1 files changed, 4 insertions(+), 7 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 8184ca9..b03204d 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -42,16 +42,13 @@ DEFINE_MUTEX(mdp_mutex);
 
 static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
 {
-	int ret = 0;
-
 	BUG_ON(!mask);
 
 	/* if the mask bits are already set return an error, this interrupt
 	 * is already enabled */
 	if (mdp_irq_mask & mask) {
-		printk(KERN_ERR "mdp irq already on already on %x %x\n",
-		       mdp_irq_mask, mask);
-		ret = -1;
+		pr_err("mdp irq already on %x %x\n", mdp_irq_mask, mask);
+		return -1;
 	}
 	/* if the mdp irq is not already enabled enable it */
 	if (!mdp_irq_mask) {
@@ -172,9 +169,9 @@ static int mdp_wait(struct mdp_info *mdp, uint32_t mask, wait_queue_head_t *wq)
 
 	spin_lock_irqsave(&mdp->lock, irq_flags);
 	if (mdp_irq_mask & mask) {
+		pr_warning("%s: timeout waiting for mdp to complete 0x%x\n",
+			   __func__, mask);
 		locked_disable_mdp_irq(mdp, mask);
-		printk(KERN_WARNING "timeout waiting for mdp to complete %x\n",
-		       mask);
 		ret = -ETIMEDOUT;
 	}
 	spin_unlock_irqrestore(&mdp->lock, irq_flags);
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 14/20] video: msm: Write IRQ mask to MDP registers
From: Carl Vanderlip @ 2011-03-18 21:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Writing MDP IRQ mask to the MDP IRQ register to fully disable interrupt.

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>
---
 drivers/video/msm/mdp.c |    6 ++++++
 1 files changed, 6 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index bdca2d9..8184ca9 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -59,9 +59,13 @@ static int locked_enable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
 		enable_irq(mdp->irq);
 	}
 
+	/* clear out any previous irqs for the requested mask*/
+	mdp_writel(mdp, mask, MDP_INTR_CLEAR);
+
 	/* update the irq mask to reflect the fact that the interrupt is
 	 * enabled */
 	mdp_irq_mask |= mask;
+	mdp_writel(mdp, mdp_irq_mask, MDP_INTR_ENABLE);
 	return 0;
 }
 
@@ -87,6 +91,8 @@ static int locked_disable_mdp_irq(struct mdp_info *mdp, uint32_t mask)
 	/* update the irq mask to reflect the fact that the interrupt is
 	 * disabled */
 	mdp_irq_mask &= ~(mask);
+	mdp_writel(mdp, mdp_irq_mask, MDP_INTR_ENABLE);
+
 	/* if no one is waiting on the interrupt, disable it */
 	if (!mdp_irq_mask) {
 		disable_irq_nosync(mdp->irq);
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 13/20] video: msm: Debugging for send_blit
From: Carl Vanderlip @ 2011-03-18 21:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Allows for mdp_writel_dbg to be redefined as needed to debug blits.

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>
---
 drivers/video/msm/mdp_hw.h  |    2 +-
 drivers/video/msm/mdp_ppp.c |   61 ++++++++++++++++++++++--------------------
 2 files changed, 33 insertions(+), 30 deletions(-)

diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index acb48f5..fdf9e5e 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -87,7 +87,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define MDP_DISPLAY0_ADDR                (0x00054)
 #define MDP_DISPLAY1_ADDR                (0x00058)
 #define MDP_EBI2_PORTMAP_MODE            (0x0005c)
-#define MDP_MODE                         (0x00060)
+#define MDP_PPP_CMD_MODE                 (0x00060)
 #define MDP_TV_OUT_STATUS                (0x00064)
 #define MDP_HW_VERSION                   (0x00070)
 #define MDP_SW_RESET                     (0x00074)
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 3d190b9..290c29a 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -331,45 +331,48 @@ static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
 	}
 }
 
+#define mdp_writel_dbg(mdp, val, reg) mdp_writel((mdp), (val), (reg))
+
 static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		     struct ppp_regs *regs, struct file *src_file,
 		     struct file *dst_file)
 {
-	mdp_writel(mdp, 1, 0x060);
-	mdp_writel(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
-	mdp_writel(mdp, regs->src0, PPP_ADDR_SRC0);
-	mdp_writel(mdp, regs->src1, PPP_ADDR_SRC1);
-	mdp_writel(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
-	mdp_writel(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
-	mdp_writel(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
-
-	mdp_writel(mdp, regs->op, PPP_ADDR_OPERATION);
-	mdp_writel(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
-	mdp_writel(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
-	mdp_writel(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
-	mdp_writel(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
-
-	mdp_writel(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
+#if 0
+	mdp_writel_dbg(mdp, 1, MDP_PPP_CMD_MODE);
+#endif
+	mdp_writel_dbg(mdp, regs->src_rect, PPP_ADDR_SRC_ROI);
+	mdp_writel_dbg(mdp, regs->src0, PPP_ADDR_SRC0);
+	mdp_writel_dbg(mdp, regs->src1, PPP_ADDR_SRC1);
+	mdp_writel_dbg(mdp, regs->src_ystride, PPP_ADDR_SRC_YSTRIDE);
+	mdp_writel_dbg(mdp, regs->src_cfg, PPP_ADDR_SRC_CFG);
+	mdp_writel_dbg(mdp, regs->src_pack, PPP_ADDR_SRC_PACK_PATTERN);
+
+	mdp_writel_dbg(mdp, regs->op, PPP_ADDR_OPERATION);
+	mdp_writel_dbg(mdp, regs->phasex_init, PPP_ADDR_PHASEX_INIT);
+	mdp_writel_dbg(mdp, regs->phasey_init, PPP_ADDR_PHASEY_INIT);
+	mdp_writel_dbg(mdp, regs->phasex_step, PPP_ADDR_PHASEX_STEP);
+	mdp_writel_dbg(mdp, regs->phasey_step, PPP_ADDR_PHASEY_STEP);
+
+	mdp_writel_dbg(mdp, regs->edge, PPP_ADDR_EDGE);
+	mdp_writel_dbg(mdp, (req->alpha << 24) | (req->transp_mask & 0xffffff),
 	       PPP_ADDR_ALPHA_TRANSP);
 
-	mdp_writel(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
-	mdp_writel(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
-	mdp_writel(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
-	mdp_writel(mdp, regs->dst0, PPP_ADDR_DST0);
-	mdp_writel(mdp, regs->dst1, PPP_ADDR_DST1);
-	mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
+	mdp_writel_dbg(mdp, regs->dst_cfg, PPP_ADDR_DST_CFG);
+	mdp_writel_dbg(mdp, regs->dst_pack, PPP_ADDR_DST_PACK_PATTERN);
+	mdp_writel_dbg(mdp, regs->dst_rect, PPP_ADDR_DST_ROI);
+	mdp_writel_dbg(mdp, regs->dst0, PPP_ADDR_DST0);
+	mdp_writel_dbg(mdp, regs->dst1, PPP_ADDR_DST1);
+	mdp_writel_dbg(mdp, regs->dst_ystride, PPP_ADDR_DST_YSTRIDE);
 
-	mdp_writel(mdp, regs->edge, PPP_ADDR_EDGE);
 	if (regs->op & PPP_OP_BLEND_ON) {
-		mdp_writel(mdp, regs->dst0, PPP_ADDR_BG0);
-		mdp_writel(mdp, regs->dst1, PPP_ADDR_BG1);
-		mdp_writel(mdp, regs->dst_ystride, PPP_ADDR_BG_YSTRIDE);
-		mdp_writel(mdp, src_img_cfg[req->dst.format], PPP_ADDR_BG_CFG);
-		mdp_writel(mdp, pack_pattern[req->dst.format],
-			   PPP_ADDR_BG_PACK_PATTERN);
+		mdp_writel_dbg(mdp, regs->bg0, PPP_ADDR_BG0);
+		mdp_writel_dbg(mdp, regs->bg1, PPP_ADDR_BG1);
+		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);
 	}
 	flush_imgs(req, regs, src_file, dst_file);
-	mdp_writel(mdp, 0x1000, MDP_DISPLAY0_START);
+	mdp_writel_dbg(mdp, 0x1000, MDP_DISPLAY0_START);
 	return 0;
 }
 
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 12/20] video: msm: Add IRQ callback for MDP interface
From: Carl Vanderlip @ 2011-03-18 21:58 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Allows interface client to setup notification for non-DMA irqs
(e.g. LCDC/TV-out frame start)

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>
---
 drivers/video/msm/mdp.c    |   41 +++++++++++++++++++++++++++++++++++++++++
 drivers/video/msm/mdp_hw.h |    9 +++++++++
 2 files changed, 50 insertions(+), 0 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 15241b4..bdca2d9 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -130,6 +130,10 @@ static irqreturn_t mdp_isr(int irq, void *data)
 			}
 			wake_up(&out_if->dma_waitqueue);
 		}
+		if (status & out_if->irq_mask) {
+			out_if->irq_cb->func(out_if->irq_cb);
+			out_if->irq_cb = NULL;
+		}
 	}
 
 	if (status & DL0_ROI_DONE)
@@ -494,6 +498,43 @@ done:
 	return ret;
 }
 
+int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
+		       uint32_t mask, struct msmfb_callback *cb)
+{
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+	unsigned long flags;
+	int ret = 0;
+
+	if (interface < 0 || interface >= MSM_MDP_NUM_INTERFACES) {
+		pr_err("%s: invalid interface (%d)\n", __func__, interface);
+		BUG();
+	} else if (!mdp->out_if[interface].registered) {
+		pr_err("%s: interface (%d) not registered\n", __func__,
+		       interface);
+		BUG();
+	}
+
+	spin_lock_irqsave(&mdp->lock, flags);
+
+	if (mask) {
+		ret = locked_enable_mdp_irq(mdp, mask);
+		if (ret) {
+			pr_err("%s: busy\n", __func__);
+			goto done;
+		}
+		mdp->out_if[interface].irq_mask = mask;
+		mdp->out_if[interface].irq_cb = cb;
+	} else {
+		locked_disable_mdp_irq(mdp, mask);
+		mdp->out_if[interface].irq_mask = 0;
+		mdp->out_if[interface].irq_cb = NULL;
+	}
+
+done:
+	spin_unlock_irqrestore(&mdp->lock, flags);
+	return ret;
+}
+
 int register_mdp_client(struct class_interface *cint)
 {
 	if (!mdp_class) {
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index cc48218..acb48f5 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -33,6 +33,11 @@ struct mdp_out_interface {
 
 	struct msmfb_callback	*dma_cb;
 	wait_queue_head_t	dma_waitqueue;
+
+	/* If the interface client wants to be notified of non-DMA irqs,
+	 * e.g. LCDC/TV-out frame start */
+	uint32_t		irq_mask;
+	struct msmfb_callback	*irq_cb;
 };
 
 struct mdp_info {
@@ -50,6 +55,10 @@ struct mdp_info {
 extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
 			       void *private_data, uint32_t dma_mask,
 			       mdp_dma_start_func_t dma_start);
+
+extern int mdp_out_if_req_irq(struct mdp_device *mdp_dev, int interface,
+			      uint32_t mask, struct msmfb_callback *cb);
+
 struct mdp_blit_req;
 struct mdp_device;
 int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 11/20] video: msm: Add MDP FB DMA configuration
From: Carl Vanderlip @ 2011-03-18 21:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Setup configure_dma, check_output_format and set_output_format functions.

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/include/mach/msm_fb.h |    3 ++
 drivers/video/msm/mdp.c                 |   61 ++++++++++++++++++++++++++++++-
 drivers/video/msm/mdp_hw.h              |   16 ++++++++
 drivers/video/msm/msm_fb.c              |    5 ++-
 4 files changed, 83 insertions(+), 2 deletions(-)

diff --git a/arch/arm/mach-msm/include/mach/msm_fb.h b/arch/arm/mach-msm/include/mach/msm_fb.h
index 2d0899c..238ea2a 100644
--- a/arch/arm/mach-msm/include/mach/msm_fb.h
+++ b/arch/arm/mach-msm/include/mach/msm_fb.h
@@ -123,6 +123,9 @@ struct mdp_device {
 	int (*blit)(struct mdp_device *mdp, struct fb_info *fb,
 		    struct mdp_blit_req *req);
 	void (*set_grp_disp)(struct mdp_device *mdp, uint32_t disp_id);
+	void (*configure_dma)(struct mdp_device *mdp);
+	int (*check_output_format)(struct mdp_device *mdp, int bpp);
+	int (*set_output_format)(struct mdp_device *mdp, int bpp);
 };
 
 struct class_interface;
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 95e19e5..15241b4 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -223,7 +223,7 @@ static void mdp_dma_to_mddi(void *priv, uint32_t addr, uint32_t stride,
 		DMA_OUT_SEL_AHB |
 		DMA_IBUF_NONCONTIGUOUS;
 
-	dma2_cfg |= DMA_IBUF_FORMAT_RGB565;
+	dma2_cfg |= mdp->format;
 
 	dma2_cfg |= DMA_OUT_SEL_MDDI;
 
@@ -304,6 +304,62 @@ void put_img(struct file *src_file, struct file *dst_file)
 {
 }
 
+void mdp_configure_dma(struct mdp_device *mdp_dev)
+{
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+	uint32_t dma_cfg;
+
+	if (!mdp->dma_config_dirty)
+		return;
+	dma_cfg = mdp_readl(mdp, MDP_DMA_P_CONFIG);
+	dma_cfg &= ~DMA_IBUF_FORMAT_MASK;
+	dma_cfg &= ~DMA_PACK_PATTERN_MASK;
+	dma_cfg |= (mdp->format | mdp->pack_pattern);
+	mdp_writel(mdp, dma_cfg, MDP_DMA_P_CONFIG);
+	mdp->dma_config_dirty = false;
+
+	return;
+}
+
+int mdp_check_output_format(struct mdp_device *mdp_dev, int bpp)
+{
+	switch (bpp) {
+	case 16:
+	case 24:
+	case 32:
+		break;
+	default:
+		return -EINVAL;
+	}
+	return 0;
+}
+
+int mdp_set_output_format(struct mdp_device *mdp_dev, int bpp)
+{
+	struct mdp_info *mdp = container_of(mdp_dev, struct mdp_info, mdp_dev);
+	uint32_t format, pack_pattern;
+
+	switch (bpp) {
+	case 16:
+		format = DMA_IBUF_FORMAT_RGB565;
+		pack_pattern = DMA_PACK_PATTERN_RGB;
+		break;
+	case 24:
+	case 32:
+		format = DMA_IBUF_FORMAT_RGB888_OR_ARGB8888;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (format != mdp->format || pack_pattern != mdp->pack_pattern) {
+		mdp->format = format;
+		mdp->pack_pattern = pack_pattern;
+		mdp->dma_config_dirty = true;
+	}
+
+	return 0;
+}
+
 int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
 		struct file *src_file, unsigned long src_start,
 		unsigned long src_len, struct file *dst_file,
@@ -540,6 +596,9 @@ int mdp_probe(struct platform_device *pdev)
 	mdp->mdp_dev.dma_wait = mdp_dma_wait;
 	mdp->mdp_dev.blit = mdp_blit;
 	mdp->mdp_dev.set_grp_disp = mdp_set_grp_disp;
+	mdp->mdp_dev.set_output_format = mdp_set_output_format;
+	mdp->mdp_dev.check_output_format = mdp_check_output_format;
+	mdp->mdp_dev.configure_dma = mdp_configure_dma;
 
 	ret = mdp_out_if_register(&mdp->mdp_dev, MSM_MDDI_PMDH_INTERFACE, mdp,
 				  MDP_DMA_P_DONE, mdp_dma_to_mddi);
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index 34a204e..cc48218 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -42,6 +42,9 @@ struct mdp_info {
 	int irq;
 	struct clk *clk;
 	struct mdp_out_interface out_if[MSM_MDP_NUM_INTERFACES];
+	int format;
+	int pack_pattern;
+	bool dma_config_dirty;
 };
 
 extern int mdp_out_if_register(struct mdp_device *mdp_dev, int interface,
@@ -183,6 +186,15 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define MDP_TEST_CAPTURED_DCLK           (0xd0210)
 #define MDP_TEST_MISR_CAPT_VAL_DCLK      (0xd0214)
 #define MDP_LCDC_CTL                     (0xe0000)
+
+#define MDP_DMA_P_START                  (0x00044)
+#define MDP_DMA_P_CONFIG                 (0x90000)
+#define MDP_DMA_P_SIZE                   (0x90004)
+#define MDP_DMA_P_IBUF_ADDR              (0x90008)
+#define MDP_DMA_P_IBUF_Y_STRIDE          (0x9000c)
+#define MDP_DMA_P_OUT_XY                 (0x90010)
+#define MDP_DMA_P_COLOR_CORRECT_CONFIG   (0x90070)
+
 #define MDP_LCDC_HSYNC_CTL               (0xe0004)
 #define MDP_LCDC_VSYNC_CTL               (0xe0008)
 #define MDP_LCDC_ACTIVE_HCTL             (0xe000c)
@@ -629,8 +641,11 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define DMA_PACK_LOOSE 0
 #define DMA_PACK_ALIGN_LSB 0
 #define DMA_PACK_ALIGN_MSB (1<<7)
+#define DMA_PACK_PATTERN_MASK (0x3f<<8)
 #define DMA_PACK_PATTERN_RGB \
 	(MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 2)<<8)
+#define DMA_PACK_PATTERN_BGR \
+	(MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 2)<<8)
 
 #define DMA_OUT_SEL_AHB  0
 #define DMA_OUT_SEL_MDDI (1<<14)
@@ -645,6 +660,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 
 #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)
 
diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 6af8b41..ccd7417 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -332,7 +332,7 @@ static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 	if ((var->xres != info->var.xres) ||
 	    (var->yres != info->var.yres) ||
 	    (var->xoffset != info->var.xoffset) ||
-	    (var->bits_per_pixel != info->var.bits_per_pixel) ||
+	    (mdp->check_output_format(mdp, var->bits_per_pixel)) ||
 	    (var->grayscale != info->var.grayscale))
 		 return -EINVAL;
 
@@ -365,6 +365,7 @@ static int msmfb_set_par(struct fb_info *info)
 		var->blue.length = 5;
 	} else
 		return -1;
+	mdp->set_output_format(mdp, var->bits_per_pixel);
 	fix->line_length = var->xres * var->bits_per_pixel / 8;
 
 	return 0;
@@ -519,6 +520,8 @@ static void setup_fb_info(struct msmfb_info *msmfb)
 	fb_info->var.blue.length = 5;
 	fb_info->var.blue.msb_right = 0;
 
+	mdp->set_output_format(mdp, fb_info->var.bits_per_pixel);
+
 	r = fb_alloc_cmap(&fb_info->cmap, 16, 0);
 	fb_info->pseudo_palette = PP;
 
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 10/20] video: msm: Separate more MDP HW specific code
From: Carl Vanderlip @ 2011-03-18 21:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Simplifies mdp_probe by moving register initialization to
mdp_hw_init

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>
---
 drivers/video/msm/mdp.c           |   96 ++++++++++++++++++-------------------
 drivers/video/msm/mdp_csc_table.h |   95 ++++++++++++++++--------------------
 drivers/video/msm/mdp_hw.h        |    9 ++++
 3 files changed, 98 insertions(+), 102 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 6aa9ed5..95e19e5 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -36,11 +36,6 @@ struct class *mdp_class;
 
 #define MDP_CMD_DEBUG_ACCESS_BASE (0x10000)
 
-static uint16_t mdp_default_ccs[] = {
-	0x254, 0x000, 0x331, 0x254, 0xF38, 0xE61, 0x254, 0x409, 0x000,
-	0x010, 0x080, 0x080
-};
-
 static DECLARE_WAIT_QUEUE_HEAD(mdp_ppp_waitqueue);
 static unsigned int mdp_irq_mask;
 DEFINE_MUTEX(mdp_mutex);
@@ -457,6 +452,52 @@ int register_mdp_client(struct class_interface *cint)
 
 void mdp_hw_init(struct mdp_info *mdp)
 {
+	int n;
+
+	mdp_irq_mask = 0;
+
+	mdp_writel(mdp, 0, MDP_INTR_ENABLE);
+
+	/* debug interface write access */
+	mdp_writel(mdp, 1, 0x60);
+	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
+
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
+	mdp_writel(mdp, 1, 0x60);
+
+	for (n = 0; n < ARRAY_SIZE(csc_color_lut); n++)
+		mdp_writel(mdp, csc_color_lut[n].val, csc_color_lut[n].reg);
+
+	/* clear up unused fg/main registers */
+	/* comp.plane 2&3 ystride */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
+
+	/* unpacked pattern */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
+
+	/* comp.plane 2 & 3 */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
+
+	/* clear unused bg registers */
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
+	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
+
+	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
 	mdp_ppp_init_scale(mdp);
 #endif
@@ -466,7 +507,6 @@ int mdp_probe(struct platform_device *pdev)
 {
 	struct resource *resource;
 	int ret;
-	int n;
 	struct mdp_info *mdp;
 
 	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -517,52 +557,8 @@ int mdp_probe(struct platform_device *pdev)
 	if (ret)
 		goto error_request_irq;
 	disable_irq(mdp->irq);
-	mdp_irq_mask = 0;
-
-	/* debug interface write access */
-	mdp_writel(mdp, 1, 0x60);
-
-	mdp_writel(mdp, MDP_ANY_INTR_MASK, MDP_INTR_ENABLE);
-	mdp_writel(mdp, 1, MDP_EBI2_PORTMAP_MODE);
-
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01f8);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01fc);
-
-	for (n = 0; n < ARRAY_SIZE(csc_table); n++)
-		mdp_writel(mdp, csc_table[n].val, csc_table[n].reg);
-
-	/* clear up unused fg/main registers */
-	/* comp.plane 2&3 ystride */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0120);
-
-	/* unpacked pattern */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x012c);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0130);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0134);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0158);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x015c);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0160);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0170);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0174);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x017c);
 
 	clk_enable(mdp->clk);
-	/* comp.plane 2 & 3 */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0114);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x0118);
-
-	/* clear unused bg registers */
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01c8);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01d0);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01dc);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
-	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
-
-	for (n = 0; n < 9; n++)
-		mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
-	mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
-	mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
-	mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
 	mdp_hw_init(mdp);
 
 	/* register mdp device */
diff --git a/drivers/video/msm/mdp_csc_table.h b/drivers/video/msm/mdp_csc_table.h
index d1cde30..6eb0fc3 100644
--- a/drivers/video/msm/mdp_csc_table.h
+++ b/drivers/video/msm/mdp_csc_table.h
@@ -1,6 +1,6 @@
 /* drivers/video/msm_fb/mdp_csc_table.h
  *
- * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007, 2011 Code Aurora Forum. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This software is licensed under the terms of the GNU General Public
@@ -16,57 +16,48 @@
 static struct {
 	uint32_t reg;
 	uint32_t val;
-} csc_table[] = {
-	{ 0x40400, 0x83 },
-	{ 0x40404, 0x102 },
-	{ 0x40408, 0x32 },
-	{ 0x4040c, 0xffffffb5 },
-	{ 0x40410, 0xffffff6c },
-	{ 0x40414, 0xe1 },
-	{ 0x40418, 0xe1 },
-	{ 0x4041c, 0xffffff45 },
-	{ 0x40420, 0xffffffdc },
-	{ 0x40440, 0x254 },
-	{ 0x40444, 0x0 },
-	{ 0x40448, 0x331 },
-	{ 0x4044c, 0x254 },
-	{ 0x40450, 0xffffff38 },
-	{ 0x40454, 0xfffffe61 },
-	{ 0x40458, 0x254 },
-	{ 0x4045c, 0x409 },
-	{ 0x40460, 0x0 },
-	{ 0x40480, 0x5d },
-	{ 0x40484, 0x13a },
-	{ 0x40488, 0x20 },
-	{ 0x4048c, 0xffffffcd },
-	{ 0x40490, 0xffffff54 },
-	{ 0x40494, 0xe1 },
-	{ 0x40498, 0xe1 },
-	{ 0x4049c, 0xffffff35 },
-	{ 0x404a0, 0xffffffec },
-	{ 0x404c0, 0x254 },
-	{ 0x404c4, 0x0 },
-	{ 0x404c8, 0x396 },
-	{ 0x404cc, 0x254 },
-	{ 0x404d0, 0xffffff94 },
-	{ 0x404d4, 0xfffffef0 },
-	{ 0x404d8, 0x254 },
-	{ 0x404dc, 0x43a },
-	{ 0x404e0, 0x0 },
-	{ 0x40500, 0x10 },
-	{ 0x40504, 0x80 },
-	{ 0x40508, 0x80 },
-	{ 0x40540, 0x10 },
-	{ 0x40544, 0x80 },
-	{ 0x40548, 0x80 },
-	{ 0x40580, 0x10 },
-	{ 0x40584, 0xeb },
-	{ 0x40588, 0x10 },
-	{ 0x4058c, 0xf0 },
-	{ 0x405c0, 0x10 },
-	{ 0x405c4, 0xeb },
-	{ 0x405c8, 0x10 },
-	{ 0x405cc, 0xf0 },
+} csc_matrix_config_table[] = {
+	/* RGB -> YUV primary forward matrix (set1). */
+	{ MDP_CSC_PFMVn(0), 0x83 },
+	{ MDP_CSC_PFMVn(1), 0x102 },
+	{ MDP_CSC_PFMVn(2), 0x32 },
+	{ MDP_CSC_PFMVn(3), 0xffffffb5 },
+	{ MDP_CSC_PFMVn(4), 0xffffff6c },
+	{ MDP_CSC_PFMVn(5), 0xe1 },
+	{ MDP_CSC_PFMVn(6), 0xe1 },
+	{ MDP_CSC_PFMVn(7), 0xffffff45 },
+	{ MDP_CSC_PFMVn(8), 0xffffffdc },
+
+	/* YUV -> RGB primary reverse matrix (set2) */
+	{ MDP_CSC_PRMVn(0), 0x254 },
+	{ MDP_CSC_PRMVn(1), 0x0 },
+	{ MDP_CSC_PRMVn(2), 0x331 },
+	{ MDP_CSC_PRMVn(3), 0x254 },
+	{ MDP_CSC_PRMVn(4), 0xffffff38 },
+	{ MDP_CSC_PRMVn(5), 0xfffffe61 },
+	{ MDP_CSC_PRMVn(6), 0x254 },
+	{ MDP_CSC_PRMVn(7), 0x409 },
+	{ MDP_CSC_PRMVn(8), 0x0 },
+
+	/* For MDP 2.2/3.0 */
+
+	/* primary limit vector */
+	{ MDP_CSC_PLVn(0), 0x10 },
+	{ MDP_CSC_PLVn(1), 0xeb },
+	{ MDP_CSC_PLVn(2), 0x10 },
+	{ MDP_CSC_PLVn(3), 0xf0 },
+
+	/* primary bias vector */
+	{ MDP_CSC_PBVn(0), 0x10 },
+	{ MDP_CSC_PBVn(1), 0x80 },
+	{ MDP_CSC_PBVn(2), 0x80 },
+
+};
+
+static struct {
+	uint32_t reg;
+	uint32_t val;
+} csc_color_lut[] = {
 	{ 0x40800, 0x0 },
 	{ 0x40804, 0x151515 },
 	{ 0x40808, 0x1d1d1d },
diff --git a/drivers/video/msm/mdp_hw.h b/drivers/video/msm/mdp_hw.h
index 05deac8..34a204e 100644
--- a/drivers/video/msm/mdp_hw.h
+++ b/drivers/video/msm/mdp_hw.h
@@ -608,6 +608,15 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 #define PPP_ADDR_BG_CFG			MDP_FULL_BYPASS_WORD53
 #define PPP_ADDR_BG_PACK_PATTERN	MDP_FULL_BYPASS_WORD54
 
+/* color conversion matrix configuration registers */
+/* pfmv is mv1, prmv is mv2 */
+#define MDP_CSC_PFMVn(n)		(0x40400 + (4 * (n)))
+#define MDP_CSC_PRMVn(n)		(0x40440 + (4 * (n)))
+#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)))
+
 /* MDP_DMA_CONFIG / MDP_FULL_BYPASS_WORD32 */
 #define DMA_DSTC0G_6BITS (1<<1)
 #define DMA_DSTC1B_6BITS (1<<3)
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 09/20] video: msm: Split out MDP2.2 HW specific code.
From: Carl Vanderlip @ 2011-03-18 21:57 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Moving MDP2.2 HW specific code allows for reuse of PPP code
when adding other MDP HW versions. Splitting also begins
simplification of mdp_probe function.

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                          |    5 +
 drivers/video/msm/Makefile                         |    4 +-
 drivers/video/msm/mdp.c                            |   14 +-
 drivers/video/msm/mdp_ppp.c                        |  358 ++++----------------
 drivers/video/msm/mdp_ppp.h                        |   12 +
 .../video/msm/{mdp_scale_tables.c => mdp_ppp22.c}  |  333 ++++++++++++++++++-
 drivers/video/msm/mdp_scale_tables.h               |   38 --
 7 files changed, 417 insertions(+), 347 deletions(-)
 rename drivers/video/msm/{mdp_scale_tables.c => mdp_ppp22.c} (69%)
 delete mode 100644 drivers/video/msm/mdp_scale_tables.h

diff --git a/arch/arm/mach-msm/Kconfig b/arch/arm/mach-msm/Kconfig
index df9d74e..d6e75c3 100644
--- a/arch/arm/mach-msm/Kconfig
+++ b/arch/arm/mach-msm/Kconfig
@@ -76,6 +76,11 @@ config HAS_MSM_DEBUG_UART_PHYS
 config  MSM_VIC
 	bool
 
+config MSM_MDP22
+	bool
+	depends on ARCH_MSM7X00A
+	default y
+
 menu "Qualcomm MSM Board Type"
 
 config MACH_HALIBUT
diff --git a/drivers/video/msm/Makefile b/drivers/video/msm/Makefile
index 802d6ae..0666aef 100644
--- a/drivers/video/msm/Makefile
+++ b/drivers/video/msm/Makefile
@@ -5,7 +5,9 @@ obj-y := msm_fb.o
 
 # MDP DMA/PPP engine
 #
-obj-y += mdp.o mdp_scale_tables.o mdp_ppp.o
+obj-y += mdp.o mdp_ppp.o
+
+obj-$(CONFIG_MSM_MDP22) += mdp_ppp22.o
 
 # MDDI interface
 #
diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index 765df06..6aa9ed5 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -30,6 +30,7 @@
 #include <linux/platform_device.h>
 
 #include "mdp_hw.h"
+#include "mdp_ppp.h"
 
 struct class *mdp_class;
 
@@ -453,7 +454,13 @@ int register_mdp_client(struct class_interface *cint)
 }
 
 #include "mdp_csc_table.h"
-#include "mdp_scale_tables.h"
+
+void mdp_hw_init(struct mdp_info *mdp)
+{
+#ifdef CONFIG_MSM_MDP22
+	mdp_ppp_init_scale(mdp);
+#endif
+}
 
 int mdp_probe(struct platform_device *pdev)
 {
@@ -551,15 +558,12 @@ int mdp_probe(struct platform_device *pdev)
 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e0);
 	mdp_writel(mdp, 0, MDP_CMD_DEBUG_ACCESS_BASE + 0x01e4);
 
-	for (n = 0; n < ARRAY_SIZE(mdp_upscale_table); n++)
-		mdp_writel(mdp, mdp_upscale_table[n].val,
-		       mdp_upscale_table[n].reg);
-
 	for (n = 0; n < 9; n++)
 		mdp_writel(mdp, mdp_default_ccs[n], 0x40440 + 4 * n);
 	mdp_writel(mdp, mdp_default_ccs[9], 0x40500 + 4 * 0);
 	mdp_writel(mdp, mdp_default_ccs[10], 0x40500 + 4 * 0);
 	mdp_writel(mdp, mdp_default_ccs[11], 0x40500 + 4 * 0);
+	mdp_hw_init(mdp);
 
 	/* register mdp device */
 	mdp->mdp_dev.dev.parent = &pdev->dev;
diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 05f3e33..3d190b9 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -20,14 +20,14 @@
 
 #include "mdp_hw.h"
 #include "mdp_ppp.h"
-#include "mdp_scale_tables.h"
 
 #define DLOG(x...) do {} while (0)
 
-#define MDP_DOWNSCALE_BLUR (MDP_DOWNSCALE_MAX + 1)
-static int downscale_y_table = MDP_DOWNSCALE_MAX;
-static int downscale_x_table = MDP_DOWNSCALE_MAX;
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
 
+#define Y_TO_CRCB_RATIO(format) \
+	((format = MDP_Y_CBCR_H2V2 || format = MDP_Y_CRCB_H2V2) ?  2 :\
+	 (format = MDP_Y_CBCR_H2V1 || format = MDP_Y_CRCB_H2V1) ?  1 : 1)
 
 static uint32_t pack_pattern[] = {
 	PPP_ARRAY0(PACK_PATTERN)
@@ -67,6 +67,19 @@ static uint32_t bg_op_chroma[] = {
 	PPP_ARRAY1(CHROMA_SAMP, BG)
 };
 
+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 rotate_dst_addr_x(struct mdp_blit_req *req,
 			      struct ppp_regs *regs)
 {
@@ -181,254 +194,30 @@ static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
 	}
 
 	regs->op |= bg_op_chroma[req->dst.format];
-}
-
-#define ONE_HALF	(1LL << 32)
-#define ONE		(1LL << 33)
-#define TWO		(2LL << 33)
-#define THREE		(3LL << 33)
-#define FRAC_MASK (ONE - 1)
-#define INT_MASK (~FRAC_MASK)
-
-static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
-			uint32_t *phase_init, uint32_t *phase_step)
-{
-	/* to improve precicsion calculations are done in U31.33 and converted
-	 * to U3.29 at the end */
-	int64_t k1, k2, k3, k4, tmp;
-	uint64_t n, d, os, os_p, od, od_p, oreq;
-	unsigned rpa = 0;
-	int64_t ip64, delta;
-
-	if (dim_out % 3 = 0)
-		rpa = !(dim_in % (dim_out / 3));
-
-	n = ((uint64_t)dim_out) << 34;
-	d = dim_in;
-	if (!d)
-		return -1;
-	do_div(n, d);
-	k3 = (n + 1) >> 1;
-	if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31)) {
-		DLOG("crap bad scale\n");
-		return -1;
-	}
-	n = ((uint64_t)dim_in) << 34;
-	d = (uint64_t)dim_out;
-	if (!d)
-		return -1;
-	do_div(n, d);
-	k1 = (n + 1) >> 1;
-	k2 = (k1 - ONE) >> 1;
-
-	*phase_init = (int)(k2 >> 4);
-	k4 = (k3 - ONE) >> 1;
-
-	if (rpa) {
-		os = ((uint64_t)origin << 33) - ONE_HALF;
-		tmp = (dim_out * os) + ONE_HALF;
-		if (!dim_in)
-			return -1;
-		do_div(tmp, dim_in);
-		od = tmp - ONE_HALF;
-	} else {
-		os = ((uint64_t)origin << 1) - 1;
-		od = (((k3 * os) >> 1) + k4);
-	}
-
-	od_p = od & INT_MASK;
-	if (od_p != od)
-		od_p += ONE;
-
-	if (rpa) {
-		tmp = (dim_in * od_p) + ONE_HALF;
-		if (!dim_in)
-			return -1;
-		do_div(tmp, dim_in);
-		os_p = tmp - ONE_HALF;
-	} else {
-		os_p = ((k1 * (od_p >> 33)) + k2);
-	}
-
-	oreq = (os_p & INT_MASK) - ONE;
-
-	ip64 = os_p - oreq;
-	delta = ((int64_t)(origin) << 33) - oreq;
-	ip64 -= delta;
-	/* limit to valid range before the left shift */
-	delta = (ip64 & (1LL << 63)) ? 4 : -4;
-	delta <<= 33;
-	while (abs((int)(ip64 >> 33)) > 4)
-		ip64 += delta;
-	*phase_init = (int)(ip64 >> 4);
-	*phase_step = (uint32_t)(k1 >> 4);
-	return 0;
-}
-
-static void load_scale_table(const struct mdp_info *mdp,
-			     struct mdp_table_entry *table, int len)
-{
-	int i;
-	for (i = 0; i < len; i++)
-		mdp_writel(mdp, table[i].val, table[i].reg);
-}
-
-enum {
-IMG_LEFT,
-IMG_RIGHT,
-IMG_TOP,
-IMG_BOTTOM,
-};
-
-static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
-			  uint32_t *interp1, uint32_t *interp2,
-			  uint32_t *repeat1, uint32_t *repeat2) {
-	if (src > 3 * dst) {
-		*interp1 = 0;
-		*interp2 = src - 1;
-		*repeat1 = 0;
-		*repeat2 = 0;
-	} else if (src = 3 * dst) {
-		*interp1 = 0;
-		*interp2 = src;
-		*repeat1 = 0;
-		*repeat2 = 1;
-	} else if (src > dst && src < 3 * dst) {
-		*interp1 = -1;
-		*interp2 = src;
-		*repeat1 = 1;
-		*repeat2 = 1;
-	} else if (src = dst) {
-		*interp1 = -1;
-		*interp2 = src + 1;
-		*repeat1 = 1;
-		*repeat2 = 2;
-	} else {
-		*interp1 = -2;
-		*interp2 = src + 1;
-		*repeat1 = 2;
-		*repeat2 = 2;
-	}
-	*interp1 += src_coord;
-	*interp2 += src_coord;
-}
-
-static int get_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
-{
-	int32_t luma_interp[4];
-	int32_t luma_repeat[4];
-	int32_t chroma_interp[4];
-	int32_t chroma_bound[4];
-	int32_t chroma_repeat[4];
-	uint32_t dst_w, dst_h;
-
-	memset(&luma_interp, 0, sizeof(int32_t) * 4);
-	memset(&luma_repeat, 0, sizeof(int32_t) * 4);
-	memset(&chroma_interp, 0, sizeof(int32_t) * 4);
-	memset(&chroma_bound, 0, sizeof(int32_t) * 4);
-	memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
-	regs->edge = 0;
-
-	if (req->flags & MDP_ROT_90) {
-		dst_w = req->dst_rect.h;
-		dst_h = req->dst_rect.w;
-	} else {
-		dst_w = req->dst_rect.w;
-		dst_h = req->dst_rect.h;
-	}
-
-	if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
-		get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
-			      &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
-			      &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
-		get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
-			      &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
-			      &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
-	} else {
-		luma_interp[IMG_LEFT] = req->src_rect.x;
-		luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
-		luma_interp[IMG_TOP] = req->src_rect.y;
-		luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
-		luma_repeat[IMG_LEFT] = 0;
-		luma_repeat[IMG_TOP] = 0;
-		luma_repeat[IMG_RIGHT] = 0;
-		luma_repeat[IMG_BOTTOM] = 0;
-	}
-
-	chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
-	chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
-	chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
-	chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
-
-	chroma_bound[IMG_LEFT] = req->src_rect.x;
-	chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
-	chroma_bound[IMG_TOP] = req->src_rect.y;
-	chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
-
-	if (IS_YCRCB(req->src.format)) {
-		chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
-		chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
-
-		chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
-		chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
-	}
 
-	if (req->src.format = MDP_Y_CBCR_H2V2 ||
-	    req->src.format = MDP_Y_CRCB_H2V2) {
-		chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
-		chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
-					    >> 1;
-		chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
-		chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
-	}
-
-	chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
-				  chroma_interp[IMG_LEFT];
-	chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
-				  chroma_bound[IMG_RIGHT];
-	chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
-				  chroma_interp[IMG_TOP];
-	chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
-				  chroma_bound[IMG_BOTTOM];
-
-	if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
-	    chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
-	    chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
-	    chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
-	    luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
-	    luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
-	    luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
-	    luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
-		return -1;
-
-	regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
-	regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
-	regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
-	regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
-	regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
-	regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
-	return 0;
+	/* since we always blend src + dst -> dst, copy most of the
+	 * configuration from dest to bg */
+	regs->bg0 = regs->dst0;
+	regs->bg1 = regs->dst1;
+	regs->bg_cfg = src_img_cfg[req->dst.format];
+	regs->bg_bpp = regs->dst_bpp;
+	regs->bg_pack = pack_pattern[req->dst.format];
+	regs->bg_ystride = regs->dst_ystride;
 }
 
 static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		      struct ppp_regs *regs)
 {
-	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
-	uint32_t scale_factor_x, scale_factor_y;
-	uint32_t downscale;
-	uint32_t dst_w, dst_h;
+	struct mdp_rect dst_rect;
 
+	memcpy(&dst_rect, &req->dst_rect, sizeof(dst_rect));
 	if (req->flags & MDP_ROT_90) {
-		dst_w = req->dst_rect.h;
-		dst_h = req->dst_rect.w;
-	} else {
-		dst_w = req->dst_rect.w;
-		dst_h = req->dst_rect.h;
+		dst_rect.w = req->dst_rect.h;
+		dst_rect.h = req->dst_rect.w;
 	}
-	if ((req->src_rect.w = dst_w)  && (req->src_rect.h = dst_h) &&
-	    !(req->flags & MDP_BLUR)) {
+
+	if ((req->src_rect.w = dst_rect.w) && (req->src_rect.h = dst_rect.h)
+	    && !(req->flags & MDP_BLUR)) {
 		regs->phasex_init = 0;
 		regs->phasey_init = 0;
 		regs->phasex_step = 0;
@@ -436,73 +225,35 @@ static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		return 0;
 	}
 
-	if (scale_params(req->src_rect.w, dst_w, 1, &phase_init_x,
-			 &phase_step_x) ||
-	    scale_params(req->src_rect.h, dst_h, 1, &phase_init_y,
-			 &phase_step_y))
+#ifdef 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");
 		return -1;
-
-	scale_factor_x = (dst_w * 10) / req->src_rect.w;
-	scale_factor_y = (dst_h * 10) / req->src_rect.h;
-
-	if (scale_factor_x > 8)
-		downscale = MDP_DOWNSCALE_PT8TO1;
-	else if (scale_factor_x > 6)
-		downscale = MDP_DOWNSCALE_PT6TOPT8;
-	else if (scale_factor_x > 4)
-		downscale = MDP_DOWNSCALE_PT4TOPT6;
-	else
-		downscale = MDP_DOWNSCALE_PT2TOPT4;
-	if (downscale != downscale_x_table) {
-		load_scale_table(mdp, mdp_downscale_x_table[downscale], 64);
-		downscale_x_table = downscale;
 	}
+#endif
 
-	if (scale_factor_y > 8)
-		downscale = MDP_DOWNSCALE_PT8TO1;
-	else if (scale_factor_y > 6)
-		downscale = MDP_DOWNSCALE_PT6TOPT8;
-	else if (scale_factor_y > 4)
-		downscale = MDP_DOWNSCALE_PT4TOPT6;
-	else
-		downscale = MDP_DOWNSCALE_PT2TOPT4;
-	if (downscale != downscale_y_table) {
-		load_scale_table(mdp, mdp_downscale_y_table[downscale], 64);
-		downscale_y_table = downscale;
-	}
-
-	regs->phasex_init = phase_init_x;
-	regs->phasey_init = phase_init_y;
-	regs->phasex_step = phase_step_x;
-	regs->phasey_step = phase_step_y;
 	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
 	return 0;
-
 }
 
 static void blit_blur(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		      struct ppp_regs *regs)
 {
+#ifdef CONFIG_MSM_MDP22
+	int ret;
+#endif
 	if (!(req->flags & MDP_BLUR))
 		return;
 
-	if (!(downscale_x_table = MDP_DOWNSCALE_BLUR &&
-	      downscale_y_table = MDP_DOWNSCALE_BLUR)) {
-		load_scale_table(mdp, mdp_gaussian_blur_table, 128);
-		downscale_x_table = MDP_DOWNSCALE_BLUR;
-		downscale_y_table = MDP_DOWNSCALE_BLUR;
-	}
-
+#ifdef CONFIG_MSM_MDP22
+	ret = mdp_ppp_load_blur(mdp);
+	if (ret)
+		return;
+#endif
 	regs->op |= (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
 }
 
-
-#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
-
-#define Y_TO_CRCB_RATIO(format) \
-	((format = MDP_Y_CBCR_H2V2 || format = MDP_Y_CRCB_H2V2) ?  2 :\
-	 (format = MDP_Y_CBCR_H2V1 || format = MDP_Y_CRCB_H2V1) ?  1 : 1)
-
 static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
 		    uint32_t *len0, uint32_t *len1)
 {
@@ -555,7 +306,6 @@ static int valid_src_dst(unsigned long src_start, unsigned long src_len,
 	return 1;
 }
 
-
 static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
 		       struct file *src_file, struct file *dst_file)
 {
@@ -643,22 +393,29 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		return -EINVAL;
 	}
 
+	if (unlikely(req->src_rect.x + req->src_rect.w > req->src.width ||
+		     req->src_rect.y + req->src_rect.h > req->src.height ||
+		     req->dst_rect.x + req->dst_rect.w > req->dst.width ||
+		     req->dst_rect.y + req->dst_rect.h > req->dst.height)) {
+		printk(KERN_ERR "mdp_ppp: img rect extends outside of img!\n");
+		return -EINVAL;
+	}
+
 	/* set the src image configuration */
 	regs.src_cfg = src_img_cfg[req->src.format];
 	regs.src_cfg |= (req->src_rect.x & 0x1) ? PPP_SRC_BPP_ROI_ODD_X : 0;
 	regs.src_cfg |= (req->src_rect.y & 0x1) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
-	regs.src_rect = (req->src_rect.h << 16) | req->src_rect.w;
 	regs.src_pack = pack_pattern[req->src.format];
 
 	/* set the dest image configuration */
 	regs.dst_cfg = dst_img_cfg[req->dst.format] | PPP_DST_OUT_SEL_AXI;
-	regs.dst_rect = (req->dst_rect.h << 16) | req->dst_rect.w;
 	regs.dst_pack = pack_pattern[req->dst.format];
 
 	/* set src, bpp, start pixel and ystride */
 	regs.src_bpp = bytes_per_pixel[req->src.format];
 	regs.src0 = src_start + req->src.offset;
 	regs.src_ystride = req->src.width * regs.src_bpp;
+	set_src_region(&req->src, &req->src_rect, &regs);
 	get_chroma_addr(&req->src, &req->src_rect, regs.src0, regs.src_bpp,
 			regs.src_cfg, &regs.src1, &regs.src_ystride);
 	regs.src0 += (req->src_rect.x + (req->src_rect.y * req->src.width)) *
@@ -668,6 +425,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 	regs.dst_bpp = bytes_per_pixel[req->dst.format];
 	regs.dst0 = dst_start + req->dst.offset;
 	regs.dst_ystride = req->dst.width * regs.dst_bpp;
+	set_dst_region(&req->dst_rect, &regs);
 	get_chroma_addr(&req->dst, &req->dst_rect, regs.dst0, regs.dst_bpp,
 			regs.dst_cfg, &regs.dst1, &regs.dst_ystride);
 	regs.dst0 += (req->dst_rect.x + (req->dst_rect.y * req->dst.width)) *
@@ -703,9 +461,11 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		req->dst_rect.x = req->dst_rect.x & (~0x1);
 		req->dst_rect.w = req->dst_rect.w & (~0x1);
 	}
-	if (get_edge_cond(req, &regs))
-		return -EINVAL;
 
+#ifdef CONFIG_MSM_MDP22
+	if (mdp_ppp_cfg_edge_cond(req, &regs))
+		return -EINVAL;
+#endif
 	send_blit(mdp, req, &regs, src_file, dst_file);
 	return 0;
 }
diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
index ef3b125..c3cd895 100644
--- a/drivers/video/msm/mdp_ppp.h
+++ b/drivers/video/msm/mdp_ppp.h
@@ -47,4 +47,16 @@ struct ppp_regs {
 	uint32_t bg_ystride;
 };
 
+struct mdp_info;
+struct mdp_rect;
+struct mdp_blit_req;
+
+void mdp_ppp_init_scale(const struct mdp_info *mdp);
+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);
+int mdp_ppp_load_blur(const struct mdp_info *mdp);
+
+int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs);
+
 #endif /* _VIDEO_MSM_MDP_PPP_H_ */
diff --git a/drivers/video/msm/mdp_scale_tables.c b/drivers/video/msm/mdp_ppp22.c
similarity index 69%
rename from drivers/video/msm/mdp_scale_tables.c
rename to drivers/video/msm/mdp_ppp22.c
index 604783b..8cfcff2 100644
--- a/drivers/video/msm/mdp_scale_tables.c
+++ b/drivers/video/msm/mdp_ppp22.c
@@ -1,6 +1,6 @@
-/* drivers/video/msm_fb/mdp_scale_tables.c
+/* drivers/video/msm/mdp_ppp22.c
  *
- * Copyright (C) 2007 QUALCOMM Incorporated
+ * Copyright (C) 2007, 2011 Code Aurora Forum. All rights reserved.
  * Copyright (C) 2007 Google Incorporated
  *
  * This software is licensed under the terms of the GNU General Public
@@ -13,10 +13,33 @@
  * GNU General Public License for more details.
  */
 
-#include "mdp_scale_tables.h"
+#include <linux/kernel.h>
+#include <linux/io.h>
+#include <linux/msm_mdp.h>
+
 #include "mdp_hw.h"
+#include "mdp_ppp.h"
+
+struct mdp_table_entry {
+	uint32_t reg;
+	uint32_t val;
+};
+
+enum {
+	MDP_DOWNSCALE_PT2TOPT4,
+	MDP_DOWNSCALE_PT4TOPT6,
+	MDP_DOWNSCALE_PT6TOPT8,
+	MDP_DOWNSCALE_PT8TO1,
+	MDP_DOWNSCALE_MAX,
+
+	/* not technically in the downscale table list */
+	MDP_DOWNSCALE_BLUR,
+};
 
-struct mdp_table_entry mdp_upscale_table[] = {
+static int downscale_x_table;
+static int downscale_y_table;
+
+static struct mdp_table_entry mdp_upscale_table[] = {
 	{ 0x5fffc, 0x0 },
 	{ 0x50200, 0x7fc00000 },
 	{ 0x5fffc, 0xff80000d },
@@ -764,3 +787,305 @@ struct mdp_table_entry mdp_gaussian_blur_table[] = {
 	{ 0x5fffc, 0x20000080 },
 	{ 0x5037c, 0x20000080 },
 };
+
+static void load_table(const struct mdp_info *mdp,
+		       struct mdp_table_entry *table, int len)
+{
+	int i;
+	for (i = 0; i < len; i++)
+		mdp_writel(mdp, table[i].val, table[i].reg);
+}
+
+enum {
+	IMG_LEFT,
+	IMG_RIGHT,
+	IMG_TOP,
+	IMG_BOTTOM,
+};
+
+static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
+			  uint32_t *interp1, uint32_t *interp2,
+			  uint32_t *repeat1, uint32_t *repeat2) {
+	if (src > 3 * dst) {
+		*interp1 = 0;
+		*interp2 = src - 1;
+		*repeat1 = 0;
+		*repeat2 = 0;
+	} else if (src = 3 * dst) {
+		*interp1 = 0;
+		*interp2 = src;
+		*repeat1 = 0;
+		*repeat2 = 1;
+	} else if (src > dst && src < 3 * dst) {
+		*interp1 = -1;
+		*interp2 = src;
+		*repeat1 = 1;
+		*repeat2 = 1;
+	} else if (src = dst) {
+		*interp1 = -1;
+		*interp2 = src + 1;
+		*repeat1 = 1;
+		*repeat2 = 2;
+	} else {
+		*interp1 = -2;
+		*interp2 = src + 1;
+		*repeat1 = 2;
+		*repeat2 = 2;
+	}
+	*interp1 += src_coord;
+	*interp2 += src_coord;
+}
+
+int mdp_ppp_cfg_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
+{
+	int32_t luma_interp[4];
+	int32_t luma_repeat[4];
+	int32_t chroma_interp[4];
+	int32_t chroma_bound[4];
+	int32_t chroma_repeat[4];
+	uint32_t dst_w, dst_h;
+
+	memset(&luma_interp, 0, sizeof(int32_t) * 4);
+	memset(&luma_repeat, 0, sizeof(int32_t) * 4);
+	memset(&chroma_interp, 0, sizeof(int32_t) * 4);
+	memset(&chroma_bound, 0, sizeof(int32_t) * 4);
+	memset(&chroma_repeat, 0, sizeof(int32_t) * 4);
+	regs->edge = 0;
+
+	if (req->flags & MDP_ROT_90) {
+		dst_w = req->dst_rect.h;
+		dst_h = req->dst_rect.w;
+	} else {
+		dst_w = req->dst_rect.w;
+		dst_h = req->dst_rect.h;
+	}
+
+	if (regs->op & (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON)) {
+		get_edge_info(req->src_rect.h, req->src_rect.y, dst_h,
+			      &luma_interp[IMG_TOP], &luma_interp[IMG_BOTTOM],
+			      &luma_repeat[IMG_TOP], &luma_repeat[IMG_BOTTOM]);
+		get_edge_info(req->src_rect.w, req->src_rect.x, dst_w,
+			      &luma_interp[IMG_LEFT], &luma_interp[IMG_RIGHT],
+			      &luma_repeat[IMG_LEFT], &luma_repeat[IMG_RIGHT]);
+	} else {
+		luma_interp[IMG_LEFT] = req->src_rect.x;
+		luma_interp[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+		luma_interp[IMG_TOP] = req->src_rect.y;
+		luma_interp[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+		luma_repeat[IMG_LEFT] = 0;
+		luma_repeat[IMG_TOP] = 0;
+		luma_repeat[IMG_RIGHT] = 0;
+		luma_repeat[IMG_BOTTOM] = 0;
+	}
+
+	chroma_interp[IMG_LEFT] = luma_interp[IMG_LEFT];
+	chroma_interp[IMG_RIGHT] = luma_interp[IMG_RIGHT];
+	chroma_interp[IMG_TOP] = luma_interp[IMG_TOP];
+	chroma_interp[IMG_BOTTOM] = luma_interp[IMG_BOTTOM];
+
+	chroma_bound[IMG_LEFT] = req->src_rect.x;
+	chroma_bound[IMG_RIGHT] = req->src_rect.x + req->src_rect.w - 1;
+	chroma_bound[IMG_TOP] = req->src_rect.y;
+	chroma_bound[IMG_BOTTOM] = req->src_rect.y + req->src_rect.h - 1;
+
+	if (IS_YCRCB(req->src.format)) {
+		chroma_interp[IMG_LEFT] = chroma_interp[IMG_LEFT] >> 1;
+		chroma_interp[IMG_RIGHT] = (chroma_interp[IMG_RIGHT] + 1) >> 1;
+
+		chroma_bound[IMG_LEFT] = chroma_bound[IMG_LEFT] >> 1;
+		chroma_bound[IMG_RIGHT] = chroma_bound[IMG_RIGHT] >> 1;
+	}
+
+	if (req->src.format = MDP_Y_CBCR_H2V2 ||
+	    req->src.format = MDP_Y_CRCB_H2V2) {
+		chroma_interp[IMG_TOP] = (chroma_interp[IMG_TOP] - 1) >> 1;
+		chroma_interp[IMG_BOTTOM] = (chroma_interp[IMG_BOTTOM] + 1)
+					    >> 1;
+		chroma_bound[IMG_TOP] = (chroma_bound[IMG_TOP] + 1) >> 1;
+		chroma_bound[IMG_BOTTOM] = chroma_bound[IMG_BOTTOM] >> 1;
+	}
+
+	chroma_repeat[IMG_LEFT] = chroma_bound[IMG_LEFT] -
+				  chroma_interp[IMG_LEFT];
+	chroma_repeat[IMG_RIGHT] = chroma_interp[IMG_RIGHT] -
+				  chroma_bound[IMG_RIGHT];
+	chroma_repeat[IMG_TOP] = chroma_bound[IMG_TOP] -
+				  chroma_interp[IMG_TOP];
+	chroma_repeat[IMG_BOTTOM] = chroma_interp[IMG_BOTTOM] -
+				  chroma_bound[IMG_BOTTOM];
+
+	if (chroma_repeat[IMG_LEFT] < 0 || chroma_repeat[IMG_LEFT] > 3 ||
+	    chroma_repeat[IMG_RIGHT] < 0 || chroma_repeat[IMG_RIGHT] > 3 ||
+	    chroma_repeat[IMG_TOP] < 0 || chroma_repeat[IMG_TOP] > 3 ||
+	    chroma_repeat[IMG_BOTTOM] < 0 || chroma_repeat[IMG_BOTTOM] > 3 ||
+	    luma_repeat[IMG_LEFT] < 0 || luma_repeat[IMG_LEFT] > 3 ||
+	    luma_repeat[IMG_RIGHT] < 0 || luma_repeat[IMG_RIGHT] > 3 ||
+	    luma_repeat[IMG_TOP] < 0 || luma_repeat[IMG_TOP] > 3 ||
+	    luma_repeat[IMG_BOTTOM] < 0 || luma_repeat[IMG_BOTTOM] > 3)
+		return -1;
+
+	regs->edge |= (chroma_repeat[IMG_LEFT] & 3) << MDP_LEFT_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_TOP] & 3) << MDP_TOP_CHROMA;
+	regs->edge |= (chroma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_CHROMA;
+	regs->edge |= (luma_repeat[IMG_LEFT] & 3) << MDP_LEFT_LUMA;
+	regs->edge |= (luma_repeat[IMG_RIGHT] & 3) << MDP_RIGHT_LUMA;
+	regs->edge |= (luma_repeat[IMG_TOP] & 3) << MDP_TOP_LUMA;
+	regs->edge |= (luma_repeat[IMG_BOTTOM] & 3) << MDP_BOTTOM_LUMA;
+	return 0;
+}
+
+#define ONE_HALF	(1LL << 32)
+#define ONE		(1LL << 33)
+#define TWO		(2LL << 33)
+#define THREE		(3LL << 33)
+#define FRAC_MASK (ONE - 1)
+#define INT_MASK (~FRAC_MASK)
+
+static int scale_params(uint32_t dim_in, uint32_t dim_out, uint32_t origin,
+			uint32_t *phase_init, uint32_t *phase_step)
+{
+	/* to improve precicsion calculations are done in U31.33 and converted
+	 * to U3.29 at the end */
+	int64_t k1, k2, k3, k4, tmp;
+	uint64_t n, d, os, os_p, od, od_p, oreq;
+	unsigned rpa = 0;
+	int64_t ip64, delta;
+
+	if (dim_out % 3 = 0)
+		rpa = !(dim_in % (dim_out / 3));
+
+	n = ((uint64_t)dim_out) << 34;
+	d = dim_in;
+	if (!d)
+		return -1;
+	do_div(n, d);
+	k3 = (n + 1) >> 1;
+	if ((k3 >> 4) < (1LL << 27) || (k3 >> 4) > (1LL << 31))
+		return -1;
+
+	n = ((uint64_t)dim_in) << 34;
+	d = (uint64_t)dim_out;
+	if (!d)
+		return -1;
+	do_div(n, d);
+	k1 = (n + 1) >> 1;
+	k2 = (k1 - ONE) >> 1;
+
+	*phase_init = (int)(k2 >> 4);
+	k4 = (k3 - ONE) >> 1;
+
+	if (rpa) {
+		os = ((uint64_t)origin << 33) - ONE_HALF;
+		tmp = (dim_out * os) + ONE_HALF;
+		if (!dim_in)
+			return -1;
+		do_div(tmp, dim_in);
+		od = tmp - ONE_HALF;
+	} else {
+		os = ((uint64_t)origin << 1) - 1;
+		od = (((k3 * os) >> 1) + k4);
+	}
+
+	od_p = od & INT_MASK;
+	if (od_p != od)
+		od_p += ONE;
+
+	if (rpa) {
+		tmp = (dim_in * od_p) + ONE_HALF;
+		if (!dim_in)
+			return -1;
+		do_div(tmp, dim_in);
+		os_p = tmp - ONE_HALF;
+	} else {
+		os_p = ((k1 * (od_p >> 33)) + k2);
+	}
+
+	oreq = (os_p & INT_MASK) - ONE;
+
+	ip64 = os_p - oreq;
+	delta = ((int64_t)(origin) << 33) - oreq;
+	ip64 -= delta;
+	/* limit to valid range before the left shift */
+	delta = (ip64 & (1LL << 63)) ? 4 : -4;
+	delta <<= 33;
+	while (abs((int)(ip64 >> 33)) > 4)
+		ip64 += delta;
+	*phase_init = (int)(ip64 >> 4);
+	*phase_step = (uint32_t)(k1 >> 4);
+	return 0;
+}
+
+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)
+{
+	int downscale;
+	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
+	uint32_t scale_factor_x, scale_factor_y;
+
+	if (scale_params(src_rect->w, dst_rect->w, 1, &phase_init_x,
+			 &phase_step_x) ||
+	    scale_params(src_rect->h, dst_rect->h, 1, &phase_init_y,
+			 &phase_step_y))
+		return -1;
+
+	regs->phasex_init = phase_init_x;
+	regs->phasey_init = phase_init_y;
+	regs->phasex_step = phase_step_x;
+	regs->phasey_step = phase_step_y;
+
+	scale_factor_x = (dst_rect->w * 10) / src_rect->w;
+	scale_factor_y = (dst_rect->h * 10) / src_rect->h;
+
+	if (scale_factor_x > 8)
+		downscale = MDP_DOWNSCALE_PT8TO1;
+	else if (scale_factor_x > 6)
+		downscale = MDP_DOWNSCALE_PT6TOPT8;
+	else if (scale_factor_x > 4)
+		downscale = MDP_DOWNSCALE_PT4TOPT6;
+	else
+		downscale = MDP_DOWNSCALE_PT2TOPT4;
+
+	if (downscale != downscale_x_table) {
+		load_table(mdp, mdp_downscale_x_table[downscale], 64);
+		downscale_x_table = downscale;
+	}
+
+	if (scale_factor_y > 8)
+		downscale = MDP_DOWNSCALE_PT8TO1;
+	else if (scale_factor_y > 6)
+		downscale = MDP_DOWNSCALE_PT6TOPT8;
+	else if (scale_factor_y > 4)
+		downscale = MDP_DOWNSCALE_PT4TOPT6;
+	else
+		downscale = MDP_DOWNSCALE_PT2TOPT4;
+
+	if (downscale != downscale_y_table) {
+		load_table(mdp, mdp_downscale_y_table[downscale], 64);
+		downscale_y_table = downscale;
+	}
+
+	return 0;
+}
+
+
+int mdp_ppp_load_blur(const struct mdp_info *mdp)
+{
+	if (!(downscale_x_table = MDP_DOWNSCALE_BLUR &&
+		downscale_y_table = MDP_DOWNSCALE_BLUR)) {
+		load_table(mdp, mdp_gaussian_blur_table, 128);
+		downscale_x_table = MDP_DOWNSCALE_BLUR;
+		downscale_y_table = MDP_DOWNSCALE_BLUR;
+	}
+
+	return 0;
+}
+
+void mdp_ppp_init_scale(const struct mdp_info *mdp)
+{
+	downscale_x_table = MDP_DOWNSCALE_MAX;
+	downscale_y_table = MDP_DOWNSCALE_MAX;
+
+	load_table(mdp, mdp_upscale_table, ARRAY_SIZE(mdp_upscale_table));
+}
diff --git a/drivers/video/msm/mdp_scale_tables.h b/drivers/video/msm/mdp_scale_tables.h
deleted file mode 100644
index 34077b1..0000000
--- a/drivers/video/msm/mdp_scale_tables.h
+++ /dev/null
@@ -1,38 +0,0 @@
-/* drivers/video/msm_fb/mdp_scale_tables.h
- *
- * Copyright (C) 2007 QUALCOMM Incorporated
- * Copyright (C) 2007 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.
- */
-#ifndef _MDP_SCALE_TABLES_H_
-#define _MDP_SCALE_TABLES_H_
-
-#include <linux/types.h>
-struct mdp_table_entry {
-	uint32_t reg;
-	uint32_t val;
-};
-
-extern struct mdp_table_entry mdp_upscale_table[64];
-
-enum {
-	MDP_DOWNSCALE_PT2TOPT4,
-	MDP_DOWNSCALE_PT4TOPT6,
-	MDP_DOWNSCALE_PT6TOPT8,
-	MDP_DOWNSCALE_PT8TO1,
-	MDP_DOWNSCALE_MAX,
-};
-
-extern struct mdp_table_entry *mdp_downscale_x_table[MDP_DOWNSCALE_MAX];
-extern struct mdp_table_entry *mdp_downscale_y_table[MDP_DOWNSCALE_MAX];
-extern struct mdp_table_entry mdp_gaussian_blur_table[];
-
-#endif
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 08/20] video: msm: Refactor mdp_regs
From: Carl Vanderlip @ 2011-03-18 21:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

To begin splitting hw specific PPP operations into different files,
the mdp_regs struct will be moved into a new generic header file
for PPP operations.

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>
---
 drivers/video/msm/mdp_ppp.c |   49 +++++++++++++-----------------------------
 drivers/video/msm/mdp_ppp.h |   50 +++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 65 insertions(+), 34 deletions(-)
 create mode 100644 drivers/video/msm/mdp_ppp.h

diff --git a/drivers/video/msm/mdp_ppp.c b/drivers/video/msm/mdp_ppp.c
index 2b04027..05f3e33 100644
--- a/drivers/video/msm/mdp_ppp.c
+++ b/drivers/video/msm/mdp_ppp.c
@@ -19,6 +19,7 @@
 #include <mach/msm_fb.h>
 
 #include "mdp_hw.h"
+#include "mdp_ppp.h"
 #include "mdp_scale_tables.h"
 
 #define DLOG(x...) do {} while (0)
@@ -27,28 +28,6 @@
 static int downscale_y_table = MDP_DOWNSCALE_MAX;
 static int downscale_x_table = MDP_DOWNSCALE_MAX;
 
-struct mdp_regs {
-	uint32_t src0;
-	uint32_t src1;
-	uint32_t dst0;
-	uint32_t dst1;
-	uint32_t src_cfg;
-	uint32_t dst_cfg;
-	uint32_t src_pack;
-	uint32_t dst_pack;
-	uint32_t src_rect;
-	uint32_t dst_rect;
-	uint32_t src_ystride;
-	uint32_t dst_ystride;
-	uint32_t op;
-	uint32_t src_bpp;
-	uint32_t dst_bpp;
-	uint32_t edge;
-	uint32_t phasex_init;
-	uint32_t phasey_init;
-	uint32_t phasex_step;
-	uint32_t phasey_step;
-};
 
 static uint32_t pack_pattern[] = {
 	PPP_ARRAY0(PACK_PATTERN)
@@ -88,7 +67,8 @@ static uint32_t bg_op_chroma[] = {
 	PPP_ARRAY1(CHROMA_SAMP, BG)
 };
 
-static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
+static void rotate_dst_addr_x(struct mdp_blit_req *req,
+			      struct ppp_regs *regs)
 {
 	regs->dst0 += (req->dst_rect.w -
 		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
@@ -96,7 +76,8 @@ static void rotate_dst_addr_x(struct mdp_blit_req *req, struct mdp_regs *regs)
 		       min((uint32_t)16, req->dst_rect.w)) * regs->dst_bpp;
 }
 
-static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
+static void rotate_dst_addr_y(struct mdp_blit_req *req,
+			      struct ppp_regs *regs)
 {
 	regs->dst0 += (req->dst_rect.h -
 		       min((uint32_t)16, req->dst_rect.h)) *
@@ -107,7 +88,7 @@ static void rotate_dst_addr_y(struct mdp_blit_req *req, struct mdp_regs *regs)
 }
 
 static void blit_rotate(struct mdp_blit_req *req,
-			struct mdp_regs *regs)
+			struct ppp_regs *regs)
 {
 	if (req->flags = MDP_ROT_NOP)
 		return;
@@ -126,7 +107,7 @@ static void blit_rotate(struct mdp_blit_req *req,
 		regs->op |= PPP_OP_FLIP_LR;
 }
 
-static void blit_convert(struct mdp_blit_req *req, struct mdp_regs *regs)
+static void blit_convert(struct mdp_blit_req *req, struct ppp_regs *regs)
 {
 	if (req->src.format = req->dst.format)
 		return;
@@ -165,7 +146,7 @@ static uint32_t transp_convert(struct mdp_blit_req *req)
 }
 #undef GET_BIT_RANGE
 
-static void blit_blend(struct mdp_blit_req *req, struct mdp_regs *regs)
+static void blit_blend(struct mdp_blit_req *req, struct ppp_regs *regs)
 {
 	/* TRANSP BLEND */
 	if (req->transp_mask != MDP_TRANSP_NOP) {
@@ -332,7 +313,7 @@ static void get_edge_info(uint32_t src, uint32_t src_coord, uint32_t dst,
 	*interp2 += src_coord;
 }
 
-static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
+static int get_edge_cond(struct mdp_blit_req *req, struct ppp_regs *regs)
 {
 	int32_t luma_interp[4];
 	int32_t luma_repeat[4];
@@ -432,7 +413,7 @@ static int get_edge_cond(struct mdp_blit_req *req, struct mdp_regs *regs)
 }
 
 static int blit_scale(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		      struct mdp_regs *regs)
+		      struct ppp_regs *regs)
 {
 	uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y;
 	uint32_t scale_factor_x, scale_factor_y;
@@ -500,7 +481,7 @@ 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 mdp_regs *regs)
+		      struct ppp_regs *regs)
 {
 	if (!(req->flags & MDP_BLUR))
 		return;
@@ -534,7 +515,7 @@ static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
 
 static int valid_src_dst(unsigned long src_start, unsigned long src_len,
 			 unsigned long dst_start, unsigned long dst_len,
-			 struct mdp_blit_req *req, struct mdp_regs *regs)
+			 struct mdp_blit_req *req, struct ppp_regs *regs)
 {
 	unsigned long src_min_ok = src_start;
 	unsigned long src_max_ok = src_start + src_len;
@@ -575,7 +556,7 @@ static int valid_src_dst(unsigned long src_start, unsigned long src_len,
 }
 
 
-static void flush_imgs(struct mdp_blit_req *req, struct mdp_regs *regs,
+static void flush_imgs(struct mdp_blit_req *req, struct ppp_regs *regs,
 		       struct file *src_file, struct file *dst_file)
 {
 }
@@ -601,7 +582,7 @@ static void get_chroma_addr(struct mdp_img *img, struct mdp_rect *rect,
 }
 
 static int send_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
-		     struct mdp_regs *regs, struct file *src_file,
+		     struct ppp_regs *regs, struct file *src_file,
 		     struct file *dst_file)
 {
 	mdp_writel(mdp, 1, 0x060);
@@ -646,7 +627,7 @@ int mdp_ppp_blit(const struct mdp_info *mdp, struct mdp_blit_req *req,
 		 struct file *src_file, unsigned long src_start, unsigned long src_len,
 		 struct file *dst_file, unsigned long dst_start, unsigned long dst_len)
 {
-	struct mdp_regs regs = {0};
+	struct ppp_regs regs = {0};
 
 	if (unlikely(req->src.format >= MDP_IMGTYPE_LIMIT ||
 		     req->dst.format >= MDP_IMGTYPE_LIMIT)) {
diff --git a/drivers/video/msm/mdp_ppp.h b/drivers/video/msm/mdp_ppp.h
new file mode 100644
index 0000000..ef3b125
--- /dev/null
+++ b/drivers/video/msm/mdp_ppp.h
@@ -0,0 +1,50 @@
+/* drivers/video/msm/mdp_ppp.h
+ *
+ * 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.
+ */
+
+#ifndef _VIDEO_MSM_MDP_PPP_H_
+#define _VIDEO_MSM_MDP_PPP_H_
+
+#include <linux/types.h>
+
+struct ppp_regs {
+	uint32_t src0;
+	uint32_t src1;
+	uint32_t dst0;
+	uint32_t dst1;
+	uint32_t src_cfg;
+	uint32_t dst_cfg;
+	uint32_t src_pack;
+	uint32_t dst_pack;
+	uint32_t src_rect;
+	uint32_t dst_rect;
+	uint32_t src_ystride;
+	uint32_t dst_ystride;
+	uint32_t op;
+	uint32_t src_bpp;
+	uint32_t dst_bpp;
+	uint32_t edge;
+	uint32_t phasex_init;
+	uint32_t phasey_init;
+	uint32_t phasex_step;
+	uint32_t phasey_step;
+
+	uint32_t bg0;
+	uint32_t bg1;
+	uint32_t bg_cfg;
+	uint32_t bg_bpp;
+	uint32_t bg_pack;
+	uint32_t bg_ystride;
+};
+
+#endif /* _VIDEO_MSM_MDP_PPP_H_ */
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 07/20] video: msm: Allow users to request a larger x and y virtual fb
From: Carl Vanderlip @ 2011-03-18 21:56 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

As long as the total size fits inside the memory allocated to the framebuffer
users can request a larger size. This change allows users to request a triple
buffered fb.

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>
---
 drivers/video/msm/msm_fb.c |   63 ++++++++++++++++++++++++++++++++++---------
 1 files changed, 50 insertions(+), 13 deletions(-)

diff --git a/drivers/video/msm/msm_fb.c b/drivers/video/msm/msm_fb.c
index 04d0067..6af8b41 100644
--- a/drivers/video/msm/msm_fb.c
+++ b/drivers/video/msm/msm_fb.c
@@ -53,6 +53,9 @@ do { \
 		printk(KERN_INFO "msmfb: "fmt, ##args); \
 } while (0)
 
+#define BITS_PER_PIXEL(info) (info->fb->var.bits_per_pixel)
+#define BYTES_PER_PIXEL(info) (info->fb->var.bits_per_pixel >> 3)
+
 static int msmfb_debug_mask;
 module_param_named(msmfb_debug_mask, msmfb_debug_mask, int,
 		   S_IRUGO | S_IWUSR | S_IWGRP);
@@ -161,9 +164,10 @@ static int msmfb_start_dma(struct msmfb_info *msmfb)
 	}
 	spin_unlock_irqrestore(&msmfb->update_lock, irq_flags);
 
-	addr = ((msmfb->xres * (yoffset + y) + x) * 2);
+	addr = ((msmfb->xres * (yoffset + y) + x) * BYTES_PER_PIXEL(msmfb));
 	mdp->dma(mdp, addr + msmfb->fb->fix.smem_start,
-		 msmfb->xres * 2, w, h, x, y, &msmfb->dma_callback,
+		 msmfb->xres * BYTES_PER_PIXEL(msmfb), w, h, x, y,
+		 &msmfb->dma_callback,
 		 panel->interface_type);
 	return 0;
 error:
@@ -323,14 +327,46 @@ error:
 
 static int msmfb_check_var(struct fb_var_screeninfo *var, struct fb_info *info)
 {
+	u32 size;
+
 	if ((var->xres != info->var.xres) ||
 	    (var->yres != info->var.yres) ||
-	    (var->xres_virtual != info->var.xres_virtual) ||
-	    (var->yres_virtual != info->var.yres_virtual) ||
 	    (var->xoffset != info->var.xoffset) ||
 	    (var->bits_per_pixel != info->var.bits_per_pixel) ||
 	    (var->grayscale != info->var.grayscale))
 		 return -EINVAL;
+
+	size = var->xres_virtual * var->yres_virtual *
+		(var->bits_per_pixel >> 3);
+	if (size > info->fix.smem_len)
+		return -EINVAL;
+	return 0;
+}
+
+static int msmfb_set_par(struct fb_info *info)
+{
+	struct fb_var_screeninfo *var = &info->var;
+	struct fb_fix_screeninfo *fix = &info->fix;
+
+	/* we only support RGB ordering for now */
+	if (var->bits_per_pixel = 32 || var->bits_per_pixel = 24) {
+		var->red.offset = 0;
+		var->red.length = 8;
+		var->green.offset = 8;
+		var->green.length = 8;
+		var->blue.offset = 16;
+		var->blue.length = 8;
+	} else if (var->bits_per_pixel = 16) {
+		var->red.offset = 11;
+		var->red.length = 5;
+		var->green.offset = 5;
+		var->green.length = 6;
+		var->blue.offset = 0;
+		var->blue.length = 5;
+	} else
+		return -1;
+	fix->line_length = var->xres * var->bits_per_pixel / 8;
+
 	return 0;
 }
 
@@ -427,6 +463,7 @@ static struct fb_ops msmfb_ops = {
 	.fb_open = msmfb_open,
 	.fb_release = msmfb_release,
 	.fb_check_var = msmfb_check_var,
+	.fb_set_par = msmfb_set_par,
 	.fb_pan_display = msmfb_pan_display,
 	.fb_fillrect = msmfb_fillrect,
 	.fb_copyarea = msmfb_copyarea,
@@ -438,8 +475,6 @@ static unsigned PP[16];
 
 
 
-#define BITS_PER_PIXEL 16
-
 static void setup_fb_info(struct msmfb_info *msmfb)
 {
 	struct fb_info *fb_info = msmfb->fb;
@@ -462,7 +497,7 @@ static void setup_fb_info(struct msmfb_info *msmfb)
 	fb_info->var.height = msmfb->panel->fb_data->height;
 	fb_info->var.xres_virtual = msmfb->xres;
 	fb_info->var.yres_virtual = msmfb->yres * 2;
-	fb_info->var.bits_per_pixel = BITS_PER_PIXEL;
+	fb_info->var.bits_per_pixel = 16;
 	fb_info->var.accel_flags = 0;
 
 	fb_info->var.yoffset = 0;
@@ -497,28 +532,30 @@ static int setup_fbmem(struct msmfb_info *msmfb, struct platform_device *pdev)
 	struct fb_info *fb = msmfb->fb;
 	struct resource *resource;
 	unsigned long size = msmfb->xres * msmfb->yres *
-			     (BITS_PER_PIXEL >> 3) * 2;
+		BYTES_PER_PIXEL(msmfb) * 2;
+	unsigned long resource_size;
 	unsigned char *fbram;
 
 	/* board file might have attached a resource describing an fb */
 	resource = platform_get_resource(pdev, IORESOURCE_MEM, 0);
 	if (!resource)
 		return -EINVAL;
+	resource_size = resource->end - resource->start + 1;
 
 	/* check the resource is large enough to fit the fb */
-	if (resource->end - resource->start < size) {
-		printk(KERN_ERR "allocated resource is too small for "
+	if (resource_size < size) {
+		printk(KERN_ERR "msmfb: allocated resource is too small for "
 				"fb\n");
 		return -ENOMEM;
 	}
 	fb->fix.smem_start = resource->start;
-	fb->fix.smem_len = resource->end - resource->start;
-	fbram = ioremap(resource->start,
-			resource->end - resource->start);
+	fb->fix.smem_len = resource_size;
+	fbram = ioremap(resource->start, resource_size);
 	if (fbram = 0) {
 		printk(KERN_ERR "msmfb: cannot allocate fbram!\n");
 		return -ENOMEM;
 	}
+
 	fb->screen_base = fbram;
 	return 0;
 }
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related

* [PATCH 06/20] video: msm: Simplify mdp_blit function
From: Carl Vanderlip @ 2011-03-18 21:55 UTC (permalink / raw)
  To: linux-arm-kernel
In-Reply-To: <1300484846-26393-1-git-send-email-carlv@codeaurora.org>

Move the enabling of mdp interrupt, blitting and waiting for blit
to complete to a separate function to simplify the actions completed
by mdp_blit.

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>
---
 drivers/video/msm/mdp.c |   53 ++++++++++++++++++++++++++--------------------
 1 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/drivers/video/msm/mdp.c b/drivers/video/msm/mdp.c
index c046982..765df06 100644
--- a/drivers/video/msm/mdp.c
+++ b/drivers/video/msm/mdp.c
@@ -308,6 +308,29 @@ void put_img(struct file *src_file, struct file *dst_file)
 {
 }
 
+int mdp_blit_and_wait(struct mdp_info *mdp, struct mdp_blit_req *req,
+		struct file *src_file, unsigned long src_start,
+		unsigned long src_len, struct file *dst_file,
+		unsigned long dst_start, unsigned long dst_len)
+{
+	int ret;
+	enable_mdp_irq(mdp, DL0_ROI_DONE);
+	ret = mdp_ppp_blit(mdp, req,
+			src_file, src_start, src_len,
+			dst_file, dst_start, dst_len);
+	if (unlikely(ret)) {
+		disable_mdp_irq(mdp, DL0_ROI_DONE);
+		return ret;
+	}
+	ret = mdp_ppp_wait(mdp);
+	if (unlikely(ret)) {
+		printk(KERN_ERR "%s: failed!\n", __func__);
+		BUG();
+		return ret;
+	}
+	return 0;
+}
+
 int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
 	     struct mdp_blit_req *req)
 {
@@ -354,15 +377,11 @@ int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
 		req->src_rect.w = 16*req->src_rect.w / req->dst_rect.h;
 		req->dst_rect.h = 16;
 		for (i = 0; i < tiles; i++) {
-			enable_mdp_irq(mdp, DL0_ROI_DONE);
-			ret = mdp_ppp_blit(mdp, req, src_file, src_start,
-					   src_len, dst_file, dst_start,
-					   dst_len);
-			if (ret)
-				goto err_bad_blit;
-			ret = mdp_ppp_wait(mdp);
+			ret = mdp_blit_and_wait(mdp, req,
+						src_file, src_start, src_len,
+						dst_file, dst_start, dst_len);
 			if (ret)
-				goto err_wait_failed;
+				goto end;
 			req->dst_rect.y += 16;
 			req->src_rect.x += req->src_rect.w;
 		}
@@ -371,24 +390,12 @@ int mdp_blit(struct mdp_device *mdp_dev, struct fb_info *fb,
 		req->src_rect.w = remainder*req->src_rect.w / req->dst_rect.h;
 		req->dst_rect.h = remainder;
 	}
-	enable_mdp_irq(mdp, DL0_ROI_DONE);
-	ret = mdp_ppp_blit(mdp, req, src_file, src_start, src_len, dst_file,
-			   dst_start,
-			   dst_len);
-	if (ret)
-		goto err_bad_blit;
-	ret = mdp_ppp_wait(mdp);
-	if (ret)
-		goto err_wait_failed;
+	ret = mdp_blit_and_wait(mdp, req,
+				src_file, src_start, src_len,
+				dst_file, dst_start, dst_len);
 end:
 	put_img(src_file, dst_file);
 	mutex_unlock(&mdp_mutex);
-	return 0;
-err_bad_blit:
-	disable_mdp_irq(mdp, DL0_ROI_DONE);
-err_wait_failed:
-	put_img(src_file, dst_file);
-	mutex_unlock(&mdp_mutex);
 	return ret;
 }
 
-- 
Sent by an employee of the Qualcomm Innovation Center, Inc.
The Qualcomm Innovation Center, Inc. is a member of the Code Aurora Forum.


^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox