Archived
14
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
linux-2.6/drivers/staging/msm/mdp_ppp.c
Stepan Moskovchenko 9d20015391 Staging: add MSM framebuffer driver
Qualcomm development of the MSM SOC framebuffer driver has
diverged significantly from the driver used by Android. This
is a snapshot of our current driver, in all it's agony. We are
putting this in staging to help with the process of converging
the two drivers.

At this point, the driver has been tested only in dumb
framebuffer mode.

Signed-off-by: Stepan Moskovchenko <stepanm@codeaurora.org>
Signed-off-by: David Brown <davidb@codeaurora.org>
Signed-off-by: Abhijeet Dharmapurikar <adharmap@codeaurora.org>
[dwalker@codeaurora.org: added a small compile fix and TODO.]
Signed-off-by: Daniel Walker <dwalker@codeaurora.org>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
2010-06-04 13:38:54 -07:00

1503 lines
39 KiB
C

/* 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;
}