summaryrefslogtreecommitdiff
path: root/drivers/staging/msm/mdp_ppp.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/staging/msm/mdp_ppp.c')
-rw-r--r--drivers/staging/msm/mdp_ppp.c1502
1 files changed, 1502 insertions, 0 deletions
diff --git a/drivers/staging/msm/mdp_ppp.c b/drivers/staging/msm/mdp_ppp.c
new file mode 100644
index 000000000000..c35a6aebca14
--- /dev/null
+++ b/drivers/staging/msm/mdp_ppp.c
@@ -0,0 +1,1502 @@
+/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
+ *
+ * Copyright (C) 2007 Google Incorporated
+ * Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
+ *
+ * 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/module.h>
+#include <linux/kernel.h>
+#include <linux/sched.h>
+#include <linux/time.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/fb.h>
+#include <msm_mdp.h>
+#include <linux/file.h>
+#include <linux/major.h>
+
+#include "linux/proc_fs.h"
+
+#include <mach/hardware.h>
+#include <linux/io.h>
+
+#include <asm/system.h>
+#include <asm/mach-types.h>
+#include <linux/semaphore.h>
+
+#include "mdp.h"
+#include "msm_fb.h"
+
+#define MDP_IS_IMGTYPE_BAD(x) (((x) >= MDP_IMGTYPE_LIMIT) && \
+ (((x) < MDP_IMGTYPE2_START) || \
+ ((x) >= MDP_IMGTYPE_LIMIT2)))
+
+static uint32_t bytes_per_pixel[] = {
+ [MDP_RGB_565] = 2,
+ [MDP_RGB_888] = 3,
+ [MDP_XRGB_8888] = 4,
+ [MDP_ARGB_8888] = 4,
+ [MDP_RGBA_8888] = 4,
+ [MDP_BGRA_8888] = 4,
+ [MDP_Y_CBCR_H2V1] = 1,
+ [MDP_Y_CBCR_H2V2] = 1,
+ [MDP_Y_CRCB_H2V1] = 1,
+ [MDP_Y_CRCB_H2V2] = 1,
+ [MDP_YCRYCB_H2V1] = 2,
+ [MDP_BGR_565] = 2
+};
+
+extern uint32 mdp_plv[];
+extern struct semaphore mdp_ppp_mutex;
+
+uint32_t mdp_get_bytes_per_pixel(uint32_t format)
+{
+ uint32_t bpp = 0;
+ if (format < ARRAY_SIZE(bytes_per_pixel))
+ bpp = bytes_per_pixel[format];
+
+ BUG_ON(!bpp);
+ return bpp;
+}
+
+static uint32 mdp_conv_matx_rgb2yuv(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector,
+ uint32 *look_up_table)
+{
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
+
+ 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 < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
+
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
+ else
+ _is_lookup_table_enabled = 1;
+
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+ }
+ /*
+ * 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 */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
+}
+
+uint32 mdp_conv_matx_yuv2rgb(uint32 input_pixel,
+ uint16 *matrix_and_bias_vector,
+ uint32 *clamp_vector, uint32 *look_up_table)
+{
+ uint8 input_C2, input_C0, input_C1;
+ uint32 output;
+ int32 comp_C2, comp_C1, comp_C0, temp;
+ int32 temp1, temp2, temp3;
+ int32 matrix[9];
+ int32 bias_vector[3];
+ int32 Y_low_limit, Y_high_limit, C_low_limit, C_high_limit;
+ int32 i;
+ uint32 _is_lookup_table_enabled;
+
+ 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 < 9; i++)
+ matrix[i] =
+ ((int32) (((int32) matrix_and_bias_vector[i]) << 20)) >> 20;
+
+ bias_vector[0] = (int32) (matrix_and_bias_vector[9] & 0xFF);
+ bias_vector[1] = (int32) (matrix_and_bias_vector[10] & 0xFF);
+ bias_vector[2] = (int32) (matrix_and_bias_vector[11] & 0xFF);
+
+ Y_low_limit = (int32) clamp_vector[0];
+ Y_high_limit = (int32) clamp_vector[1];
+ C_low_limit = (int32) clamp_vector[2];
+ C_high_limit = (int32) clamp_vector[3];
+
+ if (look_up_table == 0) /* check for NULL point */
+ _is_lookup_table_enabled = 0;
+ else
+ _is_lookup_table_enabled = 1;
+
+ /* clamp */
+ if (comp_C0 < Y_low_limit)
+ comp_C0 = Y_low_limit;
+
+ if (comp_C0 > Y_high_limit)
+ comp_C0 = Y_high_limit;
+
+ if (comp_C1 < C_low_limit)
+ comp_C1 = C_low_limit;
+
+ if (comp_C1 > C_high_limit)
+ comp_C1 = C_high_limit;
+
+ if (comp_C2 < C_low_limit)
+ comp_C2 = C_low_limit;
+
+ if (comp_C2 > C_high_limit)
+ comp_C2 = C_high_limit;
+
+ /*
+ * Color Conversion
+ * pre bias (-)
+ */
+ comp_C0 -= bias_vector[0];
+ comp_C1 -= bias_vector[1];
+ comp_C2 -= bias_vector[2];
+
+ /* 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;
+
+ /* reorder output colors */
+ temp = comp_C0;
+ comp_C0 = comp_C1;
+ comp_C1 = comp_C2;
+ comp_C2 = temp;
+
+ /* limit pixel to 8-bit */
+ if (comp_C0 < 0)
+ comp_C0 = 0;
+
+ if (comp_C0 > 255)
+ comp_C0 = 255;
+
+ if (comp_C1 < 0)
+ comp_C1 = 0;
+
+ if (comp_C1 > 255)
+ comp_C1 = 255;
+
+ if (comp_C2 < 0)
+ comp_C2 = 0;
+
+ if (comp_C2 > 255)
+ comp_C2 = 255;
+
+ /* Look-up table */
+ if (_is_lookup_table_enabled == 1) {
+ comp_C2 = (look_up_table[comp_C2] >> 16) & 0xFF;
+ comp_C1 = (look_up_table[comp_C1] >> 8) & 0xFF;
+ comp_C0 = (look_up_table[comp_C0] >> 0) & 0xFF;
+ }
+
+ output = (comp_C2 << 16) | (comp_C1 << 8) | comp_C0;
+ return output;
+}
+
+static uint32 mdp_calc_tpval(MDPIMG *mdpImg)
+{
+ uint32 tpVal;
+ uint8 plane_tp;
+
+ tpVal = 0;
+ if ((mdpImg->imgType == MDP_RGB_565)
+ || (mdpImg->imgType == MDP_BGR_565)) {
+ /*
+ * transparent color conversion into 24 bpp
+ *
+ * C2R_8BIT
+ * left shift the entire bit and or it with the upper most bits
+ */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0xF800) >> 11);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 16;
+
+ /* C1B_8BIT */
+ plane_tp = (uint8) (mdpImg->tpVal & 0x1F);
+ tpVal |= ((plane_tp << 3) | ((plane_tp & 0x1C) >> 2)) << 8;
+
+ /* C0G_8BIT */
+ plane_tp = (uint8) ((mdpImg->tpVal & 0x7E0) >> 5);
+ tpVal |= ((plane_tp << 2) | ((plane_tp & 0x30) >> 4));
+ } else {
+ /* 24bit RGB to RBG conversion */
+
+ tpVal = (mdpImg->tpVal & 0xFF00) >> 8;
+ tpVal |= (mdpImg->tpVal & 0xFF) << 8;
+ tpVal |= (mdpImg->tpVal & 0xFF0000);
+ }
+
+ return tpVal;
+}
+
+static uint8 *mdp_get_chroma_addr(MDPIBUF *iBuf)
+{
+ uint8 *dest1;
+
+ dest1 = NULL;
+ switch (iBuf->ibuf_type) {
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ dest1 = (uint8 *) iBuf->buf;
+ dest1 += iBuf->ibuf_width * iBuf->ibuf_height * iBuf->bpp;
+ break;
+
+ default:
+ break;
+ }
+
+ return dest1;
+}
+
+static void mdp_ppp_setbg(MDPIBUF *iBuf)
+{
+ uint8 *bg0_addr;
+ uint8 *bg1_addr;
+ uint32 bg0_ystride, bg1_ystride;
+ uint32 ppp_src_cfg_reg, unpack_pattern;
+ int v_slice, h_slice;
+
+ v_slice = h_slice = 1;
+ bg0_addr = (uint8 *) iBuf->buf;
+ bg1_addr = mdp_get_chroma_addr(iBuf);
+
+ bg0_ystride = iBuf->ibuf_width * iBuf->bpp;
+ bg1_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ switch (iBuf->ibuf_type) {
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ /* 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_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;
+
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+ break;
+
+ case MDP_RGB_888:
+ /*
+ * 888 = 3bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_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;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ case MDP_XRGB_8888:
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_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;
+
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_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;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ v_slice = h_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_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;
+
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ unpack_pattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ h_slice = 2;
+ break;
+
+ default:
+ return;
+ }
+
+ /* starting input address adjustment */
+ mdp_adjust_start_addr(&bg0_addr, &bg1_addr, v_slice, h_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 1);
+
+ /*
+ * 0x01c0: background plane 0 addr
+ * 0x01c4: background plane 1 addr
+ * 0x01c8: background plane 2 addr
+ * 0x01cc: bg y stride for plane 0 and 1
+ * 0x01d0: bg y stride for plane 2
+ * 0x01d4: bg src PPP config
+ * 0x01d8: unpack pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c0, bg0_addr);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01c4, bg1_addr);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01cc,
+ (bg1_ystride << 16) | bg0_ystride);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d4, ppp_src_cfg_reg);
+
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x01d8, unpack_pattern);
+}
+
+#define IS_PSEUDOPLNR(img) ((img == MDP_Y_CRCB_H2V2) | \
+ (img == MDP_Y_CBCR_H2V2) | \
+ (img == MDP_Y_CRCB_H2V1) | \
+ (img == MDP_Y_CBCR_H2V1))
+
+#define IMG_LEN(rect_h, w, rect_w, bpp) (((rect_h) * w) * bpp)
+
+#define Y_TO_CRCB_RATIO(format) \
+ ((format == MDP_Y_CBCR_H2V2 || format == MDP_Y_CRCB_H2V2) ? 2 :\
+ (format == MDP_Y_CBCR_H2V1 || format == MDP_Y_CRCB_H2V1) ? 1 : 1)
+
+static void get_len(struct mdp_img *img, struct mdp_rect *rect, uint32_t bpp,
+ uint32_t *len0, uint32_t *len1)
+{
+ *len0 = IMG_LEN(rect->h, img->width, rect->w, bpp);
+ if (IS_PSEUDOPLNR(img->format))
+ *len1 = *len0/Y_TO_CRCB_RATIO(img->format);
+ else
+ *len1 = 0;
+}
+
+static void flush_imgs(struct mdp_blit_req *req, int src_bpp, int dst_bpp,
+ struct file *p_src_file, struct file *p_dst_file)
+{
+#ifdef CONFIG_ANDROID_PMEM
+ uint32_t src0_len, src1_len, dst0_len, dst1_len;
+
+ /* flush src images to memory before dma to mdp */
+ get_len(&req->src, &req->src_rect, src_bpp,
+ &src0_len, &src1_len);
+
+ flush_pmem_file(p_src_file,
+ req->src.offset, src0_len);
+
+ if (IS_PSEUDOPLNR(req->src.format))
+ flush_pmem_file(p_src_file,
+ req->src.offset + src0_len, src1_len);
+
+ get_len(&req->dst, &req->dst_rect, dst_bpp, &dst0_len, &dst1_len);
+ flush_pmem_file(p_dst_file, req->dst.offset, dst0_len);
+
+ if (IS_PSEUDOPLNR(req->dst.format))
+ flush_pmem_file(p_dst_file,
+ req->dst.offset + dst0_len, dst1_len);
+#endif
+}
+
+static void mdp_start_ppp(struct msm_fb_data_type *mfd, MDPIBUF *iBuf,
+struct mdp_blit_req *req, struct file *p_src_file, struct file *p_dst_file)
+{
+ uint8 *src0, *src1;
+ uint8 *dest0, *dest1;
+ uint16 inpBpp;
+ uint32 dest0_ystride;
+ uint32 src_width;
+ uint32 src_height;
+ uint32 src0_ystride;
+ uint32 dst_roi_width;
+ uint32 dst_roi_height;
+ uint32 ppp_src_cfg_reg, ppp_operation_reg, ppp_dst_cfg_reg;
+ uint32 alpha, tpVal;
+ uint32 packPattern;
+ uint32 dst_packPattern;
+ boolean inputRGB, outputRGB, pseudoplanr_output;
+ int sv_slice, sh_slice;
+ int dv_slice, dh_slice;
+ boolean perPixelAlpha = FALSE;
+ boolean ppp_lookUp_enable = FALSE;
+
+ sv_slice = sh_slice = dv_slice = dh_slice = 1;
+ alpha = tpVal = 0;
+ src_width = iBuf->mdpImg.width;
+ src_height = iBuf->roi.y + iBuf->roi.height;
+ src1 = NULL;
+ dest1 = NULL;
+
+ inputRGB = outputRGB = TRUE;
+ pseudoplanr_output = FALSE;
+ ppp_operation_reg = 0;
+ ppp_dst_cfg_reg = 0;
+ ppp_src_cfg_reg = 0;
+
+ /* Wait for the pipe to clear */
+ do { } while (mdp_ppp_pipe_wait() <= 0);
+
+ /*
+ * destination config
+ */
+ switch (iBuf->ibuf_type) {
+ case MDP_RGB_888:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT | PPP_DST_C2R_8BIT |
+ 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;
+ break;
+
+ case MDP_XRGB_8888:
+ case MDP_ARGB_8888:
+ case MDP_RGBA_8888:
+ if (iBuf->ibuf_type == MDP_BGRA_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->ibuf_type == MDP_RGBA_8888)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C2R_8BIT |
+ PPP_DST_C3A_8BIT |
+ 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;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V2)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_420;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /*
+ * vertically (y direction) and horizontally (x direction)
+ * sample reduction by 2
+ */
+
+ /*
+ * H2V2(YUV420) Cosite
+ *
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ * Y Y Y Y
+ * CbCr CbCr
+ * Y Y Y Y
+ */
+ dv_slice = dh_slice = 2;
+
+ /* (x,y) and (width,height) must be even numbern */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ iBuf->roi.lcd_y = (iBuf->roi.lcd_y / 2) * 2;
+ iBuf->roi.dst_height = (iBuf->roi.dst_height / 2) * 2;
+ iBuf->roi.y = (iBuf->roi.y / 2) * 2;
+ iBuf->roi.height = (iBuf->roi.height / 2) * 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+ ppp_dst_cfg_reg =
+ PPP_DST_C2R_8BIT | PPP_DST_C0G_8BIT | PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT | 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;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ /*
+ * horizontally (x direction) sample reduction by 2
+ *
+ * H2V1(YUV422) Cosite
+ *
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ * YCbCr Y YCbCr Y
+ */
+ dh_slice = 2;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded gamma setting of 2.2 when the content is
+ * non-linear ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ if (iBuf->ibuf_type == MDP_Y_CBCR_H2V1)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C2R_8BIT |
+ PPP_DST_C0G_8BIT |
+ PPP_DST_C1B_8BIT |
+ PPP_DST_C3A_8BIT |
+ PPP_DST_PACKET_CNT_INTERLVD_2ELEM |
+ PPP_DST_PACK_TIGHT |
+ PPP_DST_PACK_ALIGN_LSB |
+ PPP_DST_OUT_SEL_AXI | PPP_DST_BPP_2BYTES;
+
+ ppp_operation_reg |= PPP_OP_DST_CHROMA_H2V1;
+ outputRGB = FALSE;
+ pseudoplanr_output = TRUE;
+ /* horizontally (x direction) sample reduction by 2 */
+ dh_slice = 2;
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ if (iBuf->ibuf_type == MDP_RGB_565)
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ dst_packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_dst_cfg_reg = PPP_DST_C0G_6BIT |
+ PPP_DST_C1B_5BIT |
+ PPP_DST_C2R_5BIT |
+ 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;
+ break;
+ }
+
+ /* source config */
+ switch (iBuf->mdpImg.imgType) {
+ case MDP_RGB_888:
+ inpBpp = 3;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_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;
+
+ packPattern = MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_BGRA_8888:
+ case MDP_RGBA_8888:
+ case MDP_ARGB_8888:
+ perPixelAlpha = TRUE;
+ case MDP_XRGB_8888:
+ inpBpp = 4;
+ /*
+ * 8888 = 4bytes
+ * ARGB = 4Components
+ * ARGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS | PPP_SRC_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;
+
+ if (iBuf->mdpImg.imgType == MDP_BGRA_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+ else if (iBuf->mdpImg.imgType == MDP_RGBA_8888)
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
+ 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
+ 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ case MDP_Y_CBCR_H2V2:
+ case MDP_Y_CRCB_H2V2:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ /*
+ * CbCr = 2bytes
+ * CbCr = 2Components
+ * Y+CbCr
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS | PPP_SRC_C0G_8BITS |
+ PPP_SRC_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;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CRCB_H2V2)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_YCBCR |
+ PPP_OP_SRC_CHROMA_420 |
+ PPP_OP_SRC_CHROMA_COSITE |
+ PPP_OP_DST_CHROMA_RGB | PPP_OP_DST_CHROMA_COSITE;
+
+ inputRGB = FALSE;
+ sh_slice = sv_slice = 2;
+ break;
+
+ case MDP_YCRYCB_H2V1:
+ inpBpp = 2;
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_C3A_8BITS |
+ PPP_SRC_BPP_INTERLVD_2BYTES |
+ PPP_SRC_INTERLVD_4COMPONENTS |
+ PPP_SRC_UNPACK_TIGHT | PPP_SRC_UNPACK_ALIGN_LSB;
+
+ packPattern =
+ MDP_GET_PACK_PATTERN(CLR_Y, CLR_CR, CLR_Y, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+
+ /*
+ * if it's TV-Out/MDP_YCRYCB_H2V1, let's go through the
+ * preloaded inverse gamma setting of 2.2 since they're
+ * symetric when the content is non-linear
+ * ppp_lookUp_enable = TRUE;
+ */
+
+ /* x and width must be even number */
+ iBuf->roi.lcd_x = (iBuf->roi.lcd_x / 2) * 2;
+ iBuf->roi.dst_width = (iBuf->roi.dst_width / 2) * 2;
+ iBuf->roi.x = (iBuf->roi.x / 2) * 2;
+ iBuf->roi.width = (iBuf->roi.width / 2) * 2;
+
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_Y_CBCR_H2V1:
+ case MDP_Y_CRCB_H2V1:
+ inpBpp = 1;
+ src1 = (uint8 *) iBuf->mdpImg.cbcr_addr;
+
+ ppp_src_cfg_reg = PPP_SRC_C2R_8BITS |
+ PPP_SRC_C0G_8BITS |
+ PPP_SRC_C1B_8BITS |
+ PPP_SRC_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;
+
+ if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V1)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CB, CLR_CR, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, 0, CLR_CR, CLR_CB, 8);
+
+ ppp_operation_reg |= PPP_OP_SRC_CHROMA_H2V1 |
+ PPP_OP_SRC_CHROMA_COSITE | PPP_OP_DST_CHROMA_COSITE;
+ inputRGB = FALSE;
+ sh_slice = 2;
+ break;
+
+ case MDP_BGR_565:
+ case MDP_RGB_565:
+ default:
+ inpBpp = 2;
+ /*
+ * 565 = 2bytes
+ * RGB = 3Components
+ * RGB interleaved
+ */
+ ppp_src_cfg_reg = PPP_SRC_C2R_5BITS | PPP_SRC_C0G_6BITS |
+ PPP_SRC_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;
+
+ if (iBuf->mdpImg.imgType == MDP_RGB_565)
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_R, CLR_G, CLR_B, 8);
+ else
+ packPattern =
+ MDP_GET_PACK_PATTERN(0, CLR_B, CLR_G, CLR_R, 8);
+
+ ppp_operation_reg |= PPP_OP_COLOR_SPACE_RGB |
+ PPP_OP_SRC_CHROMA_RGB | PPP_OP_DST_CHROMA_RGB;
+ break;
+
+ }
+
+ if (pseudoplanr_output)
+ ppp_dst_cfg_reg |= PPP_DST_PLANE_PSEUDOPLN;
+
+ /* YCbCr to RGB color conversion flag */
+ if ((!inputRGB) && (outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_YCBCR2RGB |
+ PPP_OP_CONVERT_ON;
+
+ /*
+ * primary/secondary is sort of misleading term...but
+ * in mdp2.2/3.0 we only use primary matrix (forward/rev)
+ * in mdp3.1 we use set1(prim) and set2(secd)
+ */
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_SECONDARY |
+ PPP_OP_DST_RGB;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+ }
+ }
+ /* RGB to YCbCr color conversion flag */
+ if ((inputRGB) && (!outputRGB)) {
+ ppp_operation_reg |= PPP_OP_CONVERT_RGB2YCBCR |
+ PPP_OP_CONVERT_ON;
+
+#ifdef CONFIG_FB_MSM_MDP31
+ ppp_operation_reg |= PPP_OP_CONVERT_MATRIX_PRIMARY |
+ PPP_OP_DST_YCBCR;
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0240, 0x1e);
+#endif
+
+ if (ppp_lookUp_enable) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON |
+ PPP_OP_LUT_C1_ON | PPP_OP_LUT_C2_ON;
+ }
+ }
+ /* YCbCr to YCbCr color conversion flag */
+ if ((!inputRGB) && (!outputRGB)) {
+ if ((ppp_lookUp_enable) &&
+ (iBuf->mdpImg.imgType != iBuf->ibuf_type)) {
+ ppp_operation_reg |= PPP_OP_LUT_C0_ON;
+ }
+ }
+
+ ppp_src_cfg_reg |= (iBuf->roi.x % 2) ? PPP_SRC_BPP_ROI_ODD_X : 0;
+ ppp_src_cfg_reg |= (iBuf->roi.y % 2) ? PPP_SRC_BPP_ROI_ODD_Y : 0;
+
+ if (req->flags & MDP_DEINTERLACE)
+ ppp_operation_reg |= PPP_OP_DEINT_EN;
+
+ /* Dither at DMA side only since iBuf format is RGB888 */
+ if (iBuf->mdpImg.mdpOp & MDPOP_DITHER)
+ ppp_operation_reg |= PPP_OP_DITHER_EN;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROTATION) {
+ ppp_operation_reg |= PPP_OP_ROT_ON;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
+ ppp_operation_reg |= PPP_OP_ROT_90;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_LR) {
+ ppp_operation_reg |= PPP_OP_FLIP_LR;
+ }
+ if (iBuf->mdpImg.mdpOp & MDPOP_UD) {
+ ppp_operation_reg |= PPP_OP_FLIP_UD;
+ }
+ }
+
+ src0_ystride = src_width * inpBpp;
+ dest0_ystride = iBuf->ibuf_width * iBuf->bpp;
+
+ /* no need to care about rotation since it's the real-XY. */
+ dst_roi_width = iBuf->roi.dst_width;
+ dst_roi_height = iBuf->roi.dst_height;
+
+ src0 = (uint8 *) iBuf->mdpImg.bmy_addr;
+ dest0 = (uint8 *) iBuf->buf;
+
+ /* Jumping from Y-Plane to Chroma Plane */
+ dest1 = mdp_get_chroma_addr(iBuf);
+
+ /* first pixel addr calculation */
+ mdp_adjust_start_addr(&src0, &src1, sv_slice, sh_slice, iBuf->roi.x,
+ iBuf->roi.y, src_width, src_height, inpBpp, iBuf,
+ 0);
+ mdp_adjust_start_addr(&dest0, &dest1, dv_slice, dh_slice,
+ iBuf->roi.lcd_x, iBuf->roi.lcd_y,
+ iBuf->ibuf_width, iBuf->ibuf_height, iBuf->bpp,
+ iBuf, 2);
+
+ /* set scale operation */
+ mdp_set_scale(iBuf, dst_roi_width, dst_roi_height,
+ inputRGB, outputRGB, &ppp_operation_reg);
+
+ /*
+ * setting background source for blending
+ */
+ mdp_set_blend_attr(iBuf, &alpha, &tpVal, perPixelAlpha,
+ &ppp_operation_reg);
+
+ if (ppp_operation_reg & PPP_OP_BLEND_ON) {
+ mdp_ppp_setbg(iBuf);
+
+ if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
+ ppp_operation_reg |= PPP_OP_BG_CHROMA_H2V1;
+
+ if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP) {
+ tpVal = mdp_conv_matx_rgb2yuv(tpVal,
+ (uint16 *) &
+ mdp_ccs_rgb2yuv,
+ &mdp_plv[0], NULL);
+ }
+ }
+ }
+
+ /*
+ * 0x0004: enable dbg bus
+ * 0x0100: "don't care" Edge Condit until scaling is on
+ * 0x0104: xrc tile x&y size u7.6 format = 7bit.6bit
+ * 0x0108: src pixel size
+ * 0x010c: component plane 0 starting address
+ * 0x011c: component plane 0 ystride
+ * 0x0124: PPP source config register
+ * 0x0128: unpacked pattern from lsb to msb (eg. RGB->BGR)
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0108, (iBuf->roi.height << 16 |
+ iBuf->roi.width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x010c, src0); /* comp.plane 0 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0110, src1); /* comp.plane 1 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x011c,
+ (src0_ystride << 16 | src0_ystride));
+
+ /* setup for rgb 565 */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0124, ppp_src_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0128, packPattern);
+ /*
+ * 0x0138: PPP destination operation register
+ * 0x014c: constant_alpha|transparent_color
+ * 0x0150: PPP destination config register
+ * 0x0154: PPP packing pattern
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0138, ppp_operation_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x014c, alpha << 24 | tpVal);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0150, ppp_dst_cfg_reg);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0154, dst_packPattern);
+
+ /*
+ * 0x0164: ROI height and width
+ * 0x0168: Component Plane 0 starting addr
+ * 0x016c: Component Plane 1 starting addr
+ * 0x0178: Component Plane 1/0 y stride
+ */
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0164,
+ (dst_roi_height << 16 | dst_roi_width));
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0168, dest0);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x016c, dest1);
+ MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0178,
+ (dest0_ystride << 16 | dest0_ystride));
+
+ flush_imgs(req, inpBpp, iBuf->bpp, p_src_file, p_dst_file);
+#ifdef CONFIG_MDP_PPP_ASYNC_OP
+ mdp_ppp_process_curr_djob();
+#else
+ mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
+#endif
+}
+
+static int mdp_ppp_verify_req(struct mdp_blit_req *req)
+{
+ u32 src_width, src_height, dst_width, dst_height;
+
+ if (req == NULL)
+ return -1;
+
+ if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
+ MDP_IS_IMGTYPE_BAD(req->dst.format))
+ return -1;
+
+ 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))
+
+ return -1;
+
+ if (((req->src_rect.x + req->src_rect.w) > req->src.width) ||
+ ((req->src_rect.y + req->src_rect.h) > req->src.height))
+ return -1;
+
+ if (((req->dst_rect.x + req->dst_rect.w) > req->dst.width) ||
+ ((req->dst_rect.y + req->dst_rect.h) > req->dst.height))
+ return -1;
+
+ /*
+ * scaling range check
+ */
+ 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 = (src_width / 2) * 2;
+ dst_height = (src_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 = (src_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))
+ return -1;
+
+ 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))
+ return -1;
+
+ return 0;
+}
+
+/**
+ * get_gem_img() - retrieve drm obj's start address and size
+ * @img: contains drm file descriptor and gem handle
+ * @start: repository of starting address of drm obj allocated memory
+ * @len: repository of size of drm obj alloacted memory
+ *
+ **/
+int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
+{
+ panic("waaaaaaaah");
+ //return kgsl_gem_obj_addr(img->memory_id, (int)img->priv, start, len);
+}
+
+int get_img(struct mdp_img *img, struct fb_info *info, unsigned long *start,
+ unsigned long *len, struct file **pp_file)
+{
+ int put_needed, ret = 0;
+ struct file *file;
+ unsigned long vstart;
+#ifdef CONFIG_ANDROID_PMEM
+ if (!get_pmem_file(img->memory_id, start, &vstart, len, pp_file))
+ return 0;
+#endif
+ file = fget_light(img->memory_id, &put_needed);
+ if (file == NULL)
+ return -1;
+
+ if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
+ *start = info->fix.smem_start;
+ *len = info->fix.smem_len;
+ *pp_file = file;
+ } else {
+ ret = -1;
+ fput_light(file, put_needed);
+ }
+ return ret;
+}
+
+int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req,
+ struct file **pp_src_file, struct file **pp_dst_file)
+{
+ unsigned long src_start, dst_start;
+ unsigned long src_len = 0;
+ unsigned long dst_len = 0;
+ MDPIBUF iBuf;
+ u32 dst_width, dst_height;
+ struct file *p_src_file = 0 , *p_dst_file = 0;
+ struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
+
+ 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 (req->flags & MDP_BLIT_SRC_GEM) {
+ if (get_gem_img(&req->src, &src_start, &src_len) < 0)
+ return -1;
+ } else {
+ get_img(&req->src, info, &src_start, &src_len, &p_src_file);
+ }
+ if (src_len == 0) {
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+
+ if (req->flags & MDP_BLIT_DST_GEM) {
+ if (get_gem_img(&req->dst, &dst_start, &dst_len) < 0)
+ return -1;
+ } else {
+ get_img(&req->dst, info, &dst_start, &dst_len, &p_dst_file);
+ }
+ if (dst_len == 0) {
+ printk(KERN_ERR "mdp_ppp: could not retrieve image from "
+ "memory\n");
+ return -1;
+ }
+ *pp_src_file = p_src_file;
+ *pp_dst_file = p_dst_file;
+ if (mdp_ppp_verify_req(req)) {
+ printk(KERN_ERR "mdp_ppp: invalid image!\n");
+ return -1;
+ }
+
+ iBuf.ibuf_width = req->dst.width;
+ iBuf.ibuf_height = req->dst.height;
+ iBuf.bpp = bytes_per_pixel[req->dst.format];
+
+ iBuf.ibuf_type = req->dst.format;
+ iBuf.buf = (uint8 *) dst_start;
+ iBuf.buf += req->dst.offset;
+
+ iBuf.roi.lcd_x = req->dst_rect.x;
+ iBuf.roi.lcd_y = req->dst_rect.y;
+ iBuf.roi.dst_width = req->dst_rect.w;
+ iBuf.roi.dst_height = req->dst_rect.h;
+
+ iBuf.roi.x = req->src_rect.x;
+ iBuf.roi.width = req->src_rect.w;
+ iBuf.roi.y = req->src_rect.y;
+ iBuf.roi.height = req->src_rect.h;
+
+ iBuf.mdpImg.width = req->src.width;
+ iBuf.mdpImg.imgType = req->src.format;
+
+ iBuf.mdpImg.bmy_addr = (uint32 *) (src_start + req->src.offset);
+ iBuf.mdpImg.cbcr_addr =
+ (uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
+ req->src.width * req->src.height);
+
+ iBuf.mdpImg.mdpOp = MDPOP_NOP;
+
+ /* blending check */
+ if (req->transp_mask != MDP_TRANSP_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_TRANSP;
+ iBuf.mdpImg.tpVal = req->transp_mask;
+ iBuf.mdpImg.tpVal = mdp_calc_tpval(&iBuf.mdpImg);
+ }
+
+ req->alpha &= 0xff;
+ if (req->alpha < MDP_ALPHA_NOP) {
+ iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
+ iBuf.mdpImg.alpha = req->alpha;
+ }
+
+ /* rotation check */
+ if (req->flags & MDP_FLIP_LR)
+ iBuf.mdpImg.mdpOp |= MDPOP_LR;
+ if (req->flags & MDP_FLIP_UD)
+ iBuf.mdpImg.mdpOp |= MDPOP_UD;
+ if (req->flags & MDP_ROT_90)
+ iBuf.mdpImg.mdpOp |= MDPOP_ROT90;
+ if (req->flags & MDP_DITHER)
+ iBuf.mdpImg.mdpOp |= MDPOP_DITHER;
+
+ if (req->flags & MDP_BLEND_FG_PREMULT) {
+#ifdef CONFIG_FB_MSM_MDP31
+ iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
+#else
+ return -EINVAL;
+#endif
+ }
+
+ if (req->flags & MDP_DEINTERLACE) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->src.format != MDP_Y_CBCR_H2V2) &&
+ (req->src.format != MDP_Y_CRCB_H2V2))
+#endif
+ return -EINVAL;
+ }
+
+ /* 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 ((iBuf.roi.width != dst_width) || (iBuf.roi.height != dst_height))
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE;
+
+ if (req->flags & MDP_BLUR) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if (req->flags & MDP_SHARPENING)
+ printk(KERN_WARNING
+ "mdp: MDP_SHARPENING is set with MDP_BLUR!\n");
+ req->flags |= MDP_SHARPENING;
+ req->sharpening_strength = -127;
+#else
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_BLUR;
+
+#endif
+ }
+
+ if (req->flags & MDP_SHARPENING) {
+#ifdef CONFIG_FB_MSM_MDP31
+ if ((req->sharpening_strength > 127) ||
+ (req->sharpening_strength < -127)) {
+ printk(KERN_ERR
+ "%s: sharpening strength out of range\n",
+ __func__);
+ return -EINVAL;
+ }
+
+ iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
+ iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
+#else
+ return -EINVAL;
+#endif
+ }
+
+ down(&mdp_ppp_mutex);
+ /* MDP cmd block enable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
+
+#ifdef CONFIG_FB_MSM_MDP31
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+#else
+ /* bg tile fetching HW workaround */
+ if (((iBuf.mdpImg.mdpOp & (MDPOP_TRANSP | MDPOP_ALPHAB)) ||
+ (req->src.format == MDP_ARGB_8888) ||
+ (req->src.format == MDP_BGRA_8888) ||
+ (req->src.format == MDP_RGBA_8888)) &&
+ (iBuf.mdpImg.mdpOp & MDPOP_ROT90) && (req->dst_rect.w <= 16)) {
+ int dst_h, src_w, i;
+
+ src_w = req->src_rect.w;
+ dst_h = iBuf.roi.dst_height;
+
+ for (i = 0; i < (req->dst_rect.h / 16); i++) {
+ /* this tile size */
+ iBuf.roi.dst_height = 16;
+ iBuf.roi.width =
+ (16 * req->src_rect.w) / req->dst_rect.h;
+
+ /* if it's out of scale range... */
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR;
+ else if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR)
+ iBuf.roi.width =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR;
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+
+ /* next tile location */
+ iBuf.roi.lcd_y += 16;
+ iBuf.roi.x += iBuf.roi.width;
+
+ /* this is for a remainder update */
+ dst_h -= 16;
+ src_w -= iBuf.roi.width;
+ }
+
+ if ((dst_h < 0) || (src_w < 0))
+ printk
+ ("msm_fb: mdp_blt_ex() unexpected result! line:%d\n",
+ __LINE__);
+
+ /* remainder update */
+ if ((dst_h > 0) && (src_w > 0)) {
+ u32 tmp_v;
+
+ iBuf.roi.dst_height = dst_h;
+ iBuf.roi.width = src_w;
+
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) > MDP_MAX_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MAX_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MAX_X_SCALE_FACTOR ? 1 : 0;
+
+ /* move x location as roi width gets bigger */
+ iBuf.roi.x -= tmp_v - iBuf.roi.width;
+ iBuf.roi.width = tmp_v;
+ } else
+ if (((MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ iBuf.roi.width) < MDP_MIN_X_SCALE_FACTOR) {
+ tmp_v =
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) /
+ MDP_MIN_X_SCALE_FACTOR +
+ (MDP_SCALE_Q_FACTOR * iBuf.roi.dst_height) %
+ MDP_MIN_X_SCALE_FACTOR ? 1 : 0;
+
+ /*
+ * we don't move x location for continuity of
+ * source image
+ */
+ iBuf.roi.width = tmp_v;
+ }
+
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+ } else {
+ mdp_start_ppp(mfd, &iBuf, req, p_src_file, p_dst_file);
+ }
+#endif
+
+ /* MDP cmd block disable */
+ mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_OFF, FALSE);
+ up(&mdp_ppp_mutex);
+
+ return 0;
+}