diff options
| -rw-r--r-- | drivers/video/fbdev/msm/Makefile | 1 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3.c | 167 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3.h | 26 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_ctrl.c | 61 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_hwio.h | 65 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_ppp.c | 760 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_ppp.h | 413 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_ppp_data.c | 1572 | ||||
| -rw-r--r-- | drivers/video/fbdev/msm/mdp3_ppp_hwio.c | 1184 |
9 files changed, 4206 insertions, 43 deletions
diff --git a/drivers/video/fbdev/msm/Makefile b/drivers/video/fbdev/msm/Makefile index 48f5be9373e3..7309b79794b2 100644 --- a/drivers/video/fbdev/msm/Makefile +++ b/drivers/video/fbdev/msm/Makefile @@ -1,6 +1,7 @@ ccflags-y := -Idrivers/staging/android mdss-mdp3-objs = mdp3.o mdp3_dma.o mdp3_ctrl.o +mdss-mdp3-objs += mdp3_ppp.o mdp3_ppp_hwio.o mdp3_ppp_data.o obj-$(CONFIG_FB_MSM_MDSS) += mdss-mdp3.o mdss-mdp-objs := mdss_mdp.o mdss_mdp_ctl.o mdss_mdp_pipe.o mdss_mdp_util.o diff --git a/drivers/video/fbdev/msm/mdp3.c b/drivers/video/fbdev/msm/mdp3.c index cdee6a866cf1..5fe6f4a300f9 100644 --- a/drivers/video/fbdev/msm/mdp3.c +++ b/drivers/video/fbdev/msm/mdp3.c @@ -49,11 +49,12 @@ #include "mdss_fb.h" #include "mdp3_hwio.h" #include "mdp3_ctrl.h" +#include "mdp3_ppp.h" #define MDP_CORE_HW_VERSION 0x03040310 struct mdp3_hw_resource *mdp3_res; -#define MDP_BUS_VECTOR_ENTRY(ab_val, ib_val) \ +#define MDP_BUS_VECTOR_ENTRY_DMA(ab_val, ib_val) \ { \ .src = MSM_BUS_MASTER_MDP_PORT0, \ .dst = MSM_BUS_SLAVE_EBI_CH0, \ @@ -61,20 +62,59 @@ struct mdp3_hw_resource *mdp3_res; .ib = (ib_val), \ } -static struct msm_bus_vectors mdp_bus_vectors[] = { - MDP_BUS_VECTOR_ENTRY(0, 0), - MDP_BUS_VECTOR_ENTRY(SZ_128M, SZ_256M), - MDP_BUS_VECTOR_ENTRY(SZ_256M, SZ_512M), +static struct msm_bus_vectors mdp_bus_dma_vectors[] = { + MDP_BUS_VECTOR_ENTRY_DMA(0, 0), + MDP_BUS_VECTOR_ENTRY_DMA(SZ_128M, SZ_256M), + MDP_BUS_VECTOR_ENTRY_DMA(SZ_256M, SZ_512M), +}; +static struct msm_bus_paths + mdp_bus_dma_usecases[ARRAY_SIZE(mdp_bus_dma_vectors)]; +static struct msm_bus_scale_pdata mdp_bus_dma_scale_table = { + .usecase = mdp_bus_dma_usecases, + .num_usecases = ARRAY_SIZE(mdp_bus_dma_usecases), + .name = "mdp3", }; -static struct msm_bus_paths mdp_bus_usecases[ARRAY_SIZE(mdp_bus_vectors)]; +#define MDP_BUS_VECTOR_ENTRY_PPP(ab_val, ib_val) \ + { \ + .src = MSM_BUS_MASTER_MDPE, \ + .dst = MSM_BUS_SLAVE_EBI_CH0, \ + .ab = (ab_val), \ + .ib = (ib_val), \ + } + +static struct msm_bus_vectors mdp_bus_ppp_vectors[] = { + MDP_BUS_VECTOR_ENTRY_PPP(0, 0), + MDP_BUS_VECTOR_ENTRY_PPP(SZ_128M, SZ_256M), + MDP_BUS_VECTOR_ENTRY_PPP(SZ_256M, SZ_512M), +}; -static struct msm_bus_scale_pdata mdp_bus_scale_table = { - .usecase = mdp_bus_usecases, - .num_usecases = ARRAY_SIZE(mdp_bus_usecases), +static struct msm_bus_paths + mdp_bus_ppp_usecases[ARRAY_SIZE(mdp_bus_ppp_vectors)]; + +static struct msm_bus_scale_pdata mdp_bus_ppp_scale_table = { + .usecase = mdp_bus_ppp_usecases, + .num_usecases = ARRAY_SIZE(mdp_bus_ppp_usecases), .name = "mdp3", }; +struct mdp3_bus_handle_map mdp3_bus_handle[MDP3_BUS_HANDLE_MAX] = { + [MDP3_BUS_HANDLE_DMA] = { + .bus_vector = mdp_bus_dma_vectors, + .usecases = mdp_bus_dma_usecases, + .scale_pdata = &mdp_bus_dma_scale_table, + .current_bus_idx = 0, + .handle = 0, + }, + [MDP3_BUS_HANDLE_PPP] = { + .bus_vector = mdp_bus_ppp_vectors, + .usecases = mdp_bus_ppp_usecases, + .scale_pdata = &mdp_bus_ppp_scale_table, + .current_bus_idx = 0, + .handle = 0, + }, +}; + struct mdp3_iommu_domain_map mdp3_iommu_domains[MDP3_IOMMU_DOMAIN_MAX] = { [MDP3_IOMMU_DOMAIN] = { .domain_type = MDP3_IOMMU_DOMAIN, @@ -214,71 +254,106 @@ int mdp3_set_intr_callback(u32 type, struct mdp3_intr_cb *cb) static int mdp3_bus_scale_register(void) { - if (!mdp3_res->bus_handle) { - struct msm_bus_scale_pdata *bus_pdata = &mdp_bus_scale_table; - int i; + int i; - for (i = 0; i < bus_pdata->num_usecases; i++) { - mdp_bus_usecases[i].num_paths = 1; - mdp_bus_usecases[i].vectors = &mdp_bus_vectors[i]; - } + if (!mdp3_res->bus_handle) { + pr_err("No bus handle\n"); + return -EINVAL; + } + for (i = 0; i < MDP3_BUS_HANDLE_MAX; i++) { + struct mdp3_bus_handle_map *bus_handle = + &mdp3_res->bus_handle[i]; + + if (!bus_handle->handle) { + int j; + struct msm_bus_scale_pdata *bus_pdata = + bus_handle->scale_pdata; + + for (j = 0; j < bus_pdata->num_usecases; j++) { + bus_handle->usecases[j].num_paths = 1; + bus_handle->usecases[j].vectors = + &bus_handle->bus_vector[j]; + } - mdp3_res->bus_handle = msm_bus_scale_register_client(bus_pdata); - if (!mdp3_res->bus_handle) { - pr_err("not able to get bus scale\n"); - return -ENOMEM; + bus_handle->handle = + msm_bus_scale_register_client(bus_pdata); + if (!bus_handle->handle) { + pr_err("not able to get bus scale i=%d\n", i); + return -ENOMEM; + } + pr_debug("register bus_hdl=%x\n", + bus_handle->handle); } - pr_debug("register bus_hdl=%x\n", mdp3_res->bus_handle); } return 0; } static void mdp3_bus_scale_unregister(void) { - pr_debug("unregister bus_handle=%x\n", mdp3_res->bus_handle); - - if (mdp3_res->bus_handle) - msm_bus_scale_unregister_client(mdp3_res->bus_handle); + int i; + for (i = 0; i < MDP3_BUS_HANDLE_MAX; i++) { + pr_debug("unregister index=%d bus_handle=%x\n", + i, mdp3_res->bus_handle[i].handle); + if (mdp3_res->bus_handle[i].handle) { + msm_bus_scale_unregister_client( + mdp3_res->bus_handle[i].handle); + mdp3_res->bus_handle[i].handle = 0; + } + } } int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota) { - static int current_bus_idx; + struct mdp3_bus_handle_map *bus_handle; + int cur_bus_idx; int bus_idx; + int client_idx; int rc; - if (mdp3_res->bus_handle < 1) { - pr_err("invalid bus handle %d\n", mdp3_res->bus_handle); + if (client == MDP3_CLIENT_DMA_P) { + client_idx = MDP3_BUS_HANDLE_DMA; + } else if (client == MDP3_CLIENT_PPP) { + client_idx = MDP3_BUS_HANDLE_PPP; + } else { + pr_err("invalid client %d\n", client); + return -EINVAL; + } + + bus_handle = &mdp3_res->bus_handle[client_idx]; + cur_bus_idx = bus_handle->current_bus_idx; + + if (bus_handle->handle < 1) { + pr_err("invalid bus handle %d\n", bus_handle->handle); return -EINVAL; } if ((ab_quota | ib_quota) == 0) { bus_idx = 0; } else { - int num_cases = mdp_bus_scale_table.num_usecases; + int num_cases = bus_handle->scale_pdata->num_usecases; struct msm_bus_vectors *vect = NULL; - bus_idx = (current_bus_idx % (num_cases - 1)) + 1; + bus_idx = (cur_bus_idx % (num_cases - 1)) + 1; /* aligning to avoid performing updates for small changes */ ab_quota = ALIGN(ab_quota, SZ_64M); ib_quota = ALIGN(ib_quota, SZ_64M); - vect = mdp_bus_scale_table.usecase[current_bus_idx].vectors; + vect = bus_handle->scale_pdata->usecase[cur_bus_idx].vectors; if ((ab_quota == vect->ab) && (ib_quota == vect->ib)) { pr_debug("skip bus scaling, no change in vectors\n"); return 0; } - vect = mdp_bus_scale_table.usecase[bus_idx].vectors; + vect = bus_handle->scale_pdata->usecase[bus_idx].vectors; vect->ab = ab_quota; vect->ib = ib_quota; pr_debug("bus scale idx=%d ab=%llu ib=%llu\n", bus_idx, vect->ab, vect->ib); } - current_bus_idx = bus_idx; - rc = msm_bus_scale_client_update_request(mdp3_res->bus_handle, bus_idx); + bus_handle->current_bus_idx = bus_idx; + rc = msm_bus_scale_client_update_request(bus_handle->handle, bus_idx); return rc; } @@ -299,7 +374,7 @@ static int mdp3_clk_update(u32 clk_idx, u32 enable) mdp3_res->clock_ref_count[clk_idx]--; count = mdp3_res->clock_ref_count[clk_idx]; - if (count == 1) { + if (count == 1 && enable) { pr_debug("clk=%d en=%d\n", clk_idx, enable); ret = clk_prepare_enable(clk); } else if (count == 0) { @@ -656,6 +731,7 @@ static int mdp3_res_init(void) pr_err("fail to attach DMA-P context 0\n"); return rc; } + mdp3_res->bus_handle = mdp3_bus_handle; rc = mdp3_bus_scale_register(); if (rc) { pr_err("unable to register bus scaling\n"); @@ -801,9 +877,28 @@ done: return ret; } +int mdp3_ppp_iommu_attach(void) +{ + int rc; + rc = mdp3_iommu_attach(MDP3_IOMMU_CTX_PPP_0); + rc |= mdp3_iommu_attach(MDP3_IOMMU_CTX_PPP_1); + return rc; +} + +int mdp3_ppp_iommu_dettach(void) +{ + int rc; + rc = mdp3_iommu_dettach(MDP3_IOMMU_CTX_PPP_0); + rc = mdp3_iommu_dettach(MDP3_IOMMU_CTX_PPP_1); + return rc; +} + static int mdp3_init(struct msm_fb_data_type *mfd) { - return mdp3_ctrl_init(mfd); + int rc; + rc = mdp3_ctrl_init(mfd); + rc |= mdp3_ppp_res_init(); + return rc; } u32 mdp3_fb_stride(u32 fb_index, u32 xres, int bpp) diff --git a/drivers/video/fbdev/msm/mdp3.h b/drivers/video/fbdev/msm/mdp3.h index 54ab8b0a5db1..cf4d91a0cf7c 100644 --- a/drivers/video/fbdev/msm/mdp3.h +++ b/drivers/video/fbdev/msm/mdp3.h @@ -34,6 +34,12 @@ enum { }; enum { + MDP3_BUS_HANDLE_DMA, + MDP3_BUS_HANDLE_PPP, + MDP3_BUS_HANDLE_MAX, +}; + +enum { MDP3_IOMMU_DOMAIN, MDP3_IOMMU_DOMAIN_MAX }; @@ -47,10 +53,16 @@ enum { }; enum { - MDP3_BW_CLIENT_DMA_P, - MDP3_BW_CLIENT_DMA_S, - MDP3_BW_CLIENT_DMA_E, - MDP3_BW_CLIENT_PPP, + MDP3_CLIENT_DMA_P, + MDP3_CLIENT_PPP, +}; + +struct mdp3_bus_handle_map { + struct msm_bus_vectors *bus_vector; + struct msm_bus_paths *usecases; + struct msm_bus_scale_pdata *scale_pdata; + int current_bus_idx; + u32 handle; }; struct mdp3_iommu_domain_map { @@ -85,12 +97,14 @@ struct mdp3_hw_resource { struct clk *clocks[MDP3_MAX_CLK]; int clock_ref_count[MDP3_MAX_CLK]; + unsigned long dma_core_clk_request; + unsigned long ppp_core_clk_request; char __iomem *mdp_base; size_t mdp_reg_size; u32 irq; - u32 bus_handle; + struct mdp3_bus_handle_map *bus_handle; struct ion_client *ion_client; struct mdp3_iommu_domain_map *domains; @@ -127,6 +141,8 @@ int mdp3_clk_enable(int enable); int mdp3_bus_scale_set_quota(int client, u64 ab_quota, u64 ib_quota); int mdp3_put_img(struct mdp3_img_data *data); int mdp3_get_img(struct msmfb_data *img, struct mdp3_img_data *data); +int mdp3_ppp_iommu_attach(void); +int mdp3_ppp_iommu_dettach(void); #define MDP3_REG_WRITE(addr, val) writel_relaxed(val, mdp3_res->mdp_base + addr) #define MDP3_REG_READ(addr) readl_relaxed(mdp3_res->mdp_base + addr) diff --git a/drivers/video/fbdev/msm/mdp3_ctrl.c b/drivers/video/fbdev/msm/mdp3_ctrl.c index f5ac5e99abf2..3d990c2e3776 100644 --- a/drivers/video/fbdev/msm/mdp3_ctrl.c +++ b/drivers/video/fbdev/msm/mdp3_ctrl.c @@ -22,6 +22,7 @@ #include "mdp3_ctrl.h" #include "mdp3.h" +#include "mdp3_ppp.h" #define MDP_VSYNC_CLK_RATE 19200000 #define VSYNC_PERIOD 16 @@ -127,6 +128,53 @@ static int mdp3_ctrl_vsync_enable(struct msm_fb_data_type *mfd, int enable) return 0; } +static int mdp3_ctrl_blit_req(struct msm_fb_data_type *mfd, void __user *p) +{ + const int MAX_LIST_WINDOW = 16; + struct mdp_blit_req req_list[MAX_LIST_WINDOW]; + struct mdp_blit_req_list req_list_header; + int rc, count, i, req_list_count; + + if (copy_from_user(&req_list_header, p, sizeof(req_list_header))) + return -EFAULT; + p += sizeof(req_list_header); + count = req_list_header.count; + if (count < 0 || count >= MAX_BLIT_REQ) + return -EINVAL; + while (count > 0) { + /* + * Access the requests through a narrow window to decrease copy + * overhead and make larger requests accessible to the + * coherency management code. + * NOTE: The window size is intended to be larger than the + * typical request size, but not require more than 2 + * kbytes of stack storage. + */ + req_list_count = count; + if (req_list_count > MAX_LIST_WINDOW) + req_list_count = MAX_LIST_WINDOW; + if (copy_from_user(&req_list, p, + sizeof(struct mdp_blit_req)*req_list_count)) + return -EFAULT; + /* + * Do the blit DMA, if required -- returning early only if + * there is a failure. + */ + for (i = 0; i < req_list_count; i++) { + if (!(req_list[i].flags & MDP_NO_BLIT)) { + /* Do the actual blit. */ + rc = mdp3_ppp_start_blit(mfd, &(req_list[i])); + if (rc) + return rc; + } + } + + /* Go to next window of requests. */ + count -= req_list_count; + p += sizeof(struct mdp_blit_req)*req_list_count; + } + return 0; +} static ssize_t mdp3_vsync_show_event(struct device *dev, struct device_attribute *attr, char *buf) @@ -181,9 +229,9 @@ static int mdp3_ctrl_res_req_bus(struct msm_fb_data_type *mfd, int status) ab = panel_info->xres * panel_info->yres * 4; ab *= panel_info->mipi.frame_rate; ib = (ab * 3) / 2; - rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, ab, ib); + rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, ab, ib); } else { - rc = mdp3_bus_scale_set_quota(MDP3_BW_CLIENT_DMA_P, 0, 0); + rc = mdp3_bus_scale_set_quota(MDP3_CLIENT_DMA_P, 0, 0); } return rc; } @@ -394,6 +442,12 @@ static int mdp3_ctrl_on(struct msm_fb_data_type *mfd) goto on_error; } + rc = mdp3_ppp_init(); + if (rc) { + pr_err("ppp init failed\n"); + goto on_error; + } + rc = mdp3_ctrl_intf_init(mfd, mdp3_session->intf); if (rc) { pr_err("display interface init failed\n"); @@ -701,6 +755,9 @@ static int mdp3_ctrl_ioctl_handler(struct msm_fb_data_type *mfd, rc = -EFAULT; } break; + case MSMFB_BLIT: + rc = mdp3_ctrl_blit_req(mfd, argp); + break; case MSMFB_METADATA_GET: rc = copy_from_user(&metadata, argp, sizeof(metadata)); if (rc) diff --git a/drivers/video/fbdev/msm/mdp3_hwio.h b/drivers/video/fbdev/msm/mdp3_hwio.h index 2763f46ee4b1..1c5bf4676018 100644 --- a/drivers/video/fbdev/msm/mdp3_hwio.h +++ b/drivers/video/fbdev/msm/mdp3_hwio.h @@ -148,6 +148,70 @@ #define MDP3_REG_DSI_CMD_MODE_ID_MAP 0xF1000 #define MDP3_REG_DSI_CMD_MODE_TRIGGER_EN 0xF1004 +#define MDP3_PPP_CSC_PFMVn(n) (0x40400 + (4 * (n))) +#define MDP3_PPP_CSC_PRMVn(n) (0x40440 + (4 * (n))) +#define MDP3_PPP_CSC_PBVn(n) (0x40500 + (4 * (n))) +#define MDP3_PPP_CSC_PLVn(n) (0x40580 + (4 * (n))) + +#define MDP3_PPP_CSC_SFMVn(n) (0x40480 + (4 * (n))) +#define MDP3_PPP_CSC_SRMVn(n) (0x404C0 + (4 * (n))) +#define MDP3_PPP_CSC_SBVn(n) (0x40540 + (4 * (n))) +#define MDP3_PPP_CSC_SLVn(n) (0x405C0 + (4 * (n))) + +#define MDP3_PPP_SCALE_PHASEX_INIT 0x1013C +#define MDP3_PPP_SCALE_PHASEY_INIT 0x10140 +#define MDP3_PPP_SCALE_PHASEX_STEP 0x10144 +#define MDP3_PPP_SCALE_PHASEY_STEP 0x10148 + +#define MDP3_PPP_OP_MODE 0x10138 + +#define MDP3_PPP_PRE_LUT 0x40800 +#define MDP3_PPP_POST_LUT 0x40C00 +#define MDP3_PPP_LUTn(n) ((4 * (n))) + +#define MDP3_PPP_BG_EDGE_REP 0x101BC +#define MDP3_PPP_SRC_EDGE_REP 0x101B8 + +#define MDP3_PPP_STRIDE_MASK 0x3FFF +#define MDP3_PPP_STRIDE1_OFFSET 16 + +#define MDP3_PPP_XY_MASK 0x0FFF +#define MDP3_PPP_XY_OFFSET 16 + +#define MDP3_PPP_SRC_SIZE 0x10108 +#define MDP3_PPP_SRCP0_ADDR 0x1010C +#define MDP3_PPP_SRCP1_ADDR 0x10110 +#define MDP3_PPP_SRCP3_ADDR 0x10118 +#define MDP3_PPP_SRC_YSTRIDE1_ADDR 0x1011C +#define MDP3_PPP_SRC_YSTRIDE2_ADDR 0x10120 +#define MDP3_PPP_SRC_FORMAT 0x10124 +#define MDP3_PPP_SRC_UNPACK_PATTERN1 0x10128 +#define MDP3_PPP_SRC_UNPACK_PATTERN2 0x1012C + +#define MDP3_PPP_OUT_FORMAT 0x10150 +#define MDP3_PPP_OUT_PACK_PATTERN1 0x10154 +#define MDP3_PPP_OUT_PACK_PATTERN2 0x10158 +#define MDP3_PPP_OUT_SIZE 0x10164 +#define MDP3_PPP_OUTP0_ADDR 0x10168 +#define MDP3_PPP_OUTP1_ADDR 0x1016C +#define MDP3_PPP_OUTP3_ADDR 0x10174 +#define MDP3_PPP_OUT_YSTRIDE1_ADDR 0x10178 +#define MDP3_PPP_OUT_YSTRIDE2_ADDR 0x1017C +#define MDP3_PPP_OUT_XY 0x1019C + +#define MDP3_PPP_BGP0_ADDR 0x101C0 +#define MDP3_PPP_BGP1_ADDR 0x101C4 +#define MDP3_PPP_BGP3_ADDR 0x101C8 +#define MDP3_PPP_BG_YSTRIDE1_ADDR 0x101CC +#define MDP3_PPP_BG_YSTRIDE2_ADDR 0x101D0 +#define MDP3_PPP_BG_FORMAT 0x101D4 +#define MDP3_PPP_BG_UNPACK_PATTERN1 0x101D8 +#define MDP3_PPP_BG_UNPACK_PATTERN2 0x101DC + +#define MDP3_PPP_BLEND_PARAM 0x1014C + +#define MDP3_PPP_BLEND_BG_ALPHA_SEL 0x70010 + /*interrupt mask*/ #define MDP3_INTR_DP0_ROI_DONE_BIT BIT(0) @@ -212,5 +276,6 @@ enum { #define MDP3_DMA_P_HIST_INTR_RESET_DONE_BIT BIT(0) #define MDP3_DMA_P_HIST_INTR_HIST_DONE_BIT BIT(1) +#define MDP3_PPP_DONE MDP3_INTR_DP0_ROI_DONE #endif /* MDP3_HWIO_H */ diff --git a/drivers/video/fbdev/msm/mdp3_ppp.c b/drivers/video/fbdev/msm/mdp3_ppp.c new file mode 100644 index 000000000000..7164086a3ecd --- /dev/null +++ b/drivers/video/fbdev/msm/mdp3_ppp.c @@ -0,0 +1,760 @@ +/* Copyright (c) 2007, 2013 The Linux Foundation. All rights reserved. + * 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. + */ + +#include <linux/file.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/uaccess.h> +#include <linux/sched.h> +#include <linux/mutex.h> +#include "linux/proc_fs.h" + +#include "mdss_fb.h" +#include "mdp3_ppp.h" +#include "mdp3_hwio.h" +#include "mdp3.h" + +#define MDP_IS_IMGTYPE_BAD(x) ((x) >= MDP_IMGTYPE_LIMIT) + +static const bool valid_fmt[MDP_IMGTYPE_LIMIT] = { + [MDP_RGB_565] = true, + [MDP_BGR_565] = true, + [MDP_RGB_888] = true, + [MDP_BGR_888] = true, + [MDP_BGRA_8888] = true, + [MDP_RGBA_8888] = true, + [MDP_ARGB_8888] = true, + [MDP_XRGB_8888] = true, + [MDP_RGBX_8888] = true, + [MDP_Y_CRCB_H2V2] = true, + [MDP_Y_CBCR_H2V2] = true, + [MDP_Y_CBCR_H2V2_ADRENO] = true, + [MDP_YCRYCB_H2V1] = true, + [MDP_Y_CBCR_H2V1] = true, + [MDP_Y_CRCB_H2V1] = true, +}; + +struct ppp_status { + int busy; + spinlock_t ppp_lock; + struct completion ppp_comp; + struct mutex config_mutex; +}; + +static struct ppp_status *ppp_stat; + + +int ppp_get_bpp(uint32_t format, uint32_t fb_format) +{ + int bpp = -EINVAL; + if (format == MDP_FB_FORMAT) + format = fb_format; + + bpp = ppp_bpp(format); + if (bpp <= 0) + pr_err("%s incorrect format %d\n", __func__, format); + return bpp; +} + +int mdp3_ppp_get_img(struct mdp_img *img, struct mdp_blit_req *req, + struct mdp3_img_data *data) +{ + struct msmfb_data fb_data; + fb_data.flags = img->priv; + fb_data.memory_id = img->memory_id; + fb_data.offset = 0; + + return mdp3_get_img(&fb_data, data); +} + +/* Check format */ +int mdp3_ppp_verify_fmt(struct mdp_blit_req *req) +{ + if (MDP_IS_IMGTYPE_BAD(req->src.format) || + MDP_IS_IMGTYPE_BAD(req->dst.format)) { + pr_err("%s: Color format out of range\n", __func__); + return -EINVAL; + } + + if (!valid_fmt[req->src.format] || + !valid_fmt[req->dst.format]) { + pr_err("%s: Color format not supported\n", __func__); + return -EINVAL; + } + return 0; +} + +/* Check resolution */ +int mdp3_ppp_verify_res(struct mdp_blit_req *req) +{ + if ((req->src.width == 0) || (req->src.height == 0) || + (req->src_rect.w == 0) || (req->src_rect.h == 0) || + (req->dst.width == 0) || (req->dst.height == 0) || + (req->dst_rect.w == 0) || (req->dst_rect.h == 0)) { + pr_err("%s: Height/width can't be 0\n", __func__); + return -EINVAL; + } + + if (((req->src_rect.x + req->src_rect.w) > req->src.width) || + ((req->src_rect.y + req->src_rect.h) > req->src.height)) { + pr_err("%s: src roi larger than boundary\n", __func__); + return -EINVAL; + } + + if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) || + ((req->dst_rect.y + req->dst_rect.h) > req->dst.height)) { + pr_err("%s: dst roi larger than boundary\n", __func__); + return -EINVAL; + } + return 0; +} + +/* scaling range check */ +int mdp3_ppp_verify_scale(struct mdp_blit_req *req) +{ + u32 src_width, src_height, dst_width, dst_height; + + src_width = req->src_rect.w; + src_height = req->src_rect.h; + + if (req->flags & MDP_ROT_90) { + dst_width = req->dst_rect.h; + dst_height = req->dst_rect.w; + } else { + dst_width = req->dst_rect.w; + dst_height = req->dst_rect.h; + } + + switch (req->dst.format) { + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V2: + src_width = (src_width / 2) * 2; + src_height = (src_height / 2) * 2; + dst_width = (dst_width / 2) * 2; + dst_height = (dst_height / 2) * 2; + break; + + case MDP_Y_CRCB_H2V1: + case MDP_Y_CBCR_H2V1: + case MDP_YCRYCB_H2V1: + src_width = (src_width / 2) * 2; + dst_width = (dst_width / 2) * 2; + break; + + default: + break; + } + + if (((MDP_SCALE_Q_FACTOR * dst_width) / src_width > + MDP_MAX_X_SCALE_FACTOR) + || ((MDP_SCALE_Q_FACTOR * dst_width) / src_width < + MDP_MIN_X_SCALE_FACTOR)) { + pr_err("%s: x req scale factor beyond capability\n", __func__); + return -EINVAL; + } + + if (((MDP_SCALE_Q_FACTOR * dst_height) / src_height > + MDP_MAX_Y_SCALE_FACTOR) + || ((MDP_SCALE_Q_FACTOR * dst_height) / src_height < + MDP_MIN_Y_SCALE_FACTOR)) { + pr_err("%s: y req scale factor beyond capability\n", __func__); + return -EINVAL; + } + return 0; +} + +/* operation check */ +int mdp3_ppp_verify_op(struct mdp_blit_req *req) +{ + if (req->flags & MDP_DEINTERLACE) { + pr_err("\n%s(): deinterlace not supported", __func__); + return -EINVAL; + } + + if (req->flags & MDP_SHARPENING) { + pr_err("\n%s(): sharpening not supported", __func__); + return -EINVAL; + } + return 0; +} + +int mdp3_ppp_verify_req(struct mdp_blit_req *req) +{ + int rc; + + if (req == NULL) { + pr_err("%s: req == null\n", __func__); + return -EINVAL; + } + + rc = mdp3_ppp_verify_fmt(req); + rc |= mdp3_ppp_verify_res(req); + rc |= mdp3_ppp_verify_scale(req); + rc |= mdp3_ppp_verify_op(req); + + return rc; +} + +int mdp3_ppp_pipe_wait(void) +{ + int ret = 1; + int wait; + unsigned long flag; + + /* + * wait 5 secs for operation to complete before declaring + * the MDP hung + */ + spin_lock_irqsave(&ppp_stat->ppp_lock, flag); + wait = ppp_stat->busy; + spin_unlock_irqrestore(&ppp_stat->ppp_lock, flag); + + if (wait) { + ret = wait_for_completion_interruptible_timeout( + &ppp_stat->ppp_comp, 5 * HZ); + if (!ret) + pr_err("%s: Timed out waiting for the MDP.\n", + __func__); + } + + return ret; +} + +uint32_t mdp3_calc_tpval(struct ppp_img_desc *img, uint32_t old_tp) +{ + uint32_t tpVal; + uint8_t plane_tp; + + tpVal = 0; + if ((img->color_fmt == MDP_RGB_565) + || (img->color_fmt == MDP_BGR_565)) { + /* transparent color conversion into 24 bpp */ + plane_tp = (uint8_t) ((old_tp & 0xF800) >> 11); + tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16; + plane_tp = (uint8_t) (old_tp & 0x1F); + tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8; + + plane_tp = (uint8_t) ((old_tp & 0x7E0) >> 5); + tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4)); + } else { + /* 24bit RGB to RBG conversion */ + tpVal = (old_tp & 0xFF00) >> 8; + tpVal |= (old_tp & 0xFF) << 8; + tpVal |= (old_tp & 0xFF0000); + } + + return tpVal; +} + +static void mdp3_ppp_intr_handler(int type, void *arg) +{ + spin_lock(&ppp_stat->ppp_lock); + ppp_stat->busy = false; + spin_unlock(&ppp_stat->ppp_lock); + complete(&ppp_stat->ppp_comp); + mdp3_irq_disable_nosync(type); +} + +static int mdp3_ppp_callback_setup(void) +{ + int rc; + struct mdp3_intr_cb ppp_done_cb = { + .cb = mdp3_ppp_intr_handler, + .data = NULL, + }; + + rc = mdp3_set_intr_callback(MDP3_PPP_DONE, &ppp_done_cb); + return rc; +} + +void mdp3_ppp_kickoff(void) +{ + unsigned long flag; + mdp3_irq_enable(MDP3_PPP_DONE); + + init_completion(&ppp_stat->ppp_comp); + + spin_lock_irqsave(&ppp_stat->ppp_lock, flag); + ppp_stat->busy = true; + spin_unlock_irqrestore(&ppp_stat->ppp_lock, flag); + ppp_enable(); + + mdp3_ppp_pipe_wait(); +} + +int mdp3_ppp_turnon(struct ppp_blit_op *blit_op, int on_off) +{ + unsigned long clk_rate = 0, dst_rate = 0, src_rate = 0; + int ab = 0; + int ib = 0; + if (on_off) { + dst_rate = blit_op->dst.roi.width * blit_op->dst.roi.height; + src_rate = blit_op->src.roi.width * blit_op->src.roi.height; + clk_rate = max(dst_rate, src_rate); + clk_rate = clk_rate * 36 * 12; + + ab = blit_op->dst.roi.width * blit_op->dst.roi.height * + ppp_bpp(blit_op->dst.color_fmt) * 2 + + blit_op->src.roi.width * blit_op->src.roi.height * + ppp_bpp(blit_op->src.color_fmt); + ab = ab * 120; + ib = (ab * 3) / 2; + } + mdp3_clk_enable(on_off); + mdp3_bus_scale_set_quota(MDP3_CLIENT_PPP, ab, ib); + return 0; +} + +void mdp3_start_ppp(struct ppp_blit_op *blit_op) +{ + /* Wait for the pipe to clear */ + do { } while (mdp3_ppp_pipe_wait() <= 0); + mutex_lock(&ppp_stat->config_mutex); + config_ppp_op_mode(blit_op); + mdp3_ppp_kickoff(); + mutex_unlock(&ppp_stat->config_mutex); +} + +static void mdp3_ppp_process_req(struct ppp_blit_op *blit_op, + struct mdp_blit_req *req, struct mdp3_img_data *src_data, + struct mdp3_img_data *dst_data) +{ + unsigned long srcp0_start, srcp0_len, dst_start, dst_len; + uint32_t dst_width, dst_height; + + srcp0_start = (unsigned long) src_data->addr; + srcp0_len = (unsigned long) src_data->len; + dst_start = (unsigned long) dst_data->addr; + dst_len = (unsigned long) dst_data->len; + + blit_op->dst.prop.width = req->dst.width; + blit_op->dst.prop.height = req->dst.height; + + blit_op->dst.color_fmt = req->dst.format; + blit_op->dst.p0 = (void *) dst_start; + blit_op->dst.p0 += req->dst.offset; + + blit_op->dst.roi.x = req->dst_rect.x; + blit_op->dst.roi.y = req->dst_rect.y; + blit_op->dst.roi.width = req->dst_rect.w; + blit_op->dst.roi.height = req->dst_rect.h; + + blit_op->src.roi.x = req->src_rect.x; + blit_op->src.roi.y = req->src_rect.y; + blit_op->src.roi.width = req->src_rect.w; + blit_op->src.roi.height = req->src_rect.h; + + blit_op->src.prop.width = req->src.width; + blit_op->src.color_fmt = req->src.format; + + + blit_op->src.p0 = (void *) (srcp0_start + req->src.offset); + if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_ADRENO) + blit_op->src.p1 = + (void *) ((uint32_t) blit_op->src.p0 + + ALIGN((ALIGN(req->src.width, 32) * + ALIGN(req->src.height, 32)), 4096)); + else + blit_op->src.p1 = (void *) ((uint32_t) blit_op->src.p0 + + req->src.width * req->src.height); + + if (req->flags & MDP_IS_FG) + blit_op->mdp_op |= MDPOP_LAYER_IS_FG; + + /* blending check */ + if (req->transp_mask != MDP_TRANSP_NOP) { + blit_op->mdp_op |= MDPOP_TRANSP; + blit_op->blend.trans_color = + mdp3_calc_tpval(&blit_op->src, req->transp_mask); + } else { + blit_op->blend.trans_color = 0; + } + + req->alpha &= 0xff; + if (req->alpha < MDP_ALPHA_NOP) { + blit_op->mdp_op |= MDPOP_ALPHAB; + blit_op->blend.const_alpha = req->alpha; + } else { + blit_op->blend.const_alpha = 0xff; + } + + /* rotation check */ + if (req->flags & MDP_FLIP_LR) + blit_op->mdp_op |= MDPOP_LR; + if (req->flags & MDP_FLIP_UD) + blit_op->mdp_op |= MDPOP_UD; + if (req->flags & MDP_ROT_90) + blit_op->mdp_op |= MDPOP_ROT90; + if (req->flags & MDP_DITHER) + blit_op->mdp_op |= MDPOP_DITHER; + + if (req->flags & MDP_BLEND_FG_PREMULT) + blit_op->mdp_op |= MDPOP_FG_PM_ALPHA; + + /* scale check */ + if (req->flags & MDP_ROT_90) { + dst_width = req->dst_rect.h; + dst_height = req->dst_rect.w; + } else { + dst_width = req->dst_rect.w; + dst_height = req->dst_rect.h; + } + + if ((blit_op->src.roi.width != dst_width) || + (blit_op->src.roi.height != dst_height)) + blit_op->mdp_op |= MDPOP_ASCALE; + + if (req->flags & MDP_BLUR) + blit_op->mdp_op |= MDPOP_ASCALE | MDPOP_BLUR; +} + +static void mdp3_ppp_tile_workaround(struct ppp_blit_op *blit_op, + struct mdp_blit_req *req) +{ + int dst_h, src_w, i; + uint32_t mdp_op = blit_op->mdp_op; + + src_w = req->src_rect.w; + dst_h = blit_op->dst.roi.height; + /* bg tile fetching HW workaround */ + for (i = 0; i < (req->dst_rect.h / 16); i++) { + /* this tile size */ + blit_op->dst.roi.height = 16; + blit_op->src.roi.width = + (16 * req->src_rect.w) / req->dst_rect.h; + + /* if it's out of scale range... */ + if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR) + blit_op->src.roi.width = + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + MDP_MAX_X_SCALE_FACTOR; + else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR) + blit_op->src.roi.width = + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + MDP_MIN_X_SCALE_FACTOR; + + mdp3_start_ppp(blit_op); + + /* next tile location */ + blit_op->dst.roi.y += 16; + blit_op->src.roi.x += blit_op->src.roi.width; + + /* this is for a remainder update */ + dst_h -= 16; + src_w -= blit_op->src.roi.width; + /* restore mdp_op since MDPOP_ASCALE have been cleared */ + blit_op->mdp_op = mdp_op; + } + + if ((dst_h < 0) || (src_w < 0)) + pr_err + ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n", + __LINE__); + + /* remainder update */ + if ((dst_h > 0) && (src_w > 0)) { + u32 tmp_v; + + blit_op->dst.roi.height = dst_h; + blit_op->src.roi.width = src_w; + + if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + blit_op->src.roi.width) > MDP_MAX_X_SCALE_FACTOR) { + tmp_v = + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + MDP_MAX_X_SCALE_FACTOR + + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) % + MDP_MAX_X_SCALE_FACTOR ? 1 : 0; + + /* move x location as roi width gets bigger */ + blit_op->src.roi.x -= tmp_v - blit_op->src.roi.width; + blit_op->src.roi.width = tmp_v; + } else if (((MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + blit_op->src.roi.width) < MDP_MIN_X_SCALE_FACTOR) { + tmp_v = + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) / + MDP_MIN_X_SCALE_FACTOR + + (MDP_SCALE_Q_FACTOR * blit_op->dst.roi.height) % + MDP_MIN_X_SCALE_FACTOR ? 1 : 0; + + /* + * we don't move x location for continuity of + * source image + */ + blit_op->src.roi.width = tmp_v; + } + + + mdp3_start_ppp(blit_op); + } +} + +static int mdp3_ppp_blit_addr(struct msm_fb_data_type *mfd, + struct mdp_blit_req *req, struct mdp3_img_data *src_data, + struct mdp3_img_data *dst_data) +{ + struct ppp_blit_op blit_op; + + memset(&blit_op, 0, sizeof(blit_op)); + + if (req->dst.format == MDP_FB_FORMAT) + req->dst.format = mfd->fb_imgType; + if (req->src.format == MDP_FB_FORMAT) + req->src.format = mfd->fb_imgType; + + if (mdp3_ppp_verify_req(req)) { + pr_err("%s: invalid image!\n", __func__); + return -EINVAL; + } + + mdp3_ppp_process_req(&blit_op, req, src_data, dst_data); + + mdp3_ppp_turnon(&blit_op, 1); + + if (((blit_op.mdp_op & (MDPOP_TRANSP | MDPOP_ALPHAB)) || + (req->src.format == MDP_ARGB_8888) || + (req->src.format == MDP_BGRA_8888) || + (req->src.format == MDP_RGBA_8888)) && + (blit_op.mdp_op & MDPOP_ROT90) && (req->dst_rect.w <= 16)) { + mdp3_ppp_tile_workaround(&blit_op, req); + } else { + mdp3_start_ppp(&blit_op); + } + + /* MDP cmd block disable */ + mdp3_ppp_turnon(&blit_op, 0); + + return 0; +} + +static int mdp3_ppp_blit(struct msm_fb_data_type *mfd, struct mdp_blit_req *req) +{ + struct mdp3_img_data src_data; + struct mdp3_img_data dst_data; + int rc; + mdp3_ppp_iommu_attach(); + + mdp3_ppp_get_img(&req->src, req, &src_data); + if (src_data.len == 0) { + pr_err("mdp_ppp: couldn't retrieve src img from mem\n"); + return -EINVAL; + } + + mdp3_ppp_get_img(&req->dst, req, &dst_data); + if (dst_data.len == 0) { + mdp3_put_img(&src_data); + pr_err("mdp_ppp: couldn't retrieve dest img from mem\n"); + return -EINVAL; + } + + rc = mdp3_ppp_blit_addr(mfd, req, &src_data, &dst_data); + mdp3_put_img(&src_data); + mdp3_put_img(&dst_data); + mdp3_ppp_iommu_dettach(); + return rc; +} + +static int mdp3_ppp_blit_workaround(struct msm_fb_data_type *mfd, + struct mdp_blit_req *req, unsigned int remainder) +{ + int ret; + struct mdp_blit_req splitreq; + int s_x_0, s_x_1, s_w_0, s_w_1, s_y_0, s_y_1, s_h_0, s_h_1; + int d_x_0, d_x_1, d_w_0, d_w_1, d_y_0, d_y_1, d_h_0, d_h_1; + + /* make new request as provide by user */ + splitreq = *req; + + /* break dest roi at width*/ + d_y_0 = d_y_1 = req->dst_rect.y; + d_h_0 = d_h_1 = req->dst_rect.h; + d_x_0 = req->dst_rect.x; + + if (remainder == 14 || remainder == 6) + d_w_1 = req->dst_rect.w / 2; + else + d_w_1 = (req->dst_rect.w - 1) / 2 - 1; + + d_w_0 = req->dst_rect.w - d_w_1; + d_x_1 = d_x_0 + d_w_0; + /* blit first region */ + if (((splitreq.flags & 0x07) == 0x07) || + ((splitreq.flags & 0x07) == 0x05) || + ((splitreq.flags & 0x07) == 0x02) || + ((splitreq.flags & 0x07) == 0x0)) { + + if (splitreq.flags & MDP_ROT_90) { + s_x_0 = s_x_1 = req->src_rect.x; + s_w_0 = s_w_1 = req->src_rect.w; + s_y_0 = req->src_rect.y; + s_h_1 = (req->src_rect.h * d_w_1) / + req->dst_rect.w; + s_h_0 = req->src_rect.h - s_h_1; + s_y_1 = s_y_0 + s_h_0; + if (d_w_1 >= 8 * s_h_1) { + s_h_1++; + s_y_1--; + } + } else { + s_y_0 = s_y_1 = req->src_rect.y; + s_h_0 = s_h_1 = req->src_rect.h; + s_x_0 = req->src_rect.x; + s_w_1 = (req->src_rect.w * d_w_1) / + req->dst_rect.w; + s_w_0 = req->src_rect.w - s_w_1; + s_x_1 = s_x_0 + s_w_0; + if (d_w_1 >= 8 * s_w_1) { + s_w_1++; + s_x_1--; + } + } + + splitreq.src_rect.h = s_h_0; + splitreq.src_rect.y = s_y_0; + splitreq.dst_rect.h = d_h_0; + splitreq.dst_rect.y = d_y_0; + splitreq.src_rect.x = s_x_0; + splitreq.src_rect.w = s_w_0; + splitreq.dst_rect.x = d_x_0; + splitreq.dst_rect.w = d_w_0; + } else { + if (splitreq.flags & MDP_ROT_90) { + s_x_0 = s_x_1 = req->src_rect.x; + s_w_0 = s_w_1 = req->src_rect.w; + s_y_0 = req->src_rect.y; + s_h_1 = (req->src_rect.h * d_w_0) / + req->dst_rect.w; + s_h_0 = req->src_rect.h - s_h_1; + s_y_1 = s_y_0 + s_h_0; + if (d_w_0 >= 8 * s_h_1) { + s_h_1++; + s_y_1--; + } + } else { + s_y_0 = s_y_1 = req->src_rect.y; + s_h_0 = s_h_1 = req->src_rect.h; + s_x_0 = req->src_rect.x; + s_w_1 = (req->src_rect.w * d_w_0) / + req->dst_rect.w; + s_w_0 = req->src_rect.w - s_w_1; + s_x_1 = s_x_0 + s_w_0; + if (d_w_0 >= 8 * s_w_1) { + s_w_1++; + s_x_1--; + } + } + splitreq.src_rect.h = s_h_0; + splitreq.src_rect.y = s_y_0; + splitreq.dst_rect.h = d_h_1; + splitreq.dst_rect.y = d_y_1; + splitreq.src_rect.x = s_x_0; + splitreq.src_rect.w = s_w_0; + splitreq.dst_rect.x = d_x_1; + splitreq.dst_rect.w = d_w_1; + } + + /* No need to split in height */ + ret = mdp3_ppp_blit(mfd, &splitreq); + + if (ret) + return ret; + /* blit second region */ + if (((splitreq.flags & 0x07) == 0x07) || + ((splitreq.flags & 0x07) == 0x05) || + ((splitreq.flags & 0x07) == 0x02) || + ((splitreq.flags & 0x07) == 0x0)) { + splitreq.src_rect.h = s_h_1; + splitreq.src_rect.y = s_y_1; + splitreq.dst_rect.h = d_h_1; + splitreq.dst_rect.y = d_y_1; + splitreq.src_rect.x = s_x_1; + splitreq.src_rect.w = s_w_1; + splitreq.dst_rect.x = d_x_1; + splitreq.dst_rect.w = d_w_1; + } else { + splitreq.src_rect.h = s_h_1; + splitreq.src_rect.y = s_y_1; + splitreq.dst_rect.h = d_h_0; + splitreq.dst_rect.y = d_y_0; + splitreq.src_rect.x = s_x_1; + splitreq.src_rect.w = s_w_1; + splitreq.dst_rect.x = d_x_0; + splitreq.dst_rect.w = d_w_0; + } + + /* No need to split in height ... just width */ + return mdp3_ppp_blit(mfd, &splitreq); +} + +int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd, + struct mdp_blit_req *req) +{ + int ret; + unsigned int remainder = 0, is_bpp_4 = 0; + + if (unlikely(req->src_rect.h == 0 || req->src_rect.w == 0)) { + pr_err("mdp_ppp: src img of zero size!\n"); + return -EINVAL; + } + if (unlikely(req->dst_rect.h == 0 || req->dst_rect.w == 0)) + return 0; + + if (req->flags & MDP_ROT_90) { + if (((req->dst_rect.h == 1) && ((req->src_rect.w != 1) || + (req->dst_rect.w != req->src_rect.h))) || + ((req->dst_rect.w == 1) && ((req->src_rect.h != 1) || + (req->dst_rect.h != req->src_rect.w)))) { + pr_err("mdp_ppp: error scaling when size is 1!\n"); + return -EINVAL; + } + } else { + if (((req->dst_rect.w == 1) && ((req->src_rect.w != 1) || + (req->dst_rect.h != req->src_rect.h))) || + ((req->dst_rect.h == 1) && ((req->src_rect.h != 1) || + (req->dst_rect.w != req->src_rect.w)))) { + pr_err("mdp_ppp: error scaling when size is 1!\n"); + return -EINVAL; + } + } + + /* MDP width split workaround */ + remainder = (req->dst_rect.w) % 16; + ret = ppp_get_bpp(req->dst.format, mfd->fb_imgType); + if (ret <= 0) { + pr_err("mdp_ppp: incorrect bpp!\n"); + return -EINVAL; + } + is_bpp_4 = (ret == 4) ? 1 : 0; + + if ((is_bpp_4 && (remainder == 6 || remainder == 14))) + ret = mdp3_ppp_blit_workaround(mfd, req, remainder); + else + ret = mdp3_ppp_blit(mfd, req); + + return ret; +} + +int mdp3_ppp_res_init(void) +{ + ppp_stat = kmalloc(sizeof(struct ppp_status), GFP_KERNEL); + spin_lock_init(&ppp_stat->ppp_lock); + mutex_init(&ppp_stat->config_mutex); + ppp_stat->busy = false; + mdp3_ppp_callback_setup(); + return 0; +} diff --git a/drivers/video/fbdev/msm/mdp3_ppp.h b/drivers/video/fbdev/msm/mdp3_ppp.h new file mode 100644 index 000000000000..afac419e4f3c --- /dev/null +++ b/drivers/video/fbdev/msm/mdp3_ppp.h @@ -0,0 +1,413 @@ +/* Copyright (c) 2007, 2013 The Linux Foundation. All rights reserved. + * 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 MDP3_PPP_H +#define MDP3_PPP_H +#include "mdp3.h" +#include "mdss_fb.h" + +#define PPP_WRITEL(val, off) MDP3_REG_WRITE(off, val) + +#define MAX_BLIT_REQ 256 +#define PPP_UPSCALE_MAX 64 +#define PPP_BLUR_SCALE_MAX 128 +#define PPP_LUT_MAX 256 + +/* MDP PPP Operations */ +#define MDPOP_NOP 0 +#define MDPOP_LR BIT(0) /* left to right flip */ +#define MDPOP_UD BIT(1) /* up and down flip */ +#define MDPOP_ROT90 BIT(2) /* rotate image to 90 degree */ +#define MDPOP_ROT180 (MDPOP_UD|MDPOP_LR) +#define MDPOP_ROT270 (MDPOP_ROT90|MDPOP_UD|MDPOP_LR) +#define MDPOP_ASCALE BIT(7) +#define MDPOP_ALPHAB BIT(8) /* enable alpha blending */ +#define MDPOP_TRANSP BIT(9) /* enable transparency */ +#define MDPOP_DITHER BIT(10) /* enable dither */ +#define MDPOP_SHARPENING BIT(11) /* enable sharpening */ +#define MDPOP_BLUR BIT(12) /* enable blur */ +#define MDPOP_FG_PM_ALPHA BIT(13) +#define MDPOP_LAYER_IS_FG BIT(14) + +#define MDPOP_ROTATION (MDPOP_ROT90|MDPOP_LR|MDPOP_UD) + +#define PPP_OP_CONVERT_YCBCR2RGB BIT(2) +#define PPP_OP_CONVERT_ON BIT(3) +#define PPP_OP_SCALE_X_ON BIT(0) +#define PPP_OP_SCALE_Y_ON BIT(1) +#define PPP_OP_ROT_ON BIT(8) +#define PPP_OP_ROT_90 BIT(9) +#define PPP_OP_FLIP_LR BIT(10) +#define PPP_OP_FLIP_UD BIT(11) +#define PPP_OP_BLEND_ON BIT(12) +#define PPP_OP_BLEND_CONSTANT_ALPHA BIT(14) +#define PPP_OP_DITHER_EN BIT(16) +#define PPP_BLEND_CALPHA_TRNASP BIT(24) + +#define PPP_OP_BLEND_SRCPIXEL_ALPHA 0 +#define PPP_OP_BLEND_ALPHA_BLEND_NORMAL 0 +#define PPP_OP_BLEND_ALPHA_BLEND_REVERSE BIT(15) + +#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) +#define PPP_OP_BG_CHROMA_H2V1 BIT(25) + +#define CLR_G 0x0 +#define CLR_B 0x1 +#define CLR_R 0x2 +#define CLR_ALPHA 0x3 + +#define CLR_Y CLR_G +#define CLR_CB CLR_B +#define CLR_CR CLR_R + +/* from lsb to msb */ +#define PPP_GET_PACK_PATTERN(a, x, y, z, bit) \ + (((a)<<(bit*3))|((x)<<(bit*2))|((y)<<bit)|(z)) + +/* Frame unpacking */ +#define PPP_C0G_8BITS (BIT(1)|BIT(0)) +#define PPP_C1B_8BITS (BIT(3)|BIT(2)) +#define PPP_C2R_8BITS (BIT(5)|BIT(4)) +#define PPP_C3A_8BITS (BIT(7)|BIT(6)) + +#define PPP_C0G_6BITS BIT(1) +#define PPP_C1B_6BITS BIT(3) +#define PPP_C2R_6BITS BIT(5) + +#define PPP_C0G_5BITS BIT(0) +#define PPP_C1B_5BITS BIT(2) +#define PPP_C2R_5BITS BIT(4) + +#define PPP_SRC_C3_ALPHA_EN BIT(8) + +#define PPP_SRC_BPP_INTERLVD_1BYTES 0 +#define PPP_SRC_BPP_INTERLVD_2BYTES BIT(9) +#define PPP_SRC_BPP_INTERLVD_3BYTES BIT(10) +#define PPP_SRC_BPP_INTERLVD_4BYTES (BIT(10)|BIT(9)) + +#define PPP_SRC_BPP_ROI_ODD_X BIT(11) +#define PPP_SRC_BPP_ROI_ODD_Y BIT(12) +#define PPP_SRC_INTERLVD_2COMPONENTS BIT(13) +#define PPP_SRC_INTERLVD_3COMPONENTS BIT(14) +#define PPP_SRC_INTERLVD_4COMPONENTS (BIT(14)|BIT(13)) + +#define PPP_SRC_UNPACK_TIGHT BIT(17) +#define PPP_SRC_UNPACK_LOOSE 0 +#define PPP_SRC_UNPACK_ALIGN_LSB 0 +#define PPP_SRC_UNPACK_ALIGN_MSB BIT(18) + +#define PPP_SRC_FETCH_PLANES_INTERLVD 0 +#define PPP_SRC_FETCH_PLANES_PSEUDOPLNR BIT(20) + +#define PPP_OP_SRC_CHROMA_H2V1 BIT(18) +#define PPP_OP_SRC_CHROMA_H1V2 BIT(19) +#define PPP_OP_SRC_CHROMA_420 (BIT(18)|BIT(19)) +#define PPP_OP_SRC_CHROMA_OFFSITE BIT(20) + +#define PPP_DST_PACKET_CNT_INTERLVD_2ELEM BIT(9) +#define PPP_DST_PACKET_CNT_INTERLVD_3ELEM BIT(10) +#define PPP_DST_PACKET_CNT_INTERLVD_4ELEM (BIT(10)|BIT(9)) +#define PPP_DST_PACKET_CNT_INTERLVD_6ELEM (BIT(11)|BIT(9)) + +#define PPP_DST_C3A_8BIT (BIT(7)|BIT(6)) +#define PPP_DST_C3ALPHA_EN BIT(8) + +#define PPP_DST_PACK_LOOSE 0 +#define PPP_DST_PACK_TIGHT BIT(13) +#define PPP_DST_PACK_ALIGN_LSB 0 +#define PPP_DST_PACK_ALIGN_MSB BIT(14) + +#define PPP_DST_OUT_SEL_AXI 0 +#define PPP_DST_OUT_SEL_MDDI BIT(15) + +#define PPP_DST_BPP_2BYTES BIT(16) +#define PPP_DST_BPP_3BYTES BIT(17) +#define PPP_DST_BPP_4BYTES (BIT(17)|BIT(16)) + +#define PPP_DST_PLANE_INTERLVD 0 +#define PPP_DST_PLANE_PLANAR BIT(18) +#define PPP_DST_PLANE_PSEUDOPLN BIT(19) + +#define PPP_OP_DST_CHROMA_H2V1 BIT(21) +#define PPP_OP_DST_CHROMA_420 (BIT(21)|BIT(22)) +#define PPP_OP_COLOR_SPACE_YCBCR BIT(17) + +#define MDP_SCALE_Q_FACTOR 512 +#define MDP_MAX_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) +#define MDP_MIN_X_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) +#define MDP_MAX_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR*4) +#define MDP_MIN_Y_SCALE_FACTOR (MDP_SCALE_Q_FACTOR/4) + +#define MDP_TOP_LUMA 16 +#define MDP_TOP_CHROMA 0 +#define MDP_BOTTOM_LUMA 19 +#define MDP_BOTTOM_CHROMA 3 +#define MDP_LEFT_LUMA 22 +#define MDP_LEFT_CHROMA 6 +#define MDP_RIGHT_LUMA 25 +#define MDP_RIGHT_CHROMA 9 + +#define MDP_RGB_565_SRC_REG (PPP_C2R_5BITS | PPP_C0G_6BITS | \ + PPP_C1B_5BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \ + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | \ + PPP_SRC_UNPACK_ALIGN_LSB | \ + PPP_SRC_FETCH_PLANES_INTERLVD) + +#define MDP_RGB_888_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_SRC_BPP_INTERLVD_3BYTES | \ + PPP_SRC_INTERLVD_3COMPONENTS | PPP_SRC_UNPACK_TIGHT | \ + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_INTERLVD) + +#define MDP_RGBX_8888_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_C3A_8BITS | \ + PPP_SRC_C3_ALPHA_EN | PPP_SRC_BPP_INTERLVD_4BYTES | \ + PPP_SRC_INTERLVD_4COMPONENTS | PPP_SRC_UNPACK_TIGHT | \ + PPP_SRC_UNPACK_ALIGN_LSB | \ + PPP_SRC_FETCH_PLANES_INTERLVD) + +#define MDP_Y_CBCR_H2V2_SRC_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \ + PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | \ + PPP_SRC_UNPACK_ALIGN_LSB | \ + PPP_SRC_FETCH_PLANES_PSEUDOPLNR) + +#define MDP_YCRYCB_H2V1_SRC_REG (PPP_C2R_8BITS | \ + PPP_C0G_8BITS | PPP_C1B_8BITS | \ + PPP_C3A_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \ + PPP_SRC_INTERLVD_4COMPONENTS | \ + PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB) + +#define MDP_Y_CRCB_H2V1_SRC_REG (PPP_C2R_8BITS | \ + PPP_C0G_8BITS | PPP_C1B_8BITS | \ + PPP_C3A_8BITS | PPP_SRC_BPP_INTERLVD_2BYTES | \ + PPP_SRC_INTERLVD_2COMPONENTS | PPP_SRC_UNPACK_TIGHT | \ + PPP_SRC_UNPACK_ALIGN_LSB | PPP_SRC_FETCH_PLANES_PSEUDOPLNR) + +#define MDP_RGB_565_DST_REG (PPP_C0G_6BITS | \ + PPP_C1B_5BITS | PPP_C2R_5BITS | \ + PPP_DST_PACKET_CNT_INTERLVD_3ELEM | \ + PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \ + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | \ + PPP_DST_PLANE_INTERLVD) + +#define MDP_RGB_888_DST_REG (PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_C2R_8BITS | \ + PPP_DST_PACKET_CNT_INTERLVD_3ELEM | PPP_DST_PACK_TIGHT | \ + PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | \ + PPP_DST_BPP_3BYTES | PPP_DST_PLANE_INTERLVD) + +#define MDP_RGBX_8888_DST_REG (PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_C2R_8BITS | PPP_C3A_8BITS | \ + PPP_DST_C3ALPHA_EN | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | \ + PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \ + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_4BYTES | \ + PPP_DST_PLANE_INTERLVD) + +#define MDP_Y_CBCR_H2V2_DST_REG (PPP_C2R_8BITS | \ + PPP_C0G_8BITS | PPP_C1B_8BITS | PPP_C3A_8BITS | \ + PPP_DST_PACKET_CNT_INTERLVD_2ELEM | \ + PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \ + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES) + +#define MDP_YCRYCB_H2V1_DST_REG (PPP_C2R_8BITS | PPP_C0G_8BITS | \ + PPP_C1B_8BITS | PPP_C3A_8BITS | PPP_DST_PACKET_CNT_INTERLVD_4ELEM | \ + PPP_DST_PACK_TIGHT | PPP_DST_PACK_ALIGN_LSB | \ + PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES | \ + PPP_DST_PLANE_INTERLVD) + +#define MDP_Y_CRCB_H2V1_DST_REG (PPP_C2R_8BITS | \ + PPP_C0G_8BITS | PPP_C1B_8BITS | PPP_C3A_8BITS | \ + PPP_DST_PACKET_CNT_INTERLVD_2ELEM | PPP_DST_PACK_TIGHT | \ + PPP_DST_PACK_ALIGN_LSB | PPP_DST_OUT_SEL_AXI | \ + PPP_DST_BPP_2BYTES) + +/* LUT */ +#define MDP_LUT_C0_EN BIT(5) +#define MDP_LUT_C1_EN BIT(6) +#define MDP_LUT_C2_EN BIT(7) + +/* Dither */ +#define MDP_OP_DITHER_EN BIT(16) + +/* Rotator */ +#define MDP_OP_ROT_ON BIT(8) +#define MDP_OP_ROT_90 BIT(9) +#define MDP_OP_FLIP_LR BIT(10) +#define MDP_OP_FLIP_UD BIT(11) + +/* Blend */ +#define MDP_OP_BLEND_EN BIT(12) +#define MDP_OP_BLEND_EQ_SEL BIT(15) +#define MDP_OP_BLEND_TRANSP_EN BIT(24) +#define MDP_BLEND_MASK (MDP_OP_BLEND_EN | MDP_OP_BLEND_EQ_SEL | \ + MDP_OP_BLEND_TRANSP_EN | BIT(14) | BIT(13)) + +#define MDP_BLEND_ALPHA_SEL 13 +#define MDP_BLEND_ALPHA_MASK 0x3 +#define MDP_BLEND_CONST_ALPHA 24 +#define MDP_BLEND_TRASP_COL_MASK 0xFFFFFF + +/* CSC Matrix */ +#define MDP_CSC_RGB2YUV 0 +#define MDP_CSC_YUV2RGB 1 + +#define MDP_CSC_SIZE 9 +#define MDP_BV_SIZE 3 +#define MDP_LV_SIZE 4 + +enum ppp_lut_type { + LUT_PRE_TABLE = 0, + LUT_POST_TABLE, +}; + +enum ppp_csc_matrix { + CSC_PRIMARY_MATRIX = 0, + CSC_SECONDARY_MATRIX, +}; + +/* scale tables */ +enum { + PPP_DOWNSCALE_PT2TOPT4, + PPP_DOWNSCALE_PT4TOPT6, + PPP_DOWNSCALE_PT6TOPT8, + PPP_DOWNSCALE_PT8TOPT1, + PPP_DOWNSCALE_MAX, +}; + +struct ppp_table { + uint32_t reg; + uint32_t val; +}; + +struct ppp_csc_table { + int direction; /* MDP_CCS_RGB2YUV or YUV2RGB */ + uint16_t fwd_matrix[MDP_CCS_SIZE]; /* 3x3 color coefficients */ + uint16_t rev_matrix[MDP_CCS_SIZE]; /* 3x3 color coefficients */ + uint16_t bv[MDP_BV_SIZE]; /* 1x3 bias vector */ + uint16_t lv[MDP_LV_SIZE]; /* 1x3 limit vector */ +}; + +struct ppp_blend { + int const_alpha; + int trans_color; /*color keying*/ +}; + +struct ppp_img_prop { + int32_t x; + int32_t y; + uint32_t width; + uint32_t height; +}; + +struct ppp_img_desc { + struct ppp_img_prop prop; + struct ppp_img_prop roi; + int color_fmt; + void *p0; /* plane 0 */ + void *p1; + void *p3; + int stride0; + int stride1; + int stride2; +}; + +struct ppp_blit_op { + struct ppp_img_desc src; + struct ppp_img_desc dst; + struct ppp_img_desc bg; + struct ppp_blend blend; + uint32_t mdp_op; /* Operations */ +}; + +struct ppp_edge_rep { + uint32_t dst_roi_width; + uint32_t dst_roi_height; + uint32_t is_scale_enabled; + + /* + * positions of the luma pixel(relative to the image ) required for + * scaling the ROI + */ + int32_t luma_interp_point_left; + int32_t luma_interp_point_right; + int32_t luma_interp_point_top; + int32_t luma_interp_point_bottom; + + /* + * positions of the chroma pixel(relative to the image ) required for + * interpolating a chroma value at all required luma positions + */ + int32_t chroma_interp_point_left; + int32_t chroma_interp_point_right; + int32_t chroma_interp_point_top; + int32_t chroma_interp_point_bottom; + + /* + * a rectangular region within the chroma plane of the "image". + * Chroma pixels falling inside of this rectangle belongs to the ROI + */ + int32_t chroma_bound_left; + int32_t chroma_bound_right; + int32_t chroma_bound_top; + int32_t chroma_bound_bottom; + + /* + * number of chroma pixels to replicate on the left, right, + * top and bottom edge of the ROI. + */ + int32_t chroma_repeat_left; + int32_t chroma_repeat_right; + int32_t chroma_repeat_top; + int32_t chroma_repeat_bottom; + + /* + * number of luma pixels to replicate on the left, right, + * top and bottom edge of the ROI. + */ + int32_t luma_repeat_left; + int32_t luma_repeat_right; + int32_t luma_repeat_top; + int32_t luma_repeat_bottom; +}; + +/* func for ppp register values */ +uint32_t ppp_bpp(uint32_t type); +uint32_t ppp_src_config(uint32_t type); +uint32_t ppp_out_config(uint32_t type); +uint32_t ppp_pack_pattern(uint32_t type); +uint32_t ppp_dst_op_reg(uint32_t type); +uint32_t ppp_src_op_reg(uint32_t type); +bool ppp_per_p_alpha(uint32_t type); +bool ppp_multi_plane(uint32_t type); +uint32_t *ppp_default_pre_lut(void); +uint32_t *ppp_default_post_lut(void); +struct ppp_csc_table *ppp_csc_rgb2yuv(void); +struct ppp_csc_table *ppp_csc_table2(void); +void ppp_load_up_lut(void); +void ppp_load_gaussian_lut(void); +void ppp_load_x_scale_table(int idx); +void ppp_load_y_scale_table(int idx); + +int mdp3_ppp_start_blit(struct msm_fb_data_type *mfd, + struct mdp_blit_req *req); +int mdp3_ppp_res_init(void); +int mdp3_ppp_init(void); +int config_ppp_op_mode(struct ppp_blit_op *blit_op); +void ppp_enable(void); + +#endif diff --git a/drivers/video/fbdev/msm/mdp3_ppp_data.c b/drivers/video/fbdev/msm/mdp3_ppp_data.c new file mode 100644 index 000000000000..d68faad8858e --- /dev/null +++ b/drivers/video/fbdev/msm/mdp3_ppp_data.c @@ -0,0 +1,1572 @@ +/* Copyright (c) 2007, 2012-2013 The Linux Foundation. All rights reserved. + * 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. + */ + +#include <linux/types.h> + +#include "mdss_fb.h" +#include "mdp3_ppp.h" + +/* bg_config_lut not needed since it is same as src */ +const uint32_t src_cfg_lut[MDP_IMGTYPE_LIMIT] = { + [MDP_RGB_565] = MDP_RGB_565_SRC_REG, + [MDP_BGR_565] = MDP_RGB_565_SRC_REG, + [MDP_RGB_888] = MDP_RGB_888_SRC_REG, + [MDP_BGR_888] = MDP_RGB_888_SRC_REG, + [MDP_BGRA_8888] = MDP_RGBX_8888_SRC_REG, + [MDP_RGBA_8888] = MDP_RGBX_8888_SRC_REG, + [MDP_ARGB_8888] = MDP_RGBX_8888_SRC_REG, + [MDP_XRGB_8888] = MDP_RGBX_8888_SRC_REG, + [MDP_RGBX_8888] = MDP_RGBX_8888_SRC_REG, + [MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG, + [MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_SRC_REG, + [MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_SRC_REG, + [MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_SRC_REG, + [MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG, + [MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_SRC_REG, +}; + +const uint32_t out_cfg_lut[MDP_IMGTYPE_LIMIT] = { + [MDP_RGB_565] = MDP_RGB_565_DST_REG, + [MDP_BGR_565] = MDP_RGB_565_DST_REG, + [MDP_RGB_888] = MDP_RGB_888_DST_REG, + [MDP_BGR_888] = MDP_RGB_888_DST_REG, + [MDP_BGRA_8888] = MDP_RGBX_8888_DST_REG, + [MDP_RGBA_8888] = MDP_RGBX_8888_DST_REG, + [MDP_ARGB_8888] = MDP_RGBX_8888_DST_REG, + [MDP_XRGB_8888] = MDP_RGBX_8888_DST_REG, + [MDP_RGBX_8888] = MDP_RGBX_8888_DST_REG, + [MDP_Y_CRCB_H2V2] = MDP_Y_CBCR_H2V2_DST_REG, + [MDP_Y_CBCR_H2V2] = MDP_Y_CBCR_H2V2_DST_REG, + [MDP_Y_CBCR_H2V2_ADRENO] = MDP_Y_CBCR_H2V2_DST_REG, + [MDP_YCRYCB_H2V1] = MDP_YCRYCB_H2V1_DST_REG, + [MDP_Y_CBCR_H2V1] = MDP_Y_CRCB_H2V1_DST_REG, + [MDP_Y_CRCB_H2V1] = MDP_Y_CRCB_H2V1_DST_REG, +}; + +const uint32_t pack_patt_lut[MDP_IMGTYPE_LIMIT] = { + [MDP_RGB_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8), + [MDP_BGR_565] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8), + [MDP_RGB_888] = PPP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8), + [MDP_BGR_888] = PPP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8), + [MDP_BGRA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, + CLR_G, CLR_B, 8), + [MDP_RGBA_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, + CLR_G, CLR_B, 8), + [MDP_ARGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, + CLR_G, CLR_B, 8), + [MDP_XRGB_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, + CLR_G, CLR_B, 8), + [MDP_RGBX_8888] = PPP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, + CLR_G, CLR_B, 8), + [MDP_Y_CRCB_H2V2] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8), + [MDP_Y_CBCR_H2V2] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8), + [MDP_Y_CBCR_H2V2_ADRENO] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, + CLR_CR, 8), + [MDP_YCRYCB_H2V1] = PPP_GET_PACK_PATTERN(CLR_Y, + CLR_CR, CLR_Y, CLR_CB, 8), + [MDP_Y_CBCR_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8), + [MDP_Y_CRCB_H2V1] = PPP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8), +}; + +const uint32_t dst_op_reg[MDP_IMGTYPE_LIMIT] = { + [MDP_Y_CRCB_H2V2] = PPP_OP_DST_CHROMA_420, + [MDP_Y_CBCR_H2V2] = PPP_OP_DST_CHROMA_420, + [MDP_Y_CBCR_H2V1] = PPP_OP_DST_CHROMA_H2V1, + [MDP_Y_CRCB_H2V1] = PPP_OP_DST_CHROMA_H2V1, + [MDP_YCRYCB_H2V1] = PPP_OP_DST_CHROMA_H2V1, +}; + +const uint32_t src_op_reg[MDP_IMGTYPE_LIMIT] = { + [MDP_Y_CRCB_H2V2] = PPP_OP_SRC_CHROMA_420 | PPP_OP_COLOR_SPACE_YCBCR, + [MDP_Y_CBCR_H2V2] = PPP_OP_SRC_CHROMA_420 | PPP_OP_COLOR_SPACE_YCBCR, + [MDP_Y_CBCR_H2V2_ADRENO] = PPP_OP_SRC_CHROMA_420 | + PPP_OP_COLOR_SPACE_YCBCR, + [MDP_Y_CBCR_H2V1] = PPP_OP_SRC_CHROMA_H2V1, + [MDP_Y_CRCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1, + [MDP_YCRYCB_H2V1] = PPP_OP_SRC_CHROMA_H2V1, +}; + +const uint32_t bytes_per_pixel[MDP_IMGTYPE_LIMIT] = { + [MDP_RGB_565] = 2, + [MDP_BGR_565] = 2, + [MDP_RGB_888] = 3, + [MDP_BGR_888] = 3, + [MDP_XRGB_8888] = 4, + [MDP_ARGB_8888] = 4, + [MDP_RGBA_8888] = 4, + [MDP_BGRA_8888] = 4, + [MDP_RGBX_8888] = 4, + [MDP_Y_CBCR_H2V1] = 1, + [MDP_Y_CBCR_H2V2] = 1, + [MDP_Y_CBCR_H2V2_ADRENO] = 1, + [MDP_Y_CRCB_H2V1] = 1, + [MDP_Y_CRCB_H2V2] = 1, + [MDP_YCRYCB_H2V1] = 2, +}; + +const bool per_pixel_alpha[MDP_IMGTYPE_LIMIT] = { + [MDP_BGRA_8888] = true, + [MDP_RGBA_8888] = true, + [MDP_ARGB_8888] = true, +}; + +const bool multi_plane[MDP_IMGTYPE_LIMIT] = { + [MDP_Y_CRCB_H2V2] = true, + [MDP_Y_CBCR_H2V2] = true, + [MDP_Y_CBCR_H2V1] = true, + [MDP_Y_CRCB_H2V1] = true, +}; + +/* lut default */ +uint32_t default_pre_lut_val[PPP_LUT_MAX] = { + 0x0, + 0x151515, + 0x1d1d1d, + 0x232323, + 0x272727, + 0x2b2b2b, + 0x2f2f2f, + 0x333333, + 0x363636, + 0x393939, + 0x3b3b3b, + 0x3e3e3e, + 0x404040, + 0x434343, + 0x454545, + 0x474747, + 0x494949, + 0x4b4b4b, + 0x4d4d4d, + 0x4f4f4f, + 0x515151, + 0x535353, + 0x555555, + 0x565656, + 0x585858, + 0x5a5a5a, + 0x5b5b5b, + 0x5d5d5d, + 0x5e5e5e, + 0x606060, + 0x616161, + 0x636363, + 0x646464, + 0x666666, + 0x676767, + 0x686868, + 0x6a6a6a, + 0x6b6b6b, + 0x6c6c6c, + 0x6e6e6e, + 0x6f6f6f, + 0x707070, + 0x717171, + 0x727272, + 0x747474, + 0x757575, + 0x767676, + 0x777777, + 0x787878, + 0x797979, + 0x7a7a7a, + 0x7c7c7c, + 0x7d7d7d, + 0x7e7e7e, + 0x7f7f7f, + 0x808080, + 0x818181, + 0x828282, + 0x838383, + 0x848484, + 0x858585, + 0x868686, + 0x878787, + 0x888888, + 0x898989, + 0x8a8a8a, + 0x8b8b8b, + 0x8c8c8c, + 0x8d8d8d, + 0x8e8e8e, + 0x8f8f8f, + 0x8f8f8f, + 0x909090, + 0x919191, + 0x929292, + 0x939393, + 0x949494, + 0x959595, + 0x969696, + 0x969696, + 0x979797, + 0x989898, + 0x999999, + 0x9a9a9a, + 0x9b9b9b, + 0x9c9c9c, + 0x9c9c9c, + 0x9d9d9d, + 0x9e9e9e, + 0x9f9f9f, + 0xa0a0a0, + 0xa0a0a0, + 0xa1a1a1, + 0xa2a2a2, + 0xa3a3a3, + 0xa4a4a4, + 0xa4a4a4, + 0xa5a5a5, + 0xa6a6a6, + 0xa7a7a7, + 0xa7a7a7, + 0xa8a8a8, + 0xa9a9a9, + 0xaaaaaa, + 0xaaaaaa, + 0xababab, + 0xacacac, + 0xadadad, + 0xadadad, + 0xaeaeae, + 0xafafaf, + 0xafafaf, + 0xb0b0b0, + 0xb1b1b1, + 0xb2b2b2, + 0xb2b2b2, + 0xb3b3b3, + 0xb4b4b4, + 0xb4b4b4, + 0xb5b5b5, + 0xb6b6b6, + 0xb6b6b6, + 0xb7b7b7, + 0xb8b8b8, + 0xb8b8b8, + 0xb9b9b9, + 0xbababa, + 0xbababa, + 0xbbbbbb, + 0xbcbcbc, + 0xbcbcbc, + 0xbdbdbd, + 0xbebebe, + 0xbebebe, + 0xbfbfbf, + 0xc0c0c0, + 0xc0c0c0, + 0xc1c1c1, + 0xc1c1c1, + 0xc2c2c2, + 0xc3c3c3, + 0xc3c3c3, + 0xc4c4c4, + 0xc5c5c5, + 0xc5c5c5, + 0xc6c6c6, + 0xc6c6c6, + 0xc7c7c7, + 0xc8c8c8, + 0xc8c8c8, + 0xc9c9c9, + 0xc9c9c9, + 0xcacaca, + 0xcbcbcb, + 0xcbcbcb, + 0xcccccc, + 0xcccccc, + 0xcdcdcd, + 0xcecece, + 0xcecece, + 0xcfcfcf, + 0xcfcfcf, + 0xd0d0d0, + 0xd0d0d0, + 0xd1d1d1, + 0xd2d2d2, + 0xd2d2d2, + 0xd3d3d3, + 0xd3d3d3, + 0xd4d4d4, + 0xd4d4d4, + 0xd5d5d5, + 0xd6d6d6, + 0xd6d6d6, + 0xd7d7d7, + 0xd7d7d7, + 0xd8d8d8, + 0xd8d8d8, + 0xd9d9d9, + 0xd9d9d9, + 0xdadada, + 0xdbdbdb, + 0xdbdbdb, + 0xdcdcdc, + 0xdcdcdc, + 0xdddddd, + 0xdddddd, + 0xdedede, + 0xdedede, + 0xdfdfdf, + 0xdfdfdf, + 0xe0e0e0, + 0xe0e0e0, + 0xe1e1e1, + 0xe1e1e1, + 0xe2e2e2, + 0xe3e3e3, + 0xe3e3e3, + 0xe4e4e4, + 0xe4e4e4, + 0xe5e5e5, + 0xe5e5e5, + 0xe6e6e6, + 0xe6e6e6, + 0xe7e7e7, + 0xe7e7e7, + 0xe8e8e8, + 0xe8e8e8, + 0xe9e9e9, + 0xe9e9e9, + 0xeaeaea, + 0xeaeaea, + 0xebebeb, + 0xebebeb, + 0xececec, + 0xececec, + 0xededed, + 0xededed, + 0xeeeeee, + 0xeeeeee, + 0xefefef, + 0xefefef, + 0xf0f0f0, + 0xf0f0f0, + 0xf1f1f1, + 0xf1f1f1, + 0xf2f2f2, + 0xf2f2f2, + 0xf2f2f2, + 0xf3f3f3, + 0xf3f3f3, + 0xf4f4f4, + 0xf4f4f4, + 0xf5f5f5, + 0xf5f5f5, + 0xf6f6f6, + 0xf6f6f6, + 0xf7f7f7, + 0xf7f7f7, + 0xf8f8f8, + 0xf8f8f8, + 0xf9f9f9, + 0xf9f9f9, + 0xfafafa, + 0xfafafa, + 0xfafafa, + 0xfbfbfb, + 0xfbfbfb, + 0xfcfcfc, + 0xfcfcfc, + 0xfdfdfd, + 0xfdfdfd, + 0xfefefe, + 0xfefefe, + 0xffffff, + 0xffffff, +}; + +uint32_t default_post_lut_val[PPP_LUT_MAX] = { + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x0, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x10101, + 0x20202, + 0x20202, + 0x20202, + 0x20202, + 0x20202, + 0x20202, + 0x30303, + 0x30303, + 0x30303, + 0x30303, + 0x30303, + 0x40404, + 0x40404, + 0x40404, + 0x40404, + 0x40404, + 0x50505, + 0x50505, + 0x50505, + 0x50505, + 0x60606, + 0x60606, + 0x60606, + 0x70707, + 0x70707, + 0x70707, + 0x70707, + 0x80808, + 0x80808, + 0x80808, + 0x90909, + 0x90909, + 0xa0a0a, + 0xa0a0a, + 0xa0a0a, + 0xb0b0b, + 0xb0b0b, + 0xb0b0b, + 0xc0c0c, + 0xc0c0c, + 0xd0d0d, + 0xd0d0d, + 0xe0e0e, + 0xe0e0e, + 0xe0e0e, + 0xf0f0f, + 0xf0f0f, + 0x101010, + 0x101010, + 0x111111, + 0x111111, + 0x121212, + 0x121212, + 0x131313, + 0x131313, + 0x141414, + 0x151515, + 0x151515, + 0x161616, + 0x161616, + 0x171717, + 0x171717, + 0x181818, + 0x191919, + 0x191919, + 0x1a1a1a, + 0x1b1b1b, + 0x1b1b1b, + 0x1c1c1c, + 0x1c1c1c, + 0x1d1d1d, + 0x1e1e1e, + 0x1f1f1f, + 0x1f1f1f, + 0x202020, + 0x212121, + 0x212121, + 0x222222, + 0x232323, + 0x242424, + 0x242424, + 0x252525, + 0x262626, + 0x272727, + 0x272727, + 0x282828, + 0x292929, + 0x2a2a2a, + 0x2b2b2b, + 0x2c2c2c, + 0x2c2c2c, + 0x2d2d2d, + 0x2e2e2e, + 0x2f2f2f, + 0x303030, + 0x313131, + 0x323232, + 0x333333, + 0x333333, + 0x343434, + 0x353535, + 0x363636, + 0x373737, + 0x383838, + 0x393939, + 0x3a3a3a, + 0x3b3b3b, + 0x3c3c3c, + 0x3d3d3d, + 0x3e3e3e, + 0x3f3f3f, + 0x404040, + 0x414141, + 0x424242, + 0x434343, + 0x444444, + 0x464646, + 0x474747, + 0x484848, + 0x494949, + 0x4a4a4a, + 0x4b4b4b, + 0x4c4c4c, + 0x4d4d4d, + 0x4f4f4f, + 0x505050, + 0x515151, + 0x525252, + 0x535353, + 0x545454, + 0x565656, + 0x575757, + 0x585858, + 0x595959, + 0x5b5b5b, + 0x5c5c5c, + 0x5d5d5d, + 0x5e5e5e, + 0x606060, + 0x616161, + 0x626262, + 0x646464, + 0x656565, + 0x666666, + 0x686868, + 0x696969, + 0x6a6a6a, + 0x6c6c6c, + 0x6d6d6d, + 0x6f6f6f, + 0x707070, + 0x717171, + 0x737373, + 0x747474, + 0x767676, + 0x777777, + 0x797979, + 0x7a7a7a, + 0x7c7c7c, + 0x7d7d7d, + 0x7f7f7f, + 0x808080, + 0x828282, + 0x838383, + 0x858585, + 0x868686, + 0x888888, + 0x898989, + 0x8b8b8b, + 0x8d8d8d, + 0x8e8e8e, + 0x909090, + 0x919191, + 0x939393, + 0x959595, + 0x969696, + 0x989898, + 0x9a9a9a, + 0x9b9b9b, + 0x9d9d9d, + 0x9f9f9f, + 0xa1a1a1, + 0xa2a2a2, + 0xa4a4a4, + 0xa6a6a6, + 0xa7a7a7, + 0xa9a9a9, + 0xababab, + 0xadadad, + 0xafafaf, + 0xb0b0b0, + 0xb2b2b2, + 0xb4b4b4, + 0xb6b6b6, + 0xb8b8b8, + 0xbababa, + 0xbbbbbb, + 0xbdbdbd, + 0xbfbfbf, + 0xc1c1c1, + 0xc3c3c3, + 0xc5c5c5, + 0xc7c7c7, + 0xc9c9c9, + 0xcbcbcb, + 0xcdcdcd, + 0xcfcfcf, + 0xd1d1d1, + 0xd3d3d3, + 0xd5d5d5, + 0xd7d7d7, + 0xd9d9d9, + 0xdbdbdb, + 0xdddddd, + 0xdfdfdf, + 0xe1e1e1, + 0xe3e3e3, + 0xe5e5e5, + 0xe7e7e7, + 0xe9e9e9, + 0xebebeb, + 0xeeeeee, + 0xf0f0f0, + 0xf2f2f2, + 0xf4f4f4, + 0xf6f6f6, + 0xf8f8f8, + 0xfbfbfb, + 0xfdfdfd, + 0xffffff, +}; + +struct ppp_csc_table rgb2yuv = { + .fwd_matrix = { + 0x83, + 0x102, + 0x32, + 0xffb5, + 0xff6c, + 0xe1, + 0xe1, + 0xff45, + 0xffdc, + }, + .rev_matrix = { + 0x254, + 0x0, + 0x331, + 0x254, + 0xff38, + 0xfe61, + 0x254, + 0x409, + 0x0, + }, + .bv = { + 0x10, + 0x80, + 0x80, + }, + .lv = { + 0x10, + 0xeb, + 0x10, + 0xf0, + }, +}; + +struct ppp_csc_table default_table2 = { + .fwd_matrix = { + 0x5d, + 0x13a, + 0x20, + 0xffcd, + 0xff54, + 0xe1, + 0xe1, + 0xff35, + }, + .rev_matrix = { + 0x254, + 0x0, + 0x396, + 0x254, + 0xff94, + 0xfef0, + 0x254, + 0x43a, + 0x0, + }, + .bv = { + 0x10, + 0x80, + 0x80, + }, + .lv = { + 0x10, + 0xeb, + 0x10, + 0xf0, + }, +}; + +const struct ppp_table upscale_table[PPP_UPSCALE_MAX] = { + { 0x5fffc, 0x0 }, + { 0x50200, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50204, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50208, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5020c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50210, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50214, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50218, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5021c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x50220, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x50224, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x50228, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x5022c, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x50230, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x50234, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x50238, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x5023c, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x50240, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x50244, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x50248, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x5024c, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x50250, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x50254, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x50258, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x5025c, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x50260, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x50264, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x50268, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x5026c, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x50270, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x50274, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x50278, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x5027c, 0x34003fe }, +}; + +const struct ppp_table mdp_gaussian_blur_table[PPP_BLUR_SCALE_MAX] = { + /* max variance */ + { 0x5fffc, 0x20000080 }, + { 0x50280, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50284, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50288, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5028c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50290, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50294, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50298, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5029c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502a8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ac, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502b8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502bc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502c8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502cc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502d8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502dc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502e8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502ec, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f0, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f4, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502f8, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x502fc, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50300, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50304, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50308, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5030c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50310, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50314, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50318, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5031c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50320, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50324, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50328, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5032c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50330, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50334, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50338, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5033c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50340, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50344, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50348, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5034c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50350, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50354, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50358, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5035c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50360, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50364, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50368, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5036c, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50370, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50374, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x50378, 0x20000080 }, + { 0x5fffc, 0x20000080 }, + { 0x5037c, 0x20000080 }, +}; + +const struct ppp_table downscale_x_table_pt2topt4[] = { + { 0x5fffc, 0x740008c }, + { 0x50280, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50284, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50288, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5028c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50290, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50294, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50298, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5029c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x502a0, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x502a4, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x502a8, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x502ac, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x502b0, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x502b4, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x502b8, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x502bc, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x502c0, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x502c4, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x502c8, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x502cc, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x502d0, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x502d4, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x502d8, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x502dc, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x502e0, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x502e4, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x502e8, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x502ec, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x502f0, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x502f4, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x502f8, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x502fc, 0x2300001d }, +}; + +static const struct ppp_table downscale_x_table_pt4topt6[] = { + { 0x5fffc, 0x740008c }, + { 0x50280, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50284, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50288, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5028c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50290, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50294, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50298, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5029c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x502a0, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x502a4, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x502a8, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x502ac, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x502b0, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x502b4, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x502b8, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x502bc, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x502c0, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x502c4, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x502c8, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x502cc, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x502d0, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x502d4, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x502d8, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x502dc, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x502e0, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x502e4, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x502e8, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x502ec, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x502f0, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x502f4, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x502f8, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x502fc, 0x2300001d }, +}; + +static const struct ppp_table downscale_x_table_pt6topt8[] = { + { 0x5fffc, 0xfe000070 }, + { 0x50280, 0x4bc00068 }, + { 0x5fffc, 0xfe000078 }, + { 0x50284, 0x4bc00060 }, + { 0x5fffc, 0xfe000080 }, + { 0x50288, 0x4b800059 }, + { 0x5fffc, 0xfe000089 }, + { 0x5028c, 0x4b000052 }, + { 0x5fffc, 0xfe400091 }, + { 0x50290, 0x4a80004b }, + { 0x5fffc, 0xfe40009a }, + { 0x50294, 0x4a000044 }, + { 0x5fffc, 0xfe8000a3 }, + { 0x50298, 0x4940003d }, + { 0x5fffc, 0xfec000ac }, + { 0x5029c, 0x48400037 }, + { 0x5fffc, 0xff0000b4 }, + { 0x502a0, 0x47800031 }, + { 0x5fffc, 0xff8000bd }, + { 0x502a4, 0x4640002b }, + { 0x5fffc, 0xc5 }, + { 0x502a8, 0x45000026 }, + { 0x5fffc, 0x8000ce }, + { 0x502ac, 0x43800021 }, + { 0x5fffc, 0x10000d6 }, + { 0x502b0, 0x4240001c }, + { 0x5fffc, 0x18000df }, + { 0x502b4, 0x40800018 }, + { 0x5fffc, 0x24000e6 }, + { 0x502b8, 0x3f000014 }, + { 0x5fffc, 0x30000ee }, + { 0x502bc, 0x3d400010 }, + { 0x5fffc, 0x40000f5 }, + { 0x502c0, 0x3b80000c }, + { 0x5fffc, 0x50000fc }, + { 0x502c4, 0x39800009 }, + { 0x5fffc, 0x6000102 }, + { 0x502c8, 0x37c00006 }, + { 0x5fffc, 0x7000109 }, + { 0x502cc, 0x35800004 }, + { 0x5fffc, 0x840010e }, + { 0x502d0, 0x33800002 }, + { 0x5fffc, 0x9800114 }, + { 0x502d4, 0x31400000 }, + { 0x5fffc, 0xac00119 }, + { 0x502d8, 0x2f4003fe }, + { 0x5fffc, 0xc40011e }, + { 0x502dc, 0x2d0003fc }, + { 0x5fffc, 0xdc00121 }, + { 0x502e0, 0x2b0003fb }, + { 0x5fffc, 0xf400125 }, + { 0x502e4, 0x28c003fa }, + { 0x5fffc, 0x11000128 }, + { 0x502e8, 0x268003f9 }, + { 0x5fffc, 0x12c0012a }, + { 0x502ec, 0x244003f9 }, + { 0x5fffc, 0x1480012c }, + { 0x502f0, 0x224003f8 }, + { 0x5fffc, 0x1640012e }, + { 0x502f4, 0x200003f8 }, + { 0x5fffc, 0x1800012f }, + { 0x502f8, 0x1e0003f8 }, + { 0x5fffc, 0x1a00012f }, + { 0x502fc, 0x1c0003f8 }, +}; + +static const struct ppp_table downscale_x_table_pt8topt1[] = { + { 0x5fffc, 0x0 }, + { 0x50280, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50284, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50288, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5028c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50290, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50294, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50298, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5029c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x502a0, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x502a4, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x502a8, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x502ac, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x502b0, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x502b4, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x502b8, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x502bc, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x502c0, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x502c4, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x502c8, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x502cc, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x502d0, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x502d4, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x502d8, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x502dc, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x502e0, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x502e4, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x502e8, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x502ec, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x502f0, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x502f4, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x502f8, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x502fc, 0x34003fe }, +}; + +static const struct ppp_table *downscale_x_table[PPP_DOWNSCALE_MAX] = { + [PPP_DOWNSCALE_PT2TOPT4] = downscale_x_table_pt2topt4, + [PPP_DOWNSCALE_PT4TOPT6] = downscale_x_table_pt4topt6, + [PPP_DOWNSCALE_PT6TOPT8] = downscale_x_table_pt6topt8, + [PPP_DOWNSCALE_PT8TOPT1] = downscale_x_table_pt8topt1, +}; + +static const struct ppp_table downscale_y_table_pt2topt4[] = { + { 0x5fffc, 0x740008c }, + { 0x50300, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50304, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50308, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5030c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50310, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50314, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50318, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5031c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x50320, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x50324, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x50328, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x5032c, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x50330, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x50334, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x50338, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x5033c, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x50340, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x50344, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x50348, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x5034c, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x50350, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x50354, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x50358, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x5035c, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x50360, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x50364, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x50368, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x5036c, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x50370, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x50374, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x50378, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x5037c, 0x2300001d }, +}; + +static const struct ppp_table downscale_y_table_pt4topt6[] = { + { 0x5fffc, 0x740008c }, + { 0x50300, 0x33800088 }, + { 0x5fffc, 0x800008e }, + { 0x50304, 0x33400084 }, + { 0x5fffc, 0x8400092 }, + { 0x50308, 0x33000080 }, + { 0x5fffc, 0x9000094 }, + { 0x5030c, 0x3300007b }, + { 0x5fffc, 0x9c00098 }, + { 0x50310, 0x32400077 }, + { 0x5fffc, 0xa40009b }, + { 0x50314, 0x32000073 }, + { 0x5fffc, 0xb00009d }, + { 0x50318, 0x31c0006f }, + { 0x5fffc, 0xbc000a0 }, + { 0x5031c, 0x3140006b }, + { 0x5fffc, 0xc8000a2 }, + { 0x50320, 0x31000067 }, + { 0x5fffc, 0xd8000a5 }, + { 0x50324, 0x30800062 }, + { 0x5fffc, 0xe4000a8 }, + { 0x50328, 0x2fc0005f }, + { 0x5fffc, 0xec000aa }, + { 0x5032c, 0x2fc0005b }, + { 0x5fffc, 0xf8000ad }, + { 0x50330, 0x2f400057 }, + { 0x5fffc, 0x108000b0 }, + { 0x50334, 0x2e400054 }, + { 0x5fffc, 0x114000b2 }, + { 0x50338, 0x2e000050 }, + { 0x5fffc, 0x124000b4 }, + { 0x5033c, 0x2d80004c }, + { 0x5fffc, 0x130000b6 }, + { 0x50340, 0x2d000049 }, + { 0x5fffc, 0x140000b8 }, + { 0x50344, 0x2c800045 }, + { 0x5fffc, 0x150000b9 }, + { 0x50348, 0x2c000042 }, + { 0x5fffc, 0x15c000bd }, + { 0x5034c, 0x2b40003e }, + { 0x5fffc, 0x16c000bf }, + { 0x50350, 0x2a80003b }, + { 0x5fffc, 0x17c000bf }, + { 0x50354, 0x2a000039 }, + { 0x5fffc, 0x188000c2 }, + { 0x50358, 0x29400036 }, + { 0x5fffc, 0x19c000c4 }, + { 0x5035c, 0x28800032 }, + { 0x5fffc, 0x1ac000c5 }, + { 0x50360, 0x2800002f }, + { 0x5fffc, 0x1bc000c7 }, + { 0x50364, 0x2740002c }, + { 0x5fffc, 0x1cc000c8 }, + { 0x50368, 0x26c00029 }, + { 0x5fffc, 0x1dc000c9 }, + { 0x5036c, 0x26000027 }, + { 0x5fffc, 0x1ec000cc }, + { 0x50370, 0x25000024 }, + { 0x5fffc, 0x200000cc }, + { 0x50374, 0x24800021 }, + { 0x5fffc, 0x210000cd }, + { 0x50378, 0x23800020 }, + { 0x5fffc, 0x220000ce }, + { 0x5037c, 0x2300001d }, +}; + +static const struct ppp_table downscale_y_table_pt6topt8[] = { + { 0x5fffc, 0xfe000070 }, + { 0x50300, 0x4bc00068 }, + { 0x5fffc, 0xfe000078 }, + { 0x50304, 0x4bc00060 }, + { 0x5fffc, 0xfe000080 }, + { 0x50308, 0x4b800059 }, + { 0x5fffc, 0xfe000089 }, + { 0x5030c, 0x4b000052 }, + { 0x5fffc, 0xfe400091 }, + { 0x50310, 0x4a80004b }, + { 0x5fffc, 0xfe40009a }, + { 0x50314, 0x4a000044 }, + { 0x5fffc, 0xfe8000a3 }, + { 0x50318, 0x4940003d }, + { 0x5fffc, 0xfec000ac }, + { 0x5031c, 0x48400037 }, + { 0x5fffc, 0xff0000b4 }, + { 0x50320, 0x47800031 }, + { 0x5fffc, 0xff8000bd }, + { 0x50324, 0x4640002b }, + { 0x5fffc, 0xc5 }, + { 0x50328, 0x45000026 }, + { 0x5fffc, 0x8000ce }, + { 0x5032c, 0x43800021 }, + { 0x5fffc, 0x10000d6 }, + { 0x50330, 0x4240001c }, + { 0x5fffc, 0x18000df }, + { 0x50334, 0x40800018 }, + { 0x5fffc, 0x24000e6 }, + { 0x50338, 0x3f000014 }, + { 0x5fffc, 0x30000ee }, + { 0x5033c, 0x3d400010 }, + { 0x5fffc, 0x40000f5 }, + { 0x50340, 0x3b80000c }, + { 0x5fffc, 0x50000fc }, + { 0x50344, 0x39800009 }, + { 0x5fffc, 0x6000102 }, + { 0x50348, 0x37c00006 }, + { 0x5fffc, 0x7000109 }, + { 0x5034c, 0x35800004 }, + { 0x5fffc, 0x840010e }, + { 0x50350, 0x33800002 }, + { 0x5fffc, 0x9800114 }, + { 0x50354, 0x31400000 }, + { 0x5fffc, 0xac00119 }, + { 0x50358, 0x2f4003fe }, + { 0x5fffc, 0xc40011e }, + { 0x5035c, 0x2d0003fc }, + { 0x5fffc, 0xdc00121 }, + { 0x50360, 0x2b0003fb }, + { 0x5fffc, 0xf400125 }, + { 0x50364, 0x28c003fa }, + { 0x5fffc, 0x11000128 }, + { 0x50368, 0x268003f9 }, + { 0x5fffc, 0x12c0012a }, + { 0x5036c, 0x244003f9 }, + { 0x5fffc, 0x1480012c }, + { 0x50370, 0x224003f8 }, + { 0x5fffc, 0x1640012e }, + { 0x50374, 0x200003f8 }, + { 0x5fffc, 0x1800012f }, + { 0x50378, 0x1e0003f8 }, + { 0x5fffc, 0x1a00012f }, + { 0x5037c, 0x1c0003f8 }, +}; + +static const struct ppp_table downscale_y_table_pt8topt1[] = { + { 0x5fffc, 0x0 }, + { 0x50300, 0x7fc00000 }, + { 0x5fffc, 0xff80000d }, + { 0x50304, 0x7ec003f9 }, + { 0x5fffc, 0xfec0001c }, + { 0x50308, 0x7d4003f3 }, + { 0x5fffc, 0xfe40002b }, + { 0x5030c, 0x7b8003ed }, + { 0x5fffc, 0xfd80003c }, + { 0x50310, 0x794003e8 }, + { 0x5fffc, 0xfcc0004d }, + { 0x50314, 0x76c003e4 }, + { 0x5fffc, 0xfc40005f }, + { 0x50318, 0x73c003e0 }, + { 0x5fffc, 0xfb800071 }, + { 0x5031c, 0x708003de }, + { 0x5fffc, 0xfac00085 }, + { 0x50320, 0x6d0003db }, + { 0x5fffc, 0xfa000098 }, + { 0x50324, 0x698003d9 }, + { 0x5fffc, 0xf98000ac }, + { 0x50328, 0x654003d8 }, + { 0x5fffc, 0xf8c000c1 }, + { 0x5032c, 0x610003d7 }, + { 0x5fffc, 0xf84000d5 }, + { 0x50330, 0x5c8003d7 }, + { 0x5fffc, 0xf7c000e9 }, + { 0x50334, 0x580003d7 }, + { 0x5fffc, 0xf74000fd }, + { 0x50338, 0x534003d8 }, + { 0x5fffc, 0xf6c00112 }, + { 0x5033c, 0x4e8003d8 }, + { 0x5fffc, 0xf6800126 }, + { 0x50340, 0x494003da }, + { 0x5fffc, 0xf600013a }, + { 0x50344, 0x448003db }, + { 0x5fffc, 0xf600014d }, + { 0x50348, 0x3f4003dd }, + { 0x5fffc, 0xf5c00160 }, + { 0x5034c, 0x3a4003df }, + { 0x5fffc, 0xf5c00172 }, + { 0x50350, 0x354003e1 }, + { 0x5fffc, 0xf5c00184 }, + { 0x50354, 0x304003e3 }, + { 0x5fffc, 0xf6000195 }, + { 0x50358, 0x2b0003e6 }, + { 0x5fffc, 0xf64001a6 }, + { 0x5035c, 0x260003e8 }, + { 0x5fffc, 0xf6c001b4 }, + { 0x50360, 0x214003eb }, + { 0x5fffc, 0xf78001c2 }, + { 0x50364, 0x1c4003ee }, + { 0x5fffc, 0xf80001cf }, + { 0x50368, 0x17c003f1 }, + { 0x5fffc, 0xf90001db }, + { 0x5036c, 0x134003f3 }, + { 0x5fffc, 0xfa0001e5 }, + { 0x50370, 0xf0003f6 }, + { 0x5fffc, 0xfb4001ee }, + { 0x50374, 0xac003f9 }, + { 0x5fffc, 0xfcc001f5 }, + { 0x50378, 0x70003fb }, + { 0x5fffc, 0xfe4001fb }, + { 0x5037c, 0x34003fe }, +}; + +static const struct ppp_table *downscale_y_table[PPP_DOWNSCALE_MAX] = { + [PPP_DOWNSCALE_PT2TOPT4] = downscale_y_table_pt2topt4, + [PPP_DOWNSCALE_PT4TOPT6] = downscale_y_table_pt4topt6, + [PPP_DOWNSCALE_PT6TOPT8] = downscale_y_table_pt6topt8, + [PPP_DOWNSCALE_PT8TOPT1] = downscale_y_table_pt8topt1, +}; + +void ppp_load_table(const struct ppp_table *table, int len) +{ + int i; + for (i = 0; i < len; i++) + PPP_WRITEL(table[i].val, table[i].reg); +} + +void ppp_load_up_lut(void) +{ + ppp_load_table(upscale_table, + PPP_UPSCALE_MAX); +} + +void ppp_load_gaussian_lut(void) +{ + ppp_load_table(mdp_gaussian_blur_table, + PPP_BLUR_SCALE_MAX); +} + +void ppp_load_x_scale_table(int idx) +{ + ppp_load_table(downscale_x_table[idx], 64); +} + +void ppp_load_y_scale_table(int idx) +{ + ppp_load_table(downscale_y_table[idx], 64); +} + +uint32_t ppp_bpp(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return bytes_per_pixel[type]; +} + +uint32_t ppp_src_config(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return src_cfg_lut[type]; +} + +uint32_t ppp_out_config(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return out_cfg_lut[type]; +} + +uint32_t ppp_pack_pattern(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return pack_patt_lut[type]; +} + +uint32_t ppp_dst_op_reg(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return dst_op_reg[type]; +} + +uint32_t ppp_src_op_reg(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return src_op_reg[type]; +} + +bool ppp_per_p_alpha(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return per_pixel_alpha[type]; +} + +bool ppp_multi_plane(uint32_t type) +{ + if (type > MDP_IMGTYPE_LIMIT) + return 0; + return multi_plane[type]; +} + +uint32_t *ppp_default_pre_lut(void) +{ + return default_pre_lut_val; +} + +uint32_t *ppp_default_post_lut(void) +{ + return default_post_lut_val; +} + +struct ppp_csc_table *ppp_csc_rgb2yuv(void) +{ + return &rgb2yuv; +} + +struct ppp_csc_table *ppp_csc_table2(void) +{ + return &default_table2; +} diff --git a/drivers/video/fbdev/msm/mdp3_ppp_hwio.c b/drivers/video/fbdev/msm/mdp3_ppp_hwio.c new file mode 100644 index 000000000000..309effc294ef --- /dev/null +++ b/drivers/video/fbdev/msm/mdp3_ppp_hwio.c @@ -0,0 +1,1184 @@ +/* Copyright (c) 2007, 2012-2013 The Linux Foundation. All rights reserved. + * 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. + */ + +#include <linux/file.h> +#include <linux/io.h> +#include <linux/kernel.h> +#include <linux/major.h> +#include <linux/slab.h> +#include <linux/types.h> +#include <linux/uaccess.h> +#include "linux/proc_fs.h" + +#include "mdss_fb.h" +#include "mdp3_ppp.h" +#include "mdp3_hwio.h" + +/* SHIM Q Factor */ +#define PHI_Q_FACTOR 29 +#define PQF_PLUS_5 (PHI_Q_FACTOR + 5) /* due to 32 phases */ +#define PQF_PLUS_4 (PHI_Q_FACTOR + 4) +#define PQF_PLUS_2 (PHI_Q_FACTOR + 2) /* to get 4.0 */ +#define PQF_MINUS_2 (PHI_Q_FACTOR - 2) /* to get 0.25 */ +#define PQF_PLUS_5_PLUS_2 (PQF_PLUS_5 + 2) +#define PQF_PLUS_5_MINUS_2 (PQF_PLUS_5 - 2) + +static long long mdp_do_div(long long num, long long den) +{ + do_div(num, den); + return num; +} + +static int mdp_calc_scale_params(uint32_t org, uint32_t dim_in, + uint32_t dim_out, bool is_W, int32_t *phase_init_ptr, + uint32_t *phase_step_ptr) +{ + bool rpa_on = false; + int init_phase = 0; + uint64_t numer = 0; + uint64_t denom = 0; + int64_t point5 = 1; + int64_t one = 1; + int64_t k1, k2, k3, k4; /* linear equation coefficients */ + uint64_t int_mask; + uint64_t fract_mask; + uint64_t Os; + int64_t Osprime; + int64_t Od; + int64_t Odprime; + int64_t Oreq; + uint32_t mult; + + /* + * The phase accumulator should really be rational for all cases in a + * general purpose polyphase scaler for a tiled architecture with + * non-zero * origin capability because there is no way to represent + * certain scale factors in fixed point regardless of precision. + * The error incurred in attempting to use fixed point is most + * eggregious for SF where 1/SF is an integral multiple of 1/3. + * + * Set the RPA flag for this dimension. + * + * In order for 1/SF (dim_in/dim_out) to be an integral multiple of + * 1/3, dim_out must be an integral multiple of 3. + */ + if (!(dim_out % 3)) { + mult = dim_out / 3; + rpa_on = (!(dim_in % mult)); + } + + numer = dim_out; + denom = dim_in; + + /* + * convert to U30.34 before division + * + * The K vectors carry 4 extra bits of precision + * and are rounded. + * + * We initially go 5 bits over then round by adding + * 1 and right shifting by 1 + * so final result is U31.33 + */ + numer <<= PQF_PLUS_5; + + /* now calculate the scale factor (aka k3) */ + k3 = ((mdp_do_div(numer, denom) + 1) >> 1); + + /* check scale factor for legal range [0.25 - 4.0] */ + if (((k3 >> 4) < (1LL << PQF_MINUS_2)) || + ((k3 >> 4) > (1LL << PQF_PLUS_2))) { + return -EINVAL; + } + + /* calculate inverse scale factor (aka k1) for phase init */ + numer = dim_in; + denom = dim_out; + numer <<= PQF_PLUS_5; + k1 = ((mdp_do_div(numer, denom) + 1) >> 1); + + /* + * calculate initial phase and ROI overfetch + */ + /* convert point5 & one to S39.24 (will always be positive) */ + point5 <<= (PQF_PLUS_4 - 1); + one <<= PQF_PLUS_4; + k2 = ((k1 - one) >> 1); + init_phase = (int)(k2 >> 4); + k4 = ((k3 - one) >> 1); + if (k3 != one) { + /* calculate the masks */ + fract_mask = one - 1; + int_mask = ~fract_mask; + + if (!rpa_on) { + /* + * FIXED POINT IMPLEMENTATION + */ + if (org) { + /* + * The complicated case; ROI origin != 0 + * init_phase needs to be adjusted + * OF is also position dependent + */ + + /* map (org - .5) into destination space */ + Os = ((uint64_t) org << 1) - 1; + Od = ((k3 * Os) >> 1) + k4; + + /* take the ceiling */ + Odprime = (Od & int_mask); + if (Odprime != Od) + Odprime += one; + + /* now map that back to source space */ + Osprime = (k1 * (Odprime >> PQF_PLUS_4)) + k2; + + /* then floor & decrement to calc the required + starting coordinate */ + Oreq = (Osprime & int_mask) - one; + + /* calculate initial phase */ + init_phase = (int)((Osprime - Oreq) >> 4); + } + } else { + /* + * RPA IMPLEMENTATION + * + * init_phase needs to be calculated in all RPA_on cases + * because it's a numerator, not a fixed point value. + */ + + /* map (org - .5) into destination space */ + Os = ((uint64_t) org << PQF_PLUS_4) - point5; + Od = mdp_do_div((dim_out * (Os + point5)), + dim_in); + Od -= point5; + + /* take the ceiling */ + Odprime = (Od & int_mask); + if (Odprime != Od) + Odprime += one; + + /* now map that back to source space */ + Osprime = + mdp_do_div((dim_in * (Odprime + point5)), + dim_out); + Osprime -= point5; + + /* then floor & decrement to calculate the required + starting coordinate */ + Oreq = (Osprime & int_mask) - one; + + /* calculate initial phase */ + init_phase = (int)((Osprime - Oreq) >> 4); + } + } + + /* return the scale parameters */ + *phase_init_ptr = init_phase; + *phase_step_ptr = (uint32_t) (k1 >> 4); + + return 0; +} + +static int scale_idx(int factor) +{ + int idx; + + if (factor > 80) + idx = PPP_DOWNSCALE_PT8TOPT1; + else if (factor > 60) + idx = PPP_DOWNSCALE_PT6TOPT8; + else if (factor > 40) + idx = PPP_DOWNSCALE_PT4TOPT6; + else + idx = PPP_DOWNSCALE_PT2TOPT4; + + return idx; +} + +inline int32_t comp_conv_rgb2yuv(int32_t comp, int32_t y_high, + int32_t y_low, int32_t c_high, int32_t c_low) +{ + if (comp < 0) + comp = 0; + if (comp > 255) + comp = 255; + + /* clamp */ + if (comp < y_low) + comp = y_low; + if (comp > y_high) + comp = y_high; + return comp; +} + +static uint32_t conv_rgb2yuv(uint32_t input_pixel, + uint16_t *matrix_vector, + uint16_t *bv, + uint16_t *clamp_vector) +{ + uint8_t input_C2, input_C0, input_C1; + uint32_t output; + int32_t comp_C2, comp_C1, comp_C0, temp; + int32_t temp1, temp2, temp3; + int32_t matrix[9]; + int32_t bias_vector[3]; + int32_t Y_low_limit, Y_high_limit, C_low_limit, C_high_limit; + int32_t i; + + input_C2 = (input_pixel >> 16) & 0xFF; + input_C1 = (input_pixel >> 8) & 0xFF; + input_C0 = (input_pixel >> 0) & 0xFF; + + comp_C0 = input_C0; + comp_C1 = input_C1; + comp_C2 = input_C2; + + for (i = 0; i < MDP_CSC_SIZE; i++) + matrix[i] = + ((int32_t) (((int32_t) matrix_vector[i]) << 20)) >> 20; + + bias_vector[0] = (int32_t) (bv[0] & 0xFF); + bias_vector[1] = (int32_t) (bv[1] & 0xFF); + bias_vector[2] = (int32_t) (bv[2] & 0xFF); + + Y_low_limit = (int32_t) clamp_vector[0]; + Y_high_limit = (int32_t) clamp_vector[1]; + C_low_limit = (int32_t) clamp_vector[2]; + C_high_limit = (int32_t) clamp_vector[3]; + + /* + * Color Conversion + * reorder input colors + */ + temp = comp_C2; + comp_C2 = comp_C1; + comp_C1 = comp_C0; + comp_C0 = temp; + + /* matrix multiplication */ + temp1 = comp_C0 * matrix[0] + comp_C1 * matrix[1] + comp_C2 * matrix[2]; + temp2 = comp_C0 * matrix[3] + comp_C1 * matrix[4] + comp_C2 * matrix[5]; + temp3 = comp_C0 * matrix[6] + comp_C1 * matrix[7] + comp_C2 * matrix[8]; + + comp_C0 = temp1 + 0x100; + comp_C1 = temp2 + 0x100; + comp_C2 = temp3 + 0x100; + + /* take interger part */ + comp_C0 >>= 9; + comp_C1 >>= 9; + comp_C2 >>= 9; + + /* post bias (+) */ + comp_C0 += bias_vector[0]; + comp_C1 += bias_vector[1]; + comp_C2 += bias_vector[2]; + + /* limit pixel to 8-bit */ + comp_C0 = comp_conv_rgb2yuv(comp_C0, Y_high_limit, + Y_low_limit, C_high_limit, C_low_limit); + comp_C1 = comp_conv_rgb2yuv(comp_C1, Y_high_limit, + Y_low_limit, C_high_limit, C_low_limit); + comp_C2 = comp_conv_rgb2yuv(comp_C2, Y_high_limit, + Y_low_limit, C_high_limit, C_low_limit); + + output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0; + return output; +} + +inline void y_h_even_num(struct ppp_img_desc *img) +{ + img->roi.y = (img->roi.y / 2) * 2; + img->roi.height = (img->roi.height / 2) * 2; +} + +inline void x_w_even_num(struct ppp_img_desc *img) +{ + img->roi.x = (img->roi.x / 2) * 2; + img->roi.width = (img->roi.width / 2) * 2; +} + +bool check_if_rgb(int color) +{ + bool rgb = false; + switch (color) { + case MDP_RGB_565: + case MDP_BGR_565: + case MDP_RGB_888: + case MDP_BGR_888: + case MDP_BGRA_8888: + case MDP_RGBA_8888: + case MDP_ARGB_8888: + case MDP_XRGB_8888: + case MDP_RGBX_8888: + rgb = true; + default: + break; + } + return rgb; +} + +static uint8_t *mdp_adjust_rot_addr(struct ppp_blit_op *iBuf, + uint8_t *addr, uint32_t bpp, uint32_t uv) +{ + uint32_t dest_ystride = iBuf->dst.prop.width * bpp; + uint32_t h_slice = 1; + if (0) + return 0; + + if (uv && ((iBuf->dst.color_fmt == MDP_Y_CBCR_H2V2) || + (iBuf->dst.color_fmt == MDP_Y_CRCB_H2V2))) + h_slice = 2; + + if (((iBuf->mdp_op & MDPOP_ROT90) == MDPOP_ROT90) ^ + ((iBuf->mdp_op & MDPOP_LR) == MDPOP_LR)) { + addr += + (iBuf->dst.roi.width - + MIN(16, iBuf->dst.roi.width)) * bpp; + } + if ((iBuf->mdp_op & MDPOP_UD) == MDPOP_UD) { + if (1) { + addr += + ((iBuf->dst.roi.height - + MIN(16, iBuf->dst.roi.height))/h_slice) * + dest_ystride; + } else { + addr += + (iBuf->dst.roi.width - + MIN(16, iBuf->dst.roi.width)) * bpp; + } + } + + return addr; +} + +void mdp_adjust_start_addr(struct ppp_blit_op *blit_op, + struct ppp_img_desc *img, int v_slice, + int h_slice, int layer) +{ + uint32_t bpp = ppp_bpp(img->color_fmt); + int x = img->roi.x; + int y = img->roi.y; + uint32_t width = img->prop.width; + + if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO && layer == 0) + img->p0 += (x + y * ALIGN(width, 32)) * bpp; + else + img->p0 += (x + y * width) * bpp; + if (layer != 0) + img->p0 = mdp_adjust_rot_addr(blit_op, img->p0, bpp, 0); + + if (img->p1) { + /* + * MDP_Y_CBCR_H2V2/MDP_Y_CRCB_H2V2 cosite for now + * we need to shift x direction same as y dir for offsite + */ + if (img->color_fmt == MDP_Y_CBCR_H2V2_ADRENO + && layer == 0) + img->p1 += ((x / h_slice) * h_slice + ((y == 0) ? 0 : + (((y + 1) / v_slice - 1) * (ALIGN(width/2, 32) * 2)))) + * bpp; + else + img->p1 += ((x / h_slice) * h_slice + + ((y == 0) ? 0 : ((y + 1) / v_slice - 1) * width)) * bpp; + if (layer != 0) + img->p1 = mdp_adjust_rot_addr(blit_op, img->p1, bpp, 1); + } +} + +int load_ppp_lut(int tableType, uint32_t *lut) +{ + int i; + uint32_t base_addr; + + base_addr = tableType ? MDP3_PPP_POST_LUT : MDP3_PPP_PRE_LUT; + for (i = 0; i < PPP_LUT_MAX; i++) + PPP_WRITEL(lut[i], base_addr + MDP3_PPP_LUTn(i)); + + return 0; +} + +/* Configure Primary CSC Matrix */ +int load_primary_matrix(struct ppp_csc_table *csc) +{ + int i; + + for (i = 0; i < MDP_CSC_SIZE; i++) + PPP_WRITEL(csc->fwd_matrix[i], MDP3_PPP_CSC_PFMVn(i)); + + for (i = 0; i < MDP_CSC_SIZE; i++) + PPP_WRITEL(csc->rev_matrix[i], MDP3_PPP_CSC_PRMVn(i)); + + for (i = 0; i < MDP_BV_SIZE; i++) + PPP_WRITEL(csc->bv[i], MDP3_PPP_CSC_PBVn(i)); + + for (i = 0; i < MDP_LV_SIZE; i++) + PPP_WRITEL(csc->lv[i], MDP3_PPP_CSC_PLVn(i)); + + return 0; +} + +/* Load Secondary CSC Matrix */ +int load_secondary_matrix(struct ppp_csc_table *csc) +{ + int i; + + for (i = 0; i < MDP_CSC_SIZE; i++) + PPP_WRITEL(csc->fwd_matrix[i], MDP3_PPP_CSC_SFMVn(i)); + + for (i = 0; i < MDP_CSC_SIZE; i++) + PPP_WRITEL(csc->rev_matrix[i], MDP3_PPP_CSC_SRMVn(i)); + + for (i = 0; i < MDP_BV_SIZE; i++) + PPP_WRITEL(csc->bv[i], MDP3_PPP_CSC_SBVn(i)); + + for (i = 0; i < MDP_LV_SIZE; i++) + PPP_WRITEL(csc->lv[i], MDP3_PPP_CSC_SLVn(i)); + return 0; +} + +int load_csc_matrix(int matrix_type, struct ppp_csc_table *csc) +{ + if (matrix_type == CSC_PRIMARY_MATRIX) + return load_primary_matrix(csc); + + return load_secondary_matrix(csc); +} + +int config_ppp_src(struct ppp_img_desc *src) +{ + uint32_t val; + + val = ((src->roi.height & MDP3_PPP_XY_MASK) << MDP3_PPP_XY_OFFSET) | + (src->roi.width & MDP3_PPP_XY_MASK); + PPP_WRITEL(val, MDP3_PPP_SRC_SIZE); + + PPP_WRITEL(src->p0, MDP3_PPP_SRCP0_ADDR); + PPP_WRITEL(src->p1, MDP3_PPP_SRCP1_ADDR); + PPP_WRITEL(src->p3, MDP3_PPP_SRCP3_ADDR); + + val = (src->stride0 & MDP3_PPP_STRIDE_MASK) | + ((src->stride1 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_SRC_YSTRIDE1_ADDR); + val = ((src->stride2 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_SRC_YSTRIDE2_ADDR); + + val = ppp_src_config(src->color_fmt); + val |= (src->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0; + val |= (src->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0; + PPP_WRITEL(val, MDP3_PPP_SRC_FORMAT); + PPP_WRITEL(ppp_pack_pattern(src->color_fmt), + MDP3_PPP_SRC_UNPACK_PATTERN1); + return 0; +} + +int config_ppp_out(struct ppp_img_desc *dst) +{ + uint32_t val; + bool pseudoplanr_output = false; + + switch (dst->color_fmt) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + pseudoplanr_output = true; + break; + default: + break; + } + val = ppp_out_config(dst->color_fmt); + if (pseudoplanr_output) + val |= PPP_DST_PLANE_PSEUDOPLN; + PPP_WRITEL(val, MDP3_PPP_OUT_FORMAT); + PPP_WRITEL(ppp_pack_pattern(dst->color_fmt), + MDP3_PPP_OUT_PACK_PATTERN1); + + val = ((dst->roi.height & MDP3_PPP_XY_MASK) << MDP3_PPP_XY_OFFSET) | + (dst->roi.width & MDP3_PPP_XY_MASK); + PPP_WRITEL(val, MDP3_PPP_OUT_SIZE); + + PPP_WRITEL(dst->p0, MDP3_PPP_OUTP0_ADDR); + PPP_WRITEL(dst->p1, MDP3_PPP_OUTP1_ADDR); + PPP_WRITEL(dst->p3, MDP3_PPP_OUTP3_ADDR); + + val = (dst->stride0 & MDP3_PPP_STRIDE_MASK) | + ((dst->stride1 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_OUT_YSTRIDE1_ADDR); + val = ((dst->stride2 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_OUT_YSTRIDE2_ADDR); + return 0; +} + +int config_ppp_background(struct ppp_img_desc *bg) +{ + uint32_t val; + + PPP_WRITEL(bg->p0, MDP3_PPP_BGP0_ADDR); + PPP_WRITEL(bg->p1, MDP3_PPP_BGP1_ADDR); + PPP_WRITEL(bg->p3, MDP3_PPP_BGP3_ADDR); + + val = (bg->stride0 & MDP3_PPP_STRIDE_MASK) | + ((bg->stride1 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_BG_YSTRIDE1_ADDR); + val = ((bg->stride2 & MDP3_PPP_STRIDE_MASK) << + MDP3_PPP_STRIDE1_OFFSET); + PPP_WRITEL(val, MDP3_PPP_BG_YSTRIDE2_ADDR); + + PPP_WRITEL(ppp_src_config(bg->color_fmt), + MDP3_PPP_BG_FORMAT); + PPP_WRITEL(ppp_pack_pattern(bg->color_fmt), + MDP3_PPP_BG_UNPACK_PATTERN1); + return 0; +} + +void ppp_edge_rep_luma_pixel(struct ppp_blit_op *blit_op, + struct ppp_edge_rep *er) +{ + if (blit_op->mdp_op & MDPOP_ASCALE) { + + er->is_scale_enabled = 1; + + if (blit_op->mdp_op & MDPOP_ROT90) { + er->dst_roi_width = blit_op->dst.roi.height; + er->dst_roi_height = blit_op->dst.roi.width; + } else { + er->dst_roi_width = blit_op->dst.roi.width; + er->dst_roi_height = blit_op->dst.roi.height; + } + + /* + * Find out the luma pixels needed for scaling in the + * x direction (LEFT and RIGHT). Locations of pixels are + * relative to the ROI. Upper-left corner of ROI corresponds + * to coordinates (0,0). Also set the number of luma pixel + * to repeat. + */ + if (blit_op->src.roi.width > 3 * er->dst_roi_width) { + /* scale factor < 1/3 */ + er->luma_interp_point_right = + (blit_op->src.roi.width - 1); + } else if (blit_op->src.roi.width == 3 * er->dst_roi_width) { + /* scale factor == 1/3 */ + er->luma_interp_point_right = + (blit_op->src.roi.width - 1) + 1; + er->luma_repeat_right = 1; + } else if ((blit_op->src.roi.width > er->dst_roi_width) && + (blit_op->src.roi.width < 3 * er->dst_roi_width)) { + /* 1/3 < scale factor < 1 */ + er->luma_interp_point_left = -1; + er->luma_interp_point_right = + (blit_op->src.roi.width - 1) + 1; + er->luma_repeat_left = 1; + er->luma_repeat_right = 1; + } else if (blit_op->src.roi.width == er->dst_roi_width) { + /* scale factor == 1 */ + er->luma_interp_point_left = -1; + er->luma_interp_point_right = + (blit_op->src.roi.width - 1) + 2; + er->luma_repeat_left = 1; + er->luma_repeat_right = 2; + } else { + /* scale factor > 1 */ + er->luma_interp_point_left = -2; + er->luma_interp_point_right = + (blit_op->src.roi.width - 1) + 2; + er->luma_repeat_left = 2; + er->luma_repeat_right = 2; + } + + /* + * Find out the number of pixels needed for scaling in the + * y direction (TOP and BOTTOM). Locations of pixels are + * relative to the ROI. Upper-left corner of ROI corresponds + * to coordinates (0,0). Also set the number of luma pixel + * to repeat. + */ + if (blit_op->src.roi.height > 3 * er->dst_roi_height) { + er->luma_interp_point_bottom = + (blit_op->src.roi.height - 1); + } else if (blit_op->src.roi.height == 3 * er->dst_roi_height) { + er->luma_interp_point_bottom = + (blit_op->src.roi.height - 1) + 1; + er->luma_repeat_bottom = 1; + } else if ((blit_op->src.roi.height > er->dst_roi_height) && + (blit_op->src.roi.height < 3 * er->dst_roi_height)) { + er->luma_interp_point_top = -1; + er->luma_interp_point_bottom = + (blit_op->src.roi.height - 1) + 1; + er->luma_repeat_top = 1; + er->luma_repeat_bottom = 1; + } else if (blit_op->src.roi.height == er->dst_roi_height) { + er->luma_interp_point_top = -1; + er->luma_interp_point_bottom = + (blit_op->src.roi.height - 1) + 2; + er->luma_repeat_top = 1; + er->luma_repeat_bottom = 2; + } else { + er->luma_interp_point_top = -2; + er->luma_interp_point_bottom = + (blit_op->src.roi.height - 1) + 2; + er->luma_repeat_top = 2; + er->luma_repeat_bottom = 2; + } + } else { + /* + * Since no scaling needed, Tile Fetch does not require any + * more luma pixel than what the ROI contains. + */ + er->luma_interp_point_right = + (int32_t) (blit_op->src.roi.width - 1); + er->luma_interp_point_bottom = + (int32_t) (blit_op->src.roi.height - 1); + } + /* After adding the ROI offsets, we have locations of + * luma_interp_points relative to the image. + */ + er->luma_interp_point_left += (int32_t) (blit_op->src.roi.x); + er->luma_interp_point_right += (int32_t) (blit_op->src.roi.x); + er->luma_interp_point_top += (int32_t) (blit_op->src.roi.y); + er->luma_interp_point_bottom += (int32_t) (blit_op->src.roi.y); +} + +void ppp_edge_rep_chroma_pixel(struct ppp_blit_op *blit_op, + struct ppp_edge_rep *er) +{ + bool chroma_edge_enable = true; + uint32_t is_yuv_offsite_vertical = 0; + + /* find out which chroma pixels are needed for chroma upsampling. */ + switch (blit_op->src.color_fmt) { + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + er->chroma_interp_point_left = er->luma_interp_point_left >> 1; + er->chroma_interp_point_right = + (er->luma_interp_point_right + 1) >> 1; + er->chroma_interp_point_top = er->luma_interp_point_top; + er->chroma_interp_point_bottom = er->luma_interp_point_bottom; + break; + + case MDP_Y_CBCR_H2V2: + case MDP_Y_CBCR_H2V2_ADRENO: + case MDP_Y_CRCB_H2V2: + er->chroma_interp_point_left = er->luma_interp_point_left >> 1; + er->chroma_interp_point_right = + (er->luma_interp_point_right + 1) >> 1; + er->chroma_interp_point_top = + (er->luma_interp_point_top - 1) >> 1; + er->chroma_interp_point_bottom = + (er->luma_interp_point_bottom + 1) >> 1; + is_yuv_offsite_vertical = 1; + break; + + default: + chroma_edge_enable = false; + er->chroma_interp_point_left = er->luma_interp_point_left; + er->chroma_interp_point_right = er->luma_interp_point_right; + er->chroma_interp_point_top = er->luma_interp_point_top; + er->chroma_interp_point_bottom = er->luma_interp_point_bottom; + + break; + } + + if (chroma_edge_enable) { + /* Defines which chroma pixels belongs to the roi */ + switch (blit_op->src.color_fmt) { + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + er->chroma_bound_left = blit_op->src.roi.x / 2; + /* there are half as many chroma pixel as luma pixels */ + er->chroma_bound_right = + (blit_op->src.roi.width + + blit_op->src.roi.x - 1) / 2; + er->chroma_bound_top = blit_op->src.roi.y; + er->chroma_bound_bottom = + (blit_op->src.roi.height + blit_op->src.roi.y - 1); + break; + case MDP_Y_CBCR_H2V2: + case MDP_Y_CBCR_H2V2_ADRENO: + case MDP_Y_CRCB_H2V2: + /* + * cosite in horizontal dir, and offsite in vertical dir + * width of chroma ROI is 1/2 of size of luma ROI + * height of chroma ROI is 1/2 of size of luma ROI + */ + er->chroma_bound_left = blit_op->src.roi.x / 2; + er->chroma_bound_right = + (blit_op->src.roi.width + + blit_op->src.roi.x - 1) / 2; + er->chroma_bound_top = blit_op->src.roi.y / 2; + er->chroma_bound_bottom = + (blit_op->src.roi.height + + blit_op->src.roi.y - 1) / 2; + break; + + default: + /* + * If no valid chroma sub-sampling format specified, + * assume 4:4:4 ( i.e. fully sampled). + */ + er->chroma_bound_left = blit_op->src.roi.x; + er->chroma_bound_right = blit_op->src.roi.width + + blit_op->src.roi.x - 1; + er->chroma_bound_top = blit_op->src.roi.y; + er->chroma_bound_bottom = + (blit_op->src.roi.height + blit_op->src.roi.y - 1); + break; + } + + /* + * Knowing which chroma pixels are needed, and which chroma + * pixels belong to the ROI (i.e. available for fetching ), + * calculate how many chroma pixels Tile Fetch needs to + * duplicate. If any required chroma pixels falls outside + * of the ROI, Tile Fetch must obtain them by replicating + * pixels. + */ + if (er->chroma_bound_left > er->chroma_interp_point_left) + er->chroma_repeat_left = + er->chroma_bound_left - + er->chroma_interp_point_left; + else + er->chroma_repeat_left = 0; + + if (er->chroma_interp_point_right > er->chroma_bound_right) + er->chroma_repeat_right = + er->chroma_interp_point_right - + er->chroma_bound_right; + else + er->chroma_repeat_right = 0; + + if (er->chroma_bound_top > er->chroma_interp_point_top) + er->chroma_repeat_top = + er->chroma_bound_top - + er->chroma_interp_point_top; + else + er->chroma_repeat_top = 0; + + if (er->chroma_interp_point_bottom > er->chroma_bound_bottom) + er->chroma_repeat_bottom = + er->chroma_interp_point_bottom - + er->chroma_bound_bottom; + else + er->chroma_repeat_bottom = 0; + + if (er->is_scale_enabled && (blit_op->src.roi.height == 1) + && is_yuv_offsite_vertical) { + er->chroma_repeat_bottom = 3; + er->chroma_repeat_top = 0; + } + } +} + +int config_ppp_edge_rep(struct ppp_blit_op *blit_op) +{ + uint32_t reg = 0; + struct ppp_edge_rep er; + + memset(&er, 0, sizeof(er)); + + ppp_edge_rep_luma_pixel(blit_op, &er); + + /* + * After adding the ROI offsets, we have locations of + * chroma_interp_points relative to the image. + */ + er.chroma_interp_point_left = er.luma_interp_point_left; + er.chroma_interp_point_right = er.luma_interp_point_right; + er.chroma_interp_point_top = er.luma_interp_point_top; + er.chroma_interp_point_bottom = er.luma_interp_point_bottom; + + ppp_edge_rep_chroma_pixel(blit_op, &er); + /* ensure repeats are >=0 and no larger than 3 pixels */ + if ((er.chroma_repeat_left < 0) || (er.chroma_repeat_right < 0) || + (er.chroma_repeat_top < 0) || (er.chroma_repeat_bottom < 0)) + return -EINVAL; + if ((er.chroma_repeat_left > 3) || (er.chroma_repeat_right > 3) || + (er.chroma_repeat_top > 3) || (er.chroma_repeat_bottom > 3)) + return -EINVAL; + if ((er.luma_repeat_left < 0) || (er.luma_repeat_right < 0) || + (er.luma_repeat_top < 0) || (er.luma_repeat_bottom < 0)) + return -EINVAL; + if ((er.luma_repeat_left > 3) || (er.luma_repeat_right > 3) || + (er.luma_repeat_top > 3) || (er.luma_repeat_bottom > 3)) + return -EINVAL; + + reg |= (er.chroma_repeat_left & 3) << MDP_LEFT_CHROMA; + reg |= (er.chroma_repeat_right & 3) << MDP_RIGHT_CHROMA; + reg |= (er.chroma_repeat_top & 3) << MDP_TOP_CHROMA; + reg |= (er.chroma_repeat_bottom & 3) << MDP_BOTTOM_CHROMA; + reg |= (er.luma_repeat_left & 3) << MDP_LEFT_LUMA; + reg |= (er.luma_repeat_right & 3) << MDP_RIGHT_LUMA; + reg |= (er.luma_repeat_top & 3) << MDP_TOP_LUMA; + reg |= (er.luma_repeat_bottom & 3) << MDP_BOTTOM_LUMA; + PPP_WRITEL(reg, MDP3_PPP_SRC_EDGE_REP); + return 0; +} + +int config_ppp_bg_edge_rep(struct ppp_blit_op *blit_op) +{ + uint32_t reg = 0; + + switch (blit_op->dst.color_fmt) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + if (blit_op->dst.roi.y == 0) + reg |= BIT(MDP_TOP_CHROMA); + + if ((blit_op->dst.roi.y + blit_op->dst.roi.height) == + blit_op->dst.prop.height) { + reg |= BIT(MDP_BOTTOM_CHROMA); + } + + if (((blit_op->dst.roi.x + blit_op->dst.roi.width) == + blit_op->dst.prop.width) && + ((blit_op->dst.roi.width % 2) == 0)) + reg |= BIT(MDP_RIGHT_CHROMA); + break; + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + if (((blit_op->dst.roi.x + blit_op->dst.roi.width) == + blit_op->dst.prop.width) && + ((blit_op->dst.roi.width % 2) == 0)) + reg |= BIT(MDP_RIGHT_CHROMA); + break; + default: + break; + } + PPP_WRITEL(reg, MDP3_PPP_BG_EDGE_REP); + return 0; +} + +int config_ppp_lut(uint32_t *pppop_reg_ptr, int lut_c0_en, + int lut_c1_en, int lut_c2_en) +{ + if (lut_c0_en) + *pppop_reg_ptr |= MDP_LUT_C0_EN; + if (lut_c1_en) + *pppop_reg_ptr |= MDP_LUT_C1_EN; + if (lut_c2_en) + *pppop_reg_ptr |= MDP_LUT_C2_EN; + return 0; +} + +int config_ppp_scale(struct ppp_blit_op *blit_op, uint32_t *pppop_reg_ptr) +{ + struct ppp_img_desc *src = &blit_op->src; + struct ppp_img_desc *dst = &blit_op->dst; + uint32_t dstW, dstH; + uint32_t x_fac, y_fac; + uint32_t mdp_blur = 0; + uint32_t phase_init_x, phase_init_y, phase_step_x, phase_step_y; + int x_idx, y_idx; + + if (blit_op->mdp_op & MDPOP_ASCALE) { + if (blit_op->mdp_op & MDPOP_ROT90) { + dstW = dst->roi.height; + dstH = dst->roi.width; + } else { + dstW = dst->roi.width; + dstH = dst->roi.height; + } + *pppop_reg_ptr |= + (PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON); + + mdp_blur = blit_op->mdp_op & MDPOP_BLUR; + + if ((dstW != src->roi.width) || + (dstH != src->roi.height) || mdp_blur) { + + mdp_calc_scale_params(blit_op->src.roi.x, + blit_op->src.roi.width, + dstW, 1, &phase_init_x, + &phase_step_x); + mdp_calc_scale_params(blit_op->src.roi.y, + blit_op->src.roi.height, + dstH, 0, &phase_init_y, + &phase_step_y); + + PPP_WRITEL(phase_init_x, MDP3_PPP_SCALE_PHASEX_INIT); + PPP_WRITEL(phase_init_y, MDP3_PPP_SCALE_PHASEY_INIT); + PPP_WRITEL(phase_step_x, MDP3_PPP_SCALE_PHASEX_STEP); + PPP_WRITEL(phase_step_y, MDP3_PPP_SCALE_PHASEY_STEP); + + + if (dstW > src->roi.width || dstW > src->roi.height) + ppp_load_up_lut(); + + if (mdp_blur) + ppp_load_gaussian_lut(); + + if (dstW <= src->roi.width) { + x_fac = (dstW * 100) / src->roi.width; + x_idx = scale_idx(x_fac); + ppp_load_x_scale_table(x_idx); + } + if (dstH <= src->roi.height) { + y_fac = (dstH * 100) / src->roi.height; + y_idx = scale_idx(y_fac); + ppp_load_y_scale_table(y_idx); + } + + } else { + blit_op->mdp_op &= ~(MDPOP_ASCALE); + } + } + config_ppp_edge_rep(blit_op); + config_ppp_bg_edge_rep(blit_op); + return 0; +} + +int config_ppp_csc(int src_color, int dst_color, uint32_t *pppop_reg_ptr) +{ + bool inputRGB, outputRGB; + + inputRGB = check_if_rgb(src_color); + outputRGB = check_if_rgb(dst_color); + + if ((!inputRGB) && (outputRGB)) + *pppop_reg_ptr |= PPP_OP_CONVERT_YCBCR2RGB | + PPP_OP_CONVERT_ON; + if ((inputRGB) && (!outputRGB)) + *pppop_reg_ptr |= PPP_OP_CONVERT_ON; + + return 0; +} + +int config_ppp_blend(struct ppp_blit_op *blit_op, + uint32_t *pppop_reg_ptr) +{ + struct ppp_csc_table *csc; + uint32_t alpha, trans_color; + uint32_t val = 0; + int c_fmt = blit_op->src.color_fmt; + int bg_alpha; + + csc = ppp_csc_rgb2yuv(); + alpha = blit_op->blend.const_alpha; + trans_color = blit_op->blend.trans_color; + if (blit_op->mdp_op & MDPOP_FG_PM_ALPHA) { + if (ppp_per_p_alpha(c_fmt)) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA; + } else { + if ((blit_op->mdp_op & MDPOP_ALPHAB) + && (blit_op->blend.const_alpha == 0xff)) { + blit_op->mdp_op &= ~(MDPOP_ALPHAB); + } + + if ((blit_op->mdp_op & MDPOP_ALPHAB) + || (blit_op->mdp_op & MDPOP_TRANSP)) { + + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL; + } + } + + bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL | + PPP_BLEND_BG_ALPHA_REVERSE; + + if ((ppp_per_p_alpha(c_fmt)) && !(blit_op->mdp_op & + MDPOP_LAYER_IS_FG)) { + bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA; + } else { + bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA; + bg_alpha |= blit_op->blend.const_alpha << 24; + } + PPP_WRITEL(bg_alpha, MDP3_PPP_BLEND_BG_ALPHA_SEL); + + if (blit_op->mdp_op & MDPOP_TRANSP) + *pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP; + } else if (ppp_per_p_alpha(c_fmt)) { + if (blit_op->mdp_op & MDPOP_LAYER_IS_FG) + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA; + else + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_SRCPIXEL_ALPHA; + PPP_WRITEL(0, MDP3_PPP_BLEND_BG_ALPHA_SEL); + } else { + if ((blit_op->mdp_op & MDPOP_ALPHAB) + && (blit_op->blend.const_alpha == 0xff)) { + blit_op->mdp_op &= + ~(MDPOP_ALPHAB); + } + + if ((blit_op->mdp_op & MDPOP_ALPHAB) + || (blit_op->mdp_op & MDPOP_TRANSP)) { + *pppop_reg_ptr |= PPP_OP_ROT_ON | + PPP_OP_BLEND_ON | + PPP_OP_BLEND_CONSTANT_ALPHA | + PPP_OP_BLEND_ALPHA_BLEND_NORMAL; + } + + if (blit_op->mdp_op & MDPOP_TRANSP) + *pppop_reg_ptr |= + PPP_BLEND_CALPHA_TRNASP; + PPP_WRITEL(0, MDP3_PPP_BLEND_BG_ALPHA_SEL); + } + + if (*pppop_reg_ptr & PPP_OP_BLEND_ON) { + blit_op->bg = blit_op->dst; + config_ppp_background(&blit_op->bg); + + if (blit_op->dst.color_fmt == MDP_YCRYCB_H2V1) { + *pppop_reg_ptr |= PPP_OP_BG_CHROMA_H2V1; + if (blit_op->mdp_op & MDPOP_TRANSP) { + trans_color = conv_rgb2yuv(trans_color, + &csc->fwd_matrix[0], + &csc->bv[0], + &csc->lv[0]); + } + } + } + val = (alpha << MDP_BLEND_CONST_ALPHA); + val |= (trans_color & MDP_BLEND_TRASP_COL_MASK); + PPP_WRITEL(val, MDP3_PPP_BLEND_PARAM); + return 0; +} + +int config_ppp_rotation(uint32_t mdp_op, uint32_t *pppop_reg_ptr) +{ + *pppop_reg_ptr |= PPP_OP_ROT_ON; + + if (mdp_op & MDPOP_ROT90) + *pppop_reg_ptr |= PPP_OP_ROT_90; + if (mdp_op & MDPOP_LR) + *pppop_reg_ptr |= PPP_OP_FLIP_LR; + if (mdp_op & MDPOP_UD) + *pppop_reg_ptr |= PPP_OP_FLIP_UD; + + return 0; +} + +int config_ppp_op_mode(struct ppp_blit_op *blit_op) +{ + uint32_t ppp_operation_reg = 0; + int sv_slice, sh_slice; + int dv_slice, dh_slice; + + sv_slice = sh_slice = dv_slice = dh_slice = 1; + + ppp_operation_reg |= ppp_dst_op_reg(blit_op->dst.color_fmt); + switch (blit_op->dst.color_fmt) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CRCB_H2V2: + y_h_even_num(&blit_op->dst); + y_h_even_num(&blit_op->src); + dv_slice = 2; + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + case MDP_YCRYCB_H2V1: + x_w_even_num(&blit_op->dst); + x_w_even_num(&blit_op->src); + dh_slice = 2; + break; + default: + break; + } + + ppp_operation_reg |= ppp_src_op_reg(blit_op->src.color_fmt); + switch (blit_op->src.color_fmt) { + case MDP_Y_CBCR_H2V2: + case MDP_Y_CBCR_H2V2_ADRENO: + case MDP_Y_CRCB_H2V2: + sh_slice = sv_slice = 2; + break; + case MDP_YCRYCB_H2V1: + x_w_even_num(&blit_op->dst); + x_w_even_num(&blit_op->src); + case MDP_Y_CBCR_H2V1: + case MDP_Y_CRCB_H2V1: + sh_slice = 2; + break; + default: + break; + } + + config_ppp_csc(blit_op->src.color_fmt, + blit_op->dst.color_fmt, &ppp_operation_reg); + + if (blit_op->mdp_op & MDPOP_DITHER) + ppp_operation_reg |= PPP_OP_DITHER_EN; + + if (blit_op->mdp_op & MDPOP_ROTATION) + config_ppp_rotation(blit_op->mdp_op, &ppp_operation_reg); + + if (blit_op->src.color_fmt == MDP_Y_CBCR_H2V2_ADRENO) { + blit_op->src.stride0 = ALIGN(blit_op->src.prop.width, 32) * + ppp_bpp(blit_op->src.color_fmt); + blit_op->src.stride1 = 2 * ALIGN(blit_op->src.prop.width/2, 32); + } else { + blit_op->src.stride0 = blit_op->src.prop.width * + ppp_bpp(blit_op->src.color_fmt); + blit_op->src.stride1 = blit_op->src.stride0; + } + + blit_op->dst.stride0 = blit_op->dst.prop.width * + ppp_bpp(blit_op->dst.color_fmt); + + if (ppp_multi_plane(blit_op->dst.color_fmt)) { + blit_op->dst.p1 = blit_op->dst.p0; + blit_op->dst.p1 += blit_op->dst.prop.width * + blit_op->dst.prop.height * + ppp_bpp(blit_op->dst.color_fmt); + } else { + blit_op->dst.p1 = NULL; + } + + /* Jumping from Y-Plane to Chroma Plane */ + /* first pixel addr calculation */ + mdp_adjust_start_addr(blit_op, &blit_op->src, sv_slice, sh_slice, 0); + mdp_adjust_start_addr(blit_op, &blit_op->dst, dv_slice, dh_slice, 2); + + config_ppp_scale(blit_op, &ppp_operation_reg); + + config_ppp_blend(blit_op, &ppp_operation_reg); + + config_ppp_src(&blit_op->src); + config_ppp_out(&blit_op->dst); + PPP_WRITEL(ppp_operation_reg, MDP3_PPP_OP_MODE); + mb(); + return 0; +} + +void ppp_enable(void) +{ + PPP_WRITEL(0x1000, 0x30); + mb(); +} + +int mdp3_ppp_init(void) +{ + load_ppp_lut(LUT_PRE_TABLE, ppp_default_pre_lut()); + load_ppp_lut(LUT_POST_TABLE, ppp_default_post_lut()); + load_csc_matrix(CSC_PRIMARY_MATRIX, ppp_csc_rgb2yuv()); + load_csc_matrix(CSC_SECONDARY_MATRIX, ppp_csc_table2()); + return 0; +} |
