mxc: IPU3: Forward IPUv3 common driver from imx_4.19.y kernel
This patch forwards IPUv3 common driver from imx_4.19.y kernel. This includs IPUv3 common, IPUv3 prefetch engine and VDOA support. [ Liu Ying: Fixed a minor build warning for PRE driver. ] Signed-off-by: Liu Ying <victor.liu@nxp.com>5.4-rM2-2.2.x-imx-squashed
parent
2d4f90ebd9
commit
bc77a44ba0
|
@ -228,4 +228,5 @@ source "drivers/interconnect/Kconfig"
|
||||||
|
|
||||||
source "drivers/counter/Kconfig"
|
source "drivers/counter/Kconfig"
|
||||||
|
|
||||||
|
source "drivers/mxc/Kconfig"
|
||||||
endmenu
|
endmenu
|
||||||
|
|
|
@ -186,3 +186,4 @@ obj-$(CONFIG_SIOX) += siox/
|
||||||
obj-$(CONFIG_GNSS) += gnss/
|
obj-$(CONFIG_GNSS) += gnss/
|
||||||
obj-$(CONFIG_INTERCONNECT) += interconnect/
|
obj-$(CONFIG_INTERCONNECT) += interconnect/
|
||||||
obj-$(CONFIG_COUNTER) += counter/
|
obj-$(CONFIG_COUNTER) += counter/
|
||||||
|
obj-y += mxc/
|
||||||
|
|
|
@ -0,0 +1,18 @@
|
||||||
|
# drivers/mxc/Kconfig
|
||||||
|
|
||||||
|
if ARCH_MXC
|
||||||
|
|
||||||
|
menu "MXC support drivers"
|
||||||
|
|
||||||
|
config MXC_IPU
|
||||||
|
bool "Image Processing Unit Driver"
|
||||||
|
select MXC_IPU_V3
|
||||||
|
help
|
||||||
|
If you plan to use the Image Processing unit, say
|
||||||
|
Y here. IPU is needed by Framebuffer and V4L2 drivers.
|
||||||
|
|
||||||
|
source "drivers/mxc/ipu3/Kconfig"
|
||||||
|
|
||||||
|
endmenu
|
||||||
|
|
||||||
|
endif
|
|
@ -0,0 +1 @@
|
||||||
|
obj-$(CONFIG_MXC_IPU_V3) += ipu3/
|
|
@ -0,0 +1,21 @@
|
||||||
|
config MXC_IPU_V3
|
||||||
|
bool
|
||||||
|
|
||||||
|
config MXC_IPU_V3_PRG
|
||||||
|
tristate "i.MX IPUv3 prefetch gasket engine"
|
||||||
|
depends on MXC_IPU_V3 && MXC_IPU_V3_PRE
|
||||||
|
help
|
||||||
|
This enables support for the IPUv3 prefetch gasket engine to
|
||||||
|
support double buffer handshake control bewteen IPUv3 and
|
||||||
|
prefetch engine(PRE), snoop the AXI interface for display
|
||||||
|
refresh requests to memory and modify the request address to
|
||||||
|
fetch the double buffered row of blocks in OCRAM.
|
||||||
|
|
||||||
|
config MXC_IPU_V3_PRE
|
||||||
|
tristate "i.MX IPUv3 prefetch engine"
|
||||||
|
depends on MXC_IPU_V3
|
||||||
|
select MXC_IPU_V3_PRG
|
||||||
|
help
|
||||||
|
This enables support for the IPUv3 prefetch engine to improve
|
||||||
|
the system memory performance. The engine has the capability
|
||||||
|
to resolve framebuffers in tile pixel format to linear.
|
|
@ -0,0 +1,7 @@
|
||||||
|
obj-$(CONFIG_MXC_IPU_V3) = mxc_ipu.o
|
||||||
|
|
||||||
|
obj-$(CONFIG_MXC_IPU_V3_PRG) += prg.o
|
||||||
|
obj-$(CONFIG_MXC_IPU_V3_PRE) += pre.o
|
||||||
|
|
||||||
|
mxc_ipu-objs := ipu_common.o ipu_ic.o ipu_disp.o ipu_capture.o ipu_device.o \
|
||||||
|
ipu_calc_stripes_sizes.o vdoa.o ipu_pixel_clk.o
|
|
@ -0,0 +1,495 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2009-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @file ipu_calc_stripes_sizes.c
|
||||||
|
*
|
||||||
|
* @brief IPU IC functions
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/math64.h>
|
||||||
|
|
||||||
|
#define BPP_32 0
|
||||||
|
#define BPP_16 3
|
||||||
|
#define BPP_8 5
|
||||||
|
#define BPP_24 1
|
||||||
|
#define BPP_12 4
|
||||||
|
#define BPP_18 2
|
||||||
|
|
||||||
|
static u32 truncate(u32 up, /* 0: down; else: up */
|
||||||
|
u64 a, /* must be non-negative */
|
||||||
|
u32 b)
|
||||||
|
{
|
||||||
|
u32 d;
|
||||||
|
u64 div;
|
||||||
|
div = div_u64(a, b);
|
||||||
|
d = b * (div >> 32);
|
||||||
|
if (up && (a > (((u64)d) << 32)))
|
||||||
|
return d+b;
|
||||||
|
else
|
||||||
|
return d;
|
||||||
|
}
|
||||||
|
|
||||||
|
static unsigned int f_calc(unsigned int pfs, unsigned int bpp, unsigned int *write)
|
||||||
|
{/* return input_f */
|
||||||
|
unsigned int f_calculated = 0;
|
||||||
|
switch (pfs) {
|
||||||
|
case IPU_PIX_FMT_YVU422P:
|
||||||
|
case IPU_PIX_FMT_YUV422P:
|
||||||
|
case IPU_PIX_FMT_YUV420P2:
|
||||||
|
case IPU_PIX_FMT_YUV420P:
|
||||||
|
case IPU_PIX_FMT_YVU420P:
|
||||||
|
case IPU_PIX_FMT_YUV444P:
|
||||||
|
f_calculated = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IPU_PIX_FMT_RGB565:
|
||||||
|
case IPU_PIX_FMT_YUYV:
|
||||||
|
case IPU_PIX_FMT_UYVY:
|
||||||
|
f_calculated = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IPU_PIX_FMT_NV12:
|
||||||
|
f_calculated = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
f_calculated = 0;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (!f_calculated) {
|
||||||
|
switch (bpp) {
|
||||||
|
case BPP_32:
|
||||||
|
f_calculated = 2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BPP_16:
|
||||||
|
f_calculated = 4;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BPP_8:
|
||||||
|
case BPP_24:
|
||||||
|
f_calculated = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BPP_12:
|
||||||
|
f_calculated = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BPP_18:
|
||||||
|
f_calculated = 32;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
f_calculated = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return f_calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static unsigned int m_calc(unsigned int pfs)
|
||||||
|
{
|
||||||
|
unsigned int m_calculated = 0;
|
||||||
|
switch (pfs) {
|
||||||
|
case IPU_PIX_FMT_YUV420P2:
|
||||||
|
case IPU_PIX_FMT_YUV420P:
|
||||||
|
case IPU_PIX_FMT_YVU422P:
|
||||||
|
case IPU_PIX_FMT_YUV422P:
|
||||||
|
case IPU_PIX_FMT_YVU420P:
|
||||||
|
case IPU_PIX_FMT_YUV444P:
|
||||||
|
m_calculated = 16;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IPU_PIX_FMT_NV12:
|
||||||
|
case IPU_PIX_FMT_YUYV:
|
||||||
|
case IPU_PIX_FMT_UYVY:
|
||||||
|
m_calculated = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
m_calculated = 8;
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
return m_calculated;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int calc_split_resize_coeffs(unsigned int inSize, unsigned int outSize,
|
||||||
|
unsigned int *resizeCoeff,
|
||||||
|
unsigned int *downsizeCoeff)
|
||||||
|
{
|
||||||
|
uint32_t tempSize;
|
||||||
|
uint32_t tempDownsize;
|
||||||
|
|
||||||
|
if (inSize > 4096) {
|
||||||
|
pr_debug("IC input size(%d) cannot exceed 4096\n",
|
||||||
|
inSize);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize > 1024) {
|
||||||
|
pr_debug("IC output size(%d) cannot exceed 1024\n",
|
||||||
|
outSize);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((outSize << 3) < inSize) {
|
||||||
|
pr_debug("IC cannot downsize more than 8:1\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute downsizing coefficient */
|
||||||
|
/* Output of downsizing unit cannot be more than 1024 */
|
||||||
|
tempDownsize = 0;
|
||||||
|
tempSize = inSize;
|
||||||
|
while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
|
||||||
|
(tempDownsize < 2)) {
|
||||||
|
tempSize >>= 1;
|
||||||
|
tempDownsize++;
|
||||||
|
}
|
||||||
|
*downsizeCoeff = tempDownsize;
|
||||||
|
|
||||||
|
/* compute resizing coefficient using the following equation:
|
||||||
|
resizeCoeff = M*(SI -1)/(SO - 1)
|
||||||
|
where M = 2^13, SI - input size, SO - output size */
|
||||||
|
*resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
|
||||||
|
if (*resizeCoeff >= 16384L) {
|
||||||
|
pr_debug("Overflow on IC resize coefficient.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("resizing from %u -> %u pixels, "
|
||||||
|
"downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
|
||||||
|
*downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
|
||||||
|
((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Stripe parameters calculator */
|
||||||
|
/**************************************************************************
|
||||||
|
Notes:
|
||||||
|
MSW = the maximal width allowed for a stripe
|
||||||
|
i.MX31: 720, i.MX35: 800, i.MX37/51/53: 1024
|
||||||
|
cirr = the maximal inverse resizing ratio for which overlap in the input
|
||||||
|
is requested; typically cirr~2
|
||||||
|
flags
|
||||||
|
bit 0 - equal_stripes
|
||||||
|
0 each stripe is allowed to have independent parameters
|
||||||
|
for maximal image quality
|
||||||
|
1 the stripes are requested to have identical parameters
|
||||||
|
(except the base address), for maximal performance
|
||||||
|
bit 1 - vertical/horizontal
|
||||||
|
0 horizontal
|
||||||
|
1 vertical
|
||||||
|
|
||||||
|
If performance is the top priority (above image quality)
|
||||||
|
Avoid overlap, by setting CIRR = 0
|
||||||
|
This will also force effectively identical_stripes = 1
|
||||||
|
Choose IF & OF that corresponds to the same IOX/SX for both stripes
|
||||||
|
Choose IFW & OFW such that
|
||||||
|
IFW/IM, IFW/IF, OFW/OM, OFW/OF are even integers
|
||||||
|
The function returns an error status:
|
||||||
|
0: no error
|
||||||
|
1: invalid input parameters -> aborted without result
|
||||||
|
Valid parameters should satisfy the following conditions
|
||||||
|
IFW <= OFW, otherwise downsizing is required
|
||||||
|
- which is not supported yet
|
||||||
|
4 <= IFW,OFW, so some interpolation may be needed even without overlap
|
||||||
|
IM, OM, IF, OF should not vanish
|
||||||
|
2*IF <= IFW
|
||||||
|
so the frame can be split to two equal stripes, even without overlap
|
||||||
|
2*(OF+IF/irr_opt) <= OFW
|
||||||
|
so a valid positive INW exists even for equal stripes
|
||||||
|
OF <= MSW, otherwise, the left stripe cannot be sufficiently large
|
||||||
|
MSW < OFW, so splitting to stripes is required
|
||||||
|
OFW <= 2*MSW, so two stripes are sufficient
|
||||||
|
(this also implies that 2<=MSW)
|
||||||
|
2: OF is not a multiple of OM - not fully-supported yet
|
||||||
|
Output is produced but OW is not guaranited to be a multiple of OM
|
||||||
|
4: OFW reduced to be a multiple of OM
|
||||||
|
8: CIRR > 1: truncated to 1
|
||||||
|
Overlap is not supported (and not needed) y for upsizing)
|
||||||
|
**************************************************************************/
|
||||||
|
int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
|
||||||
|
/* input frame width;>1 */
|
||||||
|
unsigned int output_frame_width, /* output frame width; >1 */
|
||||||
|
const unsigned int maximal_stripe_width,
|
||||||
|
/* the maximal width allowed for a stripe */
|
||||||
|
const unsigned long long cirr, /* see above */
|
||||||
|
const unsigned int flags, /* see above */
|
||||||
|
u32 input_pixelformat,/* pixel format after of read channel*/
|
||||||
|
u32 output_pixelformat,/* pixel format after of write channel*/
|
||||||
|
struct stripe_param *left,
|
||||||
|
struct stripe_param *right)
|
||||||
|
{
|
||||||
|
const unsigned int irr_frac_bits = 13;
|
||||||
|
const unsigned long irr_steps = 1 << irr_frac_bits;
|
||||||
|
const u64 dirr = ((u64)1) << (32 - 2);
|
||||||
|
/* The maximum relative difference allowed between the irrs */
|
||||||
|
const u64 cr = ((u64)4) << 32;
|
||||||
|
/* The importance ratio between the two terms in the cost function below */
|
||||||
|
|
||||||
|
unsigned int status;
|
||||||
|
unsigned int temp;
|
||||||
|
unsigned int onw_min;
|
||||||
|
unsigned int inw = 0, onw = 0, inw_best = 0;
|
||||||
|
/* number of pixels in the left stripe NOT hidden by the right stripe */
|
||||||
|
u64 irr_opt; /* the optimal inverse resizing ratio */
|
||||||
|
u64 rr_opt; /* the optimal resizing ratio = 1/irr_opt*/
|
||||||
|
u64 dinw; /* the misalignment between the stripes */
|
||||||
|
/* (measured in units of input columns) */
|
||||||
|
u64 difwl, difwr = 0;
|
||||||
|
/* The number of input columns not reflected in the output */
|
||||||
|
/* the resizing ratio used for the right stripe is */
|
||||||
|
/* left->irr and right->irr respectively */
|
||||||
|
u64 cost, cost_min;
|
||||||
|
u64 div; /* result of division */
|
||||||
|
bool equal_stripes = (flags & 0x1) != 0;
|
||||||
|
bool vertical = (flags & 0x2) != 0;
|
||||||
|
|
||||||
|
unsigned int input_m, input_f, output_m, output_f; /* parameters for upsizing by stripes */
|
||||||
|
unsigned int resize_coeff;
|
||||||
|
unsigned int downsize_coeff;
|
||||||
|
|
||||||
|
status = 0;
|
||||||
|
|
||||||
|
if (vertical) {
|
||||||
|
input_f = 2;
|
||||||
|
input_m = 8;
|
||||||
|
output_f = 8;
|
||||||
|
output_m = 2;
|
||||||
|
} else {
|
||||||
|
input_f = f_calc(input_pixelformat, 0, NULL);
|
||||||
|
input_m = m_calc(input_pixelformat);
|
||||||
|
output_f = input_m;
|
||||||
|
output_m = m_calc(output_pixelformat);
|
||||||
|
}
|
||||||
|
if ((input_frame_width < 4) || (output_frame_width < 4))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
irr_opt = div_u64((((u64)(input_frame_width - 1)) << 32),
|
||||||
|
(output_frame_width - 1));
|
||||||
|
rr_opt = div_u64((((u64)(output_frame_width - 1)) << 32),
|
||||||
|
(input_frame_width - 1));
|
||||||
|
|
||||||
|
if ((input_m == 0) || (output_m == 0) || (input_f == 0) || (output_f == 0)
|
||||||
|
|| (input_frame_width < (2 * input_f))
|
||||||
|
|| ((((u64)output_frame_width) << 32) <
|
||||||
|
(2 * ((((u64)output_f) << 32) + (input_f * rr_opt))))
|
||||||
|
|| (maximal_stripe_width < output_f)
|
||||||
|
|| ((output_frame_width <= maximal_stripe_width)
|
||||||
|
&& (equal_stripes == 0))
|
||||||
|
|| ((2 * maximal_stripe_width) < output_frame_width))
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
if (output_f % output_m)
|
||||||
|
status += 2;
|
||||||
|
|
||||||
|
temp = truncate(0, (((u64)output_frame_width) << 32), output_m);
|
||||||
|
if (temp < output_frame_width) {
|
||||||
|
output_frame_width = temp;
|
||||||
|
status += 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
pr_debug("---------------->\n"
|
||||||
|
"if = %d\n"
|
||||||
|
"im = %d\n"
|
||||||
|
"of = %d\n"
|
||||||
|
"om = %d\n"
|
||||||
|
"irr_opt = %llu\n"
|
||||||
|
"rr_opt = %llu\n"
|
||||||
|
"cirr = %llu\n"
|
||||||
|
"pixel in = %08x\n"
|
||||||
|
"pixel out = %08x\n"
|
||||||
|
"ifw = %d\n"
|
||||||
|
"ofwidth = %d\n",
|
||||||
|
input_f,
|
||||||
|
input_m,
|
||||||
|
output_f,
|
||||||
|
output_m,
|
||||||
|
irr_opt,
|
||||||
|
rr_opt,
|
||||||
|
cirr,
|
||||||
|
input_pixelformat,
|
||||||
|
output_pixelformat,
|
||||||
|
input_frame_width,
|
||||||
|
output_frame_width
|
||||||
|
);
|
||||||
|
|
||||||
|
if (equal_stripes) {
|
||||||
|
if ((irr_opt > cirr) /* overlap in the input is not requested */
|
||||||
|
&& ((input_frame_width % (input_m << 1)) == 0)
|
||||||
|
&& ((input_frame_width % (input_f << 1)) == 0)
|
||||||
|
&& ((output_frame_width % (output_m << 1)) == 0)
|
||||||
|
&& ((output_frame_width % (output_f << 1)) == 0)) {
|
||||||
|
/* without overlap */
|
||||||
|
left->input_width = right->input_width = right->input_column =
|
||||||
|
input_frame_width >> 1;
|
||||||
|
left->output_width = right->output_width = right->output_column =
|
||||||
|
output_frame_width >> 1;
|
||||||
|
left->input_column = 0;
|
||||||
|
left->output_column = 0;
|
||||||
|
div = div_u64(((((u64)irr_steps) << 32) *
|
||||||
|
(right->input_width - 1)), (right->output_width - 1));
|
||||||
|
left->irr = right->irr = truncate(0, div, 1);
|
||||||
|
} else { /* with overlap */
|
||||||
|
onw = truncate(0, (((u64)output_frame_width - 1) << 32) >> 1,
|
||||||
|
output_f);
|
||||||
|
inw = truncate(0, onw * irr_opt, input_f);
|
||||||
|
/* this is the maximal inw which allows the same resizing ratio */
|
||||||
|
/* in both stripes */
|
||||||
|
onw = truncate(1, (inw * rr_opt), output_f);
|
||||||
|
div = div_u64((((u64)(irr_steps * inw)) <<
|
||||||
|
32), onw);
|
||||||
|
left->irr = right->irr = truncate(0, div, 1);
|
||||||
|
left->output_width = right->output_width =
|
||||||
|
output_frame_width - onw;
|
||||||
|
/* These are valid assignments for output_width, */
|
||||||
|
/* assuming output_f is a multiple of output_m */
|
||||||
|
div = (((u64)(left->output_width-1) * (left->irr)) << 32);
|
||||||
|
div = (((u64)1) << 32) + div_u64(div, irr_steps);
|
||||||
|
|
||||||
|
left->input_width = right->input_width = truncate(1, div, input_m);
|
||||||
|
|
||||||
|
div = div_u64((((u64)((right->output_width - 1) * right->irr)) <<
|
||||||
|
32), irr_steps);
|
||||||
|
difwr = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
|
||||||
|
div = div_u64((difwr + (((u64)input_f) << 32)), 2);
|
||||||
|
left->input_column = truncate(0, div, input_f);
|
||||||
|
|
||||||
|
|
||||||
|
/* This splits the truncated input columns evenly */
|
||||||
|
/* between the left and right margins */
|
||||||
|
right->input_column = left->input_column + inw;
|
||||||
|
left->output_column = 0;
|
||||||
|
right->output_column = onw;
|
||||||
|
}
|
||||||
|
if (left->input_width > left->output_width) {
|
||||||
|
if (calc_split_resize_coeffs(left->input_width,
|
||||||
|
left->output_width,
|
||||||
|
&resize_coeff,
|
||||||
|
&downsize_coeff) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (downsize_coeff > 0) {
|
||||||
|
left->irr = right->irr =
|
||||||
|
(downsize_coeff << 14) | resize_coeff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pr_debug("inw %d, onw %d, ilw %d, ilc %d, olw %d,"
|
||||||
|
" irw %d, irc %d, orw %d, orc %d, "
|
||||||
|
"difwr %llu, lirr %u\n",
|
||||||
|
inw, onw, left->input_width,
|
||||||
|
left->input_column, left->output_width,
|
||||||
|
right->input_width, right->input_column,
|
||||||
|
right->output_width,
|
||||||
|
right->output_column, difwr, left->irr);
|
||||||
|
} else { /* independent stripes */
|
||||||
|
onw_min = output_frame_width - maximal_stripe_width;
|
||||||
|
/* onw is a multiple of output_f, in the range */
|
||||||
|
/* [max(output_f,output_frame_width-maximal_stripe_width),*/
|
||||||
|
/*min(output_frame_width-2,maximal_stripe_width)] */
|
||||||
|
/* definitely beyond the cost of any valid setting */
|
||||||
|
cost_min = (((u64)input_frame_width) << 32) + cr;
|
||||||
|
onw = truncate(0, ((u64)maximal_stripe_width), output_f);
|
||||||
|
if (output_frame_width - onw == 1)
|
||||||
|
onw -= output_f; /* => onw and output_frame_width-1-onw are positive */
|
||||||
|
inw = truncate(0, onw * irr_opt, input_f);
|
||||||
|
/* this is the maximal inw which allows the same resizing ratio */
|
||||||
|
/* in both stripes */
|
||||||
|
onw = truncate(1, inw * rr_opt, output_f);
|
||||||
|
do {
|
||||||
|
div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
|
||||||
|
left->irr = truncate(0, div, 1);
|
||||||
|
div = div_u64((((u64)(onw * left->irr)) << 32),
|
||||||
|
irr_steps);
|
||||||
|
dinw = (((u64)inw) << 32) - div;
|
||||||
|
|
||||||
|
div = div_u64((((u64)((output_frame_width - 1 - onw) * left->irr)) <<
|
||||||
|
32), irr_steps);
|
||||||
|
|
||||||
|
difwl = (((u64)(input_frame_width - 1 - inw)) << 32) - div;
|
||||||
|
|
||||||
|
cost = difwl + (((u64)(cr * dinw)) >> 32);
|
||||||
|
|
||||||
|
if (cost < cost_min) {
|
||||||
|
inw_best = inw;
|
||||||
|
cost_min = cost;
|
||||||
|
}
|
||||||
|
|
||||||
|
inw -= input_f;
|
||||||
|
onw = truncate(1, inw * rr_opt, output_f);
|
||||||
|
/* This is the minimal onw which allows the same resizing ratio */
|
||||||
|
/* in both stripes */
|
||||||
|
} while (onw >= onw_min);
|
||||||
|
|
||||||
|
inw = inw_best;
|
||||||
|
onw = truncate(1, inw * rr_opt, output_f);
|
||||||
|
div = div_u64((((u64)(irr_steps * inw)) << 32), onw);
|
||||||
|
left->irr = truncate(0, div, 1);
|
||||||
|
|
||||||
|
left->output_width = onw;
|
||||||
|
right->output_width = output_frame_width - onw;
|
||||||
|
/* These are valid assignments for output_width, */
|
||||||
|
/* assuming output_f is a multiple of output_m */
|
||||||
|
left->input_width = truncate(1, ((u64)(inw + 1)) << 32, input_m);
|
||||||
|
right->input_width = truncate(1, ((u64)(input_frame_width - inw)) <<
|
||||||
|
32, input_m);
|
||||||
|
|
||||||
|
div = div_u64((((u64)(irr_steps * (input_frame_width - 1 - inw))) <<
|
||||||
|
32), (right->output_width - 1));
|
||||||
|
right->irr = truncate(0, div, 1);
|
||||||
|
temp = truncate(0, ((u64)left->irr) * ((((u64)1) << 32) + dirr), 1);
|
||||||
|
if (temp < right->irr)
|
||||||
|
right->irr = temp;
|
||||||
|
div = div_u64(((u64)((right->output_width - 1) * right->irr) <<
|
||||||
|
32), irr_steps);
|
||||||
|
difwr = (u64)(input_frame_width - 1 - inw) - div;
|
||||||
|
|
||||||
|
|
||||||
|
div = div_u64((difwr + (((u64)input_f) << 32)), 2);
|
||||||
|
left->input_column = truncate(0, div, input_f);
|
||||||
|
|
||||||
|
/* This splits the truncated input columns evenly */
|
||||||
|
/* between the left and right margins */
|
||||||
|
right->input_column = left->input_column + inw;
|
||||||
|
left->output_column = 0;
|
||||||
|
right->output_column = onw;
|
||||||
|
if (left->input_width > left->output_width) {
|
||||||
|
if (calc_split_resize_coeffs(left->input_width,
|
||||||
|
left->output_width,
|
||||||
|
&resize_coeff,
|
||||||
|
&downsize_coeff) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
left->irr = (downsize_coeff << 14) | resize_coeff;
|
||||||
|
}
|
||||||
|
if (right->input_width > right->output_width) {
|
||||||
|
if (calc_split_resize_coeffs(right->input_width,
|
||||||
|
right->output_width,
|
||||||
|
&resize_coeff,
|
||||||
|
&downsize_coeff) < 0)
|
||||||
|
return -EINVAL;
|
||||||
|
right->irr = (downsize_coeff << 14) | resize_coeff;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return status;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_calc_stripes_sizes);
|
|
@ -0,0 +1,816 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2008-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file ipu_capture.c
|
||||||
|
*
|
||||||
|
* @brief IPU capture dase functions
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "ipu_prv.h"
|
||||||
|
#include "ipu_regs.h"
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_mclk_set
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param pixel_clk desired pixel clock frequency in Hz
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success or negative error code on fail
|
||||||
|
*/
|
||||||
|
int _ipu_csi_mclk_set(struct ipu_soc *ipu, uint32_t pixel_clk, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
int32_t div_ratio;
|
||||||
|
|
||||||
|
div_ratio = (clk_get_rate(ipu->ipu_clk) / pixel_clk) - 1;
|
||||||
|
|
||||||
|
if (div_ratio > 0xFF || div_ratio < 0) {
|
||||||
|
dev_dbg(ipu->dev, "value of pixel_clk extends normal range\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
|
||||||
|
temp &= ~CSI_SENS_CONF_DIVRATIO_MASK;
|
||||||
|
ipu_csi_write(ipu, csi, temp |
|
||||||
|
(div_ratio << CSI_SENS_CONF_DIVRATIO_SHIFT),
|
||||||
|
CSI_SENS_CONF);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_init_interface
|
||||||
|
* Sets initial values for the CSI registers.
|
||||||
|
* The width and height of the sensor and the actual frame size will be
|
||||||
|
* set to the same values.
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param width Sensor width
|
||||||
|
* @param height Sensor height
|
||||||
|
* @param pixel_fmt pixel format
|
||||||
|
* @param cfg_param ipu_csi_signal_cfg_t structure
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return 0 for success, -EINVAL for error
|
||||||
|
*/
|
||||||
|
int32_t
|
||||||
|
ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
|
||||||
|
uint32_t pixel_fmt, ipu_csi_signal_cfg_t cfg_param)
|
||||||
|
{
|
||||||
|
uint32_t data = 0;
|
||||||
|
uint32_t csi = cfg_param.csi;
|
||||||
|
|
||||||
|
/* Set SENS_DATA_FORMAT bits (8, 9 and 10)
|
||||||
|
RGB or YUV444 is 0 which is current value in data so not set
|
||||||
|
explicitly
|
||||||
|
This is also the default value if attempts are made to set it to
|
||||||
|
something invalid. */
|
||||||
|
switch (pixel_fmt) {
|
||||||
|
case IPU_PIX_FMT_YUYV:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_YUYV;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_UYVY:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_YUV422_UYVY;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGB24:
|
||||||
|
case IPU_PIX_FMT_BGR24:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB_YUV444;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_GENERIC:
|
||||||
|
case IPU_PIX_FMT_GENERIC_16:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_BAYER;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGB565:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB565;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGB555:
|
||||||
|
cfg_param.data_fmt = CSI_SENS_CONF_DATA_FMT_RGB555;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Set the CSI_SENS_CONF register remaining fields */
|
||||||
|
data |= cfg_param.data_width << CSI_SENS_CONF_DATA_WIDTH_SHIFT |
|
||||||
|
cfg_param.data_fmt << CSI_SENS_CONF_DATA_FMT_SHIFT |
|
||||||
|
cfg_param.data_pol << CSI_SENS_CONF_DATA_POL_SHIFT |
|
||||||
|
cfg_param.Vsync_pol << CSI_SENS_CONF_VSYNC_POL_SHIFT |
|
||||||
|
cfg_param.Hsync_pol << CSI_SENS_CONF_HSYNC_POL_SHIFT |
|
||||||
|
cfg_param.pixclk_pol << CSI_SENS_CONF_PIX_CLK_POL_SHIFT |
|
||||||
|
cfg_param.ext_vsync << CSI_SENS_CONF_EXT_VSYNC_SHIFT |
|
||||||
|
cfg_param.clk_mode << CSI_SENS_CONF_SENS_PRTCL_SHIFT |
|
||||||
|
cfg_param.pack_tight << CSI_SENS_CONF_PACK_TIGHT_SHIFT |
|
||||||
|
cfg_param.force_eof << CSI_SENS_CONF_FORCE_EOF_SHIFT |
|
||||||
|
cfg_param.data_en_pol << CSI_SENS_CONF_DATA_EN_POL_SHIFT;
|
||||||
|
|
||||||
|
_ipu_get(ipu);
|
||||||
|
|
||||||
|
mutex_lock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
ipu_csi_write(ipu, csi, data, CSI_SENS_CONF);
|
||||||
|
|
||||||
|
/* Setup sensor frame size */
|
||||||
|
ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_SENS_FRM_SIZE);
|
||||||
|
|
||||||
|
/* Set CCIR registers */
|
||||||
|
if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE) {
|
||||||
|
ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
|
||||||
|
ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
|
||||||
|
} else if (cfg_param.clk_mode == IPU_CSI_CLK_MODE_CCIR656_INTERLACED) {
|
||||||
|
if (width == 720 && height == 625) {
|
||||||
|
/* PAL case */
|
||||||
|
/*
|
||||||
|
* Field0BlankEnd = 0x6, Field0BlankStart = 0x2,
|
||||||
|
* Field0ActiveEnd = 0x4, Field0ActiveStart = 0
|
||||||
|
*/
|
||||||
|
ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_1);
|
||||||
|
/*
|
||||||
|
* Field1BlankEnd = 0x7, Field1BlankStart = 0x3,
|
||||||
|
* Field1ActiveEnd = 0x5, Field1ActiveStart = 0x1
|
||||||
|
*/
|
||||||
|
ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_2);
|
||||||
|
|
||||||
|
ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
|
||||||
|
|
||||||
|
} else if (width == 720 && height == 525) {
|
||||||
|
/* NTSC case */
|
||||||
|
/*
|
||||||
|
* Field0BlankEnd = 0x7, Field0BlankStart = 0x3,
|
||||||
|
* Field0ActiveEnd = 0x5, Field0ActiveStart = 0x1
|
||||||
|
*/
|
||||||
|
ipu_csi_write(ipu, csi, 0xD07DF, CSI_CCIR_CODE_1);
|
||||||
|
/*
|
||||||
|
* Field1BlankEnd = 0x6, Field1BlankStart = 0x2,
|
||||||
|
* Field1ActiveEnd = 0x4, Field1ActiveStart = 0
|
||||||
|
*/
|
||||||
|
ipu_csi_write(ipu, csi, 0x40596, CSI_CCIR_CODE_2);
|
||||||
|
ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
|
||||||
|
} else {
|
||||||
|
dev_err(ipu->dev, "Unsupported CCIR656 interlaced "
|
||||||
|
"video mode\n");
|
||||||
|
mutex_unlock(&ipu->mutex_lock);
|
||||||
|
_ipu_put(ipu);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
_ipu_csi_ccir_err_detection_enable(ipu, csi);
|
||||||
|
} else if ((cfg_param.clk_mode ==
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR) ||
|
||||||
|
(cfg_param.clk_mode ==
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR) ||
|
||||||
|
(cfg_param.clk_mode ==
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR) ||
|
||||||
|
(cfg_param.clk_mode ==
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR)) {
|
||||||
|
ipu_csi_write(ipu, csi, 0x40030, CSI_CCIR_CODE_1);
|
||||||
|
ipu_csi_write(ipu, csi, 0xFF0000, CSI_CCIR_CODE_3);
|
||||||
|
_ipu_csi_ccir_err_detection_enable(ipu, csi);
|
||||||
|
} else if ((cfg_param.clk_mode == IPU_CSI_CLK_MODE_GATED_CLK) ||
|
||||||
|
(cfg_param.clk_mode == IPU_CSI_CLK_MODE_NONGATED_CLK)) {
|
||||||
|
_ipu_csi_ccir_err_detection_disable(ipu, csi);
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "CSI_SENS_CONF = 0x%08X\n",
|
||||||
|
ipu_csi_read(ipu, csi, CSI_SENS_CONF));
|
||||||
|
dev_dbg(ipu->dev, "CSI_ACT_FRM_SIZE = 0x%08X\n",
|
||||||
|
ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE));
|
||||||
|
|
||||||
|
mutex_unlock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
_ipu_put(ipu);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_init_interface);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_get_sensor_protocol
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns sensor protocol
|
||||||
|
*/
|
||||||
|
int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
_ipu_get(ipu);
|
||||||
|
ret = (ipu_csi_read(ipu, csi, CSI_SENS_CONF) &
|
||||||
|
CSI_SENS_CONF_SENS_PRTCL_MASK) >>
|
||||||
|
CSI_SENS_CONF_SENS_PRTCL_SHIFT;
|
||||||
|
_ipu_put(ipu);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_get_sensor_protocol);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_enable_mclk
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
* @param flag true to enable mclk, false to disable mclk
|
||||||
|
* @param wait true to wait 100ms make clock stable, false not wait
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success
|
||||||
|
*/
|
||||||
|
int ipu_csi_enable_mclk(struct ipu_soc *ipu, int csi, bool flag, bool wait)
|
||||||
|
{
|
||||||
|
/* Return immediately if there is no csi_clk to manage */
|
||||||
|
if (ipu->csi_clk[csi] == NULL)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
if (flag) {
|
||||||
|
clk_enable(ipu->csi_clk[csi]);
|
||||||
|
if (wait == true)
|
||||||
|
msleep(10);
|
||||||
|
} else {
|
||||||
|
clk_disable(ipu->csi_clk[csi]);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_enable_mclk);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_get_window_size
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param width pointer to window width
|
||||||
|
* @param height pointer to window height
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
_ipu_get(ipu);
|
||||||
|
|
||||||
|
mutex_lock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
reg = ipu_csi_read(ipu, csi, CSI_ACT_FRM_SIZE);
|
||||||
|
*width = (reg & 0xFFFF) + 1;
|
||||||
|
*height = (reg >> 16 & 0xFFFF) + 1;
|
||||||
|
|
||||||
|
mutex_unlock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
_ipu_put(ipu);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_get_window_size);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_set_window_size
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param width window width
|
||||||
|
* @param height window height
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi)
|
||||||
|
{
|
||||||
|
_ipu_get(ipu);
|
||||||
|
|
||||||
|
mutex_lock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
ipu_csi_write(ipu, csi, (width - 1) | (height - 1) << 16, CSI_ACT_FRM_SIZE);
|
||||||
|
|
||||||
|
mutex_unlock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
_ipu_put(ipu);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_set_window_size);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* ipu_csi_set_window_pos
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param left uint32 window x start
|
||||||
|
* @param top uint32 window y start
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
_ipu_get(ipu);
|
||||||
|
|
||||||
|
mutex_lock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
|
||||||
|
temp &= ~(CSI_HSC_MASK | CSI_VSC_MASK);
|
||||||
|
temp |= ((top << CSI_VSC_SHIFT) | (left << CSI_HSC_SHIFT));
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
|
||||||
|
|
||||||
|
mutex_unlock(&ipu->mutex_lock);
|
||||||
|
|
||||||
|
_ipu_put(ipu);
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_csi_set_window_pos);
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_horizontal_downsize_enable
|
||||||
|
* Enable horizontal downsizing(decimation) by 2.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_horizontal_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
|
||||||
|
temp |= CSI_HORI_DOWNSIZE_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_horizontal_downsize_disable
|
||||||
|
* Disable horizontal downsizing(decimation) by 2.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_horizontal_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
|
||||||
|
temp &= ~CSI_HORI_DOWNSIZE_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_vertical_downsize_enable
|
||||||
|
* Enable vertical downsizing(decimation) by 2.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_vertical_downsize_enable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
|
||||||
|
temp |= CSI_VERT_DOWNSIZE_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_vertical_downsize_disable
|
||||||
|
* Disable vertical downsizing(decimation) by 2.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_vertical_downsize_disable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_OUT_FRM_CTRL);
|
||||||
|
temp &= ~CSI_VERT_DOWNSIZE_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_OUT_FRM_CTRL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_set_test_generator
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param active 1 for active and 0 for inactive
|
||||||
|
* @param r_value red value for the generated pattern of even pixel
|
||||||
|
* @param g_value green value for the generated pattern of even
|
||||||
|
* pixel
|
||||||
|
* @param b_value blue value for the generated pattern of even pixel
|
||||||
|
* @param pixel_clk desired pixel clock frequency in Hz
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
|
||||||
|
uint32_t g_value, uint32_t b_value, uint32_t pix_clk, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_TST_CTRL);
|
||||||
|
|
||||||
|
if (active == false) {
|
||||||
|
temp &= ~CSI_TEST_GEN_MODE_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
|
||||||
|
} else {
|
||||||
|
/* Set sensb_mclk div_ratio*/
|
||||||
|
_ipu_csi_mclk_set(ipu, pix_clk, csi);
|
||||||
|
|
||||||
|
temp &= ~(CSI_TEST_GEN_R_MASK | CSI_TEST_GEN_G_MASK |
|
||||||
|
CSI_TEST_GEN_B_MASK);
|
||||||
|
temp |= CSI_TEST_GEN_MODE_EN;
|
||||||
|
temp |= (r_value << CSI_TEST_GEN_R_SHIFT) |
|
||||||
|
(g_value << CSI_TEST_GEN_G_SHIFT) |
|
||||||
|
(b_value << CSI_TEST_GEN_B_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_TST_CTRL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_ccir_err_detection_en
|
||||||
|
* Enable error detection and correction for
|
||||||
|
* CCIR interlaced mode with protection bit.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
|
||||||
|
temp |= CSI_CCIR_ERR_DET_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_ccir_err_detection_disable
|
||||||
|
* Disable error detection and correction for
|
||||||
|
* CCIR interlaced mode with protection bit.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*/
|
||||||
|
void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_CCIR_CODE_1);
|
||||||
|
temp &= ~CSI_CCIR_ERR_DET_EN;
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_CCIR_CODE_1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_set_mipi_di
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param num MIPI data identifier 0-3 handled by CSI
|
||||||
|
* @param di_val data identifier value
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success or negative error code on fail
|
||||||
|
*/
|
||||||
|
int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
if (di_val > 0xFFL) {
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_MIPI_DI);
|
||||||
|
|
||||||
|
switch (num) {
|
||||||
|
case IPU_CSI_MIPI_DI0:
|
||||||
|
temp &= ~CSI_MIPI_DI0_MASK;
|
||||||
|
temp |= (di_val << CSI_MIPI_DI0_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
|
||||||
|
break;
|
||||||
|
case IPU_CSI_MIPI_DI1:
|
||||||
|
temp &= ~CSI_MIPI_DI1_MASK;
|
||||||
|
temp |= (di_val << CSI_MIPI_DI1_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
|
||||||
|
break;
|
||||||
|
case IPU_CSI_MIPI_DI2:
|
||||||
|
temp &= ~CSI_MIPI_DI2_MASK;
|
||||||
|
temp |= (di_val << CSI_MIPI_DI2_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
|
||||||
|
break;
|
||||||
|
case IPU_CSI_MIPI_DI3:
|
||||||
|
temp &= ~CSI_MIPI_DI3_MASK;
|
||||||
|
temp |= (di_val << CSI_MIPI_DI3_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_MIPI_DI);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
err:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_set_skip_isp
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param skip select frames to be skipped and set the
|
||||||
|
* correspond bits to 1
|
||||||
|
* @param max_ratio number of frames in a skipping set and the
|
||||||
|
* maximum value of max_ratio is 5
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success or negative error code on fail
|
||||||
|
*/
|
||||||
|
int _ipu_csi_set_skip_isp(struct ipu_soc *ipu, uint32_t skip, uint32_t max_ratio, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
if (max_ratio > 5) {
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_SKIP);
|
||||||
|
temp &= ~(CSI_MAX_RATIO_SKIP_ISP_MASK | CSI_SKIP_ISP_MASK);
|
||||||
|
temp |= (max_ratio << CSI_MAX_RATIO_SKIP_ISP_SHIFT) |
|
||||||
|
(skip << CSI_SKIP_ISP_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_SKIP);
|
||||||
|
|
||||||
|
err:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_set_skip_smfc
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param skip select frames to be skipped and set the
|
||||||
|
* correspond bits to 1
|
||||||
|
* @param max_ratio number of frames in a skipping set and the
|
||||||
|
* maximum value of max_ratio is 5
|
||||||
|
* @param id csi to smfc skipping id
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success or negative error code on fail
|
||||||
|
*/
|
||||||
|
int _ipu_csi_set_skip_smfc(struct ipu_soc *ipu, uint32_t skip,
|
||||||
|
uint32_t max_ratio, uint32_t id, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
if (max_ratio > 5 || id > 3) {
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
temp = ipu_csi_read(ipu, csi, CSI_SKIP);
|
||||||
|
temp &= ~(CSI_MAX_RATIO_SKIP_SMFC_MASK | CSI_ID_2_SKIP_MASK |
|
||||||
|
CSI_SKIP_SMFC_MASK);
|
||||||
|
temp |= (max_ratio << CSI_MAX_RATIO_SKIP_SMFC_SHIFT) |
|
||||||
|
(id << CSI_ID_2_SKIP_SHIFT) |
|
||||||
|
(skip << CSI_SKIP_SMFC_SHIFT);
|
||||||
|
ipu_csi_write(ipu, csi, temp, CSI_SKIP);
|
||||||
|
|
||||||
|
err:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_smfc_init
|
||||||
|
* Map CSI frames to IDMAC channels.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param channel IDMAC channel 0-3
|
||||||
|
* @param mipi_id mipi id number 0-3
|
||||||
|
* @param csi csi0 or csi1
|
||||||
|
*/
|
||||||
|
void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_smfc_read(ipu, SMFC_MAP);
|
||||||
|
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_MEM0:
|
||||||
|
temp &= ~SMFC_MAP_CH0_MASK;
|
||||||
|
temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH0_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM1:
|
||||||
|
temp &= ~SMFC_MAP_CH1_MASK;
|
||||||
|
temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH1_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM2:
|
||||||
|
temp &= ~SMFC_MAP_CH2_MASK;
|
||||||
|
temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH2_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM3:
|
||||||
|
temp &= ~SMFC_MAP_CH3_MASK;
|
||||||
|
temp |= ((csi << 2) | mipi_id) << SMFC_MAP_CH3_SHIFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_smfc_write(ipu, temp, SMFC_MAP);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_smfc_set_wmc
|
||||||
|
* Caution: The number of required channels, the enabled channels
|
||||||
|
* and the FIFO size per channel are configured restrictedly.
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param channel IDMAC channel 0-3
|
||||||
|
* @param set set 1 or clear 0
|
||||||
|
* @param level water mark level when FIFO is on the
|
||||||
|
* relative size
|
||||||
|
*/
|
||||||
|
void _ipu_smfc_set_wmc(struct ipu_soc *ipu, ipu_channel_t channel, bool set, uint32_t level)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_smfc_read(ipu, SMFC_WMC);
|
||||||
|
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_MEM0:
|
||||||
|
if (set == true) {
|
||||||
|
temp &= ~SMFC_WM0_SET_MASK;
|
||||||
|
temp |= level << SMFC_WM0_SET_SHIFT;
|
||||||
|
} else {
|
||||||
|
temp &= ~SMFC_WM0_CLR_MASK;
|
||||||
|
temp |= level << SMFC_WM0_CLR_SHIFT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CSI_MEM1:
|
||||||
|
if (set == true) {
|
||||||
|
temp &= ~SMFC_WM1_SET_MASK;
|
||||||
|
temp |= level << SMFC_WM1_SET_SHIFT;
|
||||||
|
} else {
|
||||||
|
temp &= ~SMFC_WM1_CLR_MASK;
|
||||||
|
temp |= level << SMFC_WM1_CLR_SHIFT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CSI_MEM2:
|
||||||
|
if (set == true) {
|
||||||
|
temp &= ~SMFC_WM2_SET_MASK;
|
||||||
|
temp |= level << SMFC_WM2_SET_SHIFT;
|
||||||
|
} else {
|
||||||
|
temp &= ~SMFC_WM2_CLR_MASK;
|
||||||
|
temp |= level << SMFC_WM2_CLR_SHIFT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case CSI_MEM3:
|
||||||
|
if (set == true) {
|
||||||
|
temp &= ~SMFC_WM3_SET_MASK;
|
||||||
|
temp |= level << SMFC_WM3_SET_SHIFT;
|
||||||
|
} else {
|
||||||
|
temp &= ~SMFC_WM3_CLR_MASK;
|
||||||
|
temp |= level << SMFC_WM3_CLR_SHIFT;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_smfc_write(ipu, temp, SMFC_WMC);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_smfc_set_burst_size
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param channel IDMAC channel 0-3
|
||||||
|
* @param bs burst size of IDMAC channel,
|
||||||
|
* the value programmed here shoud be BURST_SIZE-1
|
||||||
|
*/
|
||||||
|
void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs)
|
||||||
|
{
|
||||||
|
uint32_t temp;
|
||||||
|
|
||||||
|
temp = ipu_smfc_read(ipu, SMFC_BS);
|
||||||
|
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_MEM0:
|
||||||
|
temp &= ~SMFC_BS0_MASK;
|
||||||
|
temp |= bs << SMFC_BS0_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM1:
|
||||||
|
temp &= ~SMFC_BS1_MASK;
|
||||||
|
temp |= bs << SMFC_BS1_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM2:
|
||||||
|
temp &= ~SMFC_BS2_MASK;
|
||||||
|
temp |= bs << SMFC_BS2_SHIFT;
|
||||||
|
break;
|
||||||
|
case CSI_MEM3:
|
||||||
|
temp &= ~SMFC_BS3_MASK;
|
||||||
|
temp |= bs << SMFC_BS3_SHIFT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_smfc_write(ipu, temp, SMFC_BS);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_init
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param channel IDMAC channel
|
||||||
|
* @param csi csi 0 or csi 1
|
||||||
|
*
|
||||||
|
* @return Returns 0 on success or negative error code on fail
|
||||||
|
*/
|
||||||
|
int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi)
|
||||||
|
{
|
||||||
|
uint32_t csi_sens_conf, csi_dest;
|
||||||
|
int retval = 0;
|
||||||
|
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_MEM0:
|
||||||
|
case CSI_MEM1:
|
||||||
|
case CSI_MEM2:
|
||||||
|
case CSI_MEM3:
|
||||||
|
csi_dest = CSI_DATA_DEST_IDMAC;
|
||||||
|
break;
|
||||||
|
case CSI_PRP_ENC_MEM:
|
||||||
|
case CSI_PRP_VF_MEM:
|
||||||
|
csi_dest = CSI_DATA_DEST_IC;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
retval = -EINVAL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
|
csi_sens_conf = ipu_csi_read(ipu, csi, CSI_SENS_CONF);
|
||||||
|
csi_sens_conf &= ~CSI_SENS_CONF_DATA_DEST_MASK;
|
||||||
|
ipu_csi_write(ipu, csi, csi_sens_conf | (csi_dest <<
|
||||||
|
CSI_SENS_CONF_DATA_DEST_SHIFT), CSI_SENS_CONF);
|
||||||
|
err:
|
||||||
|
return retval;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* csi_irq_handler
|
||||||
|
*
|
||||||
|
* @param irq interrupt id
|
||||||
|
* @param dev_id pointer to ipu handler
|
||||||
|
*
|
||||||
|
* @return Returns if irq is handled
|
||||||
|
*/
|
||||||
|
static irqreturn_t csi_irq_handler(int irq, void *dev_id)
|
||||||
|
{
|
||||||
|
struct ipu_soc *ipu = dev_id;
|
||||||
|
struct completion *comp = &ipu->csi_comp;
|
||||||
|
|
||||||
|
complete(comp);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* _ipu_csi_wait4eof
|
||||||
|
*
|
||||||
|
* @param ipu ipu handler
|
||||||
|
* @param channel IDMAC channel
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
int irq = 0;
|
||||||
|
|
||||||
|
if (channel == CSI_MEM0)
|
||||||
|
irq = IPU_IRQ_CSI0_OUT_EOF;
|
||||||
|
else if (channel == CSI_MEM1)
|
||||||
|
irq = IPU_IRQ_CSI1_OUT_EOF;
|
||||||
|
else if (channel == CSI_MEM2)
|
||||||
|
irq = IPU_IRQ_CSI2_OUT_EOF;
|
||||||
|
else if (channel == CSI_MEM3)
|
||||||
|
irq = IPU_IRQ_CSI3_OUT_EOF;
|
||||||
|
else if (channel == CSI_PRP_ENC_MEM)
|
||||||
|
irq = IPU_IRQ_PRP_ENC_OUT_EOF;
|
||||||
|
else if (channel == CSI_PRP_VF_MEM)
|
||||||
|
irq = IPU_IRQ_PRP_VF_OUT_EOF;
|
||||||
|
else{
|
||||||
|
dev_err(ipu->dev, "Not a CSI channel\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
init_completion(&ipu->csi_comp);
|
||||||
|
ret = ipu_request_irq(ipu, irq, csi_irq_handler, 0, NULL, ipu);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "CSI irq %d in use\n", irq);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ret = wait_for_completion_timeout(&ipu->csi_comp, msecs_to_jiffies(500));
|
||||||
|
ipu_free_irq(ipu, irq, ipu);
|
||||||
|
dev_dbg(ipu->dev, "CSI stop timeout - %d * 10ms\n", 5 - ret);
|
||||||
|
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,924 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @file ipu_ic.c
|
||||||
|
*
|
||||||
|
* @brief IPU IC functions
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
#include <linux/errno.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
#include <linux/spinlock.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
#include <linux/videodev2.h>
|
||||||
|
|
||||||
|
#include "ipu_param_mem.h"
|
||||||
|
#include "ipu_regs.h"
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IC_TASK_VIEWFINDER,
|
||||||
|
IC_TASK_ENCODER,
|
||||||
|
IC_TASK_POST_PROCESSOR
|
||||||
|
};
|
||||||
|
|
||||||
|
static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
|
||||||
|
ipu_color_space_t out_format, int csc_index);
|
||||||
|
|
||||||
|
static int _calc_resize_coeffs(struct ipu_soc *ipu,
|
||||||
|
uint32_t inSize, uint32_t outSize,
|
||||||
|
uint32_t *resizeCoeff,
|
||||||
|
uint32_t *downsizeCoeff);
|
||||||
|
|
||||||
|
void _ipu_vdi_set_top_field_man(struct ipu_soc *ipu, bool top_field_0)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_vdi_read(ipu, VDI_C);
|
||||||
|
if (top_field_0)
|
||||||
|
reg &= ~VDI_C_TOP_FIELD_MAN_1;
|
||||||
|
else
|
||||||
|
reg |= VDI_C_TOP_FIELD_MAN_1;
|
||||||
|
ipu_vdi_write(ipu, reg, VDI_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_vdi_set_motion(struct ipu_soc *ipu, ipu_motion_sel motion_sel)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_vdi_read(ipu, VDI_C);
|
||||||
|
reg &= ~(VDI_C_MOT_SEL_FULL | VDI_C_MOT_SEL_MED | VDI_C_MOT_SEL_LOW);
|
||||||
|
if (motion_sel == HIGH_MOTION)
|
||||||
|
reg |= VDI_C_MOT_SEL_FULL;
|
||||||
|
else if (motion_sel == MED_MOTION)
|
||||||
|
reg |= VDI_C_MOT_SEL_MED;
|
||||||
|
else
|
||||||
|
reg |= VDI_C_MOT_SEL_LOW;
|
||||||
|
|
||||||
|
ipu_vdi_write(ipu, reg, VDI_C);
|
||||||
|
dev_dbg(ipu->dev, "VDI_C = \t0x%08X\n", reg);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ic_dump_register(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
printk(KERN_DEBUG "IC_CONF = \t0x%08X\n", ipu_ic_read(ipu, IC_CONF));
|
||||||
|
printk(KERN_DEBUG "IC_PRP_ENC_RSC = \t0x%08X\n",
|
||||||
|
ipu_ic_read(ipu, IC_PRP_ENC_RSC));
|
||||||
|
printk(KERN_DEBUG "IC_PRP_VF_RSC = \t0x%08X\n",
|
||||||
|
ipu_ic_read(ipu, IC_PRP_VF_RSC));
|
||||||
|
printk(KERN_DEBUG "IC_PP_RSC = \t0x%08X\n", ipu_ic_read(ipu, IC_PP_RSC));
|
||||||
|
printk(KERN_DEBUG "IC_IDMAC_1 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_1));
|
||||||
|
printk(KERN_DEBUG "IC_IDMAC_2 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_2));
|
||||||
|
printk(KERN_DEBUG "IC_IDMAC_3 = \t0x%08X\n", ipu_ic_read(ipu, IC_IDMAC_3));
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel)
|
||||||
|
{
|
||||||
|
uint32_t ic_conf;
|
||||||
|
|
||||||
|
ic_conf = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_PRP_VF_MEM:
|
||||||
|
case MEM_PRP_VF_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPVF_EN;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_PRP_VF_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPVF_EN;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPVF_EN | IC_CONF_RWS_EN ;
|
||||||
|
break;
|
||||||
|
case MEM_ROT_VF_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPVF_ROT_EN;
|
||||||
|
break;
|
||||||
|
case CSI_PRP_ENC_MEM:
|
||||||
|
case MEM_PRP_ENC_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPENC_EN;
|
||||||
|
break;
|
||||||
|
case MEM_ROT_ENC_MEM:
|
||||||
|
ic_conf |= IC_CONF_PRPENC_ROT_EN;
|
||||||
|
break;
|
||||||
|
case MEM_PP_MEM:
|
||||||
|
ic_conf |= IC_CONF_PP_EN;
|
||||||
|
break;
|
||||||
|
case MEM_ROT_PP_MEM:
|
||||||
|
ic_conf |= IC_CONF_PP_ROT_EN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ipu_ic_write(ipu, ic_conf, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel)
|
||||||
|
{
|
||||||
|
uint32_t ic_conf;
|
||||||
|
|
||||||
|
ic_conf = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
switch (channel) {
|
||||||
|
case CSI_PRP_VF_MEM:
|
||||||
|
case MEM_PRP_VF_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PRPVF_EN;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_PRP_VF_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PRPVF_EN;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_MEM:
|
||||||
|
ic_conf &= ~(IC_CONF_PRPVF_EN | IC_CONF_RWS_EN);
|
||||||
|
break;
|
||||||
|
case MEM_ROT_VF_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PRPVF_ROT_EN;
|
||||||
|
break;
|
||||||
|
case CSI_PRP_ENC_MEM:
|
||||||
|
case MEM_PRP_ENC_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PRPENC_EN;
|
||||||
|
break;
|
||||||
|
case MEM_ROT_ENC_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PRPENC_ROT_EN;
|
||||||
|
break;
|
||||||
|
case MEM_PP_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PP_EN;
|
||||||
|
break;
|
||||||
|
case MEM_ROT_PP_MEM:
|
||||||
|
ic_conf &= ~IC_CONF_PP_ROT_EN;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ipu_ic_write(ipu, ic_conf, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t pixel_fmt;
|
||||||
|
uint32_t pix_per_burst;
|
||||||
|
|
||||||
|
reg = ((params->mem_prp_vf_mem.in_height-1) << 16) |
|
||||||
|
(params->mem_prp_vf_mem.in_width-1);
|
||||||
|
ipu_vdi_write(ipu, reg, VDI_FSIZE);
|
||||||
|
|
||||||
|
/* Full motion, only vertical filter is used
|
||||||
|
Burst size is 4 accesses */
|
||||||
|
if (params->mem_prp_vf_mem.in_pixel_fmt ==
|
||||||
|
IPU_PIX_FMT_UYVY ||
|
||||||
|
params->mem_prp_vf_mem.in_pixel_fmt ==
|
||||||
|
IPU_PIX_FMT_YUYV) {
|
||||||
|
pixel_fmt = VDI_C_CH_422;
|
||||||
|
pix_per_burst = 32;
|
||||||
|
} else {
|
||||||
|
pixel_fmt = VDI_C_CH_420;
|
||||||
|
pix_per_burst = 64;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = ipu_vdi_read(ipu, VDI_C);
|
||||||
|
reg |= pixel_fmt;
|
||||||
|
switch (channel) {
|
||||||
|
case MEM_VDI_PRP_VF_MEM:
|
||||||
|
reg |= VDI_C_BURST_SIZE2_4;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_PRP_VF_MEM_P:
|
||||||
|
reg |= VDI_C_BURST_SIZE1_4 | VDI_C_VWM1_SET_1 | VDI_C_VWM1_CLR_2;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_PRP_VF_MEM_N:
|
||||||
|
reg |= VDI_C_BURST_SIZE3_4 | VDI_C_VWM3_SET_1 | VDI_C_VWM3_CLR_2;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case MEM_VDI_MEM:
|
||||||
|
reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
|
||||||
|
<< VDI_C_BURST_SIZE2_OFFSET;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_MEM_P:
|
||||||
|
reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
|
||||||
|
<< VDI_C_BURST_SIZE1_OFFSET;
|
||||||
|
reg |= VDI_C_VWM1_SET_2 | VDI_C_VWM1_CLR_2;
|
||||||
|
break;
|
||||||
|
case MEM_VDI_MEM_N:
|
||||||
|
reg |= (((pix_per_burst >> 2) - 1) & VDI_C_BURST_SIZE_MASK)
|
||||||
|
<< VDI_C_BURST_SIZE3_OFFSET;
|
||||||
|
reg |= VDI_C_VWM3_SET_2 | VDI_C_VWM3_CLR_2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
ipu_vdi_write(ipu, reg, VDI_C);
|
||||||
|
|
||||||
|
if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_TOP)
|
||||||
|
_ipu_vdi_set_top_field_man(ipu, true);
|
||||||
|
else if (params->mem_prp_vf_mem.field_fmt == IPU_DEINTERLACE_FIELD_BOTTOM)
|
||||||
|
_ipu_vdi_set_top_field_man(ipu, false);
|
||||||
|
|
||||||
|
_ipu_vdi_set_motion(ipu, params->mem_prp_vf_mem.motion_sel);
|
||||||
|
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~IC_CONF_RWS_EN;
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_vdi_uninit(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
ipu_vdi_write(ipu, 0, VDI_FSIZE);
|
||||||
|
ipu_vdi_write(ipu, 0, VDI_C);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
|
||||||
|
bool src_is_csi)
|
||||||
|
{
|
||||||
|
uint32_t reg, ic_conf;
|
||||||
|
uint32_t downsizeCoeff, resizeCoeff;
|
||||||
|
ipu_color_space_t in_fmt, out_fmt;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Setup vertical resizing */
|
||||||
|
if (!params->mem_prp_vf_mem.outv_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_height,
|
||||||
|
params->mem_prp_vf_mem.out_height,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate prpvf height "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
|
||||||
|
} else
|
||||||
|
reg = (params->mem_prp_vf_mem.outv_resize_ratio) << 16;
|
||||||
|
|
||||||
|
/* Setup horizontal resizing */
|
||||||
|
if (!params->mem_prp_vf_mem.outh_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu, params->mem_prp_vf_mem.in_width,
|
||||||
|
params->mem_prp_vf_mem.out_width,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate prpvf width "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg |= (downsizeCoeff << 14) | resizeCoeff;
|
||||||
|
} else
|
||||||
|
reg |= params->mem_prp_vf_mem.outh_resize_ratio;
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, reg, IC_PRP_VF_RSC);
|
||||||
|
|
||||||
|
ic_conf = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
|
||||||
|
/* Setup color space conversion */
|
||||||
|
in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_pixel_fmt);
|
||||||
|
out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
|
||||||
|
if (in_fmt == RGB) {
|
||||||
|
if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
|
||||||
|
/* Enable RGB->YCBCR CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 1);
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CSC1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
|
||||||
|
if (out_fmt == RGB) {
|
||||||
|
/* Enable YCBCR->RGB CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 1);
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CSC1;
|
||||||
|
} else {
|
||||||
|
/* TODO: Support YUV<->YCbCr conversion? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->mem_prp_vf_mem.graphics_combine_en) {
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CMB;
|
||||||
|
|
||||||
|
if (!(ic_conf & IC_CONF_PRPVF_CSC1)) {
|
||||||
|
/* need transparent CSC1 conversion */
|
||||||
|
_init_csc(ipu, IC_TASK_VIEWFINDER, RGB, RGB, 1);
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CSC1; /* Enable RGB->RGB CSC */
|
||||||
|
}
|
||||||
|
in_fmt = format_to_colorspace(params->mem_prp_vf_mem.in_g_pixel_fmt);
|
||||||
|
out_fmt = format_to_colorspace(params->mem_prp_vf_mem.out_pixel_fmt);
|
||||||
|
if (in_fmt == RGB) {
|
||||||
|
if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
|
||||||
|
/* Enable RGB->YCBCR CSC2 */
|
||||||
|
_init_csc(ipu, IC_TASK_VIEWFINDER, RGB, out_fmt, 2);
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CSC2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
|
||||||
|
if (out_fmt == RGB) {
|
||||||
|
/* Enable YCBCR->RGB CSC2 */
|
||||||
|
_init_csc(ipu, IC_TASK_VIEWFINDER, YCbCr, RGB, 2);
|
||||||
|
ic_conf |= IC_CONF_PRPVF_CSC2;
|
||||||
|
} else {
|
||||||
|
/* TODO: Support YUV<->YCbCr conversion? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->mem_prp_vf_mem.global_alpha_en) {
|
||||||
|
ic_conf |= IC_CONF_IC_GLB_LOC_A;
|
||||||
|
reg = ipu_ic_read(ipu, IC_CMBP_1);
|
||||||
|
reg &= ~(0xff);
|
||||||
|
reg |= params->mem_prp_vf_mem.alpha;
|
||||||
|
ipu_ic_write(ipu, reg, IC_CMBP_1);
|
||||||
|
} else
|
||||||
|
ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
|
||||||
|
|
||||||
|
if (params->mem_prp_vf_mem.key_color_en) {
|
||||||
|
ic_conf |= IC_CONF_KEY_COLOR_EN;
|
||||||
|
ipu_ic_write(ipu, params->mem_prp_vf_mem.key_color,
|
||||||
|
IC_CMBP_2);
|
||||||
|
} else
|
||||||
|
ic_conf &= ~IC_CONF_KEY_COLOR_EN;
|
||||||
|
} else {
|
||||||
|
ic_conf &= ~IC_CONF_PRPVF_CMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_is_csi)
|
||||||
|
ic_conf &= ~IC_CONF_RWS_EN;
|
||||||
|
else
|
||||||
|
ic_conf |= IC_CONF_RWS_EN;
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, ic_conf, IC_CONF);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~(IC_CONF_PRPVF_EN | IC_CONF_PRPVF_CMB |
|
||||||
|
IC_CONF_PRPVF_CSC2 | IC_CONF_PRPVF_CSC1);
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~IC_CONF_PRPVF_ROT_EN;
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
|
||||||
|
bool src_is_csi)
|
||||||
|
{
|
||||||
|
uint32_t reg, ic_conf;
|
||||||
|
uint32_t downsizeCoeff, resizeCoeff;
|
||||||
|
ipu_color_space_t in_fmt, out_fmt;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Setup vertical resizing */
|
||||||
|
if (!params->mem_prp_enc_mem.outv_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu,
|
||||||
|
params->mem_prp_enc_mem.in_height,
|
||||||
|
params->mem_prp_enc_mem.out_height,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate prpenc height "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
|
||||||
|
} else
|
||||||
|
reg = (params->mem_prp_enc_mem.outv_resize_ratio) << 16;
|
||||||
|
|
||||||
|
/* Setup horizontal resizing */
|
||||||
|
if (!params->mem_prp_enc_mem.outh_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu, params->mem_prp_enc_mem.in_width,
|
||||||
|
params->mem_prp_enc_mem.out_width,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate prpenc width "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg |= (downsizeCoeff << 14) | resizeCoeff;
|
||||||
|
} else
|
||||||
|
reg |= params->mem_prp_enc_mem.outh_resize_ratio;
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, reg, IC_PRP_ENC_RSC);
|
||||||
|
|
||||||
|
ic_conf = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
|
||||||
|
/* Setup color space conversion */
|
||||||
|
in_fmt = format_to_colorspace(params->mem_prp_enc_mem.in_pixel_fmt);
|
||||||
|
out_fmt = format_to_colorspace(params->mem_prp_enc_mem.out_pixel_fmt);
|
||||||
|
if (in_fmt == RGB) {
|
||||||
|
if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
|
||||||
|
/* Enable RGB->YCBCR CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_ENCODER, RGB, out_fmt, 1);
|
||||||
|
ic_conf |= IC_CONF_PRPENC_CSC1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
|
||||||
|
if (out_fmt == RGB) {
|
||||||
|
/* Enable YCBCR->RGB CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_ENCODER, YCbCr, RGB, 1);
|
||||||
|
ic_conf |= IC_CONF_PRPENC_CSC1;
|
||||||
|
} else {
|
||||||
|
/* TODO: Support YUV<->YCbCr conversion? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (src_is_csi)
|
||||||
|
ic_conf &= ~IC_CONF_RWS_EN;
|
||||||
|
else
|
||||||
|
ic_conf |= IC_CONF_RWS_EN;
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, ic_conf, IC_CONF);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~(IC_CONF_PRPENC_EN | IC_CONF_PRPENC_CSC1);
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~(IC_CONF_PRPENC_ROT_EN);
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
|
||||||
|
{
|
||||||
|
uint32_t reg, ic_conf;
|
||||||
|
uint32_t downsizeCoeff, resizeCoeff;
|
||||||
|
ipu_color_space_t in_fmt, out_fmt;
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
/* Setup vertical resizing */
|
||||||
|
if (!params->mem_pp_mem.outv_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_height,
|
||||||
|
params->mem_pp_mem.out_height,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate pp height "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg = (downsizeCoeff << 30) | (resizeCoeff << 16);
|
||||||
|
} else {
|
||||||
|
reg = (params->mem_pp_mem.outv_resize_ratio) << 16;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setup horizontal resizing */
|
||||||
|
if (!params->mem_pp_mem.outh_resize_ratio) {
|
||||||
|
ret = _calc_resize_coeffs(ipu, params->mem_pp_mem.in_width,
|
||||||
|
params->mem_pp_mem.out_width,
|
||||||
|
&resizeCoeff, &downsizeCoeff);
|
||||||
|
if (ret < 0) {
|
||||||
|
dev_err(ipu->dev, "failed to calculate pp width "
|
||||||
|
"scaling coefficients\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
reg |= (downsizeCoeff << 14) | resizeCoeff;
|
||||||
|
} else {
|
||||||
|
reg |= params->mem_pp_mem.outh_resize_ratio;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, reg, IC_PP_RSC);
|
||||||
|
|
||||||
|
ic_conf = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
|
||||||
|
/* Setup color space conversion */
|
||||||
|
in_fmt = format_to_colorspace(params->mem_pp_mem.in_pixel_fmt);
|
||||||
|
out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
|
||||||
|
if (in_fmt == RGB) {
|
||||||
|
if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
|
||||||
|
/* Enable RGB->YCBCR CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 1);
|
||||||
|
ic_conf |= IC_CONF_PP_CSC1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
|
||||||
|
if (out_fmt == RGB) {
|
||||||
|
/* Enable YCBCR->RGB CSC1 */
|
||||||
|
_init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 1);
|
||||||
|
ic_conf |= IC_CONF_PP_CSC1;
|
||||||
|
} else {
|
||||||
|
/* TODO: Support YUV<->YCbCr conversion? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->mem_pp_mem.graphics_combine_en) {
|
||||||
|
ic_conf |= IC_CONF_PP_CMB;
|
||||||
|
|
||||||
|
if (!(ic_conf & IC_CONF_PP_CSC1)) {
|
||||||
|
/* need transparent CSC1 conversion */
|
||||||
|
_init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, RGB, 1);
|
||||||
|
ic_conf |= IC_CONF_PP_CSC1; /* Enable RGB->RGB CSC */
|
||||||
|
}
|
||||||
|
|
||||||
|
in_fmt = format_to_colorspace(params->mem_pp_mem.in_g_pixel_fmt);
|
||||||
|
out_fmt = format_to_colorspace(params->mem_pp_mem.out_pixel_fmt);
|
||||||
|
if (in_fmt == RGB) {
|
||||||
|
if ((out_fmt == YCbCr) || (out_fmt == YUV)) {
|
||||||
|
/* Enable RGB->YCBCR CSC2 */
|
||||||
|
_init_csc(ipu, IC_TASK_POST_PROCESSOR, RGB, out_fmt, 2);
|
||||||
|
ic_conf |= IC_CONF_PP_CSC2;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ((in_fmt == YCbCr) || (in_fmt == YUV)) {
|
||||||
|
if (out_fmt == RGB) {
|
||||||
|
/* Enable YCBCR->RGB CSC2 */
|
||||||
|
_init_csc(ipu, IC_TASK_POST_PROCESSOR, YCbCr, RGB, 2);
|
||||||
|
ic_conf |= IC_CONF_PP_CSC2;
|
||||||
|
} else {
|
||||||
|
/* TODO: Support YUV<->YCbCr conversion? */
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (params->mem_pp_mem.global_alpha_en) {
|
||||||
|
ic_conf |= IC_CONF_IC_GLB_LOC_A;
|
||||||
|
reg = ipu_ic_read(ipu, IC_CMBP_1);
|
||||||
|
reg &= ~(0xff00);
|
||||||
|
reg |= (params->mem_pp_mem.alpha << 8);
|
||||||
|
ipu_ic_write(ipu, reg, IC_CMBP_1);
|
||||||
|
} else
|
||||||
|
ic_conf &= ~IC_CONF_IC_GLB_LOC_A;
|
||||||
|
|
||||||
|
if (params->mem_pp_mem.key_color_en) {
|
||||||
|
ic_conf |= IC_CONF_KEY_COLOR_EN;
|
||||||
|
ipu_ic_write(ipu, params->mem_pp_mem.key_color,
|
||||||
|
IC_CMBP_2);
|
||||||
|
} else
|
||||||
|
ic_conf &= ~IC_CONF_KEY_COLOR_EN;
|
||||||
|
} else {
|
||||||
|
ic_conf &= ~IC_CONF_PP_CMB;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, ic_conf, IC_CONF);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_pp(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~(IC_CONF_PP_EN | IC_CONF_PP_CSC1 | IC_CONF_PP_CSC2 |
|
||||||
|
IC_CONF_PP_CMB);
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
reg = ipu_ic_read(ipu, IC_CONF);
|
||||||
|
reg &= ~IC_CONF_PP_ROT_EN;
|
||||||
|
ipu_ic_write(ipu, reg, IC_CONF);
|
||||||
|
}
|
||||||
|
|
||||||
|
int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan,
|
||||||
|
uint16_t width, uint16_t height,
|
||||||
|
int burst_size, ipu_rotate_mode_t rot)
|
||||||
|
{
|
||||||
|
u32 ic_idmac_1, ic_idmac_2, ic_idmac_3;
|
||||||
|
u32 temp_rot = bitrev8(rot) >> 5;
|
||||||
|
bool need_hor_flip = false;
|
||||||
|
|
||||||
|
if ((burst_size != 8) && (burst_size != 16)) {
|
||||||
|
dev_dbg(ipu->dev, "Illegal burst length for IC\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
width--;
|
||||||
|
height--;
|
||||||
|
|
||||||
|
if (temp_rot & 0x2) /* Need horizontal flip */
|
||||||
|
need_hor_flip = true;
|
||||||
|
|
||||||
|
ic_idmac_1 = ipu_ic_read(ipu, IC_IDMAC_1);
|
||||||
|
ic_idmac_2 = ipu_ic_read(ipu, IC_IDMAC_2);
|
||||||
|
ic_idmac_3 = ipu_ic_read(ipu, IC_IDMAC_3);
|
||||||
|
if (dma_chan == 22) { /* PP output - CB2 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB2_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB2_BURST_16;
|
||||||
|
|
||||||
|
if (need_hor_flip)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_PP_FLIP_RS;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PP_FLIP_RS;
|
||||||
|
|
||||||
|
ic_idmac_2 &= ~IC_IDMAC_2_PP_HEIGHT_MASK;
|
||||||
|
ic_idmac_2 |= height << IC_IDMAC_2_PP_HEIGHT_OFFSET;
|
||||||
|
|
||||||
|
ic_idmac_3 &= ~IC_IDMAC_3_PP_WIDTH_MASK;
|
||||||
|
ic_idmac_3 |= width << IC_IDMAC_3_PP_WIDTH_OFFSET;
|
||||||
|
} else if (dma_chan == 11) { /* PP Input - CB5 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB5_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB5_BURST_16;
|
||||||
|
} else if (dma_chan == 47) { /* PP Rot input */
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PP_ROT_MASK;
|
||||||
|
ic_idmac_1 |= temp_rot << IC_IDMAC_1_PP_ROT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_chan == 12) { /* PRP Input - CB6 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB6_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB6_BURST_16;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_chan == 20) { /* PRP ENC output - CB0 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB0_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB0_BURST_16;
|
||||||
|
|
||||||
|
if (need_hor_flip)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_PRPENC_FLIP_RS;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_FLIP_RS;
|
||||||
|
|
||||||
|
ic_idmac_2 &= ~IC_IDMAC_2_PRPENC_HEIGHT_MASK;
|
||||||
|
ic_idmac_2 |= height << IC_IDMAC_2_PRPENC_HEIGHT_OFFSET;
|
||||||
|
|
||||||
|
ic_idmac_3 &= ~IC_IDMAC_3_PRPENC_WIDTH_MASK;
|
||||||
|
ic_idmac_3 |= width << IC_IDMAC_3_PRPENC_WIDTH_OFFSET;
|
||||||
|
|
||||||
|
} else if (dma_chan == 45) { /* PRP ENC Rot input */
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PRPENC_ROT_MASK;
|
||||||
|
ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPENC_ROT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_chan == 21) { /* PRP VF output - CB1 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB1_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB1_BURST_16;
|
||||||
|
|
||||||
|
if (need_hor_flip)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_PRPVF_FLIP_RS;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_FLIP_RS;
|
||||||
|
|
||||||
|
ic_idmac_2 &= ~IC_IDMAC_2_PRPVF_HEIGHT_MASK;
|
||||||
|
ic_idmac_2 |= height << IC_IDMAC_2_PRPVF_HEIGHT_OFFSET;
|
||||||
|
|
||||||
|
ic_idmac_3 &= ~IC_IDMAC_3_PRPVF_WIDTH_MASK;
|
||||||
|
ic_idmac_3 |= width << IC_IDMAC_3_PRPVF_WIDTH_OFFSET;
|
||||||
|
|
||||||
|
} else if (dma_chan == 46) { /* PRP VF Rot input */
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_PRPVF_ROT_MASK;
|
||||||
|
ic_idmac_1 |= temp_rot << IC_IDMAC_1_PRPVF_ROT_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dma_chan == 14) { /* PRP VF graphics combining input - CB3 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB3_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB3_BURST_16;
|
||||||
|
} else if (dma_chan == 15) { /* PP graphics combining input - CB4 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB4_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB4_BURST_16;
|
||||||
|
} else if (dma_chan == 5) { /* VDIC OUTPUT - CB7 */
|
||||||
|
if (burst_size == 16)
|
||||||
|
ic_idmac_1 |= IC_IDMAC_1_CB7_BURST_16;
|
||||||
|
else
|
||||||
|
ic_idmac_1 &= ~IC_IDMAC_1_CB7_BURST_16;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_ic_write(ipu, ic_idmac_1, IC_IDMAC_1);
|
||||||
|
ipu_ic_write(ipu, ic_idmac_2, IC_IDMAC_2);
|
||||||
|
ipu_ic_write(ipu, ic_idmac_3, IC_IDMAC_3);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _init_csc(struct ipu_soc *ipu, uint8_t ic_task, ipu_color_space_t in_format,
|
||||||
|
ipu_color_space_t out_format, int csc_index)
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
* Y = 0.257 * R + 0.504 * G + 0.098 * B + 16;
|
||||||
|
* U = -0.148 * R - 0.291 * G + 0.439 * B + 128;
|
||||||
|
* V = 0.439 * R - 0.368 * G - 0.071 * B + 128;
|
||||||
|
*/
|
||||||
|
static const uint32_t rgb2ycbcr_coeff[4][3] = {
|
||||||
|
{0x0042, 0x0081, 0x0019},
|
||||||
|
{0x01DA, 0x01B6, 0x0070},
|
||||||
|
{0x0070, 0x01A2, 0x01EE},
|
||||||
|
{0x0040, 0x0200, 0x0200}, /* A0, A1, A2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* transparent RGB->RGB matrix for combining
|
||||||
|
*/
|
||||||
|
static const uint32_t rgb2rgb_coeff[4][3] = {
|
||||||
|
{0x0080, 0x0000, 0x0000},
|
||||||
|
{0x0000, 0x0080, 0x0000},
|
||||||
|
{0x0000, 0x0000, 0x0080},
|
||||||
|
{0x0000, 0x0000, 0x0000}, /* A0, A1, A2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
/* R = (1.164 * (Y - 16)) + (1.596 * (Cr - 128));
|
||||||
|
G = (1.164 * (Y - 16)) - (0.392 * (Cb - 128)) - (0.813 * (Cr - 128));
|
||||||
|
B = (1.164 * (Y - 16)) + (2.017 * (Cb - 128); */
|
||||||
|
static const uint32_t ycbcr2rgb_coeff[4][3] = {
|
||||||
|
{149, 0, 204},
|
||||||
|
{149, 462, 408},
|
||||||
|
{149, 255, 0},
|
||||||
|
{8192 - 446, 266, 8192 - 554}, /* A0, A1, A2 */
|
||||||
|
};
|
||||||
|
|
||||||
|
uint32_t param;
|
||||||
|
uint32_t *base = NULL;
|
||||||
|
|
||||||
|
if (ic_task == IC_TASK_ENCODER) {
|
||||||
|
base = (uint32_t *)ipu->tpmem_base + 0x2008 / 4;
|
||||||
|
} else if (ic_task == IC_TASK_VIEWFINDER) {
|
||||||
|
if (csc_index == 1)
|
||||||
|
base = (uint32_t *)ipu->tpmem_base + 0x4028 / 4;
|
||||||
|
else
|
||||||
|
base = (uint32_t *)ipu->tpmem_base + 0x4040 / 4;
|
||||||
|
} else if (ic_task == IC_TASK_POST_PROCESSOR) {
|
||||||
|
if (csc_index == 1)
|
||||||
|
base = (uint32_t *)ipu->tpmem_base + 0x6060 / 4;
|
||||||
|
else
|
||||||
|
base = (uint32_t *)ipu->tpmem_base + 0x6078 / 4;
|
||||||
|
} else {
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((in_format == YCbCr) && (out_format == RGB)) {
|
||||||
|
/* Init CSC (YCbCr->RGB) */
|
||||||
|
param = (ycbcr2rgb_coeff[3][0] << 27) |
|
||||||
|
(ycbcr2rgb_coeff[0][0] << 18) |
|
||||||
|
(ycbcr2rgb_coeff[1][1] << 9) | ycbcr2rgb_coeff[2][2];
|
||||||
|
writel(param, base++);
|
||||||
|
/* scale = 2, sat = 0 */
|
||||||
|
param = (ycbcr2rgb_coeff[3][0] >> 5) | (2L << (40 - 32));
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param = (ycbcr2rgb_coeff[3][1] << 27) |
|
||||||
|
(ycbcr2rgb_coeff[0][1] << 18) |
|
||||||
|
(ycbcr2rgb_coeff[1][0] << 9) | ycbcr2rgb_coeff[2][0];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (ycbcr2rgb_coeff[3][1] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param = (ycbcr2rgb_coeff[3][2] << 27) |
|
||||||
|
(ycbcr2rgb_coeff[0][2] << 18) |
|
||||||
|
(ycbcr2rgb_coeff[1][2] << 9) | ycbcr2rgb_coeff[2][1];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (ycbcr2rgb_coeff[3][2] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
} else if ((in_format == RGB) && (out_format == YCbCr)) {
|
||||||
|
/* Init CSC (RGB->YCbCr) */
|
||||||
|
param = (rgb2ycbcr_coeff[3][0] << 27) |
|
||||||
|
(rgb2ycbcr_coeff[0][0] << 18) |
|
||||||
|
(rgb2ycbcr_coeff[1][1] << 9) | rgb2ycbcr_coeff[2][2];
|
||||||
|
writel(param, base++);
|
||||||
|
/* scale = 1, sat = 0 */
|
||||||
|
param = (rgb2ycbcr_coeff[3][0] >> 5) | (1UL << 8);
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param = (rgb2ycbcr_coeff[3][1] << 27) |
|
||||||
|
(rgb2ycbcr_coeff[0][1] << 18) |
|
||||||
|
(rgb2ycbcr_coeff[1][0] << 9) | rgb2ycbcr_coeff[2][0];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (rgb2ycbcr_coeff[3][1] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param = (rgb2ycbcr_coeff[3][2] << 27) |
|
||||||
|
(rgb2ycbcr_coeff[0][2] << 18) |
|
||||||
|
(rgb2ycbcr_coeff[1][2] << 9) | rgb2ycbcr_coeff[2][1];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (rgb2ycbcr_coeff[3][2] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
} else if ((in_format == RGB) && (out_format == RGB)) {
|
||||||
|
/* Init CSC */
|
||||||
|
param =
|
||||||
|
(rgb2rgb_coeff[3][0] << 27) | (rgb2rgb_coeff[0][0] << 18) |
|
||||||
|
(rgb2rgb_coeff[1][1] << 9) | rgb2rgb_coeff[2][2];
|
||||||
|
writel(param, base++);
|
||||||
|
/* scale = 2, sat = 0 */
|
||||||
|
param = (rgb2rgb_coeff[3][0] >> 5) | (2UL << 8);
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param =
|
||||||
|
(rgb2rgb_coeff[3][1] << 27) | (rgb2rgb_coeff[0][1] << 18) |
|
||||||
|
(rgb2rgb_coeff[1][0] << 9) | rgb2rgb_coeff[2][0];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (rgb2rgb_coeff[3][1] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
|
||||||
|
param =
|
||||||
|
(rgb2rgb_coeff[3][2] << 27) | (rgb2rgb_coeff[0][2] << 18) |
|
||||||
|
(rgb2rgb_coeff[1][2] << 9) | rgb2rgb_coeff[2][1];
|
||||||
|
writel(param, base++);
|
||||||
|
param = (rgb2rgb_coeff[3][2] >> 5);
|
||||||
|
writel(param, base++);
|
||||||
|
} else {
|
||||||
|
dev_err(ipu->dev, "Unsupported color space conversion\n");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _calc_resize_coeffs(struct ipu_soc *ipu,
|
||||||
|
uint32_t inSize, uint32_t outSize,
|
||||||
|
uint32_t *resizeCoeff,
|
||||||
|
uint32_t *downsizeCoeff)
|
||||||
|
{
|
||||||
|
uint32_t tempSize;
|
||||||
|
uint32_t tempDownsize;
|
||||||
|
|
||||||
|
if (inSize > 4096) {
|
||||||
|
dev_err(ipu->dev, "IC input size(%d) cannot exceed 4096\n",
|
||||||
|
inSize);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (outSize > 1024) {
|
||||||
|
dev_err(ipu->dev, "IC output size(%d) cannot exceed 1024\n",
|
||||||
|
outSize);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((outSize << 3) < inSize) {
|
||||||
|
dev_err(ipu->dev, "IC cannot downsize more than 8:1\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compute downsizing coefficient */
|
||||||
|
/* Output of downsizing unit cannot be more than 1024 */
|
||||||
|
tempDownsize = 0;
|
||||||
|
tempSize = inSize;
|
||||||
|
while (((tempSize > 1024) || (tempSize >= outSize * 2)) &&
|
||||||
|
(tempDownsize < 2)) {
|
||||||
|
tempSize >>= 1;
|
||||||
|
tempDownsize++;
|
||||||
|
}
|
||||||
|
*downsizeCoeff = tempDownsize;
|
||||||
|
|
||||||
|
/* compute resizing coefficient using the following equation:
|
||||||
|
resizeCoeff = M*(SI -1)/(SO - 1)
|
||||||
|
where M = 2^13, SI - input size, SO - output size */
|
||||||
|
*resizeCoeff = (8192L * (tempSize - 1)) / (outSize - 1);
|
||||||
|
if (*resizeCoeff >= 16384L) {
|
||||||
|
dev_err(ipu->dev, "Overflow on IC resize coefficient.\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "resizing from %u -> %u pixels, "
|
||||||
|
"downsize=%u, resize=%u.%lu (reg=%u)\n", inSize, outSize,
|
||||||
|
*downsizeCoeff, (*resizeCoeff >= 8192L) ? 1 : 0,
|
||||||
|
((*resizeCoeff & 0x1FFF) * 10000L) / 8192L, *resizeCoeff);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu)
|
||||||
|
{
|
||||||
|
uint32_t reg;
|
||||||
|
uint32_t mask_reg;
|
||||||
|
|
||||||
|
reg = ipu_vdi_read(ipu, VDI_C);
|
||||||
|
mask_reg = reg & VDI_C_TOP_FIELD_MAN_1;
|
||||||
|
if (mask_reg == VDI_C_TOP_FIELD_MAN_1)
|
||||||
|
reg &= ~VDI_C_TOP_FIELD_MAN_1;
|
||||||
|
else
|
||||||
|
reg |= VDI_C_TOP_FIELD_MAN_1;
|
||||||
|
|
||||||
|
ipu_vdi_write(ipu, reg, VDI_C);
|
||||||
|
}
|
|
@ -0,0 +1,998 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#ifndef __INCLUDE_IPU_PARAM_MEM_H__
|
||||||
|
#define __INCLUDE_IPU_PARAM_MEM_H__
|
||||||
|
|
||||||
|
#include <linux/bitrev.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "ipu_prv.h"
|
||||||
|
|
||||||
|
extern u32 *ipu_cpmem_base;
|
||||||
|
|
||||||
|
struct ipu_ch_param_word {
|
||||||
|
uint32_t data[5];
|
||||||
|
uint32_t res[3];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipu_ch_param {
|
||||||
|
struct ipu_ch_param_word word[2];
|
||||||
|
};
|
||||||
|
|
||||||
|
#define ipu_ch_param_addr(ipu, ch) \
|
||||||
|
(((struct ipu_ch_param *)(ipu)->cpmem_base) + (ch))
|
||||||
|
|
||||||
|
#define _param_word(base, w) \
|
||||||
|
(((struct ipu_ch_param *)(base))->word[(w)].data)
|
||||||
|
|
||||||
|
#define ipu_ch_param_set_field(base, w, bit, size, v) { \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
_param_word((base), (w))[i] |= (v) << off; \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
_param_word((base), (w))[i + 1] |= \
|
||||||
|
(v) >> (off ? (32 - off) : 0); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ipu_ch_param_set_field_io(base, w, bit, size, v) { \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
unsigned reg_offset; \
|
||||||
|
u32 temp; \
|
||||||
|
reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
|
||||||
|
reg_offset += i; \
|
||||||
|
temp = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp |= (v) << off; \
|
||||||
|
writel(temp, (u32 *)(base) + reg_offset); \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
reg_offset++; \
|
||||||
|
temp = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp |= (v) >> (off ? (32 - off) : 0); \
|
||||||
|
writel(temp, (u32 *)(base) + reg_offset); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ipu_ch_param_mod_field(base, w, bit, size, v) { \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
u32 mask = (1UL << (size)) - 1; \
|
||||||
|
u32 temp = _param_word((base), (w))[i]; \
|
||||||
|
temp &= ~(mask << off); \
|
||||||
|
_param_word((base), (w))[i] = temp | (v) << off; \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
temp = _param_word((base), (w))[i + 1]; \
|
||||||
|
temp &= ~(mask >> (32 - off)); \
|
||||||
|
_param_word((base), (w))[i + 1] = \
|
||||||
|
temp | ((v) >> (off ? (32 - off) : 0)); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ipu_ch_param_mod_field_io(base, w, bit, size, v) { \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
u32 mask = (1UL << (size)) - 1; \
|
||||||
|
unsigned reg_offset; \
|
||||||
|
u32 temp; \
|
||||||
|
reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
|
||||||
|
reg_offset += i; \
|
||||||
|
temp = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp &= ~(mask << off); \
|
||||||
|
temp |= (v) << off; \
|
||||||
|
writel(temp, (u32 *)(base) + reg_offset); \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
reg_offset++; \
|
||||||
|
temp = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp &= ~(mask >> (32 - off)); \
|
||||||
|
temp |= ((v) >> (off ? (32 - off) : 0)); \
|
||||||
|
writel(temp, (u32 *)(base) + reg_offset); \
|
||||||
|
} \
|
||||||
|
}
|
||||||
|
|
||||||
|
#define ipu_ch_param_read_field(base, w, bit, size) ({ \
|
||||||
|
u32 temp2; \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
u32 mask = (1UL << (size)) - 1; \
|
||||||
|
u32 temp1 = _param_word((base), (w))[i]; \
|
||||||
|
temp1 = mask & (temp1 >> off); \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
temp2 = _param_word((base), (w))[i + 1]; \
|
||||||
|
temp2 &= mask >> (off ? (32 - off) : 0); \
|
||||||
|
temp1 |= temp2 << (off ? (32 - off) : 0); \
|
||||||
|
} \
|
||||||
|
temp1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define ipu_ch_param_read_field_io(base, w, bit, size) ({ \
|
||||||
|
u32 temp1, temp2; \
|
||||||
|
int i = (bit) / 32; \
|
||||||
|
int off = (bit) % 32; \
|
||||||
|
u32 mask = (1UL << (size)) - 1; \
|
||||||
|
unsigned reg_offset; \
|
||||||
|
reg_offset = sizeof(struct ipu_ch_param_word) * (w) / 4; \
|
||||||
|
reg_offset += i; \
|
||||||
|
temp1 = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp1 = mask & (temp1 >> off); \
|
||||||
|
if (((bit)+(size)-1)/32 > i) { \
|
||||||
|
reg_offset++; \
|
||||||
|
temp2 = readl((u32 *)(base) + reg_offset); \
|
||||||
|
temp2 &= mask >> (off ? (32 - off) : 0); \
|
||||||
|
temp1 |= temp2 << (off ? (32 - off) : 0); \
|
||||||
|
} \
|
||||||
|
temp1; \
|
||||||
|
})
|
||||||
|
|
||||||
|
static inline int __ipu_ch_get_third_buf_cpmem_num(int ch)
|
||||||
|
{
|
||||||
|
switch (ch) {
|
||||||
|
case 8:
|
||||||
|
return 64;
|
||||||
|
case 9:
|
||||||
|
return 65;
|
||||||
|
case 10:
|
||||||
|
return 66;
|
||||||
|
case 13:
|
||||||
|
return 67;
|
||||||
|
case 21:
|
||||||
|
return 68;
|
||||||
|
case 23:
|
||||||
|
return 69;
|
||||||
|
case 27:
|
||||||
|
return 70;
|
||||||
|
case 28:
|
||||||
|
return 71;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _ipu_ch_params_set_packing(struct ipu_ch_param *p,
|
||||||
|
int red_width, int red_offset,
|
||||||
|
int green_width, int green_offset,
|
||||||
|
int blue_width, int blue_offset,
|
||||||
|
int alpha_width, int alpha_offset)
|
||||||
|
{
|
||||||
|
/* Setup red width and offset */
|
||||||
|
ipu_ch_param_set_field(p, 1, 116, 3, red_width - 1);
|
||||||
|
ipu_ch_param_set_field(p, 1, 128, 5, red_offset);
|
||||||
|
/* Setup green width and offset */
|
||||||
|
ipu_ch_param_set_field(p, 1, 119, 3, green_width - 1);
|
||||||
|
ipu_ch_param_set_field(p, 1, 133, 5, green_offset);
|
||||||
|
/* Setup blue width and offset */
|
||||||
|
ipu_ch_param_set_field(p, 1, 122, 3, blue_width - 1);
|
||||||
|
ipu_ch_param_set_field(p, 1, 138, 5, blue_offset);
|
||||||
|
/* Setup alpha width and offset */
|
||||||
|
ipu_ch_param_set_field(p, 1, 125, 3, alpha_width - 1);
|
||||||
|
ipu_ch_param_set_field(p, 1, 143, 5, alpha_offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_dump(struct ipu_soc *ipu, int ch)
|
||||||
|
{
|
||||||
|
struct ipu_ch_param *p = ipu_ch_param_addr(ipu, ch);
|
||||||
|
dev_dbg(ipu->dev, "ch %d word 0 - %08X %08X %08X %08X %08X\n", ch,
|
||||||
|
p->word[0].data[0], p->word[0].data[1], p->word[0].data[2],
|
||||||
|
p->word[0].data[3], p->word[0].data[4]);
|
||||||
|
dev_dbg(ipu->dev, "ch %d word 1 - %08X %08X %08X %08X %08X\n", ch,
|
||||||
|
p->word[1].data[0], p->word[1].data[1], p->word[1].data[2],
|
||||||
|
p->word[1].data[3], p->word[1].data[4]);
|
||||||
|
dev_dbg(ipu->dev, "PFS 0x%x, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 85, 4));
|
||||||
|
dev_dbg(ipu->dev, "BPP 0x%x, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3));
|
||||||
|
dev_dbg(ipu->dev, "NPB 0x%x\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7));
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "FW %d, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 125, 13));
|
||||||
|
dev_dbg(ipu->dev, "FH %d, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 138, 12));
|
||||||
|
dev_dbg(ipu->dev, "EBA0 0x%x\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 0, 29) << 3);
|
||||||
|
dev_dbg(ipu->dev, "EBA1 0x%x\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 29, 29) << 3);
|
||||||
|
dev_dbg(ipu->dev, "Stride %d\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14));
|
||||||
|
dev_dbg(ipu->dev, "scan_order %d\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1));
|
||||||
|
dev_dbg(ipu->dev, "uv_stride %d\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 14));
|
||||||
|
dev_dbg(ipu->dev, "u_offset 0x%x\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22) << 3);
|
||||||
|
dev_dbg(ipu->dev, "v_offset 0x%x\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22) << 3);
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "Width0 %d+1, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 116, 3));
|
||||||
|
dev_dbg(ipu->dev, "Width1 %d+1, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 119, 3));
|
||||||
|
dev_dbg(ipu->dev, "Width2 %d+1, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 122, 3));
|
||||||
|
dev_dbg(ipu->dev, "Width3 %d+1, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3));
|
||||||
|
dev_dbg(ipu->dev, "Offset0 %d, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 128, 5));
|
||||||
|
dev_dbg(ipu->dev, "Offset1 %d, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 133, 5));
|
||||||
|
dev_dbg(ipu->dev, "Offset2 %d, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 138, 5));
|
||||||
|
dev_dbg(ipu->dev, "Offset3 %d\n",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 143, 5));
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void fill_cpmem(struct ipu_soc *ipu, int ch, struct ipu_ch_param *params)
|
||||||
|
{
|
||||||
|
int i, w;
|
||||||
|
void *addr = ipu_ch_param_addr(ipu, ch);
|
||||||
|
|
||||||
|
/* 2 words, 5 valid data */
|
||||||
|
for (w = 0; w < 2; w++) {
|
||||||
|
for (i = 0; i < 5; i++) {
|
||||||
|
writel(params->word[w].data[i], addr);
|
||||||
|
addr += 4;
|
||||||
|
}
|
||||||
|
addr += 12;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_init(struct ipu_soc *ipu, int ch,
|
||||||
|
uint32_t pixel_fmt, uint32_t width,
|
||||||
|
uint32_t height, uint32_t stride,
|
||||||
|
uint32_t u, uint32_t v,
|
||||||
|
uint32_t uv_stride, dma_addr_t addr0,
|
||||||
|
dma_addr_t addr1, dma_addr_t addr2)
|
||||||
|
{
|
||||||
|
uint32_t u_offset = 0;
|
||||||
|
uint32_t v_offset = 0;
|
||||||
|
uint32_t bs = 0;
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
struct ipu_ch_param params;
|
||||||
|
|
||||||
|
memset(¶ms, 0, sizeof(params));
|
||||||
|
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 125, 13, width - 1);
|
||||||
|
|
||||||
|
if (((ch == 8) || (ch == 9) || (ch == 10)) && !ipu->vdoa_en) {
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 138, 12, (height / 2) - 1);
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 102, 14, (stride * 2) - 1);
|
||||||
|
} else {
|
||||||
|
/* note: for vdoa+vdi- ch8/9/10, always use band mode */
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 138, 12, height - 1);
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 102, 14, stride - 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* EBA is 8-byte aligned */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 0, 29, addr0 >> 3);
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 29, 29, addr1 >> 3);
|
||||||
|
if (addr0%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's EBA0 is not 8-byte aligned\n", ch);
|
||||||
|
if (addr1%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's EBA1 is not 8-byte aligned\n", ch);
|
||||||
|
|
||||||
|
switch (pixel_fmt) {
|
||||||
|
case IPU_PIX_FMT_GENERIC:
|
||||||
|
/*Represents 8-bit Generic data */
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 5); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 63); /* burst size */
|
||||||
|
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_GENERIC_16:
|
||||||
|
/* Represents 16-bit generic data */
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 6); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_GENERIC_32:
|
||||||
|
/*Represents 32-bit Generic data */
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGB565:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 5, 0, 6, 5, 5, 11, 8, 16);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_BGRA4444:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 4, 4, 4, 8, 4, 12, 4, 0);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_BGRA5551:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 5, 1, 5, 6, 5, 11, 1, 0);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_BGR24:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGB24:
|
||||||
|
case IPU_PIX_FMT_YUV444:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 16, 8, 8, 8, 0, 8, 24);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_VYU444:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 1); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 19); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 8, 8, 0, 8, 16, 8, 24);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_AYUV:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_BGRA32:
|
||||||
|
case IPU_PIX_FMT_BGR32:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 8, 8, 16, 8, 24, 8, 0);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_RGBA32:
|
||||||
|
case IPU_PIX_FMT_RGB32:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 24, 8, 16, 8, 8, 8, 0);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_ABGR32:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 0); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 7); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
|
||||||
|
_ipu_ch_params_set_packing(¶ms, 8, 0, 8, 8, 8, 16, 8, 24);
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_UYVY:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 0xA); /* pix format */
|
||||||
|
if ((ch == 8) || (ch == 9) || (ch == 10)) {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUYV:
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 107, 3, 3); /* bits/pixel */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 0x8); /* pix format */
|
||||||
|
if ((ch == 8) || (ch == 9) || (ch == 10)) {
|
||||||
|
if (ipu->vdoa_en) {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31);
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV420P2:
|
||||||
|
case IPU_PIX_FMT_YUV420P:
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
|
||||||
|
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
u_offset = stride * height;
|
||||||
|
v_offset = u_offset + (uv_stride * height / 2);
|
||||||
|
if ((ch == 8) || (ch == 9) || (ch == 10)) {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
uv_stride = uv_stride*2;
|
||||||
|
} else {
|
||||||
|
if (_ipu_is_smfc_chan(ch) &&
|
||||||
|
ipu->smfc_idmac_12bit_3planar_bs_fixup)
|
||||||
|
bs = 15;
|
||||||
|
else
|
||||||
|
bs = 31;
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, bs); /* burst size */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YVU420P:
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 2); /* pix format */
|
||||||
|
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
v_offset = stride * height;
|
||||||
|
u_offset = v_offset + (uv_stride * height / 2);
|
||||||
|
if ((ch == 8) || (ch == 9) || (ch == 10)) {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15); /* burst size */
|
||||||
|
uv_stride = uv_stride*2;
|
||||||
|
} else {
|
||||||
|
if (_ipu_is_smfc_chan(ch) &&
|
||||||
|
ipu->smfc_idmac_12bit_3planar_bs_fixup)
|
||||||
|
bs = 15;
|
||||||
|
else
|
||||||
|
bs = 31;
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, bs); /* burst size */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YVU422P:
|
||||||
|
/* BPP & pixel format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
v_offset = (v == 0) ? stride * height : v;
|
||||||
|
u_offset = (u == 0) ? v_offset + v_offset / 2 : u;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV422P:
|
||||||
|
/* BPP & pixel format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
u_offset = (u == 0) ? stride * height : u;
|
||||||
|
v_offset = (v == 0) ? u_offset + u_offset / 2 : v;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV444P:
|
||||||
|
/* BPP & pixel format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 0); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
uv_stride = stride;
|
||||||
|
u_offset = (u == 0) ? stride * height : u;
|
||||||
|
v_offset = (v == 0) ? u_offset * 2 : v;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_NV16:
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 1); /* pix format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
uv_stride = stride;
|
||||||
|
u_offset = (u == 0) ? stride * height : u;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_NV12:
|
||||||
|
/* BPP & pixel format */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 85, 4, 4); /* pix format */
|
||||||
|
uv_stride = stride;
|
||||||
|
u_offset = (u == 0) ? stride * height : u;
|
||||||
|
if ((ch == 8) || (ch == 9) || (ch == 10)) {
|
||||||
|
if (ipu->vdoa_en) {
|
||||||
|
/* one field buffer, memory width 64bits */
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 63);
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 15);
|
||||||
|
/* top/bottom field in one buffer*/
|
||||||
|
uv_stride = uv_stride*2;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 78, 7, 31); /* burst size */
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
/*set burst size to 16*/
|
||||||
|
|
||||||
|
|
||||||
|
if (uv_stride)
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 128, 14, uv_stride - 1);
|
||||||
|
|
||||||
|
/* Get the uv offset from user when need cropping */
|
||||||
|
if (u || v) {
|
||||||
|
u_offset = u;
|
||||||
|
v_offset = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UBO and VBO are 22-bit and 8-byte aligned */
|
||||||
|
if (u_offset/8 > 0x3fffff)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's U offset exceeds IPU limitation\n", ch);
|
||||||
|
if (v_offset/8 > 0x3fffff)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's V offset exceeds IPU limitation\n", ch);
|
||||||
|
if (u_offset%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's U offset is not 8-byte aligned\n", ch);
|
||||||
|
if (v_offset%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's V offset is not 8-byte aligned\n", ch);
|
||||||
|
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 46, 22, u_offset / 8);
|
||||||
|
ipu_ch_param_set_field(¶ms, 0, 68, 22, v_offset / 8);
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "initializing idma ch %d @ %p\n", ch, ipu_ch_param_addr(ipu, ch));
|
||||||
|
fill_cpmem(ipu, ch, ¶ms);
|
||||||
|
if (addr2) {
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 0, 29, addr2 >> 3);
|
||||||
|
ipu_ch_param_set_field(¶ms, 1, 29, 29, 0);
|
||||||
|
if (addr2%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's sub-CPMEM entry%d EBA0 is not "
|
||||||
|
"8-byte aligned\n", ch, sub_ch);
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "initializing idma ch %d @ %p sub cpmem\n", ch,
|
||||||
|
ipu_ch_param_addr(ipu, sub_ch));
|
||||||
|
fill_cpmem(ipu, sub_ch, ¶ms);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_burst_size(struct ipu_soc *ipu,
|
||||||
|
uint32_t ch,
|
||||||
|
uint16_t burst_pixels)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7,
|
||||||
|
burst_pixels - 1);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 78, 7,
|
||||||
|
burst_pixels - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int _ipu_ch_param_get_burst_size(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 78, 7) + 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int _ipu_ch_param_get_bpp(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 107, 3);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_buffer(struct ipu_soc *ipu, uint32_t ch,
|
||||||
|
int bufNum, dma_addr_t phyaddr)
|
||||||
|
{
|
||||||
|
if (bufNum == 2) {
|
||||||
|
ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (ch <= 0)
|
||||||
|
return;
|
||||||
|
bufNum = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 29 * bufNum, 29,
|
||||||
|
phyaddr / 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_rotation(struct ipu_soc *ipu, uint32_t ch,
|
||||||
|
ipu_rotate_mode_t rot)
|
||||||
|
{
|
||||||
|
u32 temp_rot = bitrev8(rot) >> 5;
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 119, 3, temp_rot);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 119, 3, temp_rot);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_block_mode(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 117, 2, 1);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 117, 2, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_alpha_use_separate_channel(struct ipu_soc *ipu,
|
||||||
|
uint32_t ch,
|
||||||
|
bool option)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
if (option) {
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 1);
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 89, 1, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if (option) {
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 1);
|
||||||
|
} else {
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 89, 1, 0);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_alpha_condition_read(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 149, 1, 1);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 149, 1, 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_alpha_buffer_memory(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
int alp_mem_idx;
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
switch (ch) {
|
||||||
|
case 14: /* PRP graphic */
|
||||||
|
alp_mem_idx = 0;
|
||||||
|
break;
|
||||||
|
case 15: /* PP graphic */
|
||||||
|
alp_mem_idx = 1;
|
||||||
|
break;
|
||||||
|
case 23: /* DP BG SYNC graphic */
|
||||||
|
alp_mem_idx = 4;
|
||||||
|
break;
|
||||||
|
case 27: /* DP FG SYNC graphic */
|
||||||
|
alp_mem_idx = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(ipu->dev, "unsupported correlative channel of local "
|
||||||
|
"alpha channel\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 90, 3, alp_mem_idx);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 90, 3, alp_mem_idx);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_interlaced_scan(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
u32 stride;
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 0, 113, 1, 1);
|
||||||
|
if (sub_ch > 0)
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 113, 1, 1);
|
||||||
|
stride = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14) + 1;
|
||||||
|
/* ILO is 20-bit and 8-byte aligned */
|
||||||
|
if (stride/8 > 0xfffff)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's ILO exceeds IPU limitation\n", ch);
|
||||||
|
if (stride%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's ILO is not 8-byte aligned\n", ch);
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 58, 20, stride / 8);
|
||||||
|
if (sub_ch > 0)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 58, 20,
|
||||||
|
stride / 8);
|
||||||
|
stride *= 2;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 102, 14, stride - 1);
|
||||||
|
if (sub_ch > 0)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 102, 14,
|
||||||
|
stride - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_axi_id(struct ipu_soc *ipu, uint32_t ch, uint32_t id)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
id %= 4;
|
||||||
|
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2, id);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 93, 2, id);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int _ipu_ch_param_get_axi_id(struct ipu_soc *ipu, uint32_t ch)
|
||||||
|
{
|
||||||
|
return ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 1, 93, 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int __ipu_ch_offset_calc(uint32_t pixel_fmt,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t u,
|
||||||
|
uint32_t v,
|
||||||
|
uint32_t uv_stride,
|
||||||
|
uint32_t vertical_offset,
|
||||||
|
uint32_t horizontal_offset,
|
||||||
|
uint32_t *u_offset,
|
||||||
|
uint32_t *v_offset)
|
||||||
|
{
|
||||||
|
uint32_t u_fix = 0;
|
||||||
|
uint32_t v_fix = 0;
|
||||||
|
|
||||||
|
switch (pixel_fmt) {
|
||||||
|
case IPU_PIX_FMT_GENERIC:
|
||||||
|
case IPU_PIX_FMT_GENERIC_16:
|
||||||
|
case IPU_PIX_FMT_GENERIC_32:
|
||||||
|
case IPU_PIX_FMT_RGB565:
|
||||||
|
case IPU_PIX_FMT_BGR24:
|
||||||
|
case IPU_PIX_FMT_RGB24:
|
||||||
|
case IPU_PIX_FMT_YUV444:
|
||||||
|
case IPU_PIX_FMT_BGRA32:
|
||||||
|
case IPU_PIX_FMT_BGR32:
|
||||||
|
case IPU_PIX_FMT_RGBA32:
|
||||||
|
case IPU_PIX_FMT_RGB32:
|
||||||
|
case IPU_PIX_FMT_ABGR32:
|
||||||
|
case IPU_PIX_FMT_UYVY:
|
||||||
|
case IPU_PIX_FMT_YUYV:
|
||||||
|
case IPU_PIX_FMT_GPU32_SB_ST:
|
||||||
|
case IPU_PIX_FMT_GPU32_SB_SRT:
|
||||||
|
case IPU_PIX_FMT_GPU32_ST:
|
||||||
|
case IPU_PIX_FMT_GPU32_SRT:
|
||||||
|
case IPU_PIX_FMT_GPU16_SB_ST:
|
||||||
|
case IPU_PIX_FMT_GPU16_SB_SRT:
|
||||||
|
case IPU_PIX_FMT_GPU16_ST:
|
||||||
|
case IPU_PIX_FMT_GPU16_SRT:
|
||||||
|
*u_offset = 0;
|
||||||
|
*v_offset = 0;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV420P2:
|
||||||
|
case IPU_PIX_FMT_YUV420P:
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
*u_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset / 2) +
|
||||||
|
horizontal_offset / 2;
|
||||||
|
*v_offset = *u_offset + (uv_stride * height / 2);
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
|
||||||
|
(horizontal_offset / 2) -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
|
||||||
|
(horizontal_offset / 2) -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*v_offset;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YVU420P:
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
*v_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset / 2) +
|
||||||
|
horizontal_offset / 2;
|
||||||
|
*u_offset = *v_offset + (uv_stride * height / 2);
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
|
||||||
|
(horizontal_offset / 2) -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
v_fix = v ? (v + (uv_stride * vertical_offset / 2) +
|
||||||
|
(horizontal_offset / 2) -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*v_offset;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YVU422P:
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
*v_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2;
|
||||||
|
*u_offset = *v_offset + uv_stride * height;
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2 -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
v_fix = v ? (v + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2 -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*v_offset;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV422P:
|
||||||
|
if (uv_stride < stride / 2)
|
||||||
|
uv_stride = stride / 2;
|
||||||
|
|
||||||
|
*u_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2;
|
||||||
|
*v_offset = *u_offset + uv_stride * height;
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2 -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
v_fix = v ? (v + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset / 2 -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*v_offset;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_YUV444P:
|
||||||
|
uv_stride = stride;
|
||||||
|
*u_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset;
|
||||||
|
*v_offset = *u_offset + uv_stride * height;
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset -
|
||||||
|
(stride * vertical_offset) -
|
||||||
|
(horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
v_fix = v ? (v + (uv_stride * vertical_offset) +
|
||||||
|
horizontal_offset -
|
||||||
|
(stride * vertical_offset) -
|
||||||
|
(horizontal_offset)) :
|
||||||
|
*v_offset;
|
||||||
|
break;
|
||||||
|
case IPU_PIX_FMT_NV12:
|
||||||
|
case IPU_PIX_FMT_NV16:
|
||||||
|
case PRE_PIX_FMT_NV21:
|
||||||
|
case PRE_PIX_FMT_NV61:
|
||||||
|
uv_stride = stride;
|
||||||
|
*u_offset = stride * (height - vertical_offset - 1) +
|
||||||
|
(stride - horizontal_offset) +
|
||||||
|
(uv_stride * vertical_offset / 2) +
|
||||||
|
horizontal_offset;
|
||||||
|
*v_offset = 0;
|
||||||
|
u_fix = u ? (u + (uv_stride * vertical_offset / 2) +
|
||||||
|
horizontal_offset -
|
||||||
|
(stride * vertical_offset) - (horizontal_offset)) :
|
||||||
|
*u_offset;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (u_fix > *u_offset)
|
||||||
|
*u_offset = u_fix;
|
||||||
|
|
||||||
|
if (v_fix > *v_offset)
|
||||||
|
*v_offset = v_fix;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IDMAC U/V offset changing support */
|
||||||
|
/* U and V input is not affected, */
|
||||||
|
/* the update is done by new calculation according to */
|
||||||
|
/* vertical_offset and horizontal_offset */
|
||||||
|
static inline void _ipu_ch_offset_update(struct ipu_soc *ipu,
|
||||||
|
int ch,
|
||||||
|
uint32_t pixel_fmt,
|
||||||
|
uint32_t width,
|
||||||
|
uint32_t height,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t u,
|
||||||
|
uint32_t v,
|
||||||
|
uint32_t uv_stride,
|
||||||
|
uint32_t vertical_offset,
|
||||||
|
uint32_t horizontal_offset)
|
||||||
|
{
|
||||||
|
uint32_t u_offset = 0;
|
||||||
|
uint32_t v_offset = 0;
|
||||||
|
uint32_t old_offset = 0;
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = __ipu_ch_offset_calc(pixel_fmt, width, height, stride,
|
||||||
|
u, v, uv_stride,
|
||||||
|
vertical_offset, horizontal_offset,
|
||||||
|
&u_offset, &v_offset);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(ipu->dev, "mxc ipu: unimplemented pixel format\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* UBO and VBO are 22-bit and 8-byte aligned */
|
||||||
|
if (u_offset/8 > 0x3fffff)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's U offset exceeds IPU limitation\n", ch);
|
||||||
|
if (v_offset/8 > 0x3fffff)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's V offset exceeds IPU limitation\n", ch);
|
||||||
|
if (u_offset%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's U offset is not 8-byte aligned\n", ch);
|
||||||
|
if (v_offset%8)
|
||||||
|
dev_warn(ipu->dev,
|
||||||
|
"IDMAC%d's V offset is not 8-byte aligned\n", ch);
|
||||||
|
|
||||||
|
old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22);
|
||||||
|
if (old_offset != u_offset / 8)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 46, 22, u_offset / 8);
|
||||||
|
old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22);
|
||||||
|
if (old_offset != v_offset / 8)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, ch), 0, 68, 22, v_offset / 8);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22);
|
||||||
|
if (old_offset != u_offset / 8)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 46, 22, u_offset / 8);
|
||||||
|
old_offset = ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22);
|
||||||
|
if (old_offset != v_offset / 8)
|
||||||
|
ipu_ch_param_mod_field_io(ipu_ch_param_addr(ipu, sub_ch), 0, 68, 22, v_offset / 8);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_params_set_alpha_width(struct ipu_soc *ipu, uint32_t ch, int alpha_width)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch), 1, 125, 3, alpha_width - 1);
|
||||||
|
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch), 1, 125, 3, alpha_width - 1);
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline void _ipu_ch_param_set_bandmode(struct ipu_soc *ipu,
|
||||||
|
uint32_t ch, uint32_t band_height)
|
||||||
|
{
|
||||||
|
int32_t sub_ch = 0;
|
||||||
|
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, ch),
|
||||||
|
0, 114, 3, band_height - 1);
|
||||||
|
sub_ch = __ipu_ch_get_third_buf_cpmem_num(ch);
|
||||||
|
if (sub_ch <= 0)
|
||||||
|
return;
|
||||||
|
ipu_ch_param_set_field_io(ipu_ch_param_addr(ipu, sub_ch),
|
||||||
|
0, 114, 3, band_height - 1);
|
||||||
|
|
||||||
|
dev_dbg(ipu->dev, "BNDM 0x%x, ",
|
||||||
|
ipu_ch_param_read_field_io(ipu_ch_param_addr(ipu, ch), 0, 114, 3));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The IPUv3 IDMAC has a bug to read 32bpp pixels from a graphics plane
|
||||||
|
* whose alpha component is at the most significant 8 bits. The bug only
|
||||||
|
* impacts on cases in which the relevant separate alpha channel is enabled.
|
||||||
|
*
|
||||||
|
* Return true on bad alpha component position, otherwise, return false.
|
||||||
|
*/
|
||||||
|
static inline bool _ipu_ch_param_bad_alpha_pos(uint32_t pixel_fmt)
|
||||||
|
{
|
||||||
|
switch (pixel_fmt) {
|
||||||
|
case IPU_PIX_FMT_BGRA32:
|
||||||
|
case IPU_PIX_FMT_BGR32:
|
||||||
|
case IPU_PIX_FMT_RGBA32:
|
||||||
|
case IPU_PIX_FMT_RGB32:
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,317 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2013-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @file ipu_pixel_clk.c
|
||||||
|
*
|
||||||
|
* @brief IPU pixel clock implementation
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <linux/clk-provider.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/string.h>
|
||||||
|
|
||||||
|
#include "ipu_prv.h"
|
||||||
|
#include "ipu_regs.h"
|
||||||
|
|
||||||
|
/*
|
||||||
|
* muxd clock implementation
|
||||||
|
*/
|
||||||
|
struct clk_di_mux {
|
||||||
|
struct clk_hw hw;
|
||||||
|
u8 ipu_id;
|
||||||
|
u8 di_id;
|
||||||
|
u8 flags;
|
||||||
|
u8 index;
|
||||||
|
};
|
||||||
|
#define to_clk_di_mux(_hw) container_of(_hw, struct clk_di_mux, hw)
|
||||||
|
|
||||||
|
static int _ipu_pixel_clk_set_parent(struct clk_hw *hw, u8 index)
|
||||||
|
{
|
||||||
|
struct clk_di_mux *mux = to_clk_di_mux(hw);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(mux->ipu_id);
|
||||||
|
u32 di_gen;
|
||||||
|
|
||||||
|
di_gen = ipu_di_read(ipu, mux->di_id, DI_GENERAL);
|
||||||
|
if (index == 0)
|
||||||
|
/* ipu1_clk or ipu2_clk internal clk */
|
||||||
|
di_gen &= ~DI_GEN_DI_CLK_EXT;
|
||||||
|
else
|
||||||
|
di_gen |= DI_GEN_DI_CLK_EXT;
|
||||||
|
|
||||||
|
ipu_di_write(ipu, mux->di_id, di_gen, DI_GENERAL);
|
||||||
|
mux->index = index;
|
||||||
|
pr_debug("ipu_pixel_clk: di_clk_ext:0x%x, di_gen reg:0x%x.\n",
|
||||||
|
!(di_gen & DI_GEN_DI_CLK_EXT), di_gen);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static u8 _ipu_pixel_clk_get_parent(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_di_mux *mux = to_clk_di_mux(hw);
|
||||||
|
|
||||||
|
return mux->index;
|
||||||
|
}
|
||||||
|
|
||||||
|
const struct clk_ops clk_mux_di_ops = {
|
||||||
|
.get_parent = _ipu_pixel_clk_get_parent,
|
||||||
|
.set_parent = _ipu_pixel_clk_set_parent,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char **parent_names, u8 num_parents, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_mux_flags)
|
||||||
|
{
|
||||||
|
struct clk_di_mux *mux;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
mux = kzalloc(sizeof(struct clk_di_mux), GFP_KERNEL);
|
||||||
|
if (!mux)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &clk_mux_di_ops;
|
||||||
|
init.flags = flags;
|
||||||
|
init.parent_names = parent_names;
|
||||||
|
init.num_parents = num_parents;
|
||||||
|
|
||||||
|
mux->ipu_id = ipu_id;
|
||||||
|
mux->di_id = di_id;
|
||||||
|
mux->flags = clk_mux_flags | CLK_SET_RATE_PARENT;
|
||||||
|
mux->hw.init = &init;
|
||||||
|
|
||||||
|
clk = clk_register(dev, &mux->hw);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(mux);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gated clock implementation
|
||||||
|
*/
|
||||||
|
struct clk_di_div {
|
||||||
|
struct clk_hw hw;
|
||||||
|
u8 ipu_id;
|
||||||
|
u8 di_id;
|
||||||
|
u8 flags;
|
||||||
|
};
|
||||||
|
#define to_clk_di_div(_hw) container_of(_hw, struct clk_di_div, hw)
|
||||||
|
|
||||||
|
static unsigned long _ipu_pixel_clk_div_recalc_rate(struct clk_hw *hw,
|
||||||
|
unsigned long parent_rate)
|
||||||
|
{
|
||||||
|
struct clk_di_div *di_div = to_clk_di_div(hw);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
|
||||||
|
u32 div;
|
||||||
|
u64 final_rate = (unsigned long long)parent_rate * 16;
|
||||||
|
|
||||||
|
_ipu_get(ipu);
|
||||||
|
div = ipu_di_read(ipu, di_div->di_id, DI_BS_CLKGEN0);
|
||||||
|
_ipu_put(ipu);
|
||||||
|
pr_debug("ipu_di%d read BS_CLKGEN0 div:%d, final_rate:%lld, prate:%ld\n",
|
||||||
|
di_div->di_id, div, final_rate, parent_rate);
|
||||||
|
|
||||||
|
if (div == 0)
|
||||||
|
return 0;
|
||||||
|
do_div(final_rate, div);
|
||||||
|
|
||||||
|
return (unsigned long)final_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static long _ipu_pixel_clk_div_round_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long *parent_clk_rate)
|
||||||
|
{
|
||||||
|
u64 div, final_rate;
|
||||||
|
u32 remainder;
|
||||||
|
u64 parent_rate = (unsigned long long)(*parent_clk_rate) * 16;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Calculate divider
|
||||||
|
* Fractional part is 4 bits,
|
||||||
|
* so simply multiply by 2^4 to get fractional part.
|
||||||
|
*/
|
||||||
|
div = parent_rate;
|
||||||
|
remainder = do_div(div, rate);
|
||||||
|
/* Round the divider value */
|
||||||
|
if (remainder > (rate/2))
|
||||||
|
div++;
|
||||||
|
if (div < 0x10) /* Min DI disp clock divider is 1 */
|
||||||
|
div = 0x10;
|
||||||
|
if (div & ~0xFEF)
|
||||||
|
div &= 0xFF8;
|
||||||
|
else {
|
||||||
|
/* Round up divider if it gets us closer to desired pix clk */
|
||||||
|
if ((div & 0xC) == 0xC) {
|
||||||
|
div += 0x10;
|
||||||
|
div &= ~0xF;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
final_rate = parent_rate;
|
||||||
|
do_div(final_rate, div);
|
||||||
|
|
||||||
|
return final_rate;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int _ipu_pixel_clk_div_set_rate(struct clk_hw *hw, unsigned long rate,
|
||||||
|
unsigned long parent_clk_rate)
|
||||||
|
{
|
||||||
|
struct clk_di_div *di_div = to_clk_di_div(hw);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(di_div->ipu_id);
|
||||||
|
u64 div, parent_rate;
|
||||||
|
u32 remainder;
|
||||||
|
|
||||||
|
parent_rate = (unsigned long long)parent_clk_rate * 16;
|
||||||
|
div = parent_rate;
|
||||||
|
remainder = do_div(div, rate);
|
||||||
|
/* Round the divider value */
|
||||||
|
if (remainder > (rate/2))
|
||||||
|
div++;
|
||||||
|
|
||||||
|
/* Round up divider if it gets us closer to desired pix clk */
|
||||||
|
if ((div & 0xC) == 0xC) {
|
||||||
|
div += 0x10;
|
||||||
|
div &= ~0xF;
|
||||||
|
}
|
||||||
|
if (div > 0x1000)
|
||||||
|
pr_err("Overflow, di:%d, DI_BS_CLKGEN0 div:0x%x\n",
|
||||||
|
di_div->di_id, (u32)div);
|
||||||
|
_ipu_get(ipu);
|
||||||
|
ipu_di_write(ipu, di_div->di_id, (u32)div, DI_BS_CLKGEN0);
|
||||||
|
|
||||||
|
/* Setup pixel clock timing */
|
||||||
|
/* FIXME: needs to be more flexible */
|
||||||
|
/* Down time is half of period */
|
||||||
|
ipu_di_write(ipu, di_div->di_id, ((u32)div / 16) << 16, DI_BS_CLKGEN1);
|
||||||
|
_ipu_put(ipu);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct clk_ops clk_div_ops = {
|
||||||
|
.recalc_rate = _ipu_pixel_clk_div_recalc_rate,
|
||||||
|
.round_rate = _ipu_pixel_clk_div_round_rate,
|
||||||
|
.set_rate = _ipu_pixel_clk_div_set_rate,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char *parent_name, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_div_flags)
|
||||||
|
{
|
||||||
|
struct clk_di_div *di_div;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
di_div = kzalloc(sizeof(struct clk_di_div), GFP_KERNEL);
|
||||||
|
if (!di_div)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
/* struct clk_di_div assignments */
|
||||||
|
di_div->ipu_id = ipu_id;
|
||||||
|
di_div->di_id = di_id;
|
||||||
|
di_div->flags = clk_div_flags;
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &clk_div_ops;
|
||||||
|
init.flags = flags | CLK_SET_RATE_PARENT;
|
||||||
|
init.parent_names = parent_name ? &parent_name : NULL;
|
||||||
|
init.num_parents = parent_name ? 1 : 0;
|
||||||
|
|
||||||
|
di_div->hw.init = &init;
|
||||||
|
|
||||||
|
clk = clk_register(dev, &di_div->hw);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(di_div);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Gated clock implementation
|
||||||
|
*/
|
||||||
|
struct clk_di_gate {
|
||||||
|
struct clk_hw hw;
|
||||||
|
u8 ipu_id;
|
||||||
|
u8 di_id;
|
||||||
|
u8 flags;
|
||||||
|
};
|
||||||
|
#define to_clk_di_gate(_hw) container_of(_hw, struct clk_di_gate, hw)
|
||||||
|
|
||||||
|
static int _ipu_pixel_clk_enable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_di_gate *gate = to_clk_di_gate(hw);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
|
||||||
|
u32 disp_gen;
|
||||||
|
|
||||||
|
disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
|
||||||
|
disp_gen |= gate->di_id ? DI1_COUNTER_RELEASE : DI0_COUNTER_RELEASE;
|
||||||
|
ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _ipu_pixel_clk_disable(struct clk_hw *hw)
|
||||||
|
{
|
||||||
|
struct clk_di_gate *gate = to_clk_di_gate(hw);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(gate->ipu_id);
|
||||||
|
u32 disp_gen;
|
||||||
|
|
||||||
|
disp_gen = ipu_cm_read(ipu, IPU_DISP_GEN);
|
||||||
|
disp_gen &= gate->di_id ? ~DI1_COUNTER_RELEASE : ~DI0_COUNTER_RELEASE;
|
||||||
|
ipu_cm_write(ipu, disp_gen, IPU_DISP_GEN);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static struct clk_ops clk_gate_di_ops = {
|
||||||
|
.enable = _ipu_pixel_clk_enable,
|
||||||
|
.disable = _ipu_pixel_clk_disable,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char *parent_name, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_gate_flags)
|
||||||
|
{
|
||||||
|
struct clk_di_gate *gate;
|
||||||
|
struct clk *clk;
|
||||||
|
struct clk_init_data init;
|
||||||
|
|
||||||
|
gate = kzalloc(sizeof(struct clk_di_gate), GFP_KERNEL);
|
||||||
|
if (!gate)
|
||||||
|
return ERR_PTR(-ENOMEM);
|
||||||
|
|
||||||
|
gate->ipu_id = ipu_id;
|
||||||
|
gate->di_id = di_id;
|
||||||
|
gate->flags = clk_gate_flags;
|
||||||
|
|
||||||
|
init.name = name;
|
||||||
|
init.ops = &clk_gate_di_ops;
|
||||||
|
init.flags = flags | CLK_SET_RATE_PARENT;
|
||||||
|
init.parent_names = parent_name ? &parent_name : NULL;
|
||||||
|
init.num_parents = parent_name ? 1 : 0;
|
||||||
|
|
||||||
|
gate->hw.init = &init;
|
||||||
|
|
||||||
|
clk = clk_register(dev, &gate->hw);
|
||||||
|
if (IS_ERR(clk))
|
||||||
|
kfree(gate);
|
||||||
|
|
||||||
|
return clk;
|
||||||
|
}
|
|
@ -0,0 +1,369 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2016 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#ifndef __INCLUDE_IPU_PRV_H__
|
||||||
|
#define __INCLUDE_IPU_PRV_H__
|
||||||
|
|
||||||
|
#include <linux/clkdev.h>
|
||||||
|
#include <linux/device.h>
|
||||||
|
#include <linux/fsl_devices.h>
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#define MXC_IPU_MAX_NUM 2
|
||||||
|
#define MXC_DI_NUM_PER_IPU 2
|
||||||
|
|
||||||
|
/* Globals */
|
||||||
|
extern int dmfc_type_setup;
|
||||||
|
|
||||||
|
#define IDMA_CHAN_INVALID 0xFF
|
||||||
|
#define HIGH_RESOLUTION_WIDTH 1024
|
||||||
|
|
||||||
|
enum ipuv3_type {
|
||||||
|
IPUv3D, /* i.MX37 */
|
||||||
|
IPUv3EX, /* i.MX51 */
|
||||||
|
IPUv3M, /* i.MX53 */
|
||||||
|
IPUv3H, /* i.MX6Q/SDL */
|
||||||
|
};
|
||||||
|
|
||||||
|
#define IPU_MAX_VDI_IN_WIDTH(type) ({ (type) >= IPUv3M ? 968 : 720; })
|
||||||
|
|
||||||
|
struct ipu_irq_node {
|
||||||
|
irqreturn_t(*handler) (int, void *); /*!< the ISR */
|
||||||
|
const char *name; /*!< device associated with the interrupt */
|
||||||
|
void *dev_id; /*!< some unique information for the ISR */
|
||||||
|
__u32 flags; /*!< not used */
|
||||||
|
};
|
||||||
|
|
||||||
|
enum csc_type_t {
|
||||||
|
RGB2YUV = 0,
|
||||||
|
YUV2RGB,
|
||||||
|
RGB2RGB,
|
||||||
|
YUV2YUV,
|
||||||
|
CSC_NONE,
|
||||||
|
CSC_NUM
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipu_soc {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int devtype;
|
||||||
|
bool online;
|
||||||
|
|
||||||
|
/*clk*/
|
||||||
|
struct clk *ipu_clk;
|
||||||
|
struct clk *di_clk[2];
|
||||||
|
struct clk *di_clk_sel[2];
|
||||||
|
struct clk *pixel_clk[2];
|
||||||
|
bool pixel_clk_en[2];
|
||||||
|
struct clk *pixel_clk_sel[2];
|
||||||
|
struct clk *csi_clk[2];
|
||||||
|
struct clk *prg_clk;
|
||||||
|
|
||||||
|
/*irq*/
|
||||||
|
int irq_sync;
|
||||||
|
int irq_err;
|
||||||
|
struct ipu_irq_node irq_list[IPU_IRQ_COUNT];
|
||||||
|
|
||||||
|
/*reg*/
|
||||||
|
void __iomem *cm_reg;
|
||||||
|
void __iomem *idmac_reg;
|
||||||
|
void __iomem *dp_reg;
|
||||||
|
void __iomem *ic_reg;
|
||||||
|
void __iomem *dc_reg;
|
||||||
|
void __iomem *dc_tmpl_reg;
|
||||||
|
void __iomem *dmfc_reg;
|
||||||
|
void __iomem *di_reg[2];
|
||||||
|
void __iomem *smfc_reg;
|
||||||
|
void __iomem *csi_reg[2];
|
||||||
|
void __iomem *cpmem_base;
|
||||||
|
void __iomem *tpmem_base;
|
||||||
|
void __iomem *vdi_reg;
|
||||||
|
|
||||||
|
struct device *dev;
|
||||||
|
|
||||||
|
ipu_channel_t csi_channel[2];
|
||||||
|
ipu_channel_t using_ic_dirct_ch;
|
||||||
|
unsigned char dc_di_assignment[10];
|
||||||
|
bool sec_chan_en[IPU_MAX_CH];
|
||||||
|
bool thrd_chan_en[IPU_MAX_CH];
|
||||||
|
bool chan_is_interlaced[52];
|
||||||
|
uint32_t channel_init_mask;
|
||||||
|
uint32_t channel_enable_mask;
|
||||||
|
|
||||||
|
/*use count*/
|
||||||
|
int dc_use_count;
|
||||||
|
int dp_use_count;
|
||||||
|
int dmfc_use_count;
|
||||||
|
int smfc_use_count;
|
||||||
|
int ic_use_count;
|
||||||
|
int rot_use_count;
|
||||||
|
int vdi_use_count;
|
||||||
|
int di_use_count[2];
|
||||||
|
int csi_use_count[2];
|
||||||
|
|
||||||
|
struct mutex mutex_lock;
|
||||||
|
spinlock_t int_reg_spin_lock;
|
||||||
|
spinlock_t rdy_reg_spin_lock;
|
||||||
|
|
||||||
|
int dmfc_size_28;
|
||||||
|
int dmfc_size_29;
|
||||||
|
int dmfc_size_24;
|
||||||
|
int dmfc_size_27;
|
||||||
|
int dmfc_size_23;
|
||||||
|
|
||||||
|
enum csc_type_t fg_csc_type;
|
||||||
|
enum csc_type_t bg_csc_type;
|
||||||
|
bool color_key_4rgb;
|
||||||
|
bool dc_swap;
|
||||||
|
struct completion dc_comp;
|
||||||
|
struct completion csi_comp;
|
||||||
|
|
||||||
|
struct rot_mem {
|
||||||
|
void *vaddr;
|
||||||
|
dma_addr_t paddr;
|
||||||
|
int size;
|
||||||
|
} rot_dma[2];
|
||||||
|
|
||||||
|
int vdoa_en;
|
||||||
|
struct task_struct *thread[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Bypass reset to avoid display channel being
|
||||||
|
* stopped by probe since it may starts to work
|
||||||
|
* in bootloader.
|
||||||
|
*/
|
||||||
|
bool bypass_reset;
|
||||||
|
|
||||||
|
unsigned int ch0123_axi;
|
||||||
|
unsigned int ch23_axi;
|
||||||
|
unsigned int ch27_axi;
|
||||||
|
unsigned int ch28_axi;
|
||||||
|
unsigned int normal_axi;
|
||||||
|
|
||||||
|
bool smfc_idmac_12bit_3planar_bs_fixup; /* workaround little stripes */
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipu_channel {
|
||||||
|
u8 video_in_dma;
|
||||||
|
u8 alpha_in_dma;
|
||||||
|
u8 graph_in_dma;
|
||||||
|
u8 out_dma;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum ipu_dmfc_type {
|
||||||
|
DMFC_NORMAL = 0,
|
||||||
|
DMFC_HIGH_RESOLUTION_DC,
|
||||||
|
DMFC_HIGH_RESOLUTION_DP,
|
||||||
|
DMFC_HIGH_RESOLUTION_ONLY_DP,
|
||||||
|
};
|
||||||
|
|
||||||
|
static inline int _ipu_is_smfc_chan(uint32_t dma_chan)
|
||||||
|
{
|
||||||
|
return dma_chan <= 3;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_cm_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->cm_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_cm_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->cm_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_idmac_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->idmac_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_idmac_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->idmac_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_dc_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->dc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_dc_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->dc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_dc_tmpl_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->dc_tmpl_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_dc_tmpl_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->dc_tmpl_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_dmfc_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->dmfc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_dmfc_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->dmfc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_dp_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->dp_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_dp_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->dp_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_di_read(struct ipu_soc *ipu, int di, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->di_reg[di] + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_di_write(struct ipu_soc *ipu, int di,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->di_reg[di] + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_csi_read(struct ipu_soc *ipu, int csi, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->csi_reg[csi] + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_csi_write(struct ipu_soc *ipu, int csi,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->csi_reg[csi] + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_smfc_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->smfc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_smfc_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->smfc_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_vdi_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->vdi_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_vdi_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->vdi_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 ipu_ic_read(struct ipu_soc *ipu, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(ipu->ic_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void ipu_ic_write(struct ipu_soc *ipu,
|
||||||
|
u32 value, unsigned offset)
|
||||||
|
{
|
||||||
|
writel(value, ipu->ic_reg + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
int register_ipu_device(struct ipu_soc *ipu, int id);
|
||||||
|
void unregister_ipu_device(struct ipu_soc *ipu, int id);
|
||||||
|
ipu_color_space_t format_to_colorspace(uint32_t fmt);
|
||||||
|
bool ipu_pixel_format_has_alpha(uint32_t fmt);
|
||||||
|
|
||||||
|
void ipu_dump_registers(struct ipu_soc *ipu);
|
||||||
|
|
||||||
|
uint32_t _ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
|
||||||
|
void ipu_disp_init(struct ipu_soc *ipu);
|
||||||
|
void _ipu_init_dc_mappings(struct ipu_soc *ipu);
|
||||||
|
int _ipu_dp_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t in_pixel_fmt,
|
||||||
|
uint32_t out_pixel_fmt);
|
||||||
|
void _ipu_dp_uninit(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
void _ipu_dc_init(struct ipu_soc *ipu, int dc_chan, int di, bool interlaced, uint32_t pixel_fmt);
|
||||||
|
void _ipu_dc_uninit(struct ipu_soc *ipu, int dc_chan);
|
||||||
|
void _ipu_dp_dc_enable(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
void _ipu_dp_dc_disable(struct ipu_soc *ipu, ipu_channel_t channel, bool swap);
|
||||||
|
void _ipu_dmfc_init(struct ipu_soc *ipu, int dmfc_type, int first);
|
||||||
|
void _ipu_dmfc_set_wait4eot(struct ipu_soc *ipu, int dma_chan, int width);
|
||||||
|
void _ipu_dmfc_set_burst_size(struct ipu_soc *ipu, int dma_chan, int burst_size);
|
||||||
|
int _ipu_disp_chan_is_interlaced(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
|
||||||
|
void _ipu_ic_enable_task(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
void _ipu_ic_disable_task(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
int _ipu_ic_init_prpvf(struct ipu_soc *ipu, ipu_channel_params_t *params,
|
||||||
|
bool src_is_csi);
|
||||||
|
void _ipu_vdi_init(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
|
||||||
|
void _ipu_vdi_uninit(struct ipu_soc *ipu);
|
||||||
|
void _ipu_ic_uninit_prpvf(struct ipu_soc *ipu);
|
||||||
|
void _ipu_ic_init_rotate_vf(struct ipu_soc *ipu, ipu_channel_params_t *params);
|
||||||
|
void _ipu_ic_uninit_rotate_vf(struct ipu_soc *ipu);
|
||||||
|
void _ipu_ic_init_csi(struct ipu_soc *ipu, ipu_channel_params_t *params);
|
||||||
|
void _ipu_ic_uninit_csi(struct ipu_soc *ipu);
|
||||||
|
int _ipu_ic_init_prpenc(struct ipu_soc *ipu, ipu_channel_params_t *params,
|
||||||
|
bool src_is_csi);
|
||||||
|
void _ipu_ic_uninit_prpenc(struct ipu_soc *ipu);
|
||||||
|
void _ipu_ic_init_rotate_enc(struct ipu_soc *ipu, ipu_channel_params_t *params);
|
||||||
|
void _ipu_ic_uninit_rotate_enc(struct ipu_soc *ipu);
|
||||||
|
int _ipu_ic_init_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
|
||||||
|
void _ipu_ic_uninit_pp(struct ipu_soc *ipu);
|
||||||
|
void _ipu_ic_init_rotate_pp(struct ipu_soc *ipu, ipu_channel_params_t *params);
|
||||||
|
void _ipu_ic_uninit_rotate_pp(struct ipu_soc *ipu);
|
||||||
|
int _ipu_ic_idma_init(struct ipu_soc *ipu, int dma_chan, uint16_t width, uint16_t height,
|
||||||
|
int burst_size, ipu_rotate_mode_t rot);
|
||||||
|
void _ipu_vdi_toggle_top_field_man(struct ipu_soc *ipu);
|
||||||
|
int _ipu_csi_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t csi);
|
||||||
|
int _ipu_csi_set_mipi_di(struct ipu_soc *ipu, uint32_t num, uint32_t di_val, uint32_t csi);
|
||||||
|
void ipu_csi_set_test_generator(struct ipu_soc *ipu, bool active, uint32_t r_value,
|
||||||
|
uint32_t g_value, uint32_t b_value,
|
||||||
|
uint32_t pix_clk, uint32_t csi);
|
||||||
|
void _ipu_csi_ccir_err_detection_enable(struct ipu_soc *ipu, uint32_t csi);
|
||||||
|
void _ipu_csi_ccir_err_detection_disable(struct ipu_soc *ipu, uint32_t csi);
|
||||||
|
void _ipu_csi_wait4eof(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
void _ipu_smfc_init(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t mipi_id, uint32_t csi);
|
||||||
|
void _ipu_smfc_set_burst_size(struct ipu_soc *ipu, ipu_channel_t channel, uint32_t bs);
|
||||||
|
void _ipu_dp_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
|
||||||
|
int32_t _ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
|
||||||
|
int16_t x_pos, int16_t y_pos);
|
||||||
|
int32_t _ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel,
|
||||||
|
int16_t *x_pos, int16_t *y_pos);
|
||||||
|
void _ipu_get(struct ipu_soc *ipu);
|
||||||
|
void _ipu_put(struct ipu_soc *ipu);
|
||||||
|
|
||||||
|
struct clk *clk_register_mux_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char **parent_names, u8 num_parents, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_mux_flags);
|
||||||
|
struct clk *clk_register_div_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char *parent_name, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_div_flags);
|
||||||
|
struct clk *clk_register_gate_pix_clk(struct device *dev, const char *name,
|
||||||
|
const char *parent_name, unsigned long flags,
|
||||||
|
u8 ipu_id, u8 di_id, u8 clk_gate_flags);
|
||||||
|
#endif /* __INCLUDE_IPU_PRV_H__ */
|
|
@ -0,0 +1,702 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2005-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @file ipu_regs.h
|
||||||
|
*
|
||||||
|
* @brief IPU Register definitions
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
#ifndef __IPU_REGS_INCLUDED__
|
||||||
|
#define __IPU_REGS_INCLUDED__
|
||||||
|
|
||||||
|
#include "ipu_prv.h"
|
||||||
|
|
||||||
|
#define IPU_MCU_T_DEFAULT 8
|
||||||
|
|
||||||
|
/* Register addresses */
|
||||||
|
/* IPU Common registers */
|
||||||
|
#define IPU_CM_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define IPU_CONF IPU_CM_REG(0)
|
||||||
|
#define IPU_SRM_PRI1 IPU_CM_REG(0x00A0)
|
||||||
|
#define IPU_SRM_PRI2 IPU_CM_REG(0x00A4)
|
||||||
|
#define IPU_FS_PROC_FLOW1 IPU_CM_REG(0x00A8)
|
||||||
|
#define IPU_FS_PROC_FLOW2 IPU_CM_REG(0x00AC)
|
||||||
|
#define IPU_FS_PROC_FLOW3 IPU_CM_REG(0x00B0)
|
||||||
|
#define IPU_FS_DISP_FLOW1 IPU_CM_REG(0x00B4)
|
||||||
|
#define IPU_FS_DISP_FLOW2 IPU_CM_REG(0x00B8)
|
||||||
|
#define IPU_SKIP IPU_CM_REG(0x00BC)
|
||||||
|
#define IPU_DISP_ALT_CONF IPU_CM_REG(0x00C0)
|
||||||
|
#define IPU_DISP_GEN IPU_CM_REG(0x00C4)
|
||||||
|
#define IPU_DISP_ALT1 IPU_CM_REG(0x00C8)
|
||||||
|
#define IPU_DISP_ALT2 IPU_CM_REG(0x00CC)
|
||||||
|
#define IPU_DISP_ALT3 IPU_CM_REG(0x00D0)
|
||||||
|
#define IPU_DISP_ALT4 IPU_CM_REG(0x00D4)
|
||||||
|
#define IPU_SNOOP IPU_CM_REG(0x00D8)
|
||||||
|
#define IPU_MEM_RST IPU_CM_REG(0x00DC)
|
||||||
|
#define IPU_PM IPU_CM_REG(0x00E0)
|
||||||
|
#define IPU_GPR IPU_CM_REG(0x00E4)
|
||||||
|
#define IPU_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0150 + 4 * ((ch) / 32))
|
||||||
|
#define IPU_ALT_CHA_DB_MODE_SEL(ch) IPU_CM_REG(0x0168 + 4 * ((ch) / 32))
|
||||||
|
/*
|
||||||
|
* IPUv3D doesn't support triple buffer, so point
|
||||||
|
* IPU_CHA_TRB_MODE_SEL, IPU_CHA_TRIPLE_CUR_BUF and
|
||||||
|
* IPU_CHA_BUF2_RDY to readonly
|
||||||
|
* IPU_ALT_CUR_BUF0 for IPUv3D.
|
||||||
|
*/
|
||||||
|
#define IPU_CHA_TRB_MODE_SEL(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0178 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x012C); })
|
||||||
|
#define IPU_CHA_TRIPLE_CUR_BUF(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0258 + \
|
||||||
|
4 * (((ch) * 2) / 32)) : \
|
||||||
|
(0x012C); })
|
||||||
|
#define IPU_CHA_BUF2_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0288 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x012C); })
|
||||||
|
#define IPU_CHA_CUR_BUF(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x023C + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0124 + 4 * ((ch) / 32)); })
|
||||||
|
#define IPU_ALT_CUR_BUF0(type) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0244) : \
|
||||||
|
(0x012C); })
|
||||||
|
#define IPU_ALT_CUR_BUF1(type) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0248) : \
|
||||||
|
(0x0130); })
|
||||||
|
#define IPU_SRM_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x024C) : \
|
||||||
|
(0x0134); })
|
||||||
|
#define IPU_PROC_TASK_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0250) : \
|
||||||
|
(0x0138); })
|
||||||
|
#define IPU_DISP_TASK_STAT(type) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0254) : \
|
||||||
|
(0x013C); })
|
||||||
|
#define IPU_CHA_BUF0_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0268 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0140 + 4 * ((ch) / 32)); })
|
||||||
|
#define IPU_CHA_BUF1_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0270 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0148 + 4 * ((ch) / 32)); })
|
||||||
|
#define IPU_ALT_CHA_BUF0_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0278 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0158 + 4 * ((ch) / 32)); })
|
||||||
|
#define IPU_ALT_CHA_BUF1_RDY(type, ch) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0280 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0160 + 4 * ((ch) / 32)); })
|
||||||
|
|
||||||
|
#define IPU_INT_CTRL(n) IPU_CM_REG(0x003C + 4 * ((n) - 1))
|
||||||
|
#define IPU_INT_STAT(type, n) IPU_CM_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0200 + 4 * ((n) - 1)) : \
|
||||||
|
(0x00E8 + 4 * ((n) - 1)); })
|
||||||
|
|
||||||
|
#define IPUIRQ_2_STATREG(type, irq) IPU_CM_REG(IPU_INT_STAT((type), 1) + 4 \
|
||||||
|
* ((irq) / 32))
|
||||||
|
#define IPUIRQ_2_CTRLREG(irq) IPU_CM_REG(IPU_INT_CTRL(1) + 4 * ((irq) / 32))
|
||||||
|
#define IPUIRQ_2_MASK(irq) (1UL << ((irq) & 0x1F))
|
||||||
|
|
||||||
|
/* IPU VDI registers */
|
||||||
|
#define IPU_VDI_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define VDI_FSIZE IPU_VDI_REG(0)
|
||||||
|
#define VDI_C IPU_VDI_REG(0x0004)
|
||||||
|
|
||||||
|
/* IPU CSI Registers */
|
||||||
|
#define IPU_CSI_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define CSI_SENS_CONF IPU_CSI_REG(0)
|
||||||
|
#define CSI_SENS_FRM_SIZE IPU_CSI_REG(0x0004)
|
||||||
|
#define CSI_ACT_FRM_SIZE IPU_CSI_REG(0x0008)
|
||||||
|
#define CSI_OUT_FRM_CTRL IPU_CSI_REG(0x000C)
|
||||||
|
#define CSI_TST_CTRL IPU_CSI_REG(0x0010)
|
||||||
|
#define CSI_CCIR_CODE_1 IPU_CSI_REG(0x0014)
|
||||||
|
#define CSI_CCIR_CODE_2 IPU_CSI_REG(0x0018)
|
||||||
|
#define CSI_CCIR_CODE_3 IPU_CSI_REG(0x001C)
|
||||||
|
#define CSI_MIPI_DI IPU_CSI_REG(0x0020)
|
||||||
|
#define CSI_SKIP IPU_CSI_REG(0x0024)
|
||||||
|
#define CSI_CPD_CTRL IPU_CSI_REG(0x0028)
|
||||||
|
#define CSI_CPD_RC(n) IPU_CSI_REG(0x002C + 4 * (n))
|
||||||
|
#define CSI_CPD_RS(n) IPU_CSI_REG(0x004C + 4 * (n))
|
||||||
|
#define CSI_CPD_GRC(n) IPU_CSI_REG(0x005C + 4 * (n))
|
||||||
|
#define CSI_CPD_GRS(n) IPU_CSI_REG(0x007C + 4 * (n))
|
||||||
|
#define CSI_CPD_GBC(n) IPU_CSI_REG(0x008C + 4 * (n))
|
||||||
|
#define CSI_CPD_GBS(n) IPU_CSI_REG(0x00AC + 4 * (n))
|
||||||
|
#define CSI_CPD_BC(n) IPU_CSI_REG(0x00BC + 4 * (n))
|
||||||
|
#define CSI_CPD_BS(n) IPU_CSI_REG(0x00DC + 4 * (n))
|
||||||
|
#define CSI_CPD_OFFSET1 IPU_CSI_REG(0x00EC)
|
||||||
|
#define CSI_CPD_OFFSET2 IPU_CSI_REG(0x00F0)
|
||||||
|
|
||||||
|
/* IPU SMFC Registers */
|
||||||
|
#define IPU_SMFC_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define SMFC_MAP IPU_SMFC_REG(0)
|
||||||
|
#define SMFC_WMC IPU_SMFC_REG(0x0004)
|
||||||
|
#define SMFC_BS IPU_SMFC_REG(0x0008)
|
||||||
|
|
||||||
|
/* IPU IC Registers */
|
||||||
|
#define IPU_IC_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define IC_CONF IPU_IC_REG(0)
|
||||||
|
#define IC_PRP_ENC_RSC IPU_IC_REG(0x0004)
|
||||||
|
#define IC_PRP_VF_RSC IPU_IC_REG(0x0008)
|
||||||
|
#define IC_PP_RSC IPU_IC_REG(0x000C)
|
||||||
|
#define IC_CMBP_1 IPU_IC_REG(0x0010)
|
||||||
|
#define IC_CMBP_2 IPU_IC_REG(0x0014)
|
||||||
|
#define IC_IDMAC_1 IPU_IC_REG(0x0018)
|
||||||
|
#define IC_IDMAC_2 IPU_IC_REG(0x001C)
|
||||||
|
#define IC_IDMAC_3 IPU_IC_REG(0x0020)
|
||||||
|
#define IC_IDMAC_4 IPU_IC_REG(0x0024)
|
||||||
|
|
||||||
|
/* IPU IDMAC Registers */
|
||||||
|
#define IPU_IDMAC_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define IDMAC_CONF IPU_IDMAC_REG(0x0000)
|
||||||
|
#define IDMAC_CHA_EN(ch) IPU_IDMAC_REG(0x0004 + 4 * ((ch) / 32))
|
||||||
|
#define IDMAC_SEP_ALPHA IPU_IDMAC_REG(0x000C)
|
||||||
|
#define IDMAC_ALT_SEP_ALPHA IPU_IDMAC_REG(0x0010)
|
||||||
|
#define IDMAC_CHA_PRI(ch) IPU_IDMAC_REG(0x0014 + 4 * ((ch) / 32))
|
||||||
|
#define IDMAC_WM_EN(ch) IPU_IDMAC_REG(0x001C + 4 * ((ch) / 32))
|
||||||
|
#define IDMAC_CH_LOCK_EN_1(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0024) : 0; })
|
||||||
|
#define IDMAC_CH_LOCK_EN_2(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0028) : \
|
||||||
|
(0x0024); })
|
||||||
|
#define IDMAC_SUB_ADDR_0(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x002C) : \
|
||||||
|
(0x0028); })
|
||||||
|
#define IDMAC_SUB_ADDR_1(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0030) : \
|
||||||
|
(0x002C); })
|
||||||
|
#define IDMAC_SUB_ADDR_2(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0034) : \
|
||||||
|
(0x0030); })
|
||||||
|
/*
|
||||||
|
* IPUv3D doesn't support IDMAC_SUB_ADDR_3 and IDMAC_SUB_ADDR_4,
|
||||||
|
* so point them to readonly IDMAC_CHA_BUSY1 for IPUv3D.
|
||||||
|
*/
|
||||||
|
#define IDMAC_SUB_ADDR_3(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0038) : \
|
||||||
|
(0x0040); })
|
||||||
|
#define IDMAC_SUB_ADDR_4(type) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x003C) : \
|
||||||
|
(0x0040); })
|
||||||
|
#define IDMAC_BAND_EN(type, ch) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0040 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0034 + 4 * ((ch) / 32)); })
|
||||||
|
#define IDMAC_CHA_BUSY(type, ch) IPU_IDMAC_REG({(type) >= IPUv3EX ? \
|
||||||
|
(0x0100 + 4 * ((ch) / 32)) : \
|
||||||
|
(0x0040 + 4 * ((ch) / 32)); })
|
||||||
|
|
||||||
|
/* IPU DI Registers */
|
||||||
|
#define IPU_DI_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define DI_GENERAL IPU_DI_REG(0)
|
||||||
|
#define DI_BS_CLKGEN0 IPU_DI_REG(0x0004)
|
||||||
|
#define DI_BS_CLKGEN1 IPU_DI_REG(0x0008)
|
||||||
|
#define DI_SW_GEN0(gen) IPU_DI_REG(0x000C + 4 * ((gen) - 1))
|
||||||
|
#define DI_SW_GEN1(gen) IPU_DI_REG(0x0030 + 4 * ((gen) - 1))
|
||||||
|
#define DI_STP_REP(gen) IPU_DI_REG(0x0148 + 4 * (((gen) - 1) / 2))
|
||||||
|
#define DI_SYNC_AS_GEN IPU_DI_REG(0x0054)
|
||||||
|
#define DI_DW_GEN(gen) IPU_DI_REG(0x0058 + 4 * (gen))
|
||||||
|
#define DI_DW_SET(gen, set) IPU_DI_REG(0x0088 + 4 * ((gen) + 0xC * (set)))
|
||||||
|
#define DI_SER_CONF IPU_DI_REG(0x015C)
|
||||||
|
#define DI_SSC IPU_DI_REG(0x0160)
|
||||||
|
#define DI_POL IPU_DI_REG(0x0164)
|
||||||
|
#define DI_AW0 IPU_DI_REG(0x0168)
|
||||||
|
#define DI_AW1 IPU_DI_REG(0x016C)
|
||||||
|
#define DI_SCR_CONF IPU_DI_REG(0x0170)
|
||||||
|
#define DI_STAT IPU_DI_REG(0x0174)
|
||||||
|
|
||||||
|
/* IPU DMFC Registers */
|
||||||
|
#define IPU_DMFC_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define DMFC_RD_CHAN IPU_DMFC_REG(0)
|
||||||
|
#define DMFC_WR_CHAN IPU_DMFC_REG(0x0004)
|
||||||
|
#define DMFC_WR_CHAN_DEF IPU_DMFC_REG(0x0008)
|
||||||
|
#define DMFC_DP_CHAN IPU_DMFC_REG(0x000C)
|
||||||
|
#define DMFC_DP_CHAN_DEF IPU_DMFC_REG(0x0010)
|
||||||
|
#define DMFC_GENERAL1 IPU_DMFC_REG(0x0014)
|
||||||
|
#define DMFC_GENERAL2 IPU_DMFC_REG(0x0018)
|
||||||
|
#define DMFC_IC_CTRL IPU_DMFC_REG(0x001C)
|
||||||
|
#define DMFC_STAT IPU_DMFC_REG(0x0020)
|
||||||
|
|
||||||
|
/* IPU DC Registers */
|
||||||
|
#define IPU_DC_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define DC_MAP_CONF_PTR(n) IPU_DC_REG(0x0108 + ((n) & ~0x1) * 2)
|
||||||
|
#define DC_MAP_CONF_VAL(n) IPU_DC_REG(0x0144 + ((n) & ~0x1) * 2)
|
||||||
|
|
||||||
|
#define _RL_CH_2_OFFSET(ch) (((ch) == 0) ? 8 : ( \
|
||||||
|
((ch) == 1) ? 0x24 : ( \
|
||||||
|
((ch) == 2) ? 0x40 : ( \
|
||||||
|
((ch) == 5) ? 0x64 : ( \
|
||||||
|
((ch) == 6) ? 0x80 : ( \
|
||||||
|
((ch) == 8) ? 0x9C : ( \
|
||||||
|
((ch) == 9) ? 0xBC : (-1))))))))
|
||||||
|
#define DC_RL_CH(ch, evt) IPU_DC_REG(_RL_CH_2_OFFSET(ch) + \
|
||||||
|
((evt) & ~0x1) * 2)
|
||||||
|
|
||||||
|
#define DC_EVT_NF 0
|
||||||
|
#define DC_EVT_NL 1
|
||||||
|
#define DC_EVT_EOF 2
|
||||||
|
#define DC_EVT_NFIELD 3
|
||||||
|
#define DC_EVT_EOL 4
|
||||||
|
#define DC_EVT_EOFIELD 5
|
||||||
|
#define DC_EVT_NEW_ADDR 6
|
||||||
|
#define DC_EVT_NEW_CHAN 7
|
||||||
|
#define DC_EVT_NEW_DATA 8
|
||||||
|
|
||||||
|
#define DC_EVT_NEW_ADDR_W_0 0
|
||||||
|
#define DC_EVT_NEW_ADDR_W_1 1
|
||||||
|
#define DC_EVT_NEW_CHAN_W_0 2
|
||||||
|
#define DC_EVT_NEW_CHAN_W_1 3
|
||||||
|
#define DC_EVT_NEW_DATA_W_0 4
|
||||||
|
#define DC_EVT_NEW_DATA_W_1 5
|
||||||
|
#define DC_EVT_NEW_ADDR_R_0 6
|
||||||
|
#define DC_EVT_NEW_ADDR_R_1 7
|
||||||
|
#define DC_EVT_NEW_CHAN_R_0 8
|
||||||
|
#define DC_EVT_NEW_CHAN_R_1 9
|
||||||
|
#define DC_EVT_NEW_DATA_R_0 10
|
||||||
|
#define DC_EVT_NEW_DATA_R_1 11
|
||||||
|
#define DC_EVEN_UGDE0 12
|
||||||
|
#define DC_ODD_UGDE0 13
|
||||||
|
#define DC_EVEN_UGDE1 14
|
||||||
|
#define DC_ODD_UGDE1 15
|
||||||
|
#define DC_EVEN_UGDE2 16
|
||||||
|
#define DC_ODD_UGDE2 17
|
||||||
|
#define DC_EVEN_UGDE3 18
|
||||||
|
#define DC_ODD_UGDE3 19
|
||||||
|
|
||||||
|
#define dc_ch_offset(ch) \
|
||||||
|
({ \
|
||||||
|
const u8 _offset[] = { \
|
||||||
|
0, 0x1C, 0x38, 0x54, 0x58, 0x5C, 0x78, 0, 0x94, 0xB4}; \
|
||||||
|
_offset[ch]; \
|
||||||
|
})
|
||||||
|
#define DC_WR_CH_CONF(ch) IPU_DC_REG(dc_ch_offset(ch))
|
||||||
|
#define DC_WR_CH_ADDR(ch) IPU_DC_REG(dc_ch_offset(ch) + 4)
|
||||||
|
|
||||||
|
#define DC_WR_CH_CONF_1 IPU_DC_REG(0x001C)
|
||||||
|
#define DC_WR_CH_ADDR_1 IPU_DC_REG(0x0020)
|
||||||
|
#define DC_WR_CH_CONF_5 IPU_DC_REG(0x005C)
|
||||||
|
#define DC_WR_CH_ADDR_5 IPU_DC_REG(0x0060)
|
||||||
|
#define DC_GEN IPU_DC_REG(0x00D4)
|
||||||
|
#define DC_DISP_CONF1(disp) IPU_DC_REG(0x00D8 + 4 * (disp))
|
||||||
|
#define DC_DISP_CONF2(disp) IPU_DC_REG(0x00E8 + 4 * (disp))
|
||||||
|
#define DC_STAT IPU_DC_REG(0x01C8)
|
||||||
|
#define DC_UGDE_0(evt) IPU_DC_REG(0x0174 + 16 * (evt))
|
||||||
|
#define DC_UGDE_1(evt) IPU_DC_REG(0x0178 + 16 * (evt))
|
||||||
|
#define DC_UGDE_2(evt) IPU_DC_REG(0x017C + 16 * (evt))
|
||||||
|
#define DC_UGDE_3(evt) IPU_DC_REG(0x0180 + 16 * (evt))
|
||||||
|
|
||||||
|
/* IPU DP Registers */
|
||||||
|
#define IPU_DP_REG(offset) (offset)
|
||||||
|
|
||||||
|
#define DP_SYNC 0
|
||||||
|
#define DP_ASYNC0 0x60
|
||||||
|
#define DP_ASYNC1 0xBC
|
||||||
|
#define DP_COM_CONF(flow) IPU_DP_REG(flow)
|
||||||
|
#define DP_GRAPH_WIND_CTRL(flow) IPU_DP_REG(0x0004 + (flow))
|
||||||
|
#define DP_FG_POS(flow) IPU_DP_REG(0x0008 + (flow))
|
||||||
|
#define DP_GAMMA_C(flow, i) IPU_DP_REG(0x0014 + (flow) + 4 * (i))
|
||||||
|
#define DP_GAMMA_S(flow, i) IPU_DP_REG(0x0034 + (flow) + 4 * (i))
|
||||||
|
#define DP_CSC_A_0(flow) IPU_DP_REG(0x0044 + (flow))
|
||||||
|
#define DP_CSC_A_1(flow) IPU_DP_REG(0x0048 + (flow))
|
||||||
|
#define DP_CSC_A_2(flow) IPU_DP_REG(0x004C + (flow))
|
||||||
|
#define DP_CSC_A_3(flow) IPU_DP_REG(0x0050 + (flow))
|
||||||
|
#define DP_CSC_0(flow) IPU_DP_REG(0x0054 + (flow))
|
||||||
|
#define DP_CSC_1(flow) IPU_DP_REG(0x0058 + (flow))
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IPU_CONF_CSI0_EN = 0x00000001,
|
||||||
|
IPU_CONF_CSI1_EN = 0x00000002,
|
||||||
|
IPU_CONF_IC_EN = 0x00000004,
|
||||||
|
IPU_CONF_ROT_EN = 0x00000008,
|
||||||
|
IPU_CONF_ISP_EN = 0x00000010,
|
||||||
|
IPU_CONF_DP_EN = 0x00000020,
|
||||||
|
IPU_CONF_DI0_EN = 0x00000040,
|
||||||
|
IPU_CONF_DI1_EN = 0x00000080,
|
||||||
|
IPU_CONF_DMFC_EN = 0x00000400,
|
||||||
|
IPU_CONF_SMFC_EN = 0x00000100,
|
||||||
|
IPU_CONF_DC_EN = 0x00000200,
|
||||||
|
IPU_CONF_VDI_EN = 0x00001000,
|
||||||
|
IPU_CONF_IDMAC_DIS = 0x00400000,
|
||||||
|
IPU_CONF_IC_DMFC_SEL = 0x02000000,
|
||||||
|
IPU_CONF_IC_DMFC_SYNC = 0x04000000,
|
||||||
|
IPU_CONF_VDI_DMFC_SYNC = 0x08000000,
|
||||||
|
IPU_CONF_CSI0_DATA_SOURCE = 0x10000000,
|
||||||
|
IPU_CONF_CSI0_DATA_SOURCE_OFFSET = 28,
|
||||||
|
IPU_CONF_CSI1_DATA_SOURCE = 0x20000000,
|
||||||
|
IPU_CONF_IC_INPUT = 0x40000000,
|
||||||
|
IPU_CONF_CSI_SEL = 0x80000000,
|
||||||
|
|
||||||
|
DI0_COUNTER_RELEASE = 0x01000000,
|
||||||
|
DI1_COUNTER_RELEASE = 0x02000000,
|
||||||
|
|
||||||
|
FS_PRPVF_ROT_SRC_SEL_MASK = 0x00000F00,
|
||||||
|
FS_PRPVF_ROT_SRC_SEL_OFFSET = 8,
|
||||||
|
FS_PRPENC_ROT_SRC_SEL_MASK = 0x0000000F,
|
||||||
|
FS_PRPENC_ROT_SRC_SEL_OFFSET = 0,
|
||||||
|
FS_PP_ROT_SRC_SEL_MASK = 0x000F0000,
|
||||||
|
FS_PP_ROT_SRC_SEL_OFFSET = 16,
|
||||||
|
FS_PP_SRC_SEL_MASK = 0x0000F000,
|
||||||
|
FS_PP_SRC_SEL_VDOA = 0x00008000,
|
||||||
|
FS_PP_SRC_SEL_OFFSET = 12,
|
||||||
|
FS_PRP_SRC_SEL_MASK = 0x0F000000,
|
||||||
|
FS_PRP_SRC_SEL_OFFSET = 24,
|
||||||
|
FS_VF_IN_VALID = 0x80000000,
|
||||||
|
FS_ENC_IN_VALID = 0x40000000,
|
||||||
|
FS_VDI_SRC_SEL_MASK = 0x30000000,
|
||||||
|
FS_VDI_SRC_SEL_VDOA = 0x20000000,
|
||||||
|
FS_VDOA_DEST_SEL_MASK = 0x00030000,
|
||||||
|
FS_VDOA_DEST_SEL_VDI = 0x00020000,
|
||||||
|
FS_VDOA_DEST_SEL_IC = 0x00010000,
|
||||||
|
FS_VDI_SRC_SEL_OFFSET = 28,
|
||||||
|
|
||||||
|
|
||||||
|
FS_PRPENC_DEST_SEL_MASK = 0x0000000F,
|
||||||
|
FS_PRPENC_DEST_SEL_OFFSET = 0,
|
||||||
|
FS_PRPVF_DEST_SEL_MASK = 0x000000F0,
|
||||||
|
FS_PRPVF_DEST_SEL_OFFSET = 4,
|
||||||
|
FS_PRPVF_ROT_DEST_SEL_MASK = 0x00000F00,
|
||||||
|
FS_PRPVF_ROT_DEST_SEL_OFFSET = 8,
|
||||||
|
FS_PP_DEST_SEL_MASK = 0x0000F000,
|
||||||
|
FS_PP_DEST_SEL_OFFSET = 12,
|
||||||
|
FS_PP_ROT_DEST_SEL_MASK = 0x000F0000,
|
||||||
|
FS_PP_ROT_DEST_SEL_OFFSET = 16,
|
||||||
|
FS_PRPENC_ROT_DEST_SEL_MASK = 0x00F00000,
|
||||||
|
FS_PRPENC_ROT_DEST_SEL_OFFSET = 20,
|
||||||
|
|
||||||
|
FS_SMFC0_DEST_SEL_MASK = 0x0000000F,
|
||||||
|
FS_SMFC0_DEST_SEL_OFFSET = 0,
|
||||||
|
FS_SMFC1_DEST_SEL_MASK = 0x00000070,
|
||||||
|
FS_SMFC1_DEST_SEL_OFFSET = 4,
|
||||||
|
FS_SMFC2_DEST_SEL_MASK = 0x00000780,
|
||||||
|
FS_SMFC2_DEST_SEL_OFFSET = 7,
|
||||||
|
FS_SMFC3_DEST_SEL_MASK = 0x00003800,
|
||||||
|
FS_SMFC3_DEST_SEL_OFFSET = 11,
|
||||||
|
|
||||||
|
FS_DC1_SRC_SEL_MASK = 0x00F00000,
|
||||||
|
FS_DC1_SRC_SEL_OFFSET = 20,
|
||||||
|
FS_DC2_SRC_SEL_MASK = 0x000F0000,
|
||||||
|
FS_DC2_SRC_SEL_OFFSET = 16,
|
||||||
|
FS_DP_SYNC0_SRC_SEL_MASK = 0x0000000F,
|
||||||
|
FS_DP_SYNC0_SRC_SEL_OFFSET = 0,
|
||||||
|
FS_DP_SYNC1_SRC_SEL_MASK = 0x000000F0,
|
||||||
|
FS_DP_SYNC1_SRC_SEL_OFFSET = 4,
|
||||||
|
FS_DP_ASYNC0_SRC_SEL_MASK = 0x00000F00,
|
||||||
|
FS_DP_ASYNC0_SRC_SEL_OFFSET = 8,
|
||||||
|
FS_DP_ASYNC1_SRC_SEL_MASK = 0x0000F000,
|
||||||
|
FS_DP_ASYNC1_SRC_SEL_OFFSET = 12,
|
||||||
|
|
||||||
|
FS_AUTO_REF_PER_MASK = 0,
|
||||||
|
FS_AUTO_REF_PER_OFFSET = 16,
|
||||||
|
|
||||||
|
TSTAT_VF_MASK = 0x0000000C,
|
||||||
|
TSTAT_VF_OFFSET = 2,
|
||||||
|
TSTAT_VF_ROT_MASK = 0x00000300,
|
||||||
|
TSTAT_VF_ROT_OFFSET = 8,
|
||||||
|
TSTAT_ENC_MASK = 0x00000003,
|
||||||
|
TSTAT_ENC_OFFSET = 0,
|
||||||
|
TSTAT_ENC_ROT_MASK = 0x000000C0,
|
||||||
|
TSTAT_ENC_ROT_OFFSET = 6,
|
||||||
|
TSTAT_PP_MASK = 0x00000030,
|
||||||
|
TSTAT_PP_OFFSET = 4,
|
||||||
|
TSTAT_PP_ROT_MASK = 0x00000C00,
|
||||||
|
TSTAT_PP_ROT_OFFSET = 10,
|
||||||
|
|
||||||
|
TASK_STAT_IDLE = 0,
|
||||||
|
TASK_STAT_ACTIVE = 1,
|
||||||
|
TASK_STAT_WAIT4READY = 2,
|
||||||
|
|
||||||
|
/* IDMAC register bits */
|
||||||
|
IDMAC_CONF_USED_BUFS_EN_R = 0x02000000,
|
||||||
|
IDMAC_CONF_USED_BUFS_MAX_R_MASK = 0x01E00000,
|
||||||
|
IDMAC_CONF_USED_BUFS_MAX_R_OFFSET = 21,
|
||||||
|
IDMAC_CONF_USED_BUFS_EN_W = 0x00100000,
|
||||||
|
IDMAC_CONF_USED_BUFS_MAX_W_MASK = 0x000E0000,
|
||||||
|
IDMAC_CONF_USED_BUFS_MAX_W_OFFSET = 17,
|
||||||
|
|
||||||
|
/* Image Converter Register bits */
|
||||||
|
IC_CONF_PRPENC_EN = 0x00000001,
|
||||||
|
IC_CONF_PRPENC_CSC1 = 0x00000002,
|
||||||
|
IC_CONF_PRPENC_ROT_EN = 0x00000004,
|
||||||
|
IC_CONF_PRPVF_EN = 0x00000100,
|
||||||
|
IC_CONF_PRPVF_CSC1 = 0x00000200,
|
||||||
|
IC_CONF_PRPVF_CSC2 = 0x00000400,
|
||||||
|
IC_CONF_PRPVF_CMB = 0x00000800,
|
||||||
|
IC_CONF_PRPVF_ROT_EN = 0x00001000,
|
||||||
|
IC_CONF_PP_EN = 0x00010000,
|
||||||
|
IC_CONF_PP_CSC1 = 0x00020000,
|
||||||
|
IC_CONF_PP_CSC2 = 0x00040000,
|
||||||
|
IC_CONF_PP_CMB = 0x00080000,
|
||||||
|
IC_CONF_PP_ROT_EN = 0x00100000,
|
||||||
|
IC_CONF_IC_GLB_LOC_A = 0x10000000,
|
||||||
|
IC_CONF_KEY_COLOR_EN = 0x20000000,
|
||||||
|
IC_CONF_RWS_EN = 0x40000000,
|
||||||
|
IC_CONF_CSI_MEM_WR_EN = 0x80000000,
|
||||||
|
|
||||||
|
IC_RSZ_MAX_RESIZE_RATIO = 0x00004000,
|
||||||
|
|
||||||
|
IC_IDMAC_1_CB0_BURST_16 = 0x00000001,
|
||||||
|
IC_IDMAC_1_CB1_BURST_16 = 0x00000002,
|
||||||
|
IC_IDMAC_1_CB2_BURST_16 = 0x00000004,
|
||||||
|
IC_IDMAC_1_CB3_BURST_16 = 0x00000008,
|
||||||
|
IC_IDMAC_1_CB4_BURST_16 = 0x00000010,
|
||||||
|
IC_IDMAC_1_CB5_BURST_16 = 0x00000020,
|
||||||
|
IC_IDMAC_1_CB6_BURST_16 = 0x00000040,
|
||||||
|
IC_IDMAC_1_CB7_BURST_16 = 0x00000080,
|
||||||
|
IC_IDMAC_1_PRPENC_ROT_MASK = 0x00003800,
|
||||||
|
IC_IDMAC_1_PRPENC_ROT_OFFSET = 11,
|
||||||
|
IC_IDMAC_1_PRPVF_ROT_MASK = 0x0001C000,
|
||||||
|
IC_IDMAC_1_PRPVF_ROT_OFFSET = 14,
|
||||||
|
IC_IDMAC_1_PP_ROT_MASK = 0x000E0000,
|
||||||
|
IC_IDMAC_1_PP_ROT_OFFSET = 17,
|
||||||
|
IC_IDMAC_1_PP_FLIP_RS = 0x00400000,
|
||||||
|
IC_IDMAC_1_PRPVF_FLIP_RS = 0x00200000,
|
||||||
|
IC_IDMAC_1_PRPENC_FLIP_RS = 0x00100000,
|
||||||
|
|
||||||
|
IC_IDMAC_2_PRPENC_HEIGHT_MASK = 0x000003FF,
|
||||||
|
IC_IDMAC_2_PRPENC_HEIGHT_OFFSET = 0,
|
||||||
|
IC_IDMAC_2_PRPVF_HEIGHT_MASK = 0x000FFC00,
|
||||||
|
IC_IDMAC_2_PRPVF_HEIGHT_OFFSET = 10,
|
||||||
|
IC_IDMAC_2_PP_HEIGHT_MASK = 0x3FF00000,
|
||||||
|
IC_IDMAC_2_PP_HEIGHT_OFFSET = 20,
|
||||||
|
|
||||||
|
IC_IDMAC_3_PRPENC_WIDTH_MASK = 0x000003FF,
|
||||||
|
IC_IDMAC_3_PRPENC_WIDTH_OFFSET = 0,
|
||||||
|
IC_IDMAC_3_PRPVF_WIDTH_MASK = 0x000FFC00,
|
||||||
|
IC_IDMAC_3_PRPVF_WIDTH_OFFSET = 10,
|
||||||
|
IC_IDMAC_3_PP_WIDTH_MASK = 0x3FF00000,
|
||||||
|
IC_IDMAC_3_PP_WIDTH_OFFSET = 20,
|
||||||
|
|
||||||
|
CSI_SENS_CONF_DATA_FMT_SHIFT = 8,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_MASK = 0x00000700,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_RGB_YUV444 = 0L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_YUV422_YUYV = 1L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_YUV422_UYVY = 2L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_BAYER = 3L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_RGB565 = 4L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_RGB555 = 5L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_RGB444 = 6L,
|
||||||
|
CSI_SENS_CONF_DATA_FMT_JPEG = 7L,
|
||||||
|
|
||||||
|
CSI_SENS_CONF_VSYNC_POL_SHIFT = 0,
|
||||||
|
CSI_SENS_CONF_HSYNC_POL_SHIFT = 1,
|
||||||
|
CSI_SENS_CONF_DATA_POL_SHIFT = 2,
|
||||||
|
CSI_SENS_CONF_PIX_CLK_POL_SHIFT = 3,
|
||||||
|
CSI_SENS_CONF_SENS_PRTCL_MASK = 0x00000070L,
|
||||||
|
CSI_SENS_CONF_SENS_PRTCL_SHIFT = 4,
|
||||||
|
CSI_SENS_CONF_PACK_TIGHT_SHIFT = 7,
|
||||||
|
CSI_SENS_CONF_DATA_WIDTH_SHIFT = 11,
|
||||||
|
CSI_SENS_CONF_EXT_VSYNC_SHIFT = 15,
|
||||||
|
CSI_SENS_CONF_DIVRATIO_SHIFT = 16,
|
||||||
|
|
||||||
|
CSI_SENS_CONF_DIVRATIO_MASK = 0x00FF0000L,
|
||||||
|
CSI_SENS_CONF_DATA_DEST_SHIFT = 24,
|
||||||
|
CSI_SENS_CONF_DATA_DEST_MASK = 0x07000000L,
|
||||||
|
CSI_SENS_CONF_JPEG8_EN_SHIFT = 27,
|
||||||
|
CSI_SENS_CONF_JPEG_EN_SHIFT = 28,
|
||||||
|
CSI_SENS_CONF_FORCE_EOF_SHIFT = 29,
|
||||||
|
CSI_SENS_CONF_DATA_EN_POL_SHIFT = 31,
|
||||||
|
|
||||||
|
CSI_DATA_DEST_ISP = 1L,
|
||||||
|
CSI_DATA_DEST_IC = 2L,
|
||||||
|
CSI_DATA_DEST_IDMAC = 4L,
|
||||||
|
|
||||||
|
CSI_CCIR_ERR_DET_EN = 0x01000000L,
|
||||||
|
CSI_HORI_DOWNSIZE_EN = 0x80000000L,
|
||||||
|
CSI_VERT_DOWNSIZE_EN = 0x40000000L,
|
||||||
|
CSI_TEST_GEN_MODE_EN = 0x01000000L,
|
||||||
|
|
||||||
|
CSI_HSC_MASK = 0x1FFF0000,
|
||||||
|
CSI_HSC_SHIFT = 16,
|
||||||
|
CSI_VSC_MASK = 0x00000FFF,
|
||||||
|
CSI_VSC_SHIFT = 0,
|
||||||
|
|
||||||
|
CSI_TEST_GEN_R_MASK = 0x000000FFL,
|
||||||
|
CSI_TEST_GEN_R_SHIFT = 0,
|
||||||
|
CSI_TEST_GEN_G_MASK = 0x0000FF00L,
|
||||||
|
CSI_TEST_GEN_G_SHIFT = 8,
|
||||||
|
CSI_TEST_GEN_B_MASK = 0x00FF0000L,
|
||||||
|
CSI_TEST_GEN_B_SHIFT = 16,
|
||||||
|
|
||||||
|
CSI_MIPI_DI0_MASK = 0x000000FFL,
|
||||||
|
CSI_MIPI_DI0_SHIFT = 0,
|
||||||
|
CSI_MIPI_DI1_MASK = 0x0000FF00L,
|
||||||
|
CSI_MIPI_DI1_SHIFT = 8,
|
||||||
|
CSI_MIPI_DI2_MASK = 0x00FF0000L,
|
||||||
|
CSI_MIPI_DI2_SHIFT = 16,
|
||||||
|
CSI_MIPI_DI3_MASK = 0xFF000000L,
|
||||||
|
CSI_MIPI_DI3_SHIFT = 24,
|
||||||
|
|
||||||
|
CSI_MAX_RATIO_SKIP_ISP_MASK = 0x00070000L,
|
||||||
|
CSI_MAX_RATIO_SKIP_ISP_SHIFT = 16,
|
||||||
|
CSI_SKIP_ISP_MASK = 0x00F80000L,
|
||||||
|
CSI_SKIP_ISP_SHIFT = 19,
|
||||||
|
CSI_MAX_RATIO_SKIP_SMFC_MASK = 0x00000007L,
|
||||||
|
CSI_MAX_RATIO_SKIP_SMFC_SHIFT = 0,
|
||||||
|
CSI_SKIP_SMFC_MASK = 0x000000F8L,
|
||||||
|
CSI_SKIP_SMFC_SHIFT = 3,
|
||||||
|
CSI_ID_2_SKIP_MASK = 0x00000300L,
|
||||||
|
CSI_ID_2_SKIP_SHIFT = 8,
|
||||||
|
|
||||||
|
CSI_COLOR_FIRST_ROW_MASK = 0x00000002L,
|
||||||
|
CSI_COLOR_FIRST_COMP_MASK = 0x00000001L,
|
||||||
|
|
||||||
|
SMFC_MAP_CH0_MASK = 0x00000007L,
|
||||||
|
SMFC_MAP_CH0_SHIFT = 0,
|
||||||
|
SMFC_MAP_CH1_MASK = 0x00000038L,
|
||||||
|
SMFC_MAP_CH1_SHIFT = 3,
|
||||||
|
SMFC_MAP_CH2_MASK = 0x000001C0L,
|
||||||
|
SMFC_MAP_CH2_SHIFT = 6,
|
||||||
|
SMFC_MAP_CH3_MASK = 0x00000E00L,
|
||||||
|
SMFC_MAP_CH3_SHIFT = 9,
|
||||||
|
|
||||||
|
SMFC_WM0_SET_MASK = 0x00000007L,
|
||||||
|
SMFC_WM0_SET_SHIFT = 0,
|
||||||
|
SMFC_WM1_SET_MASK = 0x000001C0L,
|
||||||
|
SMFC_WM1_SET_SHIFT = 6,
|
||||||
|
SMFC_WM2_SET_MASK = 0x00070000L,
|
||||||
|
SMFC_WM2_SET_SHIFT = 16,
|
||||||
|
SMFC_WM3_SET_MASK = 0x01C00000L,
|
||||||
|
SMFC_WM3_SET_SHIFT = 22,
|
||||||
|
|
||||||
|
SMFC_WM0_CLR_MASK = 0x00000038L,
|
||||||
|
SMFC_WM0_CLR_SHIFT = 3,
|
||||||
|
SMFC_WM1_CLR_MASK = 0x00000E00L,
|
||||||
|
SMFC_WM1_CLR_SHIFT = 9,
|
||||||
|
SMFC_WM2_CLR_MASK = 0x00380000L,
|
||||||
|
SMFC_WM2_CLR_SHIFT = 19,
|
||||||
|
SMFC_WM3_CLR_MASK = 0x0E000000L,
|
||||||
|
SMFC_WM3_CLR_SHIFT = 25,
|
||||||
|
|
||||||
|
SMFC_BS0_MASK = 0x0000000FL,
|
||||||
|
SMFC_BS0_SHIFT = 0,
|
||||||
|
SMFC_BS1_MASK = 0x000000F0L,
|
||||||
|
SMFC_BS1_SHIFT = 4,
|
||||||
|
SMFC_BS2_MASK = 0x00000F00L,
|
||||||
|
SMFC_BS2_SHIFT = 8,
|
||||||
|
SMFC_BS3_MASK = 0x0000F000L,
|
||||||
|
SMFC_BS3_SHIFT = 12,
|
||||||
|
|
||||||
|
PF_CONF_TYPE_MASK = 0x00000007,
|
||||||
|
PF_CONF_TYPE_SHIFT = 0,
|
||||||
|
PF_CONF_PAUSE_EN = 0x00000010,
|
||||||
|
PF_CONF_RESET = 0x00008000,
|
||||||
|
PF_CONF_PAUSE_ROW_MASK = 0x00FF0000,
|
||||||
|
PF_CONF_PAUSE_ROW_SHIFT = 16,
|
||||||
|
|
||||||
|
DI_DW_GEN_ACCESS_SIZE_OFFSET = 24,
|
||||||
|
DI_DW_GEN_COMPONENT_SIZE_OFFSET = 16,
|
||||||
|
|
||||||
|
DI_GEN_DI_CLK_EXT = 0x100000,
|
||||||
|
DI_GEN_POLARITY_DISP_CLK = 0x00020000,
|
||||||
|
DI_GEN_POLARITY_1 = 0x00000001,
|
||||||
|
DI_GEN_POLARITY_2 = 0x00000002,
|
||||||
|
DI_GEN_POLARITY_3 = 0x00000004,
|
||||||
|
DI_GEN_POLARITY_4 = 0x00000008,
|
||||||
|
DI_GEN_POLARITY_5 = 0x00000010,
|
||||||
|
DI_GEN_POLARITY_6 = 0x00000020,
|
||||||
|
DI_GEN_POLARITY_7 = 0x00000040,
|
||||||
|
DI_GEN_POLARITY_8 = 0x00000080,
|
||||||
|
|
||||||
|
DI_POL_DRDY_DATA_POLARITY = 0x00000080,
|
||||||
|
DI_POL_DRDY_POLARITY_15 = 0x00000010,
|
||||||
|
|
||||||
|
DI_VSYNC_SEL_OFFSET = 13,
|
||||||
|
|
||||||
|
DC_WR_CH_CONF_FIELD_MODE = 0x00000200,
|
||||||
|
DC_WR_CH_CONF_PROG_TYPE_OFFSET = 5,
|
||||||
|
DC_WR_CH_CONF_PROG_TYPE_MASK = 0x000000E0,
|
||||||
|
DC_WR_CH_CONF_PROG_DI_ID = 0x00000004,
|
||||||
|
DC_WR_CH_CONF_PROG_DISP_ID_OFFSET = 3,
|
||||||
|
DC_WR_CH_CONF_PROG_DISP_ID_MASK = 0x00000018,
|
||||||
|
|
||||||
|
DC_UGDE_0_ODD_EN = 0x02000000,
|
||||||
|
DC_UGDE_0_ID_CODED_MASK = 0x00000007,
|
||||||
|
DC_UGDE_0_ID_CODED_OFFSET = 0,
|
||||||
|
DC_UGDE_0_EV_PRIORITY_MASK = 0x00000078,
|
||||||
|
DC_UGDE_0_EV_PRIORITY_OFFSET = 3,
|
||||||
|
|
||||||
|
DP_COM_CONF_FG_EN = 0x00000001,
|
||||||
|
DP_COM_CONF_GWSEL = 0x00000002,
|
||||||
|
DP_COM_CONF_GWAM = 0x00000004,
|
||||||
|
DP_COM_CONF_GWCKE = 0x00000008,
|
||||||
|
DP_COM_CONF_CSC_DEF_MASK = 0x00000300,
|
||||||
|
DP_COM_CONF_CSC_DEF_OFFSET = 8,
|
||||||
|
DP_COM_CONF_CSC_DEF_FG = 0x00000300,
|
||||||
|
DP_COM_CONF_CSC_DEF_BG = 0x00000200,
|
||||||
|
DP_COM_CONF_CSC_DEF_BOTH = 0x00000100,
|
||||||
|
DP_COM_CONF_GAMMA_EN = 0x00001000,
|
||||||
|
DP_COM_CONF_GAMMA_YUV_EN = 0x00002000,
|
||||||
|
|
||||||
|
DI_SER_CONF_LLA_SER_ACCESS = 0x00000020,
|
||||||
|
DI_SER_CONF_SERIAL_CLK_POL = 0x00000010,
|
||||||
|
DI_SER_CONF_SERIAL_DATA_POL = 0x00000008,
|
||||||
|
DI_SER_CONF_SERIAL_RS_POL = 0x00000004,
|
||||||
|
DI_SER_CONF_SERIAL_CS_POL = 0x00000002,
|
||||||
|
DI_SER_CONF_WAIT4SERIAL = 0x00000001,
|
||||||
|
|
||||||
|
VDI_C_CH_420 = 0x00000000,
|
||||||
|
VDI_C_CH_422 = 0x00000002,
|
||||||
|
VDI_C_MOT_SEL_FULL = 0x00000008,
|
||||||
|
VDI_C_MOT_SEL_LOW = 0x00000004,
|
||||||
|
VDI_C_MOT_SEL_MED = 0x00000000,
|
||||||
|
VDI_C_BURST_SIZE1_4 = 0x00000030,
|
||||||
|
VDI_C_BURST_SIZE2_4 = 0x00000300,
|
||||||
|
VDI_C_BURST_SIZE3_4 = 0x00003000,
|
||||||
|
VDI_C_BURST_SIZE_MASK = 0xF,
|
||||||
|
VDI_C_BURST_SIZE1_OFFSET = 4,
|
||||||
|
VDI_C_BURST_SIZE2_OFFSET = 8,
|
||||||
|
VDI_C_BURST_SIZE3_OFFSET = 12,
|
||||||
|
VDI_C_VWM1_SET_1 = 0x00000000,
|
||||||
|
VDI_C_VWM1_SET_2 = 0x00010000,
|
||||||
|
VDI_C_VWM1_CLR_2 = 0x00080000,
|
||||||
|
VDI_C_VWM3_SET_1 = 0x00000000,
|
||||||
|
VDI_C_VWM3_SET_2 = 0x00400000,
|
||||||
|
VDI_C_VWM3_CLR_2 = 0x02000000,
|
||||||
|
VDI_C_TOP_FIELD_MAN_1 = 0x40000000,
|
||||||
|
VDI_C_TOP_FIELD_AUTO_1 = 0x80000000,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum di_pins {
|
||||||
|
DI_PIN11 = 0,
|
||||||
|
DI_PIN12 = 1,
|
||||||
|
DI_PIN13 = 2,
|
||||||
|
DI_PIN14 = 3,
|
||||||
|
DI_PIN15 = 4,
|
||||||
|
DI_PIN16 = 5,
|
||||||
|
DI_PIN17 = 6,
|
||||||
|
DI_PIN_CS = 7,
|
||||||
|
|
||||||
|
DI_PIN_SER_CLK = 0,
|
||||||
|
DI_PIN_SER_RS = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum di_sync_wave {
|
||||||
|
DI_SYNC_NONE = -1,
|
||||||
|
DI_SYNC_CLK = 0,
|
||||||
|
DI_SYNC_INT_HSYNC = 1,
|
||||||
|
DI_SYNC_HSYNC = 2,
|
||||||
|
DI_SYNC_VSYNC = 3,
|
||||||
|
DI_SYNC_DE = 5,
|
||||||
|
};
|
||||||
|
|
||||||
|
/* DC template opcodes */
|
||||||
|
#define WROD(lf) (0x18 | ((lf) << 1))
|
||||||
|
#define WRG (0x01)
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,480 @@
|
||||||
|
/*
|
||||||
|
* Freescale PRE Register Definitions
|
||||||
|
*
|
||||||
|
* Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __ARCH_ARM___PRE_H
|
||||||
|
#define __ARCH_ARM___PRE_H
|
||||||
|
|
||||||
|
|
||||||
|
#define HW_PRE_CTRL (0x00000000)
|
||||||
|
#define HW_PRE_CTRL_SET (0x00000004)
|
||||||
|
#define HW_PRE_CTRL_CLR (0x00000008)
|
||||||
|
#define HW_PRE_CTRL_TOG (0x0000000c)
|
||||||
|
|
||||||
|
#define BM_PRE_CTRL_SFTRST 0x80000000
|
||||||
|
#define BF_PRE_CTRL_SFTRST(v) \
|
||||||
|
(((v) << 31) & BM_PRE_CTRL_SFTRST)
|
||||||
|
#define BM_PRE_CTRL_CLKGATE 0x40000000
|
||||||
|
#define BF_PRE_CTRL_CLKGATE(v) \
|
||||||
|
(((v) << 30) & BM_PRE_CTRL_CLKGATE)
|
||||||
|
#define BM_PRE_CTRL_TPR_RESET_SEL 0x20000000
|
||||||
|
#define BF_PRE_CTRL_TPR_RESET_SEL(v) \
|
||||||
|
(((v) << 29) & BM_PRE_CTRL_TPR_RESET_SEL)
|
||||||
|
#define BM_PRE_CTRL_EN_REPEAT 0x10000000
|
||||||
|
#define BF_PRE_CTRL_EN_REPEAT(v) \
|
||||||
|
(((v) << 28) & BM_PRE_CTRL_EN_REPEAT)
|
||||||
|
#define BP_PRE_CTRL_RSVD2 16
|
||||||
|
#define BM_PRE_CTRL_RSVD2 0x0FFF0000
|
||||||
|
#define BF_PRE_CTRL_RSVD2(v) \
|
||||||
|
(((v) << 16) & BM_PRE_CTRL_RSVD2)
|
||||||
|
#define BP_PRE_CTRL_RSVD1 12
|
||||||
|
#define BM_PRE_CTRL_RSVD1 0x0000F000
|
||||||
|
#define BF_PRE_CTRL_RSVD1(v) \
|
||||||
|
(((v) << 12) & BM_PRE_CTRL_RSVD1)
|
||||||
|
#define BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN 0x00000800
|
||||||
|
#define BF_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN(v) \
|
||||||
|
(((v) << 11) & BM_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN)
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN__0 0x0
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_ABORT_SKIP_EN__1 0x1
|
||||||
|
#define BP_PRE_CTRL_HANDSHAKE_LINE_NUM 9
|
||||||
|
#define BM_PRE_CTRL_HANDSHAKE_LINE_NUM 0x00000600
|
||||||
|
#define BF_PRE_CTRL_HANDSHAKE_LINE_NUM(v) \
|
||||||
|
(((v) << 9) & BM_PRE_CTRL_HANDSHAKE_LINE_NUM)
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__0 0x0
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__1 0x1
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_LINE_NUM__2 0x2
|
||||||
|
#define BM_PRE_CTRL_HANDSHAKE_EN 0x00000100
|
||||||
|
#define BF_PRE_CTRL_HANDSHAKE_EN(v) \
|
||||||
|
(((v) << 8) & BM_PRE_CTRL_HANDSHAKE_EN)
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_EN__0 0x0
|
||||||
|
#define BV_PRE_CTRL_HANDSHAKE_EN__1 0x1
|
||||||
|
#define BM_PRE_CTRL_INTERLACED_FIELD 0x00000080
|
||||||
|
#define BF_PRE_CTRL_INTERLACED_FIELD(v) \
|
||||||
|
(((v) << 7) & BM_PRE_CTRL_INTERLACED_FIELD)
|
||||||
|
#define BM_PRE_CTRL_SO 0x00000040
|
||||||
|
#define BF_PRE_CTRL_SO(v) \
|
||||||
|
(((v) << 6) & BM_PRE_CTRL_SO)
|
||||||
|
#define BM_PRE_CTRL_VFLIP 0x00000020
|
||||||
|
#define BF_PRE_CTRL_VFLIP(v) \
|
||||||
|
(((v) << 5) & BM_PRE_CTRL_VFLIP)
|
||||||
|
#define BM_PRE_CTRL_SDW_UPDATE 0x00000010
|
||||||
|
#define BF_PRE_CTRL_SDW_UPDATE(v) \
|
||||||
|
(((v) << 4) & BM_PRE_CTRL_SDW_UPDATE)
|
||||||
|
#define BM_PRE_CTRL_RSVD0 0x00000008
|
||||||
|
#define BF_PRE_CTRL_RSVD0(v) \
|
||||||
|
(((v) << 3) & BM_PRE_CTRL_RSVD0)
|
||||||
|
#define BM_PRE_CTRL_BLOCK_16 0x00000004
|
||||||
|
#define BF_PRE_CTRL_BLOCK_16(v) \
|
||||||
|
(((v) << 2) & BM_PRE_CTRL_BLOCK_16)
|
||||||
|
#define BV_PRE_CTRL_BLOCK_16__32x4 0x0
|
||||||
|
#define BV_PRE_CTRL_BLOCK_16__16x4 0x1
|
||||||
|
#define BM_PRE_CTRL_BLOCK_EN 0x00000002
|
||||||
|
#define BF_PRE_CTRL_BLOCK_EN(v) \
|
||||||
|
(((v) << 1) & BM_PRE_CTRL_BLOCK_EN)
|
||||||
|
#define BV_PRE_CTRL_BLOCK_EN__0 0x0
|
||||||
|
#define BV_PRE_CTRL_BLOCK_EN__1 0x1
|
||||||
|
#define BM_PRE_CTRL_ENABLE 0x00000001
|
||||||
|
#define BF_PRE_CTRL_ENABLE(v) \
|
||||||
|
(((v) << 0) & BM_PRE_CTRL_ENABLE)
|
||||||
|
|
||||||
|
#define HW_PRE_IRQ_MASK (0x00000010)
|
||||||
|
#define HW_PRE_IRQ_MASK_SET (0x00000014)
|
||||||
|
#define HW_PRE_IRQ_MASK_CLR (0x00000018)
|
||||||
|
#define HW_PRE_IRQ_MASK_TOG (0x0000001c)
|
||||||
|
|
||||||
|
#define BP_PRE_IRQ_MASK_RSVD1 4
|
||||||
|
#define BM_PRE_IRQ_MASK_RSVD1 0xFFFFFFF0
|
||||||
|
#define BF_PRE_IRQ_MASK_RSVD1(v) \
|
||||||
|
(((v) << 4) & BM_PRE_IRQ_MASK_RSVD1)
|
||||||
|
#define BM_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN 0x00000008
|
||||||
|
#define BF_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN(v) \
|
||||||
|
(((v) << 3) & BM_PRE_IRQ_MASK_TPR_RD_NUM_BYTES_OVFL_IRQ_EN)
|
||||||
|
#define BM_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN 0x00000004
|
||||||
|
#define BF_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN(v) \
|
||||||
|
(((v) << 2) & BM_PRE_IRQ_MASK_HANDSHAKE_ABORT_IRQ_EN)
|
||||||
|
#define BM_PRE_IRQ_MASK_STORE_IRQ_EN 0x00000002
|
||||||
|
#define BF_PRE_IRQ_MASK_STORE_IRQ_EN(v) \
|
||||||
|
(((v) << 1) & BM_PRE_IRQ_MASK_STORE_IRQ_EN)
|
||||||
|
#define BM_PRE_IRQ_MASK_PREFETCH_IRQ_EN 0x00000001
|
||||||
|
#define BF_PRE_IRQ_MASK_PREFETCH_IRQ_EN(v) \
|
||||||
|
(((v) << 0) & BM_PRE_IRQ_MASK_PREFETCH_IRQ_EN)
|
||||||
|
|
||||||
|
#define HW_PRE_IRQ (0x00000020)
|
||||||
|
#define HW_PRE_IRQ_SET (0x00000024)
|
||||||
|
#define HW_PRE_IRQ_CLR (0x00000028)
|
||||||
|
#define HW_PRE_IRQ_TOG (0x0000002c)
|
||||||
|
|
||||||
|
#define BP_PRE_IRQ_RSVD1 14
|
||||||
|
#define BM_PRE_IRQ_RSVD1 0xFFFFC000
|
||||||
|
#define BF_PRE_IRQ_RSVD1(v) \
|
||||||
|
(((v) << 14) & BM_PRE_IRQ_RSVD1)
|
||||||
|
#define BP_PRE_IRQ_AXI_ERROR_ID 10
|
||||||
|
#define BM_PRE_IRQ_AXI_ERROR_ID 0x00003C00
|
||||||
|
#define BF_PRE_IRQ_AXI_ERROR_ID(v) \
|
||||||
|
(((v) << 10) & BM_PRE_IRQ_AXI_ERROR_ID)
|
||||||
|
#define BM_PRE_IRQ_AXI_READ_ERROR 0x00000200
|
||||||
|
#define BF_PRE_IRQ_AXI_READ_ERROR(v) \
|
||||||
|
(((v) << 9) & BM_PRE_IRQ_AXI_READ_ERROR)
|
||||||
|
#define BM_PRE_IRQ_AXI_WRITE_ERROR 0x00000100
|
||||||
|
#define BF_PRE_IRQ_AXI_WRITE_ERROR(v) \
|
||||||
|
(((v) << 8) & BM_PRE_IRQ_AXI_WRITE_ERROR)
|
||||||
|
#define BP_PRE_IRQ_RSVD0 5
|
||||||
|
#define BM_PRE_IRQ_RSVD0 0x000000E0
|
||||||
|
#define BF_PRE_IRQ_RSVD0(v) \
|
||||||
|
(((v) << 5) & BM_PRE_IRQ_RSVD0)
|
||||||
|
#define BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ 0x00000010
|
||||||
|
#define BF_PRE_IRQ_HANDSHAKE_ERROR_IRQ(v) \
|
||||||
|
(((v) << 4) & BM_PRE_IRQ_HANDSHAKE_ERROR_IRQ)
|
||||||
|
#define BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ 0x00000008
|
||||||
|
#define BF_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ(v) \
|
||||||
|
(((v) << 3) & BM_PRE_IRQ_TPR_RD_NUM_BYTES_OVFL_IRQ)
|
||||||
|
#define BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ 0x00000004
|
||||||
|
#define BF_PRE_IRQ_HANDSHAKE_ABORT_IRQ(v) \
|
||||||
|
(((v) << 2) & BM_PRE_IRQ_HANDSHAKE_ABORT_IRQ)
|
||||||
|
#define BM_PRE_IRQ_STORE_IRQ 0x00000002
|
||||||
|
#define BF_PRE_IRQ_STORE_IRQ(v) \
|
||||||
|
(((v) << 1) & BM_PRE_IRQ_STORE_IRQ)
|
||||||
|
#define BM_PRE_IRQ_PREFETCH_IRQ 0x00000001
|
||||||
|
#define BF_PRE_IRQ_PREFETCH_IRQ(v) \
|
||||||
|
(((v) << 0) & BM_PRE_IRQ_PREFETCH_IRQ)
|
||||||
|
|
||||||
|
#define HW_PRE_CUR_BUF (0x00000030)
|
||||||
|
|
||||||
|
#define BP_PRE_CUR_BUF_ADDR 0
|
||||||
|
#define BM_PRE_CUR_BUF_ADDR 0xFFFFFFFF
|
||||||
|
#define BF_PRE_CUR_BUF_ADDR(v) (v)
|
||||||
|
|
||||||
|
#define HW_PRE_NEXT_BUF (0x00000040)
|
||||||
|
|
||||||
|
#define BP_PRE_NEXT_BUF_ADDR 0
|
||||||
|
#define BM_PRE_NEXT_BUF_ADDR 0xFFFFFFFF
|
||||||
|
#define BF_PRE_NEXT_BUF_ADDR(v) (v)
|
||||||
|
|
||||||
|
#define HW_PRE_U_BUF_OFFSET (0x00000050)
|
||||||
|
|
||||||
|
#define BP_PRE_U_BUF_OFFSET_RSVD0 25
|
||||||
|
#define BM_PRE_U_BUF_OFFSET_RSVD0 0xFE000000
|
||||||
|
#define BF_PRE_U_BUF_OFFSET_RSVD0(v) \
|
||||||
|
(((v) << 25) & BM_PRE_U_BUF_OFFSET_RSVD0)
|
||||||
|
#define BP_PRE_U_BUF_OFFSET_UBO 0
|
||||||
|
#define BM_PRE_U_BUF_OFFSET_UBO 0x01FFFFFF
|
||||||
|
#define BF_PRE_U_BUF_OFFSET_UBO(v) \
|
||||||
|
(((v) << 0) & BM_PRE_U_BUF_OFFSET_UBO)
|
||||||
|
|
||||||
|
#define HW_PRE_V_BUF_OFFSET (0x00000060)
|
||||||
|
|
||||||
|
#define BP_PRE_V_BUF_OFFSET_RSVD0 25
|
||||||
|
#define BM_PRE_V_BUF_OFFSET_RSVD0 0xFE000000
|
||||||
|
#define BF_PRE_V_BUF_OFFSET_RSVD0(v) \
|
||||||
|
(((v) << 25) & BM_PRE_V_BUF_OFFSET_RSVD0)
|
||||||
|
#define BP_PRE_V_BUF_OFFSET_VBO 0
|
||||||
|
#define BM_PRE_V_BUF_OFFSET_VBO 0x01FFFFFF
|
||||||
|
#define BF_PRE_V_BUF_OFFSET_VBO(v) \
|
||||||
|
(((v) << 0) & BM_PRE_V_BUF_OFFSET_VBO)
|
||||||
|
|
||||||
|
#define HW_PRE_TPR_CTRL (0x00000070)
|
||||||
|
#define HW_PRE_TPR_CTRL_SET (0x00000074)
|
||||||
|
#define HW_PRE_TPR_CTRL_CLR (0x00000078)
|
||||||
|
#define HW_PRE_TPR_CTRL_TOG (0x0000007c)
|
||||||
|
|
||||||
|
#define BP_PRE_TPR_CTRL_RSVD 8
|
||||||
|
#define BM_PRE_TPR_CTRL_RSVD 0xFFFFFF00
|
||||||
|
#define BF_PRE_TPR_CTRL_RSVD(v) \
|
||||||
|
(((v) << 8) & BM_PRE_TPR_CTRL_RSVD)
|
||||||
|
#define BP_PRE_TPR_CTRL_TILE_FORMAT 0
|
||||||
|
#define BM_PRE_TPR_CTRL_TILE_FORMAT 0x000000FF
|
||||||
|
#define BF_PRE_TPR_CTRL_TILE_FORMAT(v) \
|
||||||
|
(((v) << 0) & BM_PRE_TPR_CTRL_TILE_FORMAT)
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__BYPASS 0x00
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SB_ST 0x10
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SB_SRT 0x50
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_ST 0x20
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_SRT 0x60
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_MST 0xA0
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU32_MSRT 0xE0
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SB_ST 0x11
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SB_SRT 0x51
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_ST 0x21
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_SRT 0x61
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_MST 0xA1
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__GPU16_MSRT 0xE1
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__VPU8_PRO 0x22
|
||||||
|
#define BV_PRE_TPR_CTRL_TILE_FORMAT__VPU8_SB_INT 0x13
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_CTRL (0x00000080)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_CTRL_SET (0x00000084)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_CTRL_CLR (0x00000088)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_CTRL_TOG (0x0000008c)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_CTRL_RSVD1 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_RSVD1 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_RSVD1(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_CTRL_RSVD1)
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN 0x00008000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN(v) \
|
||||||
|
(((v) << 15) & BM_PRE_PREFETCH_ENGINE_CTRL_TPR_COOR_OFFSET_EN)
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP 0x00004000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP(v) \
|
||||||
|
(((v) << 14) & BM_PRE_PREFETCH_ENGINE_CTRL_PARTIAL_UV_SWAP)
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_CROP_EN 0x00002000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_CROP_EN(v) \
|
||||||
|
(((v) << 13) & BM_PRE_PREFETCH_ENGINE_CTRL_CROP_EN)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_CROP_EN__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_CROP_EN__1 0x1
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE 0x00001000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE(v) \
|
||||||
|
(((v) << 12) & BM_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_FIELD_INVERSE__1 0x1
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS 0x00000800
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS(v) \
|
||||||
|
(((v) << 11) & BM_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_SHIFT_BYPASS__1 0x1
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT 8
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT 0x00000700
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT(v) \
|
||||||
|
(((v) << 8) & BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__1 0x1
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__2 0x2
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__3 0x3
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__4 0x4
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_PIXEL_FORMAT__5 0x5
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_CTRL_RSVD0 6
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_RSVD0 0x000000C0
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_RSVD0(v) \
|
||||||
|
(((v) << 6) & BM_PRE_PREFETCH_ENGINE_CTRL_RSVD0)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP 4
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP 0x00000030
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP(v) \
|
||||||
|
(((v) << 4) & BM_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__1 0x1
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__2 0x2
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_INPUT_ACTIVE_BPP__3 0x3
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES 1
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES 0x0000000E
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES(v) \
|
||||||
|
(((v) << 1) & BM_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__8_bytes 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__16_bytes 0x1
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__32_bytes 0x2
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__64_bytes 0x3
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_RD_NUM_BYTES__128_bytes 0x4
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN 0x00000001
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN)
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN__0 0x0
|
||||||
|
#define BV_PRE_PREFETCH_ENGINE_CTRL_PREFETCH_EN__1 0x1
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_STATUS (0x00000090)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y 0x3FFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_Y)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X 0x0000FFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_STATUS_PREFETCH_BLOCK_X)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_INPUT_SIZE (0x000000a0)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_HEIGHT)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH 0x0000FFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_INPUT_SIZE_INPUT_WIDTH)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC (0x000000b0)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_Y)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X 0x0000FFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_ULC_OUTPUT_SIZE_ULC_X)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC (0x000000c0)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_Y)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X 0x0000FFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_OUTPUT_SIZE_LRC_OUTPUT_SIZE_LRC_X)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_PITCH (0x000000d0)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_UV_PITCH)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH 0x0000FFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_PITCH_INPUT_Y_PITCH)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET (0x000000e0)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_SET (0x000000e4)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_CLR (0x000000e8)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_TOG (0x000000ec)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0 29
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0 0xE0000000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0(v) \
|
||||||
|
(((v) << 29) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD0)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3 24
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3 0x1F000000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3(v) \
|
||||||
|
(((v) << 24) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET3)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1 21
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1 0x00E00000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1(v) \
|
||||||
|
(((v) << 21) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD1)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2 0x001F0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET2)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2 13
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2 0x0000E000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2(v) \
|
||||||
|
(((v) << 13) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD2)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1 8
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1 0x00001F00
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1(v) \
|
||||||
|
(((v) << 8) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET1)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3 5
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3 0x000000E0
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3(v) \
|
||||||
|
(((v) << 5) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_RSVD3)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0 0x0000001F
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_SHIFT_OFFSET_OFFSET0)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH (0x000000f0)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_SET (0x000000f4)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_CLR (0x000000f8)
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_TOG (0x000000fc)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0 16
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0 0xFFFF0000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0(v) \
|
||||||
|
(((v) << 16) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_RSVD0)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3 12
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3 0x0000F000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3(v) \
|
||||||
|
(((v) << 12) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH3)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2 8
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2 0x00000F00
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2(v) \
|
||||||
|
(((v) << 8) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH2)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1 4
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1 0x000000F0
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1(v) \
|
||||||
|
(((v) << 4) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH1)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0 0x0000000F
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_SHIFT_WIDTH_WIDTH0)
|
||||||
|
|
||||||
|
#define HW_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET (0x00000100)
|
||||||
|
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0 23
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0 0xFF800000
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0(v) \
|
||||||
|
(((v) << 23) & BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_RSVD0)
|
||||||
|
#define BP_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET 0
|
||||||
|
#define BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET 0xFFFFFFFF
|
||||||
|
#define BF_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET(v) \
|
||||||
|
(((v) << 0) & BM_PRE_PREFETCH_ENGINE_INTERLACE_OFFSET_INTERLACE_OFFSET)
|
||||||
|
|
||||||
|
#define HW_PRE_STORE_ENGINE_CTRL (0x00000110)
|
||||||
|
#define HW_PRE_STORE_ENGINE_CTRL_SET (0x00000114)
|
||||||
|
#define HW_PRE_STORE_ENGINE_CTRL_CLR (0x00000118)
|
||||||
|
#define HW_PRE_STORE_ENGINE_CTRL_TOG (0x0000011c)
|
||||||
|
|
||||||
|
#define BP_PRE_STORE_ENGINE_CTRL_RSVD0 6
|
||||||
|
#define BM_PRE_STORE_ENGINE_CTRL_RSVD0 0xFFFFFFC0
|
||||||
|
#define BF_PRE_STORE_ENGINE_CTRL_RSVD0(v) \
|
||||||
|
(((v) << 6) & BM_PRE_STORE_ENGINE_CTRL_RSVD0)
|
||||||
|
#define BP_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP 4
|
||||||
|
#define BM_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP 0x00000030
|
||||||
|
#define BF_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP(v) \
|
||||||
|
(((v) << 4) & BM_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP)
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__8_bits 0x0
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__16_bits 0x1
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__32_bits 0x2
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_OUTPUT_ACTIVE_BPP__64_bits 0x3
|
||||||
|
#define BP_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES 1
|
||||||
|
#define BM_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES 0x0000000E
|
||||||
|
#define BF_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES(v) \
|
||||||
|
(((v) << 1) & BM_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES)
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__8_bytes 0x0
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__16_bytes 0x1
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__32_bytes 0x2
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__64_bytes 0x3
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_WR_NUM_BYTES__128_bytes 0x4
|
||||||
|
#define BM_PRE_STORE_ENGINE_CTRL_STORE_EN 0x00000001
|
||||||
|
#define BF_PRE_STORE_ENGINE_CTRL_STORE_EN(v) \
|
||||||
|
(((v) << 0) & BM_PRE_STORE_ENGINE_CTRL_STORE_EN)
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_STORE_EN__0 0x0
|
||||||
|
#define BV_PRE_STORE_ENGINE_CTRL_STORE_EN__1 0x1
|
||||||
|
|
||||||
|
#define HW_PRE_STORE_ENGINE_STATUS (0x00000120)
|
||||||
|
|
||||||
|
#define BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y 16
|
||||||
|
#define BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y 0x3FFF0000
|
||||||
|
#define BF_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y(v) \
|
||||||
|
(((v) << 16) & BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_Y)
|
||||||
|
#define BP_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X 0
|
||||||
|
#define BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X 0x0000FFFF
|
||||||
|
#define BF_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X(v) \
|
||||||
|
(((v) << 0) & BM_PRE_STORE_ENGINE_STATUS_STORE_BLOCK_X)
|
||||||
|
|
||||||
|
#define HW_PRE_STORE_ENGINE_SIZE (0x00000130)
|
||||||
|
|
||||||
|
#define BP_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT 16
|
||||||
|
#define BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT 0xFFFF0000
|
||||||
|
#define BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT(v) \
|
||||||
|
(((v) << 16) & BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_HEIGHT)
|
||||||
|
#define BP_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH 0
|
||||||
|
#define BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH 0x0000FFFF
|
||||||
|
#define BF_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH(v) \
|
||||||
|
(((v) << 0) & BM_PRE_STORE_ENGINE_SIZE_INPUT_TOTAL_WIDTH)
|
||||||
|
|
||||||
|
#define HW_PRE_STORE_ENGINE_PITCH (0x00000140)
|
||||||
|
|
||||||
|
#define BP_PRE_STORE_ENGINE_PITCH_RSVD0 16
|
||||||
|
#define BM_PRE_STORE_ENGINE_PITCH_RSVD0 0xFFFF0000
|
||||||
|
#define BF_PRE_STORE_ENGINE_PITCH_RSVD0(v) \
|
||||||
|
(((v) << 16) & BM_PRE_STORE_ENGINE_PITCH_RSVD0)
|
||||||
|
#define BP_PRE_STORE_ENGINE_PITCH_OUT_PITCH 0
|
||||||
|
#define BM_PRE_STORE_ENGINE_PITCH_OUT_PITCH 0x0000FFFF
|
||||||
|
#define BF_PRE_STORE_ENGINE_PITCH_OUT_PITCH(v) \
|
||||||
|
(((v) << 0) & BM_PRE_STORE_ENGINE_PITCH_OUT_PITCH)
|
||||||
|
|
||||||
|
#define HW_PRE_STORE_ENGINE_ADDR (0x00000150)
|
||||||
|
|
||||||
|
#define BP_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR 0
|
||||||
|
#define BM_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR 0xFFFFFFFF
|
||||||
|
#define BF_PRE_STORE_ENGINE_ADDR_OUT_BASE_ADDR(v) (v)
|
||||||
|
#endif /* __ARCH_ARM___PRE_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,70 @@
|
||||||
|
/*
|
||||||
|
* Freescale IPU PRG Register Definitions
|
||||||
|
*
|
||||||
|
* Copyright 2014-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#include <linux/bitops.h>
|
||||||
|
|
||||||
|
#ifndef __IPU_PRG_H__
|
||||||
|
#define __IPU_PRG_H__
|
||||||
|
|
||||||
|
#define IPU_PR_CTRL 0x00
|
||||||
|
#define IPU_PR_STATUS 0x04
|
||||||
|
#define IPU_PR_QOS 0x08
|
||||||
|
#define IPU_PR_REG_UPDATE 0x0c
|
||||||
|
#define IPU_PR_STRIDE(ch) (0x10 + (ch) * 4)
|
||||||
|
#define IPU_PR_CROP_LINE 0x1c
|
||||||
|
#define IPU_PR_ADDR_THD 0x20
|
||||||
|
#define IPU_PR_CH_BADDR(ch) (0x24 + (ch) * 4)
|
||||||
|
#define IPU_PR_CH_OFFSET(ch) (0x30 + (ch) * 4)
|
||||||
|
#define IPU_PR_CH_ILO(ch) (0x3c + (ch) * 4)
|
||||||
|
#define IPU_PR_CH_HEIGHT(ch) (0x48 + (ch) * 4)
|
||||||
|
|
||||||
|
#define IPU_PR_CTRL_CH_BYPASS(ch) (0x1 << (ch))
|
||||||
|
#define IPU_PR_CTRL_SOFT_CH_ARID(ch, n) ((n) << ((ch) * 2 + 8))
|
||||||
|
#define IPU_PR_CTRL_SOFT_CH_ARID_MASK(ch) (0x3 << ((ch) * 2 + 8))
|
||||||
|
#define IPU_PR_CTRL_CH_SO(ch, interlace) ((interlace) << ((ch) + 16))
|
||||||
|
#define IPU_PR_CTRL_CH_SO_MASK(ch) (0x1 << ((ch) + 16))
|
||||||
|
#define IPU_PR_CTRL_CH_VFLIP(ch, vflip) ((vflip) << ((ch) + 19))
|
||||||
|
#define IPU_PR_CTRL_CH_VFLIP_MASK(ch) (0x1 << ((ch) + 19))
|
||||||
|
#define IPU_PR_CTRL_CH_BLOCK_MODE(ch, mode) ((mode) << ((ch) + 22))
|
||||||
|
#define IPU_PR_CTRL_CH_BLOCK_MODE_MASK(ch) (0x1 << ((ch) + 22))
|
||||||
|
#define IPU_PR_CTRL_CH_CNT_LOAD_EN(ch) (0x1 << ((ch) + 25))
|
||||||
|
#define IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK (0x7 << 25)
|
||||||
|
#define IPU_PR_CTRL_SOFTRST BIT(30)
|
||||||
|
#define IPU_PR_CTRL_SHADOW_EN BIT(31)
|
||||||
|
|
||||||
|
#define IPU_PR_STATUS_BUF_RDY(ch, buf) (1 << ((ch) * 2 + (buf)))
|
||||||
|
|
||||||
|
#define IPU_PR_QOS_PRI(id, qos) ((qos) << ((id) * 4))
|
||||||
|
#define IPU_PR_QOS_MASK(id) (0xf << ((id) * 4))
|
||||||
|
|
||||||
|
#define IPU_PR_REG_UPDATE_EN BIT(0)
|
||||||
|
|
||||||
|
#define IPU_PR_STRIDE_MASK 0x3fff
|
||||||
|
|
||||||
|
#define IPU_PR_CROP_LINE_NUM(ch, n) ((n) << ((ch) * 4))
|
||||||
|
#define IPU_PR_CROP_LINE_MASK(ch) (0xf << ((ch) * 4))
|
||||||
|
|
||||||
|
#define IPU_PR_ADDR_THD_MASK 0xffffffff
|
||||||
|
|
||||||
|
#define IPU_PR_CH_BADDR_MASK 0xffffffff
|
||||||
|
|
||||||
|
#define IPU_PR_CH_OFFSET_MASK 0xffffffff
|
||||||
|
|
||||||
|
#define IPU_PR_CH_ILO_MASK 0x007fffff
|
||||||
|
#define IPU_PR_CH_ILO_NUM(ilo) ((ilo) & IPU_PR_CH_ILO_MASK)
|
||||||
|
|
||||||
|
#define IPU_PR_CH_HEIGHT_MASK 0x00000fff
|
||||||
|
#define IPU_PR_CH_HEIGHT_NUM(fh) (((fh) - 1) & IPU_PR_CH_HEIGHT_MASK)
|
||||||
|
#define IPU_PR_CH_IPU_HEIGHT_MASK 0x0fff0000
|
||||||
|
#define IPU_PR_CH_IPU_HEIGHT_NUM(fh) ((((fh) - 1) << 16) & IPU_PR_CH_IPU_HEIGHT_MASK)
|
||||||
|
|
||||||
|
#endif /* __IPU_PRG_H__ */
|
|
@ -0,0 +1,506 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/delay.h>
|
||||||
|
#include <linux/init.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ipu-v3-prg.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <linux/mfd/syscon.h>
|
||||||
|
#include <linux/mfd/syscon/imx6q-iomuxc-gpr.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/mutex.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/of_address.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/regmap.h>
|
||||||
|
|
||||||
|
#include "prg-regs.h"
|
||||||
|
|
||||||
|
#define PRG_CHAN_NUM 3
|
||||||
|
|
||||||
|
struct prg_chan {
|
||||||
|
unsigned int pre_num;
|
||||||
|
struct mutex mutex; /* for in_use */
|
||||||
|
bool in_use;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipu_prg_data {
|
||||||
|
unsigned int id;
|
||||||
|
void __iomem *base;
|
||||||
|
unsigned long memory;
|
||||||
|
struct clk *axi_clk;
|
||||||
|
struct clk *apb_clk;
|
||||||
|
struct list_head list;
|
||||||
|
struct device *dev;
|
||||||
|
struct prg_chan chan[PRG_CHAN_NUM];
|
||||||
|
struct regmap *regmap;
|
||||||
|
struct regmap_field *pre_prg_sel[2];
|
||||||
|
spinlock_t lock;
|
||||||
|
};
|
||||||
|
|
||||||
|
static LIST_HEAD(prg_list);
|
||||||
|
static DEFINE_MUTEX(prg_lock);
|
||||||
|
|
||||||
|
static inline void prg_write(struct ipu_prg_data *prg,
|
||||||
|
u32 value, unsigned int offset)
|
||||||
|
{
|
||||||
|
writel(value, prg->base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline u32 prg_read(struct ipu_prg_data *prg, unsigned offset)
|
||||||
|
{
|
||||||
|
return readl(prg->base + offset);
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct ipu_prg_data *get_prg(unsigned int ipu_id)
|
||||||
|
{
|
||||||
|
struct ipu_prg_data *prg;
|
||||||
|
|
||||||
|
mutex_lock(&prg_lock);
|
||||||
|
list_for_each_entry(prg, &prg_list, list) {
|
||||||
|
if (prg->id == ipu_id) {
|
||||||
|
mutex_unlock(&prg_lock);
|
||||||
|
return prg;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
mutex_unlock(&prg_lock);
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int assign_prg_chan(struct ipu_prg_data *prg, unsigned int pre_num,
|
||||||
|
ipu_channel_t ipu_ch)
|
||||||
|
{
|
||||||
|
int prg_ch;
|
||||||
|
|
||||||
|
if (!prg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
switch (ipu_ch) {
|
||||||
|
case MEM_BG_SYNC:
|
||||||
|
prg_ch = 0;
|
||||||
|
break;
|
||||||
|
case MEM_FG_SYNC:
|
||||||
|
prg_ch = 1;
|
||||||
|
break;
|
||||||
|
case MEM_DC_SYNC:
|
||||||
|
prg_ch = 2;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
dev_err(prg->dev, "wrong ipu channel type\n");
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
mutex_lock(&prg->chan[prg_ch].mutex);
|
||||||
|
if (!prg->chan[prg_ch].in_use) {
|
||||||
|
prg->chan[prg_ch].in_use = true;
|
||||||
|
prg->chan[prg_ch].pre_num = pre_num;
|
||||||
|
|
||||||
|
if (prg_ch != 0) {
|
||||||
|
unsigned int pmux, psel; /* primary */
|
||||||
|
unsigned int smux, ssel; /* secondary */
|
||||||
|
struct regmap_field *pfield, *sfield;
|
||||||
|
|
||||||
|
psel = pre_num - 1;
|
||||||
|
ssel = psel ? 0 : 1;
|
||||||
|
|
||||||
|
pfield = prg->pre_prg_sel[psel];
|
||||||
|
sfield = prg->pre_prg_sel[ssel];
|
||||||
|
pmux = (prg_ch - 1) + (prg->id << 1);
|
||||||
|
|
||||||
|
mutex_lock(&prg_lock);
|
||||||
|
regmap_field_write(pfield, pmux);
|
||||||
|
|
||||||
|
/*
|
||||||
|
* PRE1 and PRE2 cannot bind with a same channel of
|
||||||
|
* one PRG even if one of the two PREs is disabled.
|
||||||
|
*/
|
||||||
|
regmap_field_read(sfield, &smux);
|
||||||
|
if (smux == pmux) {
|
||||||
|
smux = pmux ^ 0x1;
|
||||||
|
regmap_field_write(sfield, smux);
|
||||||
|
}
|
||||||
|
mutex_unlock(&prg_lock);
|
||||||
|
}
|
||||||
|
mutex_unlock(&prg->chan[prg_ch].mutex);
|
||||||
|
dev_dbg(prg->dev, "bind prg%u ch%d with pre%u\n",
|
||||||
|
prg->id, prg_ch, pre_num);
|
||||||
|
return prg_ch;
|
||||||
|
}
|
||||||
|
mutex_unlock(&prg->chan[prg_ch].mutex);
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline int get_prg_chan(struct ipu_prg_data *prg, unsigned int pre_num)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (!prg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
for (i = 0; i < PRG_CHAN_NUM; i++) {
|
||||||
|
mutex_lock(&prg->chan[i].mutex);
|
||||||
|
if (prg->chan[i].in_use &&
|
||||||
|
prg->chan[i].pre_num == pre_num) {
|
||||||
|
mutex_unlock(&prg->chan[i].mutex);
|
||||||
|
return i;
|
||||||
|
}
|
||||||
|
mutex_unlock(&prg->chan[i].mutex);
|
||||||
|
}
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_prg_config(struct ipu_prg_config *config)
|
||||||
|
{
|
||||||
|
struct ipu_prg_data *prg = get_prg(config->id);
|
||||||
|
struct ipu_soc *ipu = ipu_get_soc(config->id);
|
||||||
|
int prg_ch, axi_id;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (!prg || config->crop_line > 3 || !ipu)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
if (config->height & ~IPU_PR_CH_HEIGHT_MASK)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
prg_ch = assign_prg_chan(prg, config->pre_num, config->ipu_ch);
|
||||||
|
if (prg_ch < 0)
|
||||||
|
return prg_ch;
|
||||||
|
|
||||||
|
axi_id = ipu_ch_param_get_axi_id(ipu, config->ipu_ch, IPU_INPUT_BUFFER);
|
||||||
|
|
||||||
|
clk_prepare_enable(prg->axi_clk);
|
||||||
|
clk_prepare_enable(prg->apb_clk);
|
||||||
|
|
||||||
|
spin_lock(&prg->lock);
|
||||||
|
/* clear all load enable to impact other channels */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK;
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* counter load enable */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg |= IPU_PR_CTRL_CH_CNT_LOAD_EN(prg_ch);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* AXI ID */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_SOFT_CH_ARID_MASK(prg_ch);
|
||||||
|
reg |= IPU_PR_CTRL_SOFT_CH_ARID(prg_ch, axi_id);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* so */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_SO_MASK(prg_ch);
|
||||||
|
reg |= IPU_PR_CTRL_CH_SO(prg_ch, config->so);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* vflip */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_VFLIP_MASK(prg_ch);
|
||||||
|
reg |= IPU_PR_CTRL_CH_VFLIP(prg_ch, config->vflip);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* block mode */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_BLOCK_MODE_MASK(prg_ch);
|
||||||
|
reg |= IPU_PR_CTRL_CH_BLOCK_MODE(prg_ch, config->block_mode);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* disable bypass */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_BYPASS(prg_ch);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* stride */
|
||||||
|
reg = prg_read(prg, IPU_PR_STRIDE(prg_ch));
|
||||||
|
reg &= ~IPU_PR_STRIDE_MASK;
|
||||||
|
reg |= config->stride - 1;
|
||||||
|
prg_write(prg, reg, IPU_PR_STRIDE(prg_ch));
|
||||||
|
|
||||||
|
/* ilo */
|
||||||
|
reg = prg_read(prg, IPU_PR_CH_ILO(prg_ch));
|
||||||
|
reg &= ~IPU_PR_CH_ILO_MASK;
|
||||||
|
reg |= IPU_PR_CH_ILO_NUM(config->ilo);
|
||||||
|
prg_write(prg, reg, IPU_PR_CH_ILO(prg_ch));
|
||||||
|
|
||||||
|
/* height */
|
||||||
|
reg = prg_read(prg, IPU_PR_CH_HEIGHT(prg_ch));
|
||||||
|
reg &= ~IPU_PR_CH_HEIGHT_MASK;
|
||||||
|
reg |= IPU_PR_CH_HEIGHT_NUM(config->height);
|
||||||
|
prg_write(prg, reg, IPU_PR_CH_HEIGHT(prg_ch));
|
||||||
|
|
||||||
|
/* ipu height */
|
||||||
|
reg = prg_read(prg, IPU_PR_CH_HEIGHT(prg_ch));
|
||||||
|
reg &= ~IPU_PR_CH_IPU_HEIGHT_MASK;
|
||||||
|
reg |= IPU_PR_CH_IPU_HEIGHT_NUM(config->ipu_height);
|
||||||
|
prg_write(prg, reg, IPU_PR_CH_HEIGHT(prg_ch));
|
||||||
|
|
||||||
|
/* crop */
|
||||||
|
reg = prg_read(prg, IPU_PR_CROP_LINE);
|
||||||
|
reg &= ~IPU_PR_CROP_LINE_MASK(prg_ch);
|
||||||
|
reg |= IPU_PR_CROP_LINE_NUM(prg_ch, config->crop_line);
|
||||||
|
prg_write(prg, reg, IPU_PR_CROP_LINE);
|
||||||
|
|
||||||
|
/* buffer address */
|
||||||
|
reg = prg_read(prg, IPU_PR_CH_BADDR(prg_ch));
|
||||||
|
reg &= ~IPU_PR_CH_BADDR_MASK;
|
||||||
|
reg |= config->baddr;
|
||||||
|
prg_write(prg, reg, IPU_PR_CH_BADDR(prg_ch));
|
||||||
|
|
||||||
|
/* offset */
|
||||||
|
reg = prg_read(prg, IPU_PR_CH_OFFSET(prg_ch));
|
||||||
|
reg &= ~IPU_PR_CH_OFFSET_MASK;
|
||||||
|
reg |= config->offset;
|
||||||
|
prg_write(prg, reg, IPU_PR_CH_OFFSET(prg_ch));
|
||||||
|
|
||||||
|
/* threshold */
|
||||||
|
reg = prg_read(prg, IPU_PR_ADDR_THD);
|
||||||
|
reg &= ~IPU_PR_ADDR_THD_MASK;
|
||||||
|
reg |= prg->memory;
|
||||||
|
prg_write(prg, reg, IPU_PR_ADDR_THD);
|
||||||
|
|
||||||
|
/* shadow enable */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg |= IPU_PR_CTRL_SHADOW_EN;
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* register update */
|
||||||
|
reg = prg_read(prg, IPU_PR_REG_UPDATE);
|
||||||
|
reg |= IPU_PR_REG_UPDATE_EN;
|
||||||
|
prg_write(prg, reg, IPU_PR_REG_UPDATE);
|
||||||
|
spin_unlock(&prg->lock);
|
||||||
|
|
||||||
|
clk_disable_unprepare(prg->apb_clk);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_prg_config);
|
||||||
|
|
||||||
|
int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num)
|
||||||
|
{
|
||||||
|
struct ipu_prg_data *prg = get_prg(ipu_id);
|
||||||
|
int prg_ch;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (!prg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
prg_ch = get_prg_chan(prg, pre_num);
|
||||||
|
if (prg_ch < 0)
|
||||||
|
return prg_ch;
|
||||||
|
|
||||||
|
clk_prepare_enable(prg->apb_clk);
|
||||||
|
|
||||||
|
spin_lock(&prg->lock);
|
||||||
|
/* clear all load enable to impact other channels */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg &= ~IPU_PR_CTRL_CH_CNT_LOAD_EN_MASK;
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* counter load enable */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg |= IPU_PR_CTRL_CH_CNT_LOAD_EN(prg_ch);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* enable bypass */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg |= IPU_PR_CTRL_CH_BYPASS(prg_ch);
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* shadow enable */
|
||||||
|
reg = prg_read(prg, IPU_PR_CTRL);
|
||||||
|
reg |= IPU_PR_CTRL_SHADOW_EN;
|
||||||
|
prg_write(prg, reg, IPU_PR_CTRL);
|
||||||
|
|
||||||
|
/* register update */
|
||||||
|
reg = prg_read(prg, IPU_PR_REG_UPDATE);
|
||||||
|
reg |= IPU_PR_REG_UPDATE_EN;
|
||||||
|
prg_write(prg, reg, IPU_PR_REG_UPDATE);
|
||||||
|
spin_unlock(&prg->lock);
|
||||||
|
|
||||||
|
clk_disable_unprepare(prg->apb_clk);
|
||||||
|
clk_disable_unprepare(prg->axi_clk);
|
||||||
|
|
||||||
|
mutex_lock(&prg->chan[prg_ch].mutex);
|
||||||
|
prg->chan[prg_ch].in_use = false;
|
||||||
|
mutex_unlock(&prg->chan[prg_ch].mutex);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_prg_disable);
|
||||||
|
|
||||||
|
int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
|
||||||
|
unsigned int hsk_line_num,
|
||||||
|
int pre_store_out_height)
|
||||||
|
{
|
||||||
|
struct ipu_prg_data *prg = get_prg(ipu_id);
|
||||||
|
int prg_ch, timeout = 1000;
|
||||||
|
u32 reg;
|
||||||
|
|
||||||
|
if (!prg)
|
||||||
|
return -EINVAL;
|
||||||
|
|
||||||
|
prg_ch = get_prg_chan(prg, pre_num);
|
||||||
|
if (prg_ch < 0)
|
||||||
|
return prg_ch;
|
||||||
|
|
||||||
|
clk_prepare_enable(prg->apb_clk);
|
||||||
|
|
||||||
|
spin_lock(&prg->lock);
|
||||||
|
if (pre_store_out_height <= (4 << hsk_line_num)) {
|
||||||
|
do {
|
||||||
|
reg = prg_read(prg, IPU_PR_STATUS);
|
||||||
|
udelay(1000);
|
||||||
|
timeout--;
|
||||||
|
} while (!(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 0)) && timeout);
|
||||||
|
} else {
|
||||||
|
do {
|
||||||
|
reg = prg_read(prg, IPU_PR_STATUS);
|
||||||
|
udelay(1000);
|
||||||
|
timeout--;
|
||||||
|
} while ((!(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 0)) ||
|
||||||
|
!(reg & IPU_PR_STATUS_BUF_RDY(prg_ch, 1))) && timeout);
|
||||||
|
}
|
||||||
|
spin_unlock(&prg->lock);
|
||||||
|
|
||||||
|
clk_disable_unprepare(prg->apb_clk);
|
||||||
|
|
||||||
|
if (!timeout)
|
||||||
|
dev_err(prg->dev, "wait for buffer ready timeout\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
EXPORT_SYMBOL(ipu_prg_wait_buf_ready);
|
||||||
|
|
||||||
|
static int ipu_prg_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct device_node *np = pdev->dev.of_node, *memory;
|
||||||
|
struct ipu_prg_data *prg;
|
||||||
|
struct resource *res;
|
||||||
|
struct reg_field reg_field0 = REG_FIELD(IOMUXC_GPR5,
|
||||||
|
IMX6Q_GPR5_PRE_PRG_SEL0_LSB,
|
||||||
|
IMX6Q_GPR5_PRE_PRG_SEL0_MSB);
|
||||||
|
struct reg_field reg_field1 = REG_FIELD(IOMUXC_GPR5,
|
||||||
|
IMX6Q_GPR5_PRE_PRG_SEL1_LSB,
|
||||||
|
IMX6Q_GPR5_PRE_PRG_SEL1_MSB);
|
||||||
|
int id, i;
|
||||||
|
|
||||||
|
prg = devm_kzalloc(&pdev->dev, sizeof(*prg), GFP_KERNEL);
|
||||||
|
if (!prg)
|
||||||
|
return -ENOMEM;
|
||||||
|
prg->dev = &pdev->dev;
|
||||||
|
|
||||||
|
for (i = 0; i < PRG_CHAN_NUM; i++)
|
||||||
|
mutex_init(&prg->chan[i].mutex);
|
||||||
|
|
||||||
|
spin_lock_init(&prg->lock);
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
prg->base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (IS_ERR(prg->base))
|
||||||
|
return PTR_ERR(prg->base);
|
||||||
|
|
||||||
|
prg->axi_clk = devm_clk_get(&pdev->dev, "axi");
|
||||||
|
if (IS_ERR(prg->axi_clk)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get the axi clk\n");
|
||||||
|
return PTR_ERR(prg->axi_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
prg->apb_clk = devm_clk_get(&pdev->dev, "apb");
|
||||||
|
if (IS_ERR(prg->apb_clk)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get the apb clk\n");
|
||||||
|
return PTR_ERR(prg->apb_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
prg->regmap = syscon_regmap_lookup_by_phandle(np, "gpr");
|
||||||
|
if (IS_ERR(prg->regmap)) {
|
||||||
|
dev_err(&pdev->dev, "failed to get regmap\n");
|
||||||
|
return PTR_ERR(prg->regmap);
|
||||||
|
}
|
||||||
|
|
||||||
|
prg->pre_prg_sel[0] = devm_regmap_field_alloc(&pdev->dev, prg->regmap,
|
||||||
|
reg_field0);
|
||||||
|
if (IS_ERR(prg->pre_prg_sel[0]))
|
||||||
|
return PTR_ERR(prg->pre_prg_sel[0]);
|
||||||
|
|
||||||
|
prg->pre_prg_sel[1] = devm_regmap_field_alloc(&pdev->dev, prg->regmap,
|
||||||
|
reg_field1);
|
||||||
|
if (IS_ERR(prg->pre_prg_sel[1]))
|
||||||
|
return PTR_ERR(prg->pre_prg_sel[1]);
|
||||||
|
|
||||||
|
memory = of_parse_phandle(np, "memory-region", 0);
|
||||||
|
if (!memory)
|
||||||
|
return -ENODEV;
|
||||||
|
|
||||||
|
prg->memory = of_translate_address(memory,
|
||||||
|
of_get_address(memory, 0, NULL, NULL));
|
||||||
|
|
||||||
|
id = of_alias_get_id(np, "prg");
|
||||||
|
if (id < 0) {
|
||||||
|
dev_err(&pdev->dev, "failed to get PRG id\n");
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
prg->id = id;
|
||||||
|
|
||||||
|
mutex_lock(&prg_lock);
|
||||||
|
list_add_tail(&prg->list, &prg_list);
|
||||||
|
mutex_unlock(&prg_lock);
|
||||||
|
|
||||||
|
platform_set_drvdata(pdev, prg);
|
||||||
|
|
||||||
|
dev_info(&pdev->dev, "driver probed\n");
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ipu_prg_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct ipu_prg_data *prg = platform_get_drvdata(pdev);
|
||||||
|
|
||||||
|
mutex_lock(&prg_lock);
|
||||||
|
list_del(&prg->list);
|
||||||
|
mutex_unlock(&prg_lock);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const struct of_device_id imx_ipu_prg_dt_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx6q-prg", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(of, imx_ipu_prg_dt_ids);
|
||||||
|
|
||||||
|
static struct platform_driver ipu_prg_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "imx-prg",
|
||||||
|
.of_match_table = of_match_ptr(imx_ipu_prg_dt_ids),
|
||||||
|
},
|
||||||
|
.probe = ipu_prg_probe,
|
||||||
|
.remove = ipu_prg_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init ipu_prg_init(void)
|
||||||
|
{
|
||||||
|
return platform_driver_register(&ipu_prg_driver);
|
||||||
|
}
|
||||||
|
subsys_initcall(ipu_prg_init);
|
||||||
|
|
||||||
|
static void __exit ipu_prg_exit(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&ipu_prg_driver);
|
||||||
|
}
|
||||||
|
module_exit(ipu_prg_exit);
|
||||||
|
|
||||||
|
MODULE_DESCRIPTION("i.MX PRG driver");
|
||||||
|
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,538 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
* Copyright 2018 NXP
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#include <linux/clk.h>
|
||||||
|
#include <linux/err.h>
|
||||||
|
#include <linux/io.h>
|
||||||
|
#include <linux/ipu.h>
|
||||||
|
#include <linux/genalloc.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
#include <linux/of.h>
|
||||||
|
#include <linux/platform_device.h>
|
||||||
|
#include <linux/slab.h>
|
||||||
|
#include <linux/types.h>
|
||||||
|
|
||||||
|
#include "vdoa.h"
|
||||||
|
/* 6band(3field* double buffer) * (width*2) * bandline(8)
|
||||||
|
= 6x1024x2x8 = 96k or 72k(1.5byte) */
|
||||||
|
#define MAX_VDOA_IRAM_SIZE (1024*96)
|
||||||
|
#define VDOA_IRAM_SIZE (1024*72)
|
||||||
|
|
||||||
|
#define VDOAC_BAND_HEIGHT_32LINES (32)
|
||||||
|
#define VDOAC_BAND_HEIGHT_16LINES (16)
|
||||||
|
#define VDOAC_BAND_HEIGHT_8LINES (8)
|
||||||
|
#define VDOAC_THREE_FRAMES (0x1 << 2)
|
||||||
|
#define VDOAC_SYNC_BAND_MODE (0x1 << 3)
|
||||||
|
#define VDOAC_SCAN_ORDER_INTERLACED (0x1 << 4)
|
||||||
|
#define VDOAC_PFS_YUYV (0x1 << 5)
|
||||||
|
#define VDOAC_IPU_SEL_1 (0x1 << 6)
|
||||||
|
#define VDOAFP_FH_MASK (0x1FFF)
|
||||||
|
#define VDOAFP_FH_SHIFT (16)
|
||||||
|
#define VDOAFP_FW_MASK (0x3FFF)
|
||||||
|
#define VDOAFP_FW_SHIFT (0)
|
||||||
|
#define VDOASL_VSLY_MASK (0x3FFF)
|
||||||
|
#define VDOASL_VSLY_SHIFT (16)
|
||||||
|
#define VDOASL_ISLY_MASK (0x7FFF)
|
||||||
|
#define VDOASL_ISLY_SHIFT (0)
|
||||||
|
#define VDOASRR_START_XFER (0x2)
|
||||||
|
#define VDOASRR_SWRST (0x1)
|
||||||
|
#define VDOAIEIST_TRANSFER_ERR (0x2)
|
||||||
|
#define VDOAIEIST_TRANSFER_END (0x1)
|
||||||
|
|
||||||
|
#define VDOAC (0x0) /* Control Register */
|
||||||
|
#define VDOASRR (0x4) /* Start and Reset Register */
|
||||||
|
#define VDOAIE (0x8) /* Interrupt Enable Register */
|
||||||
|
#define VDOAIST (0xc) /* Interrupt Status Register */
|
||||||
|
#define VDOAFP (0x10) /* Frame Parameters Register */
|
||||||
|
#define VDOAIEBA00 (0x14) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOAIEBA01 (0x18) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOAIEBA02 (0x1c) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOAIEBA10 (0x20) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOAIEBA11 (0x24) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOAIEBA12 (0x28) /* External Buffer n Frame m Address Register */
|
||||||
|
#define VDOASL (0x2c) /* IPU Stride Line Register */
|
||||||
|
#define VDOAIUBO (0x30) /* IPU Chroma Buffer Offset Register */
|
||||||
|
#define VDOAVEBA0 (0x34) /* External Buffer m Address Register */
|
||||||
|
#define VDOAVEBA1 (0x38) /* External Buffer m Address Register */
|
||||||
|
#define VDOAVEBA2 (0x3c) /* External Buffer m Address Register */
|
||||||
|
#define VDOAVUBO (0x40) /* VPU Chroma Buffer Offset */
|
||||||
|
#define VDOASR (0x44) /* Status Register */
|
||||||
|
#define VDOATD (0x48) /* Test Debug Register */
|
||||||
|
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VDOA_INIT = 0x1,
|
||||||
|
VDOA_GET = 0x2,
|
||||||
|
VDOA_SETUP = 0x4,
|
||||||
|
VDOA_GET_OBUF = 0x8,
|
||||||
|
VDOA_START = 0x10,
|
||||||
|
VDOA_INIRQ = 0x20,
|
||||||
|
VDOA_STOP = 0x40,
|
||||||
|
VDOA_PUT = VDOA_INIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
VDOA_NULL = 0,
|
||||||
|
VDOA_FRAME = 1,
|
||||||
|
VDOA_PREV_FIELD = 2,
|
||||||
|
VDOA_CURR_FIELD = 3,
|
||||||
|
VDOA_NEXT_FIELD = 4,
|
||||||
|
};
|
||||||
|
|
||||||
|
#define CHECK_STATE(expect, retcode) \
|
||||||
|
do { \
|
||||||
|
if (!((expect) & vdoa->state)) { \
|
||||||
|
dev_err(vdoa->dev, "ERR: %s state:0x%x, expect:0x%x.\n",\
|
||||||
|
__func__, vdoa->state, (expect)); \
|
||||||
|
retcode; \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
#define CHECK_NULL_PTR(ptr) \
|
||||||
|
do { \
|
||||||
|
pr_debug("vdoa_ptr:0x%p in %s state:0x%x.\n", \
|
||||||
|
vdoa, __func__, vdoa->state); \
|
||||||
|
if (NULL == (ptr)) { \
|
||||||
|
pr_err("ERR vdoa: %s state:0x%x null ptr.\n", \
|
||||||
|
__func__, vdoa->state); \
|
||||||
|
} \
|
||||||
|
} while (0)
|
||||||
|
|
||||||
|
struct vdoa_info {
|
||||||
|
int state;
|
||||||
|
struct device *dev;
|
||||||
|
struct clk *vdoa_clk;
|
||||||
|
void __iomem *reg_base;
|
||||||
|
struct gen_pool *iram_pool;
|
||||||
|
unsigned long iram_base;
|
||||||
|
unsigned long iram_paddr;
|
||||||
|
int irq;
|
||||||
|
int field;
|
||||||
|
struct completion comp;
|
||||||
|
};
|
||||||
|
|
||||||
|
static struct vdoa_info *g_vdoa;
|
||||||
|
static unsigned long iram_size;
|
||||||
|
static DEFINE_MUTEX(vdoa_lock);
|
||||||
|
|
||||||
|
static inline void vdoa_read_register(struct vdoa_info *vdoa,
|
||||||
|
u32 reg, u32 *val)
|
||||||
|
{
|
||||||
|
*val = ioread32(vdoa->reg_base + reg);
|
||||||
|
dev_dbg(vdoa->dev, "read_reg:0x%02x, val:0x%08x.\n", reg, *val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void vdoa_write_register(struct vdoa_info *vdoa,
|
||||||
|
u32 reg, u32 val)
|
||||||
|
{
|
||||||
|
iowrite32(val, vdoa->reg_base + reg);
|
||||||
|
dev_dbg(vdoa->dev, "\t\twrite_reg:0x%02x, val:0x%08x.\n", reg, val);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void dump_registers(struct vdoa_info *vdoa)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
u32 data;
|
||||||
|
|
||||||
|
for (i = VDOAC; i < VDOATD; i += 4)
|
||||||
|
vdoa_read_register(vdoa, i, &data);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params)
|
||||||
|
{
|
||||||
|
int band_size;
|
||||||
|
int total_band_size = 0;
|
||||||
|
int ipu_stride;
|
||||||
|
u32 data;
|
||||||
|
struct vdoa_info *vdoa = (struct vdoa_info *)handle;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_GET | VDOA_GET_OBUF | VDOA_STOP, return -EINVAL);
|
||||||
|
if (VDOA_GET == vdoa->state) {
|
||||||
|
dev_dbg(vdoa->dev, "w:%d, h:%d.\n",
|
||||||
|
params->width, params->height);
|
||||||
|
data = (params->band_lines == VDOAC_BAND_HEIGHT_32LINES) ? 2 :
|
||||||
|
((params->band_lines == VDOAC_BAND_HEIGHT_16LINES) ?
|
||||||
|
1 : 0);
|
||||||
|
data |= params->scan_order ? VDOAC_SCAN_ORDER_INTERLACED : 0;
|
||||||
|
data |= params->band_mode ? VDOAC_SYNC_BAND_MODE : 0;
|
||||||
|
data |= params->pfs ? VDOAC_PFS_YUYV : 0;
|
||||||
|
data |= params->ipu_num ? VDOAC_IPU_SEL_1 : 0;
|
||||||
|
vdoa_write_register(vdoa, VDOAC, data);
|
||||||
|
|
||||||
|
data = ((params->width & VDOAFP_FW_MASK) << VDOAFP_FW_SHIFT) |
|
||||||
|
((params->height & VDOAFP_FH_MASK) << VDOAFP_FH_SHIFT);
|
||||||
|
vdoa_write_register(vdoa, VDOAFP, data);
|
||||||
|
|
||||||
|
ipu_stride = params->pfs ? params->width << 1 : params->width;
|
||||||
|
data = ((params->vpu_stride & VDOASL_VSLY_MASK) <<
|
||||||
|
VDOASL_VSLY_SHIFT) |
|
||||||
|
((ipu_stride & VDOASL_ISLY_MASK) << VDOASL_ISLY_SHIFT);
|
||||||
|
vdoa_write_register(vdoa, VDOASL, data);
|
||||||
|
|
||||||
|
dev_dbg(vdoa->dev, "band_mode:%d, band_line:%d, base:0x%lx.\n",
|
||||||
|
params->band_mode, params->band_lines, vdoa->iram_paddr);
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
* band size = (luma_per_line + chroma_per_line) * bandLines
|
||||||
|
* = width * (3/2 or 2) * bandLines
|
||||||
|
* double buffer mode used.
|
||||||
|
*/
|
||||||
|
if (params->pfs)
|
||||||
|
band_size = (params->width << 1) * params->band_lines;
|
||||||
|
else
|
||||||
|
band_size = ((params->width * 3) >> 1) *
|
||||||
|
params->band_lines;
|
||||||
|
if (params->interlaced) {
|
||||||
|
total_band_size = 6 * band_size; /* 3 frames*double buffer */
|
||||||
|
if (iram_size < total_band_size) {
|
||||||
|
dev_err(vdoa->dev, "iram_size:0x%lx is smaller than "
|
||||||
|
"request:0x%x!\n", iram_size, total_band_size);
|
||||||
|
return -EINVAL;
|
||||||
|
}
|
||||||
|
if (params->vfield_buf.prev_veba) {
|
||||||
|
if (params->band_mode) {
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA00,
|
||||||
|
vdoa->iram_paddr);
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA10,
|
||||||
|
vdoa->iram_paddr + band_size);
|
||||||
|
} else
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA00,
|
||||||
|
params->ieba0);
|
||||||
|
vdoa_write_register(vdoa, VDOAVEBA0,
|
||||||
|
params->vfield_buf.prev_veba);
|
||||||
|
vdoa->field = VDOA_PREV_FIELD;
|
||||||
|
}
|
||||||
|
if (params->vfield_buf.cur_veba) {
|
||||||
|
if (params->band_mode) {
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA01,
|
||||||
|
vdoa->iram_paddr + band_size * 2);
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA11,
|
||||||
|
vdoa->iram_paddr + band_size * 3);
|
||||||
|
} else
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA01,
|
||||||
|
params->ieba1);
|
||||||
|
vdoa_write_register(vdoa, VDOAVEBA1,
|
||||||
|
params->vfield_buf.cur_veba);
|
||||||
|
vdoa->field = VDOA_CURR_FIELD;
|
||||||
|
}
|
||||||
|
if (params->vfield_buf.next_veba) {
|
||||||
|
if (params->band_mode) {
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA02,
|
||||||
|
vdoa->iram_paddr + band_size * 4);
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA12,
|
||||||
|
vdoa->iram_paddr + band_size * 5);
|
||||||
|
} else
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA02,
|
||||||
|
params->ieba2);
|
||||||
|
vdoa_write_register(vdoa, VDOAVEBA2,
|
||||||
|
params->vfield_buf.next_veba);
|
||||||
|
vdoa->field = VDOA_NEXT_FIELD;
|
||||||
|
vdoa_read_register(vdoa, VDOAC, &data);
|
||||||
|
data |= VDOAC_THREE_FRAMES;
|
||||||
|
vdoa_write_register(vdoa, VDOAC, data);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!params->pfs)
|
||||||
|
vdoa_write_register(vdoa, VDOAIUBO,
|
||||||
|
params->width * params->band_lines);
|
||||||
|
vdoa_write_register(vdoa, VDOAVUBO,
|
||||||
|
params->vfield_buf.vubo);
|
||||||
|
dev_dbg(vdoa->dev, "total band_size:0x%x.\n", band_size*6);
|
||||||
|
} else if (params->band_mode) {
|
||||||
|
/* used for progressive frame resize on PrP channel */
|
||||||
|
BUG(); /* currently not support */
|
||||||
|
/* progressvie frame: band mode */
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA00, vdoa->iram_paddr);
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA10,
|
||||||
|
vdoa->iram_paddr + band_size);
|
||||||
|
if (!params->pfs)
|
||||||
|
vdoa_write_register(vdoa, VDOAIUBO,
|
||||||
|
params->width * params->band_lines);
|
||||||
|
dev_dbg(vdoa->dev, "total band_size:0x%x\n", band_size*2);
|
||||||
|
} else {
|
||||||
|
/* progressive frame: mem->mem, non-band mode */
|
||||||
|
vdoa->field = VDOA_FRAME;
|
||||||
|
vdoa_write_register(vdoa, VDOAVEBA0, params->vframe_buf.veba);
|
||||||
|
vdoa_write_register(vdoa, VDOAVUBO, params->vframe_buf.vubo);
|
||||||
|
vdoa_write_register(vdoa, VDOAIEBA00, params->ieba0);
|
||||||
|
if (!params->pfs)
|
||||||
|
/* note: iubo is relative value, based on ieba0 */
|
||||||
|
vdoa_write_register(vdoa, VDOAIUBO,
|
||||||
|
params->width * params->height);
|
||||||
|
}
|
||||||
|
vdoa->state = VDOA_SETUP;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf)
|
||||||
|
{
|
||||||
|
u32 data;
|
||||||
|
struct vdoa_info *vdoa = (struct vdoa_info *)handle;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_SETUP, return);
|
||||||
|
vdoa->state = VDOA_GET_OBUF;
|
||||||
|
memset(buf, 0, sizeof(*buf));
|
||||||
|
|
||||||
|
vdoa_read_register(vdoa, VDOAC, &data);
|
||||||
|
switch (vdoa->field) {
|
||||||
|
case VDOA_FRAME:
|
||||||
|
case VDOA_PREV_FIELD:
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA00, &buf->ieba0);
|
||||||
|
if (data & VDOAC_SYNC_BAND_MODE)
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA10, &buf->ieba1);
|
||||||
|
break;
|
||||||
|
case VDOA_CURR_FIELD:
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA01, &buf->ieba0);
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA11, &buf->ieba1);
|
||||||
|
break;
|
||||||
|
case VDOA_NEXT_FIELD:
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA02, &buf->ieba0);
|
||||||
|
vdoa_read_register(vdoa, VDOAIEBA12, &buf->ieba1);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
BUG();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (!(data & VDOAC_PFS_YUYV))
|
||||||
|
vdoa_read_register(vdoa, VDOAIUBO, &buf->iubo);
|
||||||
|
}
|
||||||
|
|
||||||
|
int vdoa_start(vdoa_handle_t handle, int timeout_ms)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct vdoa_info *vdoa = (struct vdoa_info *)handle;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_GET_OBUF, return -EINVAL);
|
||||||
|
vdoa->state = VDOA_START;
|
||||||
|
init_completion(&vdoa->comp);
|
||||||
|
vdoa_write_register(vdoa, VDOAIST,
|
||||||
|
VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
|
||||||
|
vdoa_write_register(vdoa, VDOAIE,
|
||||||
|
VDOAIEIST_TRANSFER_ERR | VDOAIEIST_TRANSFER_END);
|
||||||
|
|
||||||
|
enable_irq(vdoa->irq);
|
||||||
|
vdoa_write_register(vdoa, VDOASRR, VDOASRR_START_XFER);
|
||||||
|
dump_registers(vdoa);
|
||||||
|
|
||||||
|
ret = wait_for_completion_timeout(&vdoa->comp,
|
||||||
|
msecs_to_jiffies(timeout_ms));
|
||||||
|
|
||||||
|
return ret > 0 ? 0 : -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdoa_stop(vdoa_handle_t handle)
|
||||||
|
{
|
||||||
|
struct vdoa_info *vdoa = (struct vdoa_info *)handle;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_GET | VDOA_START | VDOA_INIRQ, return);
|
||||||
|
vdoa->state = VDOA_STOP;
|
||||||
|
|
||||||
|
disable_irq(vdoa->irq);
|
||||||
|
|
||||||
|
vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdoa_get_handle(vdoa_handle_t *handle)
|
||||||
|
{
|
||||||
|
struct vdoa_info *vdoa = g_vdoa;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(handle);
|
||||||
|
*handle = (vdoa_handle_t *)NULL;
|
||||||
|
CHECK_STATE(VDOA_INIT, return);
|
||||||
|
mutex_lock(&vdoa_lock);
|
||||||
|
clk_prepare_enable(vdoa->vdoa_clk);
|
||||||
|
vdoa->state = VDOA_GET;
|
||||||
|
vdoa->field = VDOA_NULL;
|
||||||
|
vdoa_write_register(vdoa, VDOASRR, VDOASRR_SWRST);
|
||||||
|
|
||||||
|
*handle = (vdoa_handle_t *)vdoa;
|
||||||
|
}
|
||||||
|
|
||||||
|
void vdoa_put_handle(vdoa_handle_t *handle)
|
||||||
|
{
|
||||||
|
struct vdoa_info *vdoa = (struct vdoa_info *)(*handle);
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_STOP, return);
|
||||||
|
if (vdoa != g_vdoa)
|
||||||
|
BUG();
|
||||||
|
|
||||||
|
clk_disable_unprepare(vdoa->vdoa_clk);
|
||||||
|
vdoa->state = VDOA_PUT;
|
||||||
|
*handle = (vdoa_handle_t *)NULL;
|
||||||
|
mutex_unlock(&vdoa_lock);
|
||||||
|
}
|
||||||
|
|
||||||
|
static irqreturn_t vdoa_irq_handler(int irq, void *data)
|
||||||
|
{
|
||||||
|
u32 status, mask, val;
|
||||||
|
struct vdoa_info *vdoa = data;
|
||||||
|
|
||||||
|
CHECK_NULL_PTR(vdoa);
|
||||||
|
CHECK_STATE(VDOA_START, return IRQ_HANDLED);
|
||||||
|
vdoa->state = VDOA_INIRQ;
|
||||||
|
vdoa_read_register(vdoa, VDOAIST, &status);
|
||||||
|
vdoa_read_register(vdoa, VDOAIE, &mask);
|
||||||
|
val = status & mask;
|
||||||
|
vdoa_write_register(vdoa, VDOAIST, val);
|
||||||
|
if (VDOAIEIST_TRANSFER_ERR & val)
|
||||||
|
dev_err(vdoa->dev, "vdoa Transfer err irq!\n");
|
||||||
|
if (VDOAIEIST_TRANSFER_END & val)
|
||||||
|
dev_dbg(vdoa->dev, "vdoa Transfer end irq!\n");
|
||||||
|
if (0 == val) {
|
||||||
|
dev_err(vdoa->dev, "vdoa unknown irq!\n");
|
||||||
|
BUG();
|
||||||
|
}
|
||||||
|
|
||||||
|
complete(&vdoa->comp);
|
||||||
|
return IRQ_HANDLED;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* IRAM Size in Kbytes, example:vdoa_iram_size=64, 64KBytes */
|
||||||
|
static int __init vdoa_iram_size_setup(char *options)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = kstrtoul(options, 0, &iram_size);
|
||||||
|
if (ret)
|
||||||
|
iram_size = 0;
|
||||||
|
else
|
||||||
|
iram_size *= SZ_1K;
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
__setup("vdoa_iram_size=", vdoa_iram_size_setup);
|
||||||
|
|
||||||
|
static const struct of_device_id imx_vdoa_dt_ids[] = {
|
||||||
|
{ .compatible = "fsl,imx6q-vdoa", },
|
||||||
|
{ /* sentinel */ }
|
||||||
|
};
|
||||||
|
|
||||||
|
static int vdoa_probe(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
struct vdoa_info *vdoa;
|
||||||
|
struct resource *res;
|
||||||
|
struct resource *res_irq;
|
||||||
|
struct device *dev = &pdev->dev;
|
||||||
|
struct device_node *np = pdev->dev.of_node;
|
||||||
|
|
||||||
|
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||||
|
if (!res) {
|
||||||
|
dev_err(dev, "can't get device resources\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||||
|
if (!res_irq) {
|
||||||
|
dev_err(dev, "failed to get irq resource\n");
|
||||||
|
return -ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdoa = devm_kzalloc(dev, sizeof(struct vdoa_info), GFP_KERNEL);
|
||||||
|
if (!vdoa)
|
||||||
|
return -ENOMEM;
|
||||||
|
vdoa->dev = dev;
|
||||||
|
|
||||||
|
vdoa->reg_base = devm_ioremap_resource(&pdev->dev, res);
|
||||||
|
if (!vdoa->reg_base)
|
||||||
|
return -EBUSY;
|
||||||
|
|
||||||
|
vdoa->irq = res_irq->start;
|
||||||
|
ret = devm_request_irq(dev, vdoa->irq, vdoa_irq_handler, 0,
|
||||||
|
"vdoa", vdoa);
|
||||||
|
if (ret) {
|
||||||
|
dev_err(dev, "can't claim irq %d\n", vdoa->irq);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
disable_irq(vdoa->irq);
|
||||||
|
|
||||||
|
vdoa->vdoa_clk = devm_clk_get(dev, NULL);
|
||||||
|
if (IS_ERR(vdoa->vdoa_clk)) {
|
||||||
|
dev_err(dev, "failed to get vdoa_clk\n");
|
||||||
|
return PTR_ERR(vdoa->vdoa_clk);
|
||||||
|
}
|
||||||
|
|
||||||
|
vdoa->iram_pool = of_gen_pool_get(np, "iram", 0);
|
||||||
|
if (!vdoa->iram_pool) {
|
||||||
|
dev_err(&pdev->dev, "iram pool not available\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((iram_size == 0) || (iram_size > MAX_VDOA_IRAM_SIZE))
|
||||||
|
iram_size = VDOA_IRAM_SIZE;
|
||||||
|
|
||||||
|
vdoa->iram_base = gen_pool_alloc(vdoa->iram_pool, iram_size);
|
||||||
|
if (!vdoa->iram_base) {
|
||||||
|
dev_err(&pdev->dev, "unable to alloc iram\n");
|
||||||
|
return -ENOMEM;
|
||||||
|
}
|
||||||
|
|
||||||
|
vdoa->iram_paddr = gen_pool_virt_to_phys(vdoa->iram_pool,
|
||||||
|
vdoa->iram_base);
|
||||||
|
|
||||||
|
dev_dbg(dev, "iram_base:0x%lx,iram_paddr:0x%lx,size:0x%lx\n",
|
||||||
|
vdoa->iram_base, vdoa->iram_paddr, iram_size);
|
||||||
|
|
||||||
|
vdoa->state = VDOA_INIT;
|
||||||
|
dev_set_drvdata(dev, vdoa);
|
||||||
|
g_vdoa = vdoa;
|
||||||
|
dev_info(dev, "i.MX Video Data Order Adapter(VDOA) driver probed\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int vdoa_remove(struct platform_device *pdev)
|
||||||
|
{
|
||||||
|
struct vdoa_info *vdoa = dev_get_drvdata(&pdev->dev);
|
||||||
|
|
||||||
|
gen_pool_free(vdoa->iram_pool, vdoa->iram_base, iram_size);
|
||||||
|
kfree(vdoa);
|
||||||
|
dev_set_drvdata(&pdev->dev, NULL);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static struct platform_driver vdoa_driver = {
|
||||||
|
.driver = {
|
||||||
|
.name = "mxc_vdoa",
|
||||||
|
.of_match_table = imx_vdoa_dt_ids,
|
||||||
|
},
|
||||||
|
.probe = vdoa_probe,
|
||||||
|
.remove = vdoa_remove,
|
||||||
|
};
|
||||||
|
|
||||||
|
static int __init vdoa_init(void)
|
||||||
|
{
|
||||||
|
int err;
|
||||||
|
|
||||||
|
err = platform_driver_register(&vdoa_driver);
|
||||||
|
if (err) {
|
||||||
|
pr_err("vdoa_driver register failed\n");
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void __exit vdoa_cleanup(void)
|
||||||
|
{
|
||||||
|
platform_driver_unregister(&vdoa_driver);
|
||||||
|
}
|
||||||
|
|
||||||
|
subsys_initcall(vdoa_init);
|
||||||
|
module_exit(vdoa_cleanup);
|
||||||
|
|
||||||
|
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
|
||||||
|
MODULE_DESCRIPTION("i.MX Video Data Order Adapter(VDOA) driver");
|
||||||
|
MODULE_LICENSE("GPL");
|
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2012-2015 Freescale Semiconductor, Inc. All Rights Reserved.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __VDOA_H__
|
||||||
|
#define __VDOA_H__
|
||||||
|
|
||||||
|
#define VDOA_PFS_YUYV (1)
|
||||||
|
#define VDOA_PFS_NV12 (0)
|
||||||
|
|
||||||
|
|
||||||
|
struct vfield_buf {
|
||||||
|
u32 prev_veba;
|
||||||
|
u32 cur_veba;
|
||||||
|
u32 next_veba;
|
||||||
|
u32 vubo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vframe_buf {
|
||||||
|
u32 veba;
|
||||||
|
u32 vubo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vdoa_params {
|
||||||
|
u32 width;
|
||||||
|
u32 height;
|
||||||
|
int vpu_stride;
|
||||||
|
int interlaced;
|
||||||
|
int scan_order;
|
||||||
|
int ipu_num;
|
||||||
|
int band_lines;
|
||||||
|
int band_mode;
|
||||||
|
int pfs;
|
||||||
|
u32 ieba0;
|
||||||
|
u32 ieba1;
|
||||||
|
u32 ieba2;
|
||||||
|
struct vframe_buf vframe_buf;
|
||||||
|
struct vfield_buf vfield_buf;
|
||||||
|
};
|
||||||
|
struct vdoa_ipu_buf {
|
||||||
|
u32 ieba0;
|
||||||
|
u32 ieba1;
|
||||||
|
u32 iubo;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct vdoa_info;
|
||||||
|
typedef void *vdoa_handle_t;
|
||||||
|
|
||||||
|
int vdoa_setup(vdoa_handle_t handle, struct vdoa_params *params);
|
||||||
|
void vdoa_get_output_buf(vdoa_handle_t handle, struct vdoa_ipu_buf *buf);
|
||||||
|
int vdoa_start(vdoa_handle_t handle, int timeout_ms);
|
||||||
|
void vdoa_stop(vdoa_handle_t handle);
|
||||||
|
void vdoa_get_handle(vdoa_handle_t *handle);
|
||||||
|
void vdoa_put_handle(vdoa_handle_t *handle);
|
||||||
|
#endif
|
|
@ -0,0 +1,155 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#ifndef __LINUX_IPU_V3_PRE_H_
|
||||||
|
#define __LINUX_IPU_V3_PRE_H_
|
||||||
|
|
||||||
|
#define IPU_PRE_MAX_WIDTH 1920
|
||||||
|
#define IPU_PRE_MAX_BPP 4
|
||||||
|
#define IPU_PRE_SMALL_LINE 9 /* to workaround errata ERR009624*/
|
||||||
|
|
||||||
|
struct ipu_rect {
|
||||||
|
int left;
|
||||||
|
int top;
|
||||||
|
int width;
|
||||||
|
int height;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct ipu_pre_context {
|
||||||
|
bool repeat;
|
||||||
|
bool vflip;
|
||||||
|
bool handshake_en;
|
||||||
|
bool hsk_abort_en;
|
||||||
|
unsigned int hsk_line_num;
|
||||||
|
bool sdw_update;
|
||||||
|
unsigned int block_size;
|
||||||
|
unsigned int interlaced;
|
||||||
|
unsigned int prefetch_mode;
|
||||||
|
|
||||||
|
unsigned long cur_buf;
|
||||||
|
unsigned long next_buf;
|
||||||
|
|
||||||
|
unsigned int tile_fmt;
|
||||||
|
|
||||||
|
unsigned int read_burst;
|
||||||
|
unsigned int prefetch_input_bpp;
|
||||||
|
unsigned int prefetch_input_pixel_fmt;
|
||||||
|
unsigned int prefetch_shift_offset;
|
||||||
|
unsigned int prefetch_shift_width;
|
||||||
|
bool shift_bypass;
|
||||||
|
bool field_inverse;
|
||||||
|
bool tpr_coor_offset_en;
|
||||||
|
/* the output of prefetch is
|
||||||
|
* also the input of store
|
||||||
|
*/
|
||||||
|
struct ipu_rect prefetch_output_size;
|
||||||
|
unsigned int prefetch_input_active_width;
|
||||||
|
unsigned int prefetch_input_width;
|
||||||
|
unsigned int prefetch_input_height;
|
||||||
|
unsigned int store_pitch;
|
||||||
|
int interlace_offset;
|
||||||
|
|
||||||
|
bool store_en;
|
||||||
|
unsigned int write_burst;
|
||||||
|
unsigned int store_output_bpp;
|
||||||
|
|
||||||
|
unsigned int sec_buf_off;
|
||||||
|
unsigned int trd_buf_off;
|
||||||
|
|
||||||
|
/* return for IPU fb caller */
|
||||||
|
unsigned long store_addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* In order to workaround the PRE SoC bug recorded by errata ERR009624,
|
||||||
|
* the software cannot write the PRE_CTRL register when the PRE writes
|
||||||
|
* the PRE_CTRL register automatically to set the ENABLE bit(bit0) to 1
|
||||||
|
* in the PRE repeat mode.
|
||||||
|
* The software mechanism to set the PRE_CTRL register is different for
|
||||||
|
* PRE Y resolution higher than 9 lines and lower or equal to 9 lines.
|
||||||
|
* Use this helper to check the Y resolution.
|
||||||
|
*/
|
||||||
|
static inline bool ipu_pre_yres_is_small(unsigned int yres)
|
||||||
|
{
|
||||||
|
return yres <= IPU_PRE_SMALL_LINE;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef CONFIG_MXC_IPU_V3_PRE
|
||||||
|
int ipu_pre_alloc(int ipu_id, ipu_channel_t ipu_ch);
|
||||||
|
void ipu_pre_free(unsigned int *id);
|
||||||
|
unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size);
|
||||||
|
void ipu_pre_free_double_buffer(unsigned int id);
|
||||||
|
int ipu_pre_config(int id, struct ipu_pre_context *config);
|
||||||
|
int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config);
|
||||||
|
int ipu_pre_enable(int id);
|
||||||
|
void ipu_pre_disable(int id);
|
||||||
|
int ipu_pre_set_fb_buffer(int id, bool resolve,
|
||||||
|
unsigned long fb_paddr,
|
||||||
|
unsigned int y_res,
|
||||||
|
unsigned int x_crop,
|
||||||
|
unsigned int y_crop,
|
||||||
|
unsigned int sec_buf_off,
|
||||||
|
unsigned int trd_buf_off);
|
||||||
|
int ipu_pre_sdw_update(int id);
|
||||||
|
#else
|
||||||
|
int ipu_pre_alloc(int ipu_id, ipu_channel_t channel)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipu_pre_free(unsigned int *id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long ipu_pre_alloc_double_buffer(unsigned int id, unsigned int size)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipu_pre_free_double_buffer(unsigned int id)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_pre_config(int id, struct ipu_pre_context *config)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_pre_set_ctrl(unsigned int id, struct ipu_pre_context *config)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_pre_enable(int id)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ipu_pre_disable(int id)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_pre_set_fb_buffer(int id, bool resolve,
|
||||||
|
unsigned long fb_paddr,
|
||||||
|
unsigned int y_res,
|
||||||
|
unsigned int x_crop,
|
||||||
|
unsigned int y_crop,
|
||||||
|
unsigned int sec_buf_off,
|
||||||
|
unsigned int trd_buf_off)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
int ipu_pre_sdw_update(int id)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __LINUX_IPU_V3_PRE_H_ */
|
|
@ -0,0 +1,61 @@
|
||||||
|
/*
|
||||||
|
* Copyright (C) 2014-2015 Freescale Semiconductor, Inc.
|
||||||
|
*
|
||||||
|
* The code contained herein is licensed under the GNU General Public
|
||||||
|
* License. You may obtain a copy of the GNU General Public License
|
||||||
|
* Version 2 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/gpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/gpl.html
|
||||||
|
*/
|
||||||
|
#ifndef __LINUX_IPU_V3_PRG_H_
|
||||||
|
#define __LINUX_IPU_V3_PRG_H_
|
||||||
|
|
||||||
|
#include <linux/ipu-v3.h>
|
||||||
|
|
||||||
|
#define PRG_SO_INTERLACE 1
|
||||||
|
#define PRG_SO_PROGRESSIVE 0
|
||||||
|
#define PRG_BLOCK_MODE 1
|
||||||
|
#define PRG_SCAN_MODE 0
|
||||||
|
|
||||||
|
struct ipu_prg_config {
|
||||||
|
unsigned int id;
|
||||||
|
unsigned int pre_num;
|
||||||
|
ipu_channel_t ipu_ch;
|
||||||
|
unsigned int stride;
|
||||||
|
unsigned int height;
|
||||||
|
unsigned int ipu_height;
|
||||||
|
unsigned int crop_line;
|
||||||
|
unsigned int so;
|
||||||
|
unsigned int ilo;
|
||||||
|
unsigned int block_mode;
|
||||||
|
bool vflip;
|
||||||
|
u32 baddr;
|
||||||
|
u32 offset;
|
||||||
|
};
|
||||||
|
|
||||||
|
#ifdef CONFIG_MXC_IPU_V3_PRG
|
||||||
|
int ipu_prg_config(struct ipu_prg_config *config);
|
||||||
|
int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num);
|
||||||
|
int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
|
||||||
|
unsigned int hsk_line_num,
|
||||||
|
int pre_store_out_height);
|
||||||
|
#else
|
||||||
|
int ipu_prg_config(struct ipu_prg_config *config)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_prg_disable(unsigned int ipu_id, unsigned int pre_num)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_prg_wait_buf_ready(unsigned int ipu_id, unsigned int pre_num,
|
||||||
|
unsigned int hsk_line_num,
|
||||||
|
int pre_store_out_height)
|
||||||
|
{
|
||||||
|
return -ENODEV;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
#endif /* __LINUX_IPU_V3_PRG_H_ */
|
|
@ -0,0 +1,770 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2010 Sascha Hauer <s.hauer@pengutronix.de>
|
||||||
|
* Copyright (C) 2011-2015 Freescale Semiconductor, Inc.
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms of the GNU General Public License as published by the
|
||||||
|
* Free Software Foundation; either version 2 of the License, or (at your
|
||||||
|
* option) any later version.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope that it will be useful, but
|
||||||
|
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
|
||||||
|
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
||||||
|
* for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LINUX_IPU_V3_H_
|
||||||
|
#define __LINUX_IPU_V3_H_
|
||||||
|
|
||||||
|
#include <linux/ipu.h>
|
||||||
|
|
||||||
|
/* IPU Driver channels definitions. */
|
||||||
|
/* Note these are different from IDMA channels */
|
||||||
|
#define IPU_MAX_CH 32
|
||||||
|
#define _MAKE_CHAN(num, v_in, g_in, a_in, out) \
|
||||||
|
((num << 24) | (v_in << 18) | (g_in << 12) | (a_in << 6) | out)
|
||||||
|
#define _MAKE_ALT_CHAN(ch) (ch | (IPU_MAX_CH << 24))
|
||||||
|
#define IPU_CHAN_ID(ch) (ch >> 24)
|
||||||
|
#define IPU_CHAN_ALT(ch) (ch & 0x02000000)
|
||||||
|
#define IPU_CHAN_ALPHA_IN_DMA(ch) ((uint32_t) (ch >> 6) & 0x3F)
|
||||||
|
#define IPU_CHAN_GRAPH_IN_DMA(ch) ((uint32_t) (ch >> 12) & 0x3F)
|
||||||
|
#define IPU_CHAN_VIDEO_IN_DMA(ch) ((uint32_t) (ch >> 18) & 0x3F)
|
||||||
|
#define IPU_CHAN_OUT_DMA(ch) ((uint32_t) (ch & 0x3F))
|
||||||
|
#define NO_DMA 0x3F
|
||||||
|
#define ALT 1
|
||||||
|
/*!
|
||||||
|
* Enumeration of IPU logical channels. An IPU logical channel is defined as a
|
||||||
|
* combination of an input (memory to IPU), output (IPU to memory), and/or
|
||||||
|
* secondary input IDMA channels and in some cases an Image Converter task.
|
||||||
|
* Some channels consist of only an input or output.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
CHAN_NONE = -1,
|
||||||
|
MEM_ROT_ENC_MEM = _MAKE_CHAN(1, 45, NO_DMA, NO_DMA, 48),
|
||||||
|
MEM_ROT_VF_MEM = _MAKE_CHAN(2, 46, NO_DMA, NO_DMA, 49),
|
||||||
|
MEM_ROT_PP_MEM = _MAKE_CHAN(3, 47, NO_DMA, NO_DMA, 50),
|
||||||
|
|
||||||
|
MEM_PRP_ENC_MEM = _MAKE_CHAN(4, 12, 14, 17, 20),
|
||||||
|
MEM_PRP_VF_MEM = _MAKE_CHAN(5, 12, 14, 17, 21),
|
||||||
|
MEM_PP_MEM = _MAKE_CHAN(6, 11, 15, 18, 22),
|
||||||
|
|
||||||
|
MEM_DC_SYNC = _MAKE_CHAN(7, 28, NO_DMA, NO_DMA, NO_DMA),
|
||||||
|
MEM_DC_ASYNC = _MAKE_CHAN(8, 41, NO_DMA, NO_DMA, NO_DMA),
|
||||||
|
MEM_BG_SYNC = _MAKE_CHAN(9, 23, NO_DMA, 51, NO_DMA),
|
||||||
|
MEM_FG_SYNC = _MAKE_CHAN(10, 27, NO_DMA, 31, NO_DMA),
|
||||||
|
|
||||||
|
MEM_BG_ASYNC0 = _MAKE_CHAN(11, 24, NO_DMA, 52, NO_DMA),
|
||||||
|
MEM_FG_ASYNC0 = _MAKE_CHAN(12, 29, NO_DMA, 33, NO_DMA),
|
||||||
|
MEM_BG_ASYNC1 = _MAKE_ALT_CHAN(MEM_BG_ASYNC0),
|
||||||
|
MEM_FG_ASYNC1 = _MAKE_ALT_CHAN(MEM_FG_ASYNC0),
|
||||||
|
|
||||||
|
DIRECT_ASYNC0 = _MAKE_CHAN(13, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
|
||||||
|
DIRECT_ASYNC1 = _MAKE_CHAN(14, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
|
||||||
|
|
||||||
|
CSI_MEM0 = _MAKE_CHAN(15, NO_DMA, NO_DMA, NO_DMA, 0),
|
||||||
|
CSI_MEM1 = _MAKE_CHAN(16, NO_DMA, NO_DMA, NO_DMA, 1),
|
||||||
|
CSI_MEM2 = _MAKE_CHAN(17, NO_DMA, NO_DMA, NO_DMA, 2),
|
||||||
|
CSI_MEM3 = _MAKE_CHAN(18, NO_DMA, NO_DMA, NO_DMA, 3),
|
||||||
|
|
||||||
|
CSI_MEM = CSI_MEM0,
|
||||||
|
|
||||||
|
CSI_PRP_ENC_MEM = _MAKE_CHAN(19, NO_DMA, NO_DMA, NO_DMA, 20),
|
||||||
|
CSI_PRP_VF_MEM = _MAKE_CHAN(20, NO_DMA, NO_DMA, NO_DMA, 21),
|
||||||
|
|
||||||
|
/* for vdi mem->vdi->ic->mem , add graphics plane and alpha*/
|
||||||
|
MEM_VDI_PRP_VF_MEM_P = _MAKE_CHAN(21, 8, 14, 17, 21),
|
||||||
|
MEM_VDI_PRP_VF_MEM = _MAKE_CHAN(22, 9, 14, 17, 21),
|
||||||
|
MEM_VDI_PRP_VF_MEM_N = _MAKE_CHAN(23, 10, 14, 17, 21),
|
||||||
|
|
||||||
|
/* for vdi mem->vdi->mem */
|
||||||
|
MEM_VDI_MEM_P = _MAKE_CHAN(24, 8, NO_DMA, NO_DMA, 5),
|
||||||
|
MEM_VDI_MEM = _MAKE_CHAN(25, 9, NO_DMA, NO_DMA, 5),
|
||||||
|
MEM_VDI_MEM_N = _MAKE_CHAN(26, 10, NO_DMA, NO_DMA, 5),
|
||||||
|
|
||||||
|
/* fake channel for vdoa to link with IPU */
|
||||||
|
MEM_VDOA_MEM = _MAKE_CHAN(27, NO_DMA, NO_DMA, NO_DMA, NO_DMA),
|
||||||
|
|
||||||
|
MEM_PP_ADC = CHAN_NONE,
|
||||||
|
ADC_SYS2 = CHAN_NONE,
|
||||||
|
|
||||||
|
} ipu_channel_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of types of buffers for a logical channel.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
IPU_OUTPUT_BUFFER = 0, /*!< Buffer for output from IPU */
|
||||||
|
IPU_ALPHA_IN_BUFFER = 1, /*!< Buffer for input to IPU */
|
||||||
|
IPU_GRAPH_IN_BUFFER = 2, /*!< Buffer for input to IPU */
|
||||||
|
IPU_VIDEO_IN_BUFFER = 3, /*!< Buffer for input to IPU */
|
||||||
|
IPU_INPUT_BUFFER = IPU_VIDEO_IN_BUFFER,
|
||||||
|
IPU_SEC_INPUT_BUFFER = IPU_GRAPH_IN_BUFFER,
|
||||||
|
} ipu_buffer_t;
|
||||||
|
|
||||||
|
#define IPU_PANEL_SERIAL 1
|
||||||
|
#define IPU_PANEL_PARALLEL 2
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC channel operation mode.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
Disable,
|
||||||
|
WriteTemplateNonSeq,
|
||||||
|
ReadTemplateNonSeq,
|
||||||
|
WriteTemplateUnCon,
|
||||||
|
ReadTemplateUnCon,
|
||||||
|
WriteDataWithRS,
|
||||||
|
WriteDataWoRS,
|
||||||
|
WriteCmd
|
||||||
|
} mcu_mode_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC channel addressing mode.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
FullWoBE,
|
||||||
|
FullWithBE,
|
||||||
|
XY
|
||||||
|
} display_addressing_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Union of initialization parameters for a logical channel.
|
||||||
|
*/
|
||||||
|
typedef union {
|
||||||
|
struct {
|
||||||
|
uint32_t csi;
|
||||||
|
uint32_t mipi_id;
|
||||||
|
uint32_t mipi_vc;
|
||||||
|
bool mipi_en;
|
||||||
|
bool interlaced;
|
||||||
|
} csi_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
uint32_t outh_resize_ratio;
|
||||||
|
uint32_t outv_resize_ratio;
|
||||||
|
uint32_t csi;
|
||||||
|
uint32_t mipi_id;
|
||||||
|
uint32_t mipi_vc;
|
||||||
|
bool mipi_en;
|
||||||
|
} csi_prp_enc_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
uint32_t outh_resize_ratio;
|
||||||
|
uint32_t outv_resize_ratio;
|
||||||
|
} mem_prp_enc_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
} mem_rot_enc_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
uint32_t outh_resize_ratio;
|
||||||
|
uint32_t outv_resize_ratio;
|
||||||
|
bool graphics_combine_en;
|
||||||
|
bool global_alpha_en;
|
||||||
|
bool key_color_en;
|
||||||
|
uint32_t in_g_pixel_fmt;
|
||||||
|
uint8_t alpha;
|
||||||
|
uint32_t key_color;
|
||||||
|
bool alpha_chan_en;
|
||||||
|
ipu_motion_sel motion_sel;
|
||||||
|
enum v4l2_field field_fmt;
|
||||||
|
uint32_t csi;
|
||||||
|
uint32_t mipi_id;
|
||||||
|
uint32_t mipi_vc;
|
||||||
|
bool mipi_en;
|
||||||
|
} csi_prp_vf_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
bool graphics_combine_en;
|
||||||
|
bool global_alpha_en;
|
||||||
|
bool key_color_en;
|
||||||
|
display_port_t disp;
|
||||||
|
uint32_t out_left;
|
||||||
|
uint32_t out_top;
|
||||||
|
} csi_prp_vf_adc;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
uint32_t outh_resize_ratio;
|
||||||
|
uint32_t outv_resize_ratio;
|
||||||
|
bool graphics_combine_en;
|
||||||
|
bool global_alpha_en;
|
||||||
|
bool key_color_en;
|
||||||
|
uint32_t in_g_pixel_fmt;
|
||||||
|
uint8_t alpha;
|
||||||
|
uint32_t key_color;
|
||||||
|
bool alpha_chan_en;
|
||||||
|
ipu_motion_sel motion_sel;
|
||||||
|
enum v4l2_field field_fmt;
|
||||||
|
} mem_prp_vf_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t temp;
|
||||||
|
} mem_prp_vf_adc;
|
||||||
|
struct {
|
||||||
|
uint32_t temp;
|
||||||
|
} mem_rot_vf_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
uint32_t outh_resize_ratio;
|
||||||
|
uint32_t outv_resize_ratio;
|
||||||
|
bool graphics_combine_en;
|
||||||
|
bool global_alpha_en;
|
||||||
|
bool key_color_en;
|
||||||
|
uint32_t in_g_pixel_fmt;
|
||||||
|
uint8_t alpha;
|
||||||
|
uint32_t key_color;
|
||||||
|
bool alpha_chan_en;
|
||||||
|
} mem_pp_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t temp;
|
||||||
|
} mem_rot_mem;
|
||||||
|
struct {
|
||||||
|
uint32_t in_width;
|
||||||
|
uint32_t in_height;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_width;
|
||||||
|
uint32_t out_height;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
bool graphics_combine_en;
|
||||||
|
bool global_alpha_en;
|
||||||
|
bool key_color_en;
|
||||||
|
display_port_t disp;
|
||||||
|
uint32_t out_left;
|
||||||
|
uint32_t out_top;
|
||||||
|
} mem_pp_adc;
|
||||||
|
struct {
|
||||||
|
uint32_t di;
|
||||||
|
bool interlaced;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
} mem_dc_sync;
|
||||||
|
struct {
|
||||||
|
uint32_t temp;
|
||||||
|
} mem_sdc_fg;
|
||||||
|
struct {
|
||||||
|
uint32_t di;
|
||||||
|
bool interlaced;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
bool alpha_chan_en;
|
||||||
|
} mem_dp_bg_sync;
|
||||||
|
struct {
|
||||||
|
uint32_t temp;
|
||||||
|
} mem_sdc_bg;
|
||||||
|
struct {
|
||||||
|
uint32_t di;
|
||||||
|
bool interlaced;
|
||||||
|
uint32_t in_pixel_fmt;
|
||||||
|
uint32_t out_pixel_fmt;
|
||||||
|
bool alpha_chan_en;
|
||||||
|
} mem_dp_fg_sync;
|
||||||
|
struct {
|
||||||
|
uint32_t di;
|
||||||
|
} direct_async;
|
||||||
|
struct {
|
||||||
|
display_port_t disp;
|
||||||
|
mcu_mode_t ch_mode;
|
||||||
|
uint32_t out_left;
|
||||||
|
uint32_t out_top;
|
||||||
|
} adc_sys1;
|
||||||
|
struct {
|
||||||
|
display_port_t disp;
|
||||||
|
mcu_mode_t ch_mode;
|
||||||
|
uint32_t out_left;
|
||||||
|
uint32_t out_top;
|
||||||
|
} adc_sys2;
|
||||||
|
} ipu_channel_params_t;
|
||||||
|
|
||||||
|
/*
|
||||||
|
* IPU_IRQF_ONESHOT - Interrupt is not reenabled after the irq handler finished.
|
||||||
|
*/
|
||||||
|
#define IPU_IRQF_NONE 0x00000000
|
||||||
|
#define IPU_IRQF_ONESHOT 0x00000001
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of IPU interrupt sources.
|
||||||
|
*/
|
||||||
|
enum ipu_irq_line {
|
||||||
|
IPU_IRQ_CSI0_OUT_EOF = 0,
|
||||||
|
IPU_IRQ_CSI1_OUT_EOF = 1,
|
||||||
|
IPU_IRQ_CSI2_OUT_EOF = 2,
|
||||||
|
IPU_IRQ_CSI3_OUT_EOF = 3,
|
||||||
|
IPU_IRQ_VDIC_OUT_EOF = 5,
|
||||||
|
IPU_IRQ_VDI_P_IN_EOF = 8,
|
||||||
|
IPU_IRQ_VDI_C_IN_EOF = 9,
|
||||||
|
IPU_IRQ_VDI_N_IN_EOF = 10,
|
||||||
|
IPU_IRQ_PP_IN_EOF = 11,
|
||||||
|
IPU_IRQ_PRP_IN_EOF = 12,
|
||||||
|
IPU_IRQ_PRP_GRAPH_IN_EOF = 14,
|
||||||
|
IPU_IRQ_PP_GRAPH_IN_EOF = 15,
|
||||||
|
IPU_IRQ_PRP_ALPHA_IN_EOF = 17,
|
||||||
|
IPU_IRQ_PP_ALPHA_IN_EOF = 18,
|
||||||
|
IPU_IRQ_PRP_ENC_OUT_EOF = 20,
|
||||||
|
IPU_IRQ_PRP_VF_OUT_EOF = 21,
|
||||||
|
IPU_IRQ_PP_OUT_EOF = 22,
|
||||||
|
IPU_IRQ_BG_SYNC_EOF = 23,
|
||||||
|
IPU_IRQ_BG_ASYNC_EOF = 24,
|
||||||
|
IPU_IRQ_FG_SYNC_EOF = 27,
|
||||||
|
IPU_IRQ_DC_SYNC_EOF = 28,
|
||||||
|
IPU_IRQ_FG_ASYNC_EOF = 29,
|
||||||
|
IPU_IRQ_FG_ALPHA_SYNC_EOF = 31,
|
||||||
|
|
||||||
|
IPU_IRQ_FG_ALPHA_ASYNC_EOF = 33,
|
||||||
|
IPU_IRQ_DC_READ_EOF = 40,
|
||||||
|
IPU_IRQ_DC_ASYNC_EOF = 41,
|
||||||
|
IPU_IRQ_DC_CMD1_EOF = 42,
|
||||||
|
IPU_IRQ_DC_CMD2_EOF = 43,
|
||||||
|
IPU_IRQ_DC_MASK_EOF = 44,
|
||||||
|
IPU_IRQ_PRP_ENC_ROT_IN_EOF = 45,
|
||||||
|
IPU_IRQ_PRP_VF_ROT_IN_EOF = 46,
|
||||||
|
IPU_IRQ_PP_ROT_IN_EOF = 47,
|
||||||
|
IPU_IRQ_PRP_ENC_ROT_OUT_EOF = 48,
|
||||||
|
IPU_IRQ_PRP_VF_ROT_OUT_EOF = 49,
|
||||||
|
IPU_IRQ_PP_ROT_OUT_EOF = 50,
|
||||||
|
IPU_IRQ_BG_ALPHA_SYNC_EOF = 51,
|
||||||
|
IPU_IRQ_BG_ALPHA_ASYNC_EOF = 52,
|
||||||
|
|
||||||
|
IPU_IRQ_BG_SYNC_NFACK = 64 + 23,
|
||||||
|
IPU_IRQ_FG_SYNC_NFACK = 64 + 27,
|
||||||
|
IPU_IRQ_DC_SYNC_NFACK = 64 + 28,
|
||||||
|
|
||||||
|
IPU_IRQ_DP_SF_START = 448 + 2,
|
||||||
|
IPU_IRQ_DP_SF_END = 448 + 3,
|
||||||
|
IPU_IRQ_BG_SF_END = IPU_IRQ_DP_SF_END,
|
||||||
|
IPU_IRQ_DC_FC_0 = 448 + 8,
|
||||||
|
IPU_IRQ_DC_FC_1 = 448 + 9,
|
||||||
|
IPU_IRQ_DC_FC_2 = 448 + 10,
|
||||||
|
IPU_IRQ_DC_FC_3 = 448 + 11,
|
||||||
|
IPU_IRQ_DC_FC_4 = 448 + 12,
|
||||||
|
IPU_IRQ_DC_FC_6 = 448 + 13,
|
||||||
|
IPU_IRQ_VSYNC_PRE_0 = 448 + 14,
|
||||||
|
IPU_IRQ_VSYNC_PRE_1 = 448 + 15,
|
||||||
|
|
||||||
|
IPU_IRQ_COUNT
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Bitfield of Display Interface signal polarities.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned datamask_en:1;
|
||||||
|
unsigned int_clk:1;
|
||||||
|
unsigned interlaced:1;
|
||||||
|
unsigned odd_field_first:1;
|
||||||
|
unsigned clksel_en:1;
|
||||||
|
unsigned clkidle_en:1;
|
||||||
|
unsigned data_pol:1; /* true = inverted */
|
||||||
|
unsigned clk_pol:1; /* true = rising edge */
|
||||||
|
unsigned enable_pol:1;
|
||||||
|
unsigned Hsync_pol:1; /* true = active high */
|
||||||
|
unsigned Vsync_pol:1;
|
||||||
|
} ipu_di_signal_cfg_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Bitfield of CSI signal polarities and modes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
unsigned data_width:4;
|
||||||
|
unsigned clk_mode:3;
|
||||||
|
unsigned ext_vsync:1;
|
||||||
|
unsigned Vsync_pol:1;
|
||||||
|
unsigned Hsync_pol:1;
|
||||||
|
unsigned pixclk_pol:1;
|
||||||
|
unsigned data_pol:1;
|
||||||
|
unsigned sens_clksrc:1;
|
||||||
|
unsigned pack_tight:1;
|
||||||
|
unsigned force_eof:1;
|
||||||
|
unsigned data_en_pol:1;
|
||||||
|
unsigned data_fmt;
|
||||||
|
unsigned csi;
|
||||||
|
unsigned mclk;
|
||||||
|
} ipu_csi_signal_cfg_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of CSI data bus widths.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IPU_CSI_DATA_WIDTH_4 = 0,
|
||||||
|
IPU_CSI_DATA_WIDTH_8 = 1,
|
||||||
|
IPU_CSI_DATA_WIDTH_10 = 3,
|
||||||
|
IPU_CSI_DATA_WIDTH_16 = 9,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of CSI clock modes.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IPU_CSI_CLK_MODE_GATED_CLK,
|
||||||
|
IPU_CSI_CLK_MODE_NONGATED_CLK,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR656_PROGRESSIVE,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR656_INTERLACED,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_DDR,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_PROGRESSIVE_SDR,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_DDR,
|
||||||
|
IPU_CSI_CLK_MODE_CCIR1120_INTERLACED_SDR,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IPU_CSI_MIPI_DI0,
|
||||||
|
IPU_CSI_MIPI_DI1,
|
||||||
|
IPU_CSI_MIPI_DI2,
|
||||||
|
IPU_CSI_MIPI_DI3,
|
||||||
|
};
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
RGB,
|
||||||
|
YCbCr,
|
||||||
|
YUV
|
||||||
|
} ipu_color_space_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC vertical sync mode.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
VsyncNone,
|
||||||
|
VsyncInternal,
|
||||||
|
VsyncCSI,
|
||||||
|
VsyncExternal
|
||||||
|
} vsync_t;
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
DAT,
|
||||||
|
CMD
|
||||||
|
} cmddata_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC display update mode.
|
||||||
|
*/
|
||||||
|
typedef enum {
|
||||||
|
IPU_ADC_REFRESH_NONE,
|
||||||
|
IPU_ADC_AUTO_REFRESH,
|
||||||
|
IPU_ADC_AUTO_REFRESH_SNOOP,
|
||||||
|
IPU_ADC_SNOOPING,
|
||||||
|
} ipu_adc_update_mode_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC display interface types (serial or parallel).
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IPU_ADC_IFC_MODE_SYS80_TYPE1,
|
||||||
|
IPU_ADC_IFC_MODE_SYS80_TYPE2,
|
||||||
|
IPU_ADC_IFC_MODE_SYS68K_TYPE1,
|
||||||
|
IPU_ADC_IFC_MODE_SYS68K_TYPE2,
|
||||||
|
IPU_ADC_IFC_MODE_3WIRE_SERIAL,
|
||||||
|
IPU_ADC_IFC_MODE_4WIRE_SERIAL,
|
||||||
|
IPU_ADC_IFC_MODE_5WIRE_SERIAL_CLK,
|
||||||
|
IPU_ADC_IFC_MODE_5WIRE_SERIAL_CS,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
IPU_ADC_IFC_WIDTH_8,
|
||||||
|
IPU_ADC_IFC_WIDTH_16,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC display interface burst mode.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IPU_ADC_BURST_WCS,
|
||||||
|
IPU_ADC_BURST_WBLCK,
|
||||||
|
IPU_ADC_BURST_NONE,
|
||||||
|
IPU_ADC_BURST_SERIAL,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC display interface RW signal timing modes.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
IPU_ADC_SER_NO_RW,
|
||||||
|
IPU_ADC_SER_RW_BEFORE_RS,
|
||||||
|
IPU_ADC_SER_RW_AFTER_RS,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Bitfield of ADC signal polarities and modes.
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
unsigned data_pol:1;
|
||||||
|
unsigned clk_pol:1;
|
||||||
|
unsigned cs_pol:1;
|
||||||
|
unsigned rs_pol:1;
|
||||||
|
unsigned addr_pol:1;
|
||||||
|
unsigned read_pol:1;
|
||||||
|
unsigned write_pol:1;
|
||||||
|
unsigned Vsync_pol:1;
|
||||||
|
unsigned burst_pol:1;
|
||||||
|
unsigned burst_mode:2;
|
||||||
|
unsigned ifc_mode:3;
|
||||||
|
unsigned ifc_width:5;
|
||||||
|
unsigned ser_preamble_len:4;
|
||||||
|
unsigned ser_preamble:8;
|
||||||
|
unsigned ser_rw_mode:2;
|
||||||
|
} ipu_adc_sig_cfg_t;
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC template commands.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
RD_DATA,
|
||||||
|
RD_ACK,
|
||||||
|
RD_WAIT,
|
||||||
|
WR_XADDR,
|
||||||
|
WR_YADDR,
|
||||||
|
WR_ADDR,
|
||||||
|
WR_CMND,
|
||||||
|
WR_DATA,
|
||||||
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Enumeration of ADC template command flow control.
|
||||||
|
*/
|
||||||
|
enum {
|
||||||
|
SINGLE_STEP,
|
||||||
|
PAUSE,
|
||||||
|
STOP,
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/*Define template constants*/
|
||||||
|
#define ATM_ADDR_RANGE 0x20 /*offset address of DISP */
|
||||||
|
#define TEMPLATE_BUF_SIZE 0x20 /*size of template */
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* Define to create ADC template command entry.
|
||||||
|
*/
|
||||||
|
#define ipu_adc_template_gen(oc, rs, fc, dat) (((rs) << 29) | ((fc) << 27) | \
|
||||||
|
((oc) << 24) | (dat))
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
u32 reg;
|
||||||
|
u32 value;
|
||||||
|
} ipu_lpmc_reg_t;
|
||||||
|
|
||||||
|
#define IPU_LPMC_REG_READ 0x80000000L
|
||||||
|
|
||||||
|
#define CSI_MCLK_VF 1
|
||||||
|
#define CSI_MCLK_ENC 2
|
||||||
|
#define CSI_MCLK_RAW 4
|
||||||
|
#define CSI_MCLK_I2C 8
|
||||||
|
|
||||||
|
struct ipu_soc;
|
||||||
|
/* Common IPU API */
|
||||||
|
struct ipu_soc *ipu_get_soc(int id);
|
||||||
|
int32_t ipu_init_channel(struct ipu_soc *ipu, ipu_channel_t channel, ipu_channel_params_t *params);
|
||||||
|
void ipu_uninit_channel(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
void ipu_disable_hsp_clk(struct ipu_soc *ipu);
|
||||||
|
|
||||||
|
static inline bool ipu_can_rotate_in_place(ipu_rotate_mode_t rot)
|
||||||
|
{
|
||||||
|
#ifdef CONFIG_MXC_IPU_V3D
|
||||||
|
return (rot < IPU_ROTATE_HORIZ_FLIP);
|
||||||
|
#else
|
||||||
|
return (rot < IPU_ROTATE_90_RIGHT);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t ipu_init_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
|
||||||
|
uint32_t pixel_fmt,
|
||||||
|
uint16_t width, uint16_t height,
|
||||||
|
uint32_t stride,
|
||||||
|
ipu_rotate_mode_t rot_mode,
|
||||||
|
dma_addr_t phyaddr_0, dma_addr_t phyaddr_1,
|
||||||
|
dma_addr_t phyaddr_2,
|
||||||
|
uint32_t u_offset, uint32_t v_offset);
|
||||||
|
|
||||||
|
int32_t ipu_update_channel_buffer(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
|
||||||
|
uint32_t bufNum, dma_addr_t phyaddr);
|
||||||
|
|
||||||
|
int32_t ipu_update_channel_offset(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
|
||||||
|
uint32_t pixel_fmt,
|
||||||
|
uint16_t width, uint16_t height,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t u, uint32_t v,
|
||||||
|
uint32_t vertical_offset, uint32_t horizontal_offset);
|
||||||
|
|
||||||
|
int32_t ipu_get_channel_offset(uint32_t pixel_fmt,
|
||||||
|
uint16_t width, uint16_t height,
|
||||||
|
uint32_t stride,
|
||||||
|
uint32_t u, uint32_t v,
|
||||||
|
uint32_t vertical_offset, uint32_t horizontal_offset,
|
||||||
|
uint32_t *u_offset, uint32_t *v_offset);
|
||||||
|
|
||||||
|
int32_t ipu_select_buffer(struct ipu_soc *ipu, ipu_channel_t channel,
|
||||||
|
ipu_buffer_t type, uint32_t bufNum);
|
||||||
|
int32_t ipu_select_multi_vdi_buffer(struct ipu_soc *ipu, uint32_t bufNum);
|
||||||
|
|
||||||
|
int32_t ipu_link_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
|
||||||
|
int32_t ipu_unlink_channels(struct ipu_soc *ipu, ipu_channel_t src_ch, ipu_channel_t dest_ch);
|
||||||
|
|
||||||
|
int32_t ipu_is_channel_busy(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
int32_t ipu_check_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
|
||||||
|
uint32_t bufNum);
|
||||||
|
void ipu_clear_buffer_ready(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type,
|
||||||
|
uint32_t bufNum);
|
||||||
|
uint32_t ipu_get_cur_buffer_idx(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
|
||||||
|
int32_t ipu_enable_channel(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
int32_t ipu_disable_channel(struct ipu_soc *ipu, ipu_channel_t channel, bool wait_for_stop);
|
||||||
|
int32_t ipu_swap_channel(struct ipu_soc *ipu, ipu_channel_t from_ch, ipu_channel_t to_ch);
|
||||||
|
uint32_t ipu_channel_status(struct ipu_soc *ipu, ipu_channel_t channel);
|
||||||
|
|
||||||
|
int32_t ipu_enable_csi(struct ipu_soc *ipu, uint32_t csi);
|
||||||
|
int32_t ipu_disable_csi(struct ipu_soc *ipu, uint32_t csi);
|
||||||
|
|
||||||
|
int ipu_lowpwr_display_enable(void);
|
||||||
|
int ipu_lowpwr_display_disable(void);
|
||||||
|
|
||||||
|
int ipu_enable_irq(struct ipu_soc *ipu, uint32_t irq);
|
||||||
|
void ipu_disable_irq(struct ipu_soc *ipu, uint32_t irq);
|
||||||
|
void ipu_clear_irq(struct ipu_soc *ipu, uint32_t irq);
|
||||||
|
int ipu_request_irq(struct ipu_soc *ipu, uint32_t irq,
|
||||||
|
irqreturn_t(*handler) (int, void *),
|
||||||
|
uint32_t irq_flags, const char *devname, void *dev_id);
|
||||||
|
void ipu_free_irq(struct ipu_soc *ipu, uint32_t irq, void *dev_id);
|
||||||
|
bool ipu_get_irq_status(struct ipu_soc *ipu, uint32_t irq);
|
||||||
|
void ipu_set_csc_coefficients(struct ipu_soc *ipu, ipu_channel_t channel, int32_t param[][3]);
|
||||||
|
int32_t ipu_set_channel_bandmode(struct ipu_soc *ipu, ipu_channel_t channel,
|
||||||
|
ipu_buffer_t type, uint32_t band_height);
|
||||||
|
|
||||||
|
/* two stripe calculations */
|
||||||
|
struct stripe_param{
|
||||||
|
unsigned int input_width; /* width of the input stripe */
|
||||||
|
unsigned int output_width; /* width of the output stripe */
|
||||||
|
unsigned int input_column; /* the first column on the input stripe */
|
||||||
|
unsigned int output_column; /* the first column on the output stripe */
|
||||||
|
unsigned int idr;
|
||||||
|
/* inverse downisizing ratio parameter; expressed as a power of 2 */
|
||||||
|
unsigned int irr;
|
||||||
|
/* inverse resizing ratio parameter; expressed as a multiple of 2^-13 */
|
||||||
|
};
|
||||||
|
int ipu_calc_stripes_sizes(const unsigned int input_frame_width,
|
||||||
|
unsigned int output_frame_width,
|
||||||
|
const unsigned int maximal_stripe_width,
|
||||||
|
const unsigned long long cirr,
|
||||||
|
const unsigned int equal_stripes,
|
||||||
|
u32 input_pixelformat,
|
||||||
|
u32 output_pixelformat,
|
||||||
|
struct stripe_param *left,
|
||||||
|
struct stripe_param *right);
|
||||||
|
|
||||||
|
/* SDC API */
|
||||||
|
int32_t ipu_init_sync_panel(struct ipu_soc *ipu, int disp,
|
||||||
|
uint32_t pixel_clk,
|
||||||
|
uint16_t width, uint16_t height,
|
||||||
|
uint32_t pixel_fmt,
|
||||||
|
uint16_t h_start_width, uint16_t h_sync_width,
|
||||||
|
uint16_t h_end_width, uint16_t v_start_width,
|
||||||
|
uint16_t v_sync_width, uint16_t v_end_width,
|
||||||
|
uint32_t v_to_h_sync, ipu_di_signal_cfg_t sig);
|
||||||
|
|
||||||
|
void ipu_uninit_sync_panel(struct ipu_soc *ipu, int disp);
|
||||||
|
|
||||||
|
int32_t ipu_disp_set_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t x_pos,
|
||||||
|
int16_t y_pos);
|
||||||
|
int32_t ipu_disp_get_window_pos(struct ipu_soc *ipu, ipu_channel_t channel, int16_t *x_pos,
|
||||||
|
int16_t *y_pos);
|
||||||
|
int32_t ipu_disp_set_global_alpha(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
|
||||||
|
uint8_t alpha);
|
||||||
|
int32_t ipu_disp_set_color_key(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
|
||||||
|
uint32_t colorKey);
|
||||||
|
int32_t ipu_disp_set_gamma_correction(struct ipu_soc *ipu, ipu_channel_t channel, bool enable,
|
||||||
|
int constk[], int slopek[]);
|
||||||
|
|
||||||
|
int ipu_init_async_panel(struct ipu_soc *ipu, int disp, int type, uint32_t cycle_time,
|
||||||
|
uint32_t pixel_fmt, ipu_adc_sig_cfg_t sig);
|
||||||
|
void ipu_reset_disp_panel(struct ipu_soc *ipu);
|
||||||
|
|
||||||
|
/* CMOS Sensor Interface API */
|
||||||
|
int32_t ipu_csi_init_interface(struct ipu_soc *ipu, uint16_t width, uint16_t height,
|
||||||
|
uint32_t pixel_fmt, ipu_csi_signal_cfg_t sig);
|
||||||
|
|
||||||
|
int32_t ipu_csi_get_sensor_protocol(struct ipu_soc *ipu, uint32_t csi);
|
||||||
|
|
||||||
|
int32_t ipu_csi_enable_mclk(struct ipu_soc *ipu, int src, bool flag, bool wait);
|
||||||
|
|
||||||
|
static inline int32_t ipu_csi_enable_mclk_if(struct ipu_soc *ipu, int src, uint32_t csi,
|
||||||
|
bool flag, bool wait)
|
||||||
|
{
|
||||||
|
return ipu_csi_enable_mclk(ipu, csi, flag, wait);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ipu_csi_read_mclk_flag(void);
|
||||||
|
|
||||||
|
void ipu_csi_flash_strobe(bool flag);
|
||||||
|
|
||||||
|
void ipu_csi_get_window_size(struct ipu_soc *ipu, uint32_t *width, uint32_t *height, uint32_t csi);
|
||||||
|
|
||||||
|
void ipu_csi_set_window_size(struct ipu_soc *ipu, uint32_t width, uint32_t height, uint32_t csi);
|
||||||
|
|
||||||
|
void ipu_csi_set_window_pos(struct ipu_soc *ipu, uint32_t left, uint32_t top, uint32_t csi);
|
||||||
|
|
||||||
|
uint32_t bytes_per_pixel(uint32_t fmt);
|
||||||
|
|
||||||
|
bool ipu_ch_param_bad_alpha_pos(uint32_t fmt);
|
||||||
|
int ipu_ch_param_get_axi_id(struct ipu_soc *ipu, ipu_channel_t channel, ipu_buffer_t type);
|
||||||
|
ipu_color_space_t format_to_colorspace(uint32_t fmt);
|
||||||
|
bool ipu_pixel_format_is_gpu_tile(uint32_t fmt);
|
||||||
|
bool ipu_pixel_format_is_split_gpu_tile(uint32_t fmt);
|
||||||
|
bool ipu_pixel_format_is_pre_yuv(uint32_t fmt);
|
||||||
|
bool ipu_pixel_format_is_multiplanar_yuv(uint32_t fmt);
|
||||||
|
|
||||||
|
struct ipuv3_fb_platform_data {
|
||||||
|
char disp_dev[32];
|
||||||
|
u32 interface_pix_fmt;
|
||||||
|
char *mode_str;
|
||||||
|
int default_bpp;
|
||||||
|
bool int_clk;
|
||||||
|
|
||||||
|
/* reserved mem */
|
||||||
|
resource_size_t res_base[2];
|
||||||
|
resource_size_t res_size[2];
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Late init to avoid display channel being
|
||||||
|
* re-initialized as we've probably setup the
|
||||||
|
* channel in bootloader.
|
||||||
|
*/
|
||||||
|
bool late_init;
|
||||||
|
|
||||||
|
/* Enable prefetch engine or not? */
|
||||||
|
bool prefetch;
|
||||||
|
|
||||||
|
/* Enable the PRE resolve engine or not? */
|
||||||
|
bool resolve;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif /* __LINUX_IPU_V3_H_ */
|
|
@ -0,0 +1,38 @@
|
||||||
|
/*
|
||||||
|
* Copyright 2005-2015 Freescale Semiconductor, Inc.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
* The code contained herein is licensed under the GNU Lesser General
|
||||||
|
* Public License. You may obtain a copy of the GNU Lesser General
|
||||||
|
* Public License Version 2.1 or later at the following locations:
|
||||||
|
*
|
||||||
|
* http://www.opensource.org/licenses/lgpl-license.html
|
||||||
|
* http://www.gnu.org/copyleft/lgpl.html
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*!
|
||||||
|
* @defgroup IPU MXC Image Processing Unit (IPU) Driver
|
||||||
|
*/
|
||||||
|
/*!
|
||||||
|
* @file linux/ipu.h
|
||||||
|
*
|
||||||
|
* @brief This file contains the IPU driver API declarations.
|
||||||
|
*
|
||||||
|
* @ingroup IPU
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef __LINUX_IPU_H__
|
||||||
|
#define __LINUX_IPU_H__
|
||||||
|
|
||||||
|
#include <linux/interrupt.h>
|
||||||
|
#include <uapi/linux/ipu.h>
|
||||||
|
|
||||||
|
unsigned int fmt_to_bpp(unsigned int pixelformat);
|
||||||
|
cs_t colorspaceofpixel(int fmt);
|
||||||
|
int need_csc(int ifmt, int ofmt);
|
||||||
|
|
||||||
|
int ipu_queue_task(struct ipu_task *task);
|
||||||
|
int ipu_check_task(struct ipu_task *task);
|
||||||
|
|
||||||
|
#endif
|
Loading…
Reference in New Issue