1713 lines
45 KiB
C
1713 lines
45 KiB
C
|
/* drivers/video/msm/src/drv/mdp/mdp_ppp.c
|
||
|
*
|
||
|
* Copyright (C) 2007 Google Incorporated
|
||
|
* Copyright (c) 2008-2009, 2012 The Linux Foundation. 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 <linux/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 <linux/msm_kgsl.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_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,
|
||
|
[MDP_BGR_565] = 2
|
||
|
};
|
||
|
|
||
|
extern uint32 mdp_plv[];
|
||
|
extern struct semaphore mdp_ppp_mutex;
|
||
|
static struct ion_client *ppp_display_iclient;
|
||
|
|
||
|
int mdp_get_bytes_per_pixel(uint32_t format,
|
||
|
struct msm_fb_data_type *mfd)
|
||
|
{
|
||
|
int bpp = -EINVAL;
|
||
|
if (format == MDP_FB_FORMAT)
|
||
|
format = mfd->fb_imgType;
|
||
|
if (format < ARRAY_SIZE(bytes_per_pixel))
|
||
|
bpp = bytes_per_pixel[format];
|
||
|
|
||
|
if (bpp <= 0)
|
||
|
printk(KERN_ERR "%s incorrect format %d\n", __func__, format);
|
||
|
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:
|
||
|
case MDP_RGBX_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 ||
|
||
|
iBuf->ibuf_type == MDP_RGBX_8888)
|
||
|
unpack_pattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
|
||
|
8);
|
||
|
else if (iBuf->ibuf_type == MDP_XRGB_8888)
|
||
|
unpack_pattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
|
||
|
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_CBCR_H2V2_ADRENO) | \
|
||
|
(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_CBCR_H2V2_ADRENO || \
|
||
|
format == MDP_Y_CRCB_H2V2) ? 2 : (format == MDP_Y_CBCR_H2V1 || \
|
||
|
format == MDP_Y_CRCB_H2V1) ? 1 : 1)
|
||
|
|
||
|
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) { }
|
||
|
|
||
|
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 src0_y1stride;
|
||
|
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_BGRA_8888:
|
||
|
case MDP_XRGB_8888:
|
||
|
case MDP_ARGB_8888:
|
||
|
case MDP_RGBA_8888:
|
||
|
case MDP_RGBX_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 ||
|
||
|
iBuf->ibuf_type == MDP_RGBX_8888)
|
||
|
dst_packPattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
|
||
|
8);
|
||
|
else if (iBuf->ibuf_type == MDP_XRGB_8888)
|
||
|
dst_packPattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
|
||
|
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:
|
||
|
case MDP_RGBX_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 ||
|
||
|
iBuf->mdpImg.imgType == MDP_RGBX_8888)
|
||
|
packPattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_B, CLR_G, CLR_R,
|
||
|
8);
|
||
|
else if (iBuf->ibuf_type == MDP_XRGB_8888)
|
||
|
packPattern =
|
||
|
MDP_GET_PACK_PATTERN(CLR_ALPHA, CLR_R, CLR_G, CLR_B,
|
||
|
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_CBCR_H2V2_ADRENO:
|
||
|
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;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
|
||
|
src0_ystride = ALIGN(src_width, 32) * inpBpp;
|
||
|
else
|
||
|
src0_ystride = src_width * inpBpp;
|
||
|
|
||
|
if (iBuf->mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
|
||
|
src0_y1stride = 2 * ALIGN(src_width/2, 32);
|
||
|
else
|
||
|
src0_y1stride = src0_ystride;
|
||
|
|
||
|
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_y1stride << 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 &
|
||
|
0xffffff));
|
||
|
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_FB_MSM_MDP31
|
||
|
MDP_OUTP(MDP_BASE + 0x00100, 0xFF00);
|
||
|
#endif
|
||
|
mdp_pipe_kickoff(MDP_PPP_TERM, mfd);
|
||
|
}
|
||
|
|
||
|
static int mdp_ppp_verify_req(struct mdp_blit_req *req)
|
||
|
{
|
||
|
u32 src_width, src_height, dst_width, dst_height;
|
||
|
|
||
|
if (req == NULL) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
return -1;
|
||
|
}
|
||
|
|
||
|
if (MDP_IS_IMGTYPE_BAD(req->src.format) ||
|
||
|
MDP_IS_IMGTYPE_BAD(req->dst.format)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
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)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
|
||
|
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)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
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)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
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)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
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)) {
|
||
|
printk(KERN_ERR "\n%s(): Error in Line %u", __func__,
|
||
|
__LINE__);
|
||
|
return -1;
|
||
|
}
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int get_gem_img(struct mdp_img *img, unsigned long *start, unsigned long *len)
|
||
|
{
|
||
|
/* Set len to zero to appropriately error out if
|
||
|
kgsl_gem_obj_addr fails */
|
||
|
|
||
|
*len = 0;
|
||
|
return kgsl_gem_obj_addr(img->memory_id, (int) img->priv, start, len);
|
||
|
}
|
||
|
|
||
|
int get_img(struct mdp_img *img, struct mdp_blit_req *req,
|
||
|
struct fb_info *info, unsigned long *start, unsigned long *len,
|
||
|
struct file **srcp_file, struct ion_handle **srcp_ihdl)
|
||
|
{
|
||
|
int put_needed, fb_num, ret = 0;
|
||
|
struct file *file;
|
||
|
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
|
||
|
struct msm_fb_data_type *mfd = (struct msm_fb_data_type *)info->par;
|
||
|
#endif
|
||
|
|
||
|
if (req->flags & MDP_MEMORY_ID_TYPE_FB) {
|
||
|
file = fget_light(img->memory_id, &put_needed);
|
||
|
if (file == NULL)
|
||
|
return -EINVAL;
|
||
|
|
||
|
if (MAJOR(file->f_dentry->d_inode->i_rdev) == FB_MAJOR) {
|
||
|
fb_num = MINOR(file->f_dentry->d_inode->i_rdev);
|
||
|
if (get_fb_phys_info(start, len, fb_num,
|
||
|
DISPLAY_SUBSYSTEM_ID)) {
|
||
|
pr_err("get_fb_phys_info() failed\n");
|
||
|
fput_light(file, put_needed);
|
||
|
} else {
|
||
|
*srcp_file = file;
|
||
|
}
|
||
|
|
||
|
return ret;
|
||
|
} else {
|
||
|
fput_light(file, put_needed);
|
||
|
}
|
||
|
}
|
||
|
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
|
||
|
*srcp_ihdl = ion_import_dma_buf(mfd->iclient, img->memory_id);
|
||
|
if (IS_ERR_OR_NULL(*srcp_ihdl))
|
||
|
return PTR_ERR(*srcp_ihdl);
|
||
|
|
||
|
if (!ion_phys(mfd->iclient, *srcp_ihdl, start, (size_t *) len))
|
||
|
return ret;
|
||
|
else
|
||
|
return -EINVAL;
|
||
|
#endif
|
||
|
|
||
|
}
|
||
|
|
||
|
void put_img(struct file *p_src_file, struct ion_handle *p_ihdl)
|
||
|
{
|
||
|
#ifdef CONFIG_MSM_MULTIMEDIA_USE_ION
|
||
|
if (!IS_ERR_OR_NULL(p_ihdl))
|
||
|
ion_free(ppp_display_iclient, p_ihdl);
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
|
||
|
static int mdp_ppp_blit_addr(struct fb_info *info, struct mdp_blit_req *req,
|
||
|
unsigned long srcp0_start, unsigned long srcp0_len,
|
||
|
unsigned long srcp1_start, unsigned long srcp1_len,
|
||
|
unsigned long dst_start, unsigned long dst_len,
|
||
|
struct file *p_src_file, struct file *p_dst_file,
|
||
|
struct ion_handle **src_ihdl, struct ion_handle **dst_ihdl)
|
||
|
{
|
||
|
MDPIBUF iBuf;
|
||
|
u32 dst_width, dst_height;
|
||
|
struct msm_fb_data_type *mfd = 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 (mdp_ppp_verify_req(req)) {
|
||
|
pr_err("mdp_ppp: invalid image!\n");
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
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 *) (srcp0_start + req->src.offset);
|
||
|
if (iBuf.mdpImg.imgType == MDP_Y_CBCR_H2V2_ADRENO)
|
||
|
iBuf.mdpImg.cbcr_addr =
|
||
|
(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
|
||
|
ALIGN((ALIGN(req->src.width, 32) *
|
||
|
ALIGN(req->src.height, 32)), 4096));
|
||
|
else
|
||
|
iBuf.mdpImg.cbcr_addr = srcp1_start ? (uint32 *)srcp1_start :
|
||
|
(uint32 *) ((uint32) iBuf.mdpImg.bmy_addr +
|
||
|
req->src.width * req->src.height);
|
||
|
|
||
|
iBuf.mdpImg.mdpOp = MDPOP_NOP;
|
||
|
|
||
|
if (req->flags & MDP_IS_FG)
|
||
|
iBuf.mdpImg.mdpOp |= MDPOP_LAYER_IS_FG;
|
||
|
|
||
|
/* 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);
|
||
|
} else {
|
||
|
iBuf.mdpImg.tpVal = 0;
|
||
|
}
|
||
|
|
||
|
req->alpha &= 0xff;
|
||
|
if (req->alpha < MDP_ALPHA_NOP) {
|
||
|
iBuf.mdpImg.mdpOp |= MDPOP_ALPHAB;
|
||
|
iBuf.mdpImg.alpha = req->alpha;
|
||
|
} else {
|
||
|
iBuf.mdpImg.alpha = 0xff;
|
||
|
}
|
||
|
|
||
|
/* 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) {
|
||
|
#if defined(CONFIG_FB_MSM_MDP31) || defined(CONFIG_FB_MSM_MDP303)
|
||
|
iBuf.mdpImg.mdpOp |= MDPOP_FG_PM_ALPHA;
|
||
|
#else
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
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
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
return -EINVAL;
|
||
|
#ifdef CONFIG_FB_MSM_MDP31
|
||
|
}
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
/* 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__);
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
iBuf.mdpImg.mdpOp |= MDPOP_ASCALE | MDPOP_SHARPENING;
|
||
|
iBuf.mdpImg.sp_value = req->sharpening_strength & 0xff;
|
||
|
#else
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
return -EINVAL;
|
||
|
#endif
|
||
|
}
|
||
|
|
||
|
down(&mdp_ppp_mutex);
|
||
|
/* MDP cmd block enable */
|
||
|
mdp_pipe_ctrl(MDP_CMD_BLOCK, MDP_BLOCK_POWER_ON, FALSE);
|
||
|
|
||
|
#ifndef CONFIG_FB_MSM_MDP22
|
||
|
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;
|
||
|
uint32 mdpOp = iBuf.mdpImg.mdpOp;
|
||
|
|
||
|
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;
|
||
|
/* restore mdpOp since MDPOP_ASCALE have been cleared */
|
||
|
iBuf.mdpImg.mdpOp = mdpOp;
|
||
|
}
|
||
|
|
||
|
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);
|
||
|
|
||
|
put_img(p_src_file, *src_ihdl);
|
||
|
put_img(p_dst_file, *dst_ihdl);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int mdp_ppp_blit(struct fb_info *info, struct mdp_blit_req *req)
|
||
|
{
|
||
|
unsigned long src_start, dst_start;
|
||
|
unsigned long src_len = 0;
|
||
|
unsigned long dst_len = 0;
|
||
|
struct file *p_src_file = 0 , *p_dst_file = 0;
|
||
|
struct ion_handle *src_ihdl = NULL;
|
||
|
struct ion_handle *dst_ihdl = NULL;
|
||
|
struct msm_fb_data_type *mfd = info->par;
|
||
|
ppp_display_iclient = mfd->iclient;
|
||
|
|
||
|
if (req->flags & MDP_BLIT_SRC_GEM)
|
||
|
get_gem_img(&req->src, &src_start, &src_len);
|
||
|
else
|
||
|
get_img(&req->src, req, info, &src_start, &src_len, &p_src_file,
|
||
|
&src_ihdl);
|
||
|
if (src_len == 0) {
|
||
|
pr_err("mdp_ppp: could not retrieve source image from "
|
||
|
"memory\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
if (req->flags & MDP_BLIT_DST_GEM)
|
||
|
get_gem_img(&req->dst, &dst_start, &dst_len);
|
||
|
else
|
||
|
get_img(&req->dst, req, info, &dst_start, &dst_len, &p_dst_file,
|
||
|
&dst_ihdl);
|
||
|
|
||
|
if (dst_len == 0) {
|
||
|
put_img(p_src_file, src_ihdl);
|
||
|
pr_err("mdp_ppp: could not retrieve destination image from "
|
||
|
"memory\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
return mdp_ppp_blit_addr(info, req, src_start, src_len, 0, 0, dst_start,
|
||
|
dst_len, p_src_file, p_dst_file, &src_ihdl, &dst_ihdl);
|
||
|
}
|
||
|
|
||
|
static struct mdp_blit_req overlay_req;
|
||
|
static bool mdp_overlay_req_set;
|
||
|
|
||
|
int mdp_ppp_v4l2_overlay_set(struct fb_info *info, struct mdp_overlay *req)
|
||
|
{
|
||
|
memset(&overlay_req, 0, sizeof(struct mdp_blit_req));
|
||
|
|
||
|
overlay_req.src.width = req->src.width;
|
||
|
overlay_req.src.height = req->src.height;
|
||
|
overlay_req.src.format = req->src.format;
|
||
|
|
||
|
|
||
|
overlay_req.dst.width = req->dst_rect.w;
|
||
|
overlay_req.dst.height = req->dst_rect.h;
|
||
|
overlay_req.dst.format = MDP_FB_FORMAT;
|
||
|
overlay_req.transp_mask = req->transp_mask;
|
||
|
overlay_req.flags = req->flags;
|
||
|
overlay_req.alpha = req->alpha;
|
||
|
|
||
|
overlay_req.src_rect.x = req->src_rect.x;
|
||
|
overlay_req.src_rect.y = req->src_rect.y;
|
||
|
overlay_req.src_rect.w = req->src_rect.w;
|
||
|
overlay_req.src_rect.h = req->src_rect.h;
|
||
|
overlay_req.dst_rect.x = req->dst_rect.x;
|
||
|
overlay_req.dst_rect.y = req->dst_rect.y;
|
||
|
overlay_req.dst_rect.w = req->dst_rect.w;
|
||
|
overlay_req.dst_rect.h = req->dst_rect.h;
|
||
|
mdp_overlay_req_set = true;
|
||
|
|
||
|
pr_debug("%s: Overlay parameters:", __func__);
|
||
|
pr_debug("Src_Image (%u %u)\n", overlay_req.src.width,
|
||
|
overlay_req.src.height);
|
||
|
|
||
|
if (overlay_req.src.format == MDP_Y_CRCB_H2V2)
|
||
|
pr_debug("Overlay format MDP_Y_CRCB_H2V2\n");
|
||
|
else if (overlay_req.src.format == MDP_RGB_565)
|
||
|
pr_debug("Overlay format MDP_RGB_565\n");
|
||
|
else
|
||
|
pr_debug("Overlay format(%u) unknown\n",
|
||
|
overlay_req.src.format);
|
||
|
|
||
|
pr_debug("Dst_Image (%u %u)\n", overlay_req.dst.width,
|
||
|
overlay_req.dst.height);
|
||
|
pr_debug("Src rect: (%u,%u,%u,%u), Dst rect: (%u,%u,%u,%u)\n",
|
||
|
overlay_req.src_rect.x, overlay_req.src_rect.y,
|
||
|
overlay_req.src_rect.w, overlay_req.src_rect.h,
|
||
|
overlay_req.dst_rect.x, overlay_req.dst_rect.y,
|
||
|
overlay_req.dst_rect.w, overlay_req.dst_rect.h);
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int mdp_ppp_v4l2_overlay_clear(void)
|
||
|
{
|
||
|
memset(&overlay_req, 0, sizeof(struct mdp_overlay));
|
||
|
mdp_overlay_req_set = false;
|
||
|
return 0;
|
||
|
}
|
||
|
|
||
|
int mdp_ppp_v4l2_overlay_play(struct fb_info *info, bool bUserPtr,
|
||
|
unsigned long srcp0_addr, unsigned long srcp0_size,
|
||
|
unsigned long srcp1_addr, unsigned long srcp1_size)
|
||
|
{
|
||
|
int ret;
|
||
|
unsigned long srcp0_start = 0, srcp1_start = 0;
|
||
|
unsigned long srcp0_len = 0, srcp1_len = 0;
|
||
|
|
||
|
struct ion_handle *srcp0_ihdl = NULL;
|
||
|
struct ion_handle *srcp1_ihdl = NULL;
|
||
|
struct msm_fb_data_type *mfd = info->par;
|
||
|
|
||
|
ppp_display_iclient = mfd->iclient;
|
||
|
if (!mdp_overlay_req_set) {
|
||
|
pr_err("mdp_ppp:v4l2:No overlay set, ignore play req\n");
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
|
||
|
overlay_req.dst.width = info->var.xres;
|
||
|
overlay_req.dst.height = info->var.yres;
|
||
|
|
||
|
if (bUserPtr) {
|
||
|
overlay_req.src.memory_id = srcp0_addr;
|
||
|
get_img(&overlay_req.src, &overlay_req, info, &srcp0_start,
|
||
|
&srcp0_len, NULL, &srcp0_ihdl);
|
||
|
if (srcp0_len == 0) {
|
||
|
pr_err("%s: could not retrieve source image0"
|
||
|
, __func__);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
srcp0_addr = srcp0_start + srcp0_size;
|
||
|
srcp0_size = srcp0_len;
|
||
|
|
||
|
if (srcp1_addr) {
|
||
|
overlay_req.src.memory_id = srcp1_addr;
|
||
|
get_img(&overlay_req.src, &overlay_req, info,
|
||
|
&srcp1_start, &srcp1_len, NULL, &srcp1_ihdl);
|
||
|
if (srcp1_len == 0) {
|
||
|
pr_err("%s: could not retrieve source image1"
|
||
|
, __func__);
|
||
|
return -EINVAL;
|
||
|
}
|
||
|
srcp1_addr = srcp1_start + srcp1_size;
|
||
|
srcp1_size = srcp1_len;
|
||
|
}
|
||
|
}
|
||
|
ret = mdp_ppp_blit_addr(info, &overlay_req,
|
||
|
srcp0_addr, srcp0_size, srcp1_addr, srcp1_size,
|
||
|
info->fix.smem_start, info->fix.smem_len, NULL, NULL,
|
||
|
NULL, NULL);
|
||
|
|
||
|
if (ret)
|
||
|
pr_err("%s:Blitting overlay failed(%d)\n", __func__, ret);
|
||
|
|
||
|
return ret;
|
||
|
}
|