![Stepan Moskovchenko](/assets/img/avatar_default.png)
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>
829 lines
24 KiB
C
829 lines
24 KiB
C
/* Copyright (c) 2008-2010, Code Aurora Forum. All rights reserved.
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 and
|
|
* only version 2 as published by the Free Software Foundation.
|
|
*
|
|
* 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.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software
|
|
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
* 02110-1301, USA.
|
|
*/
|
|
|
|
#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/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 <asm/div64.h>
|
|
|
|
#include "mdp.h"
|
|
#include "msm_fb.h"
|
|
|
|
#define MDP_SCALE_COEFF_NUM 32
|
|
#define MDP_SCALE_0P2_TO_0P4_INDEX 0
|
|
#define MDP_SCALE_0P4_TO_0P6_INDEX 32
|
|
#define MDP_SCALE_0P6_TO_0P8_INDEX 64
|
|
#define MDP_SCALE_0P8_TO_8P0_INDEX 96
|
|
#define MDP_SCALE_COEFF_MASK 0x3ff
|
|
|
|
#define MDP_SCALE_PR 0
|
|
#define MDP_SCALE_FIR 1
|
|
|
|
static uint32 mdp_scale_0p8_to_8p0_mode;
|
|
static uint32 mdp_scale_0p6_to_0p8_mode;
|
|
static uint32 mdp_scale_0p4_to_0p6_mode;
|
|
static uint32 mdp_scale_0p2_to_0p4_mode;
|
|
|
|
/* -------- All scaling range, "pixel repeat" -------- */
|
|
static int16 mdp_scale_pixel_repeat_C0[MDP_SCALE_COEFF_NUM] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
static int16 mdp_scale_pixel_repeat_C1[MDP_SCALE_COEFF_NUM] = {
|
|
511, 511, 511, 511, 511, 511, 511, 511,
|
|
511, 511, 511, 511, 511, 511, 511, 511,
|
|
511, 511, 511, 511, 511, 511, 511, 511,
|
|
511, 511, 511, 511, 511, 511, 511, 511
|
|
};
|
|
|
|
static int16 mdp_scale_pixel_repeat_C2[MDP_SCALE_COEFF_NUM] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
static int16 mdp_scale_pixel_repeat_C3[MDP_SCALE_COEFF_NUM] = {
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0,
|
|
0, 0, 0, 0, 0, 0, 0, 0
|
|
};
|
|
|
|
/* --------------------------- FIR ------------------------------------- */
|
|
/* -------- Downscale, ranging from 0.8x to 8.0x of original size -------- */
|
|
|
|
static int16 mdp_scale_0p8_to_8p0_C0[MDP_SCALE_COEFF_NUM] = {
|
|
0, -7, -13, -19, -24, -28, -32, -34, -37, -39,
|
|
-40, -41, -41, -41, -40, -40, -38, -37, -35, -33,
|
|
-31, -29, -26, -24, -21, -18, -15, -13, -10, -7,
|
|
-5, -2
|
|
};
|
|
|
|
static int16 mdp_scale_0p8_to_8p0_C1[MDP_SCALE_COEFF_NUM] = {
|
|
511, 507, 501, 494, 485, 475, 463, 450, 436, 422,
|
|
405, 388, 370, 352, 333, 314, 293, 274, 253, 233,
|
|
213, 193, 172, 152, 133, 113, 95, 77, 60, 43,
|
|
28, 13
|
|
};
|
|
|
|
static int16 mdp_scale_0p8_to_8p0_C2[MDP_SCALE_COEFF_NUM] = {
|
|
0, 13, 28, 43, 60, 77, 95, 113, 133, 152,
|
|
172, 193, 213, 233, 253, 274, 294, 314, 333, 352,
|
|
370, 388, 405, 422, 436, 450, 463, 475, 485, 494,
|
|
501, 507,
|
|
};
|
|
|
|
static int16 mdp_scale_0p8_to_8p0_C3[MDP_SCALE_COEFF_NUM] = {
|
|
0, -2, -5, -7, -10, -13, -15, -18, -21, -24,
|
|
-26, -29, -31, -33, -35, -37, -38, -40, -40, -41,
|
|
-41, -41, -40, -39, -37, -34, -32, -28, -24, -19,
|
|
-13, -7
|
|
};
|
|
|
|
/* -------- Downscale, ranging from 0.6x to 0.8x of original size -------- */
|
|
|
|
static int16 mdp_scale_0p6_to_0p8_C0[MDP_SCALE_COEFF_NUM] = {
|
|
104, 96, 89, 82, 75, 68, 61, 55, 49, 43,
|
|
38, 33, 28, 24, 20, 16, 12, 9, 6, 4,
|
|
2, 0, -2, -4, -5, -6, -7, -7, -8, -8,
|
|
-8, -8
|
|
};
|
|
|
|
static int16 mdp_scale_0p6_to_0p8_C1[MDP_SCALE_COEFF_NUM] = {
|
|
303, 303, 302, 300, 298, 296, 293, 289, 286, 281,
|
|
276, 270, 265, 258, 252, 245, 238, 230, 223, 214,
|
|
206, 197, 189, 180, 172, 163, 154, 145, 137, 128,
|
|
120, 112
|
|
};
|
|
|
|
static int16 mdp_scale_0p6_to_0p8_C2[MDP_SCALE_COEFF_NUM] = {
|
|
112, 120, 128, 137, 145, 154, 163, 172, 180, 189,
|
|
197, 206, 214, 223, 230, 238, 245, 252, 258, 265,
|
|
270, 276, 281, 286, 289, 293, 296, 298, 300, 302,
|
|
303, 303
|
|
};
|
|
|
|
static int16 mdp_scale_0p6_to_0p8_C3[MDP_SCALE_COEFF_NUM] = {
|
|
-8, -8, -8, -8, -7, -7, -6, -5, -4, -2,
|
|
0, 2, 4, 6, 9, 12, 16, 20, 24, 28,
|
|
33, 38, 43, 49, 55, 61, 68, 75, 82, 89,
|
|
96, 104
|
|
};
|
|
|
|
/* -------- Downscale, ranging from 0.4x to 0.6x of original size -------- */
|
|
|
|
static int16 mdp_scale_0p4_to_0p6_C0[MDP_SCALE_COEFF_NUM] = {
|
|
136, 132, 128, 123, 119, 115, 111, 107, 103, 98,
|
|
95, 91, 87, 84, 80, 76, 73, 69, 66, 62,
|
|
59, 57, 54, 50, 47, 44, 41, 39, 36, 33,
|
|
32, 29
|
|
};
|
|
|
|
static int16 mdp_scale_0p4_to_0p6_C1[MDP_SCALE_COEFF_NUM] = {
|
|
206, 205, 204, 204, 201, 200, 199, 197, 196, 194,
|
|
191, 191, 189, 185, 184, 182, 180, 178, 176, 173,
|
|
170, 168, 165, 162, 160, 157, 155, 152, 148, 146,
|
|
142, 140
|
|
};
|
|
|
|
static int16 mdp_scale_0p4_to_0p6_C2[MDP_SCALE_COEFF_NUM] = {
|
|
140, 142, 146, 148, 152, 155, 157, 160, 162, 165,
|
|
168, 170, 173, 176, 178, 180, 182, 184, 185, 189,
|
|
191, 191, 194, 196, 197, 199, 200, 201, 204, 204,
|
|
205, 206
|
|
};
|
|
|
|
static int16 mdp_scale_0p4_to_0p6_C3[MDP_SCALE_COEFF_NUM] = {
|
|
29, 32, 33, 36, 39, 41, 44, 47, 50, 54,
|
|
57, 59, 62, 66, 69, 73, 76, 80, 84, 87,
|
|
91, 95, 98, 103, 107, 111, 115, 119, 123, 128,
|
|
132, 136
|
|
};
|
|
|
|
/* -------- Downscale, ranging from 0.2x to 0.4x of original size -------- */
|
|
|
|
static int16 mdp_scale_0p2_to_0p4_C0[MDP_SCALE_COEFF_NUM] = {
|
|
131, 131, 130, 129, 128, 127, 127, 126, 125, 125,
|
|
124, 123, 123, 121, 120, 119, 119, 118, 117, 117,
|
|
116, 115, 115, 114, 113, 112, 111, 110, 109, 109,
|
|
108, 107
|
|
};
|
|
|
|
static int16 mdp_scale_0p2_to_0p4_C1[MDP_SCALE_COEFF_NUM] = {
|
|
141, 140, 140, 140, 140, 139, 138, 138, 138, 137,
|
|
137, 137, 136, 137, 137, 137, 136, 136, 136, 135,
|
|
135, 135, 134, 134, 134, 134, 134, 133, 133, 132,
|
|
132, 132
|
|
};
|
|
|
|
static int16 mdp_scale_0p2_to_0p4_C2[MDP_SCALE_COEFF_NUM] = {
|
|
132, 132, 132, 133, 133, 134, 134, 134, 134, 134,
|
|
135, 135, 135, 136, 136, 136, 137, 137, 137, 136,
|
|
137, 137, 137, 138, 138, 138, 139, 140, 140, 140,
|
|
140, 141
|
|
};
|
|
|
|
static int16 mdp_scale_0p2_to_0p4_C3[MDP_SCALE_COEFF_NUM] = {
|
|
107, 108, 109, 109, 110, 111, 112, 113, 114, 115,
|
|
115, 116, 117, 117, 118, 119, 119, 120, 121, 123,
|
|
123, 124, 125, 125, 126, 127, 127, 128, 129, 130,
|
|
131, 131
|
|
};
|
|
|
|
static void mdp_update_scale_table(int index, int16 *c0, int16 *c1,
|
|
int16 *c2, int16 *c3)
|
|
{
|
|
int i, val;
|
|
|
|
for (i = 0; i < MDP_SCALE_COEFF_NUM; i++) {
|
|
val =
|
|
((MDP_SCALE_COEFF_MASK & c1[i]) << 16) |
|
|
(MDP_SCALE_COEFF_MASK & c0[i]);
|
|
MDP_OUTP(MDP_PPP_SCALE_COEFF_LSBn(index), val);
|
|
val =
|
|
((MDP_SCALE_COEFF_MASK & c3[i]) << 16) |
|
|
(MDP_SCALE_COEFF_MASK & c2[i]);
|
|
MDP_OUTP(MDP_PPP_SCALE_COEFF_MSBn(index), val);
|
|
index++;
|
|
}
|
|
}
|
|
|
|
void mdp_init_scale_table(void)
|
|
{
|
|
mdp_scale_0p2_to_0p4_mode = MDP_SCALE_FIR;
|
|
mdp_update_scale_table(MDP_SCALE_0P2_TO_0P4_INDEX,
|
|
mdp_scale_0p2_to_0p4_C0,
|
|
mdp_scale_0p2_to_0p4_C1,
|
|
mdp_scale_0p2_to_0p4_C2,
|
|
mdp_scale_0p2_to_0p4_C3);
|
|
|
|
mdp_scale_0p4_to_0p6_mode = MDP_SCALE_FIR;
|
|
mdp_update_scale_table(MDP_SCALE_0P4_TO_0P6_INDEX,
|
|
mdp_scale_0p4_to_0p6_C0,
|
|
mdp_scale_0p4_to_0p6_C1,
|
|
mdp_scale_0p4_to_0p6_C2,
|
|
mdp_scale_0p4_to_0p6_C3);
|
|
|
|
mdp_scale_0p6_to_0p8_mode = MDP_SCALE_FIR;
|
|
mdp_update_scale_table(MDP_SCALE_0P6_TO_0P8_INDEX,
|
|
mdp_scale_0p6_to_0p8_C0,
|
|
mdp_scale_0p6_to_0p8_C1,
|
|
mdp_scale_0p6_to_0p8_C2,
|
|
mdp_scale_0p6_to_0p8_C3);
|
|
|
|
mdp_scale_0p8_to_8p0_mode = MDP_SCALE_FIR;
|
|
mdp_update_scale_table(MDP_SCALE_0P8_TO_8P0_INDEX,
|
|
mdp_scale_0p8_to_8p0_C0,
|
|
mdp_scale_0p8_to_8p0_C1,
|
|
mdp_scale_0p8_to_8p0_C2,
|
|
mdp_scale_0p8_to_8p0_C3);
|
|
}
|
|
|
|
static long long mdp_do_div(long long num, long long den)
|
|
{
|
|
do_div(num, den);
|
|
return num;
|
|
}
|
|
|
|
#define SCALER_PHASE_BITS 29
|
|
#define HAL_MDP_PHASE_STEP_2P50 0x50000000
|
|
#define HAL_MDP_PHASE_STEP_1P66 0x35555555
|
|
#define HAL_MDP_PHASE_STEP_1P25 0x28000000
|
|
|
|
struct phase_val {
|
|
int phase_init_x;
|
|
int phase_init_y;
|
|
int phase_step_x;
|
|
int phase_step_y;
|
|
};
|
|
|
|
static void mdp_calc_scaleInitPhase_3p1(uint32 in_w,
|
|
uint32 in_h,
|
|
uint32 out_w,
|
|
uint32 out_h,
|
|
boolean is_rotate,
|
|
boolean is_pp_x,
|
|
boolean is_pp_y, struct phase_val *pval)
|
|
{
|
|
uint64 dst_ROI_width;
|
|
uint64 dst_ROI_height;
|
|
uint64 src_ROI_width;
|
|
uint64 src_ROI_height;
|
|
|
|
/*
|
|
* phase_step_x, phase_step_y, phase_init_x and phase_init_y
|
|
* are represented in fixed-point, unsigned 3.29 format
|
|
*/
|
|
uint32 phase_step_x = 0;
|
|
uint32 phase_step_y = 0;
|
|
uint32 phase_init_x = 0;
|
|
uint32 phase_init_y = 0;
|
|
uint32 yscale_filter_sel, xscale_filter_sel;
|
|
uint32 scale_unit_sel_x, scale_unit_sel_y;
|
|
|
|
uint64 numerator, denominator;
|
|
uint64 temp_dim;
|
|
|
|
src_ROI_width = in_w;
|
|
src_ROI_height = in_h;
|
|
dst_ROI_width = out_w;
|
|
dst_ROI_height = out_h;
|
|
|
|
/* if there is a 90 degree rotation */
|
|
if (is_rotate) {
|
|
/* decide whether to use FIR or M/N for scaling */
|
|
|
|
/* if down-scaling by a factor smaller than 1/4 */
|
|
if (src_ROI_width > (4 * dst_ROI_height))
|
|
scale_unit_sel_x = 1; /* use M/N scalar */
|
|
else
|
|
scale_unit_sel_x = 0; /* use FIR scalar */
|
|
|
|
/* if down-scaling by a factor smaller than 1/4 */
|
|
if (src_ROI_height > (4 * dst_ROI_width))
|
|
scale_unit_sel_y = 1; /* use M/N scalar */
|
|
else
|
|
scale_unit_sel_y = 0; /* use FIR scalar */
|
|
} else {
|
|
/* decide whether to use FIR or M/N for scaling */
|
|
|
|
if (src_ROI_width > (4 * dst_ROI_width))
|
|
scale_unit_sel_x = 1; /* use M/N scalar */
|
|
else
|
|
scale_unit_sel_x = 0; /* use FIR scalar */
|
|
|
|
if (src_ROI_height > (4 * dst_ROI_height))
|
|
scale_unit_sel_y = 1; /* use M/N scalar */
|
|
else
|
|
scale_unit_sel_y = 0; /* use FIR scalar */
|
|
|
|
}
|
|
|
|
/* if there is a 90 degree rotation */
|
|
if (is_rotate) {
|
|
/* swap the width and height of dst ROI */
|
|
temp_dim = dst_ROI_width;
|
|
dst_ROI_width = dst_ROI_height;
|
|
dst_ROI_height = temp_dim;
|
|
}
|
|
|
|
/* calculate phase step for the x direction */
|
|
|
|
/* if destination is only 1 pixel wide, the value of phase_step_x
|
|
is unimportant. Assigning phase_step_x to src ROI width
|
|
as an arbitrary value. */
|
|
if (dst_ROI_width == 1)
|
|
phase_step_x = (uint32) ((src_ROI_width) << SCALER_PHASE_BITS);
|
|
|
|
/* if using FIR scalar */
|
|
else if (scale_unit_sel_x == 0) {
|
|
|
|
/* Calculate the quotient ( src_ROI_width - 1 ) / ( dst_ROI_width - 1)
|
|
with u3.29 precision. Quotient is rounded up to the larger
|
|
29th decimal point. */
|
|
numerator = (src_ROI_width - 1) << SCALER_PHASE_BITS;
|
|
denominator = (dst_ROI_width - 1); /* never equals to 0 because of the "( dst_ROI_width == 1 ) case" */
|
|
phase_step_x = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* divide and round up to the larger 29th decimal point. */
|
|
|
|
}
|
|
|
|
/* if M/N scalar */
|
|
else if (scale_unit_sel_x == 1) {
|
|
/* Calculate the quotient ( src_ROI_width ) / ( dst_ROI_width)
|
|
with u3.29 precision. Quotient is rounded down to the
|
|
smaller 29th decimal point. */
|
|
numerator = (src_ROI_width) << SCALER_PHASE_BITS;
|
|
denominator = (dst_ROI_width);
|
|
phase_step_x = (uint32) mdp_do_div(numerator, denominator);
|
|
}
|
|
/* calculate phase step for the y direction */
|
|
|
|
/* if destination is only 1 pixel wide, the value of
|
|
phase_step_x is unimportant. Assigning phase_step_x
|
|
to src ROI width as an arbitrary value. */
|
|
if (dst_ROI_height == 1)
|
|
phase_step_y = (uint32) ((src_ROI_height) << SCALER_PHASE_BITS);
|
|
|
|
/* if FIR scalar */
|
|
else if (scale_unit_sel_y == 0) {
|
|
/* Calculate the quotient ( src_ROI_height - 1 ) / ( dst_ROI_height - 1)
|
|
with u3.29 precision. Quotient is rounded up to the larger
|
|
29th decimal point. */
|
|
numerator = (src_ROI_height - 1) << SCALER_PHASE_BITS;
|
|
denominator = (dst_ROI_height - 1); /* never equals to 0 because of the "( dst_ROI_height == 1 )" case */
|
|
phase_step_y = (uint32) mdp_do_div((numerator + denominator - 1), denominator); /* Quotient is rounded up to the larger 29th decimal point. */
|
|
|
|
}
|
|
|
|
/* if M/N scalar */
|
|
else if (scale_unit_sel_y == 1) {
|
|
/* Calculate the quotient ( src_ROI_height ) / ( dst_ROI_height)
|
|
with u3.29 precision. Quotient is rounded down to the smaller
|
|
29th decimal point. */
|
|
numerator = (src_ROI_height) << SCALER_PHASE_BITS;
|
|
denominator = (dst_ROI_height);
|
|
phase_step_y = (uint32) mdp_do_div(numerator, denominator);
|
|
}
|
|
|
|
/* decide which set of FIR coefficients to use */
|
|
if (phase_step_x > HAL_MDP_PHASE_STEP_2P50)
|
|
xscale_filter_sel = 0;
|
|
else if (phase_step_x > HAL_MDP_PHASE_STEP_1P66)
|
|
xscale_filter_sel = 1;
|
|
else if (phase_step_x > HAL_MDP_PHASE_STEP_1P25)
|
|
xscale_filter_sel = 2;
|
|
else
|
|
xscale_filter_sel = 3;
|
|
|
|
if (phase_step_y > HAL_MDP_PHASE_STEP_2P50)
|
|
yscale_filter_sel = 0;
|
|
else if (phase_step_y > HAL_MDP_PHASE_STEP_1P66)
|
|
yscale_filter_sel = 1;
|
|
else if (phase_step_y > HAL_MDP_PHASE_STEP_1P25)
|
|
yscale_filter_sel = 2;
|
|
else
|
|
yscale_filter_sel = 3;
|
|
|
|
/* calculate phase init for the x direction */
|
|
|
|
/* if using FIR scalar */
|
|
if (scale_unit_sel_x == 0) {
|
|
if (dst_ROI_width == 1)
|
|
phase_init_x =
|
|
(uint32) ((src_ROI_width - 1) << SCALER_PHASE_BITS);
|
|
else
|
|
phase_init_x = 0;
|
|
|
|
}
|
|
/* M over N scalar */
|
|
else if (scale_unit_sel_x == 1)
|
|
phase_init_x = 0;
|
|
|
|
/* calculate phase init for the y direction
|
|
if using FIR scalar */
|
|
if (scale_unit_sel_y == 0) {
|
|
if (dst_ROI_height == 1)
|
|
phase_init_y =
|
|
(uint32) ((src_ROI_height -
|
|
1) << SCALER_PHASE_BITS);
|
|
else
|
|
phase_init_y = 0;
|
|
|
|
}
|
|
/* M over N scalar */
|
|
else if (scale_unit_sel_y == 1)
|
|
phase_init_y = 0;
|
|
|
|
/* write registers */
|
|
pval->phase_step_x = (uint32) phase_step_x;
|
|
pval->phase_step_y = (uint32) phase_step_y;
|
|
pval->phase_init_x = (uint32) phase_init_x;
|
|
pval->phase_init_y = (uint32) phase_init_y;
|
|
|
|
return;
|
|
}
|
|
|
|
void mdp_set_scale(MDPIBUF *iBuf,
|
|
uint32 dst_roi_width,
|
|
uint32 dst_roi_height,
|
|
boolean inputRGB, boolean outputRGB, uint32 *pppop_reg_ptr)
|
|
{
|
|
uint32 dst_roi_width_scale;
|
|
uint32 dst_roi_height_scale;
|
|
struct phase_val pval;
|
|
boolean use_pr;
|
|
uint32 ppp_scale_config = 0;
|
|
|
|
if (!inputRGB)
|
|
ppp_scale_config |= BIT(6);
|
|
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_ASCALE) {
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_ROT90) {
|
|
dst_roi_width_scale = dst_roi_height;
|
|
dst_roi_height_scale = dst_roi_width;
|
|
} else {
|
|
dst_roi_width_scale = dst_roi_width;
|
|
dst_roi_height_scale = dst_roi_height;
|
|
}
|
|
|
|
if ((dst_roi_width_scale != iBuf->roi.width) ||
|
|
(dst_roi_height_scale != iBuf->roi.height) ||
|
|
(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
|
|
*pppop_reg_ptr |=
|
|
(PPP_OP_SCALE_Y_ON | PPP_OP_SCALE_X_ON);
|
|
|
|
mdp_calc_scaleInitPhase_3p1(iBuf->roi.width,
|
|
iBuf->roi.height,
|
|
dst_roi_width,
|
|
dst_roi_height,
|
|
iBuf->mdpImg.
|
|
mdpOp & MDPOP_ROT90, 1, 1,
|
|
&pval);
|
|
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x013c,
|
|
pval.phase_init_x);
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0140,
|
|
pval.phase_init_y);
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0144,
|
|
pval.phase_step_x);
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0148,
|
|
pval.phase_step_y);
|
|
|
|
use_pr = (inputRGB) && (outputRGB);
|
|
|
|
/* x-direction */
|
|
if ((dst_roi_width_scale == iBuf->roi.width) &&
|
|
!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
|
|
*pppop_reg_ptr &= ~PPP_OP_SCALE_X_ON;
|
|
} else
|
|
if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
|
|
8) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p8_to_8p0_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p8_to_8p0_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P8_TO_8P0_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p8_to_8p0_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p8_to_8p0_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P8_TO_8P0_INDEX,
|
|
mdp_scale_0p8_to_8p0_C0,
|
|
mdp_scale_0p8_to_8p0_C1,
|
|
mdp_scale_0p8_to_8p0_C2,
|
|
mdp_scale_0p8_to_8p0_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_U1_SET << 2);
|
|
} else
|
|
if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
|
|
6) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p6_to_0p8_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p6_to_0p8_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P6_TO_0P8_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p6_to_0p8_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p6_to_0p8_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P6_TO_0P8_INDEX,
|
|
mdp_scale_0p6_to_0p8_C0,
|
|
mdp_scale_0p6_to_0p8_C1,
|
|
mdp_scale_0p6_to_0p8_C2,
|
|
mdp_scale_0p6_to_0p8_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D2_SET << 2);
|
|
} else
|
|
if (((dst_roi_width_scale * 10) / iBuf->roi.width) >
|
|
4) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p4_to_0p6_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p4_to_0p6_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P4_TO_0P6_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p4_to_0p6_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p4_to_0p6_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P4_TO_0P6_INDEX,
|
|
mdp_scale_0p4_to_0p6_C0,
|
|
mdp_scale_0p4_to_0p6_C1,
|
|
mdp_scale_0p4_to_0p6_C2,
|
|
mdp_scale_0p4_to_0p6_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D1_SET << 2);
|
|
} else
|
|
if (((dst_roi_width_scale * 4) / iBuf->roi.width) >=
|
|
1) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p2_to_0p4_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p2_to_0p4_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P2_TO_0P4_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p2_to_0p4_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p2_to_0p4_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P2_TO_0P4_INDEX,
|
|
mdp_scale_0p2_to_0p4_C0,
|
|
mdp_scale_0p2_to_0p4_C1,
|
|
mdp_scale_0p2_to_0p4_C2,
|
|
mdp_scale_0p2_to_0p4_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D0_SET << 2);
|
|
} else
|
|
ppp_scale_config |= BIT(0);
|
|
|
|
/* y-direction */
|
|
if ((dst_roi_height_scale == iBuf->roi.height) &&
|
|
!(iBuf->mdpImg.mdpOp & MDPOP_SHARPENING)) {
|
|
*pppop_reg_ptr &= ~PPP_OP_SCALE_Y_ON;
|
|
} else if (((dst_roi_height_scale * 10) /
|
|
iBuf->roi.height) > 8) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p8_to_8p0_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p8_to_8p0_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P8_TO_8P0_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p8_to_8p0_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p8_to_8p0_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P8_TO_8P0_INDEX,
|
|
mdp_scale_0p8_to_8p0_C0,
|
|
mdp_scale_0p8_to_8p0_C1,
|
|
mdp_scale_0p8_to_8p0_C2,
|
|
mdp_scale_0p8_to_8p0_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_U1_SET << 4);
|
|
} else
|
|
if (((dst_roi_height_scale * 10) /
|
|
iBuf->roi.height) > 6) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p6_to_0p8_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p6_to_0p8_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P6_TO_0P8_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p6_to_0p8_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p6_to_0p8_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P6_TO_0P8_INDEX,
|
|
mdp_scale_0p6_to_0p8_C0,
|
|
mdp_scale_0p6_to_0p8_C1,
|
|
mdp_scale_0p6_to_0p8_C2,
|
|
mdp_scale_0p6_to_0p8_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D2_SET << 4);
|
|
} else
|
|
if (((dst_roi_height_scale * 10) /
|
|
iBuf->roi.height) > 4) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p4_to_0p6_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p4_to_0p6_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P4_TO_0P6_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p4_to_0p6_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p4_to_0p6_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P4_TO_0P6_INDEX,
|
|
mdp_scale_0p4_to_0p6_C0,
|
|
mdp_scale_0p4_to_0p6_C1,
|
|
mdp_scale_0p4_to_0p6_C2,
|
|
mdp_scale_0p4_to_0p6_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D1_SET << 4);
|
|
} else
|
|
if (((dst_roi_height_scale * 4) /
|
|
iBuf->roi.height) >= 1) {
|
|
if ((use_pr)
|
|
&& (mdp_scale_0p2_to_0p4_mode !=
|
|
MDP_SCALE_PR)) {
|
|
mdp_scale_0p2_to_0p4_mode =
|
|
MDP_SCALE_PR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P2_TO_0P4_INDEX,
|
|
mdp_scale_pixel_repeat_C0,
|
|
mdp_scale_pixel_repeat_C1,
|
|
mdp_scale_pixel_repeat_C2,
|
|
mdp_scale_pixel_repeat_C3);
|
|
} else if ((!use_pr)
|
|
&& (mdp_scale_0p2_to_0p4_mode !=
|
|
MDP_SCALE_FIR)) {
|
|
mdp_scale_0p2_to_0p4_mode =
|
|
MDP_SCALE_FIR;
|
|
mdp_update_scale_table
|
|
(MDP_SCALE_0P2_TO_0P4_INDEX,
|
|
mdp_scale_0p2_to_0p4_C0,
|
|
mdp_scale_0p2_to_0p4_C1,
|
|
mdp_scale_0p2_to_0p4_C2,
|
|
mdp_scale_0p2_to_0p4_C3);
|
|
}
|
|
ppp_scale_config |= (SCALE_D0_SET << 4);
|
|
} else
|
|
ppp_scale_config |= BIT(1);
|
|
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_SHARPENING) {
|
|
ppp_scale_config |= BIT(7);
|
|
MDP_OUTP(MDP_BASE + 0x50020,
|
|
iBuf->mdpImg.sp_value);
|
|
}
|
|
|
|
MDP_OUTP(MDP_BASE + 0x10230, ppp_scale_config);
|
|
} else {
|
|
iBuf->mdpImg.mdpOp &= ~(MDPOP_ASCALE);
|
|
}
|
|
}
|
|
}
|
|
|
|
void mdp_adjust_start_addr(uint8 **src0,
|
|
uint8 **src1,
|
|
int v_slice,
|
|
int h_slice,
|
|
int x,
|
|
int y,
|
|
uint32 width,
|
|
uint32 height, int bpp, MDPIBUF *iBuf, int layer)
|
|
{
|
|
switch (layer) {
|
|
case 0:
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0200, (y << 16) | (x));
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0208,
|
|
(height << 16) | (width));
|
|
break;
|
|
|
|
case 1:
|
|
/* MDP 3.1 HW bug workaround */
|
|
if (iBuf->ibuf_type == MDP_YCRYCB_H2V1) {
|
|
*src0 += (x + y * width) * bpp;
|
|
x = y = 0;
|
|
width = iBuf->roi.dst_width;
|
|
height = iBuf->roi.dst_height;
|
|
}
|
|
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x0204, (y << 16) | (x));
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x020c,
|
|
(height << 16) | (width));
|
|
break;
|
|
|
|
case 2:
|
|
MDP_OUTP(MDP_CMD_DEBUG_ACCESS_BASE + 0x019c, (y << 16) | (x));
|
|
break;
|
|
}
|
|
}
|
|
|
|
void mdp_set_blend_attr(MDPIBUF *iBuf,
|
|
uint32 *alpha,
|
|
uint32 *tpVal,
|
|
uint32 perPixelAlpha, uint32 *pppop_reg_ptr)
|
|
{
|
|
int bg_alpha;
|
|
|
|
*alpha = iBuf->mdpImg.alpha;
|
|
*tpVal = iBuf->mdpImg.tpVal;
|
|
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_FG_PM_ALPHA) {
|
|
*pppop_reg_ptr |= PPP_OP_ROT_ON |
|
|
PPP_OP_BLEND_ON | PPP_OP_BLEND_CONSTANT_ALPHA;
|
|
|
|
bg_alpha = PPP_BLEND_BG_USE_ALPHA_SEL |
|
|
PPP_BLEND_BG_ALPHA_REVERSE;
|
|
|
|
if (perPixelAlpha)
|
|
bg_alpha |= PPP_BLEND_BG_SRCPIXEL_ALPHA;
|
|
else
|
|
bg_alpha |= PPP_BLEND_BG_CONSTANT_ALPHA;
|
|
|
|
outpdw(MDP_BASE + 0x70010, bg_alpha);
|
|
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
|
|
*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
|
|
} else if (perPixelAlpha) {
|
|
*pppop_reg_ptr |= PPP_OP_ROT_ON |
|
|
PPP_OP_BLEND_ON | PPP_OP_BLEND_SRCPIXEL_ALPHA;
|
|
} else {
|
|
if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
|
|
&& (iBuf->mdpImg.alpha == 0xff)) {
|
|
iBuf->mdpImg.mdpOp &= ~(MDPOP_ALPHAB);
|
|
}
|
|
|
|
if ((iBuf->mdpImg.mdpOp & MDPOP_ALPHAB)
|
|
|| (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)) {
|
|
*pppop_reg_ptr |=
|
|
PPP_OP_ROT_ON | PPP_OP_BLEND_ON |
|
|
PPP_OP_BLEND_CONSTANT_ALPHA |
|
|
PPP_OP_BLEND_ALPHA_BLEND_NORMAL;
|
|
}
|
|
|
|
if (iBuf->mdpImg.mdpOp & MDPOP_TRANSP)
|
|
*pppop_reg_ptr |= PPP_BLEND_CALPHA_TRNASP;
|
|
}
|
|
}
|