Fixed MTP to work with TWRP

This commit is contained in:
awab228 2018-06-19 23:16:04 +02:00
commit f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions

View file

@ -0,0 +1,5 @@
obj-$(CONFIG_VIDEO_TI_VPE) += ti-vpe.o
ti-vpe-y := vpe.o sc.o csc.o vpdma.o
ccflags-$(CONFIG_VIDEO_TI_VPE_DEBUG) += -DDEBUG

View file

@ -0,0 +1,196 @@
/*
* Color space converter library
*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include "csc.h"
/*
* 16 coefficients in the order:
* a0, b0, c0, a1, b1, c1, a2, b2, c2, d0, d1, d2
* (we may need to pass non-default values from user space later on, we might
* need to make the coefficient struct more easy to populate)
*/
struct colorspace_coeffs {
u16 sd[12];
u16 hd[12];
};
/* VIDEO_RANGE: limited range, GRAPHICS_RANGE: full range */
#define CSC_COEFFS_VIDEO_RANGE_Y2R 0
#define CSC_COEFFS_GRAPHICS_RANGE_Y2R 1
#define CSC_COEFFS_VIDEO_RANGE_R2Y 2
#define CSC_COEFFS_GRAPHICS_RANGE_R2Y 3
/* default colorspace coefficients */
static struct colorspace_coeffs colorspace_coeffs[4] = {
[CSC_COEFFS_VIDEO_RANGE_Y2R] = {
{
/* SDTV */
0x0400, 0x0000, 0x057D, 0x0400, 0x1EA7, 0x1D35,
0x0400, 0x06EF, 0x1FFE, 0x0D40, 0x0210, 0x0C88,
},
{
/* HDTV */
0x0400, 0x0000, 0x0629, 0x0400, 0x1F45, 0x1E2B,
0x0400, 0x0742, 0x0000, 0x0CEC, 0x0148, 0x0C60,
},
},
[CSC_COEFFS_GRAPHICS_RANGE_Y2R] = {
{
/* SDTV */
0x04A8, 0x1FFE, 0x0662, 0x04A8, 0x1E6F, 0x1CBF,
0x04A8, 0x0812, 0x1FFF, 0x0C84, 0x0220, 0x0BAC,
},
{
/* HDTV */
0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
},
},
[CSC_COEFFS_VIDEO_RANGE_R2Y] = {
{
/* SDTV */
0x0132, 0x0259, 0x0075, 0x1F50, 0x1EA5, 0x020B,
0x020B, 0x1E4A, 0x1FAB, 0x0000, 0x0200, 0x0200,
},
{
/* HDTV */
0x00DA, 0x02DC, 0x004A, 0x1F88, 0x1E6C, 0x020C,
0x020C, 0x1E24, 0x1FD0, 0x0000, 0x0200, 0x0200,
},
},
[CSC_COEFFS_GRAPHICS_RANGE_R2Y] = {
{
/* SDTV */
0x0107, 0x0204, 0x0064, 0x1F68, 0x1ED6, 0x01C2,
0x01C2, 0x1E87, 0x1FB7, 0x0040, 0x0200, 0x0200,
},
{
/* HDTV */
0x04A8, 0x0000, 0x072C, 0x04A8, 0x1F26, 0x1DDE,
0x04A8, 0x0873, 0x0000, 0x0C20, 0x0134, 0x0B7C,
},
},
};
void csc_dump_regs(struct csc_data *csc)
{
struct device *dev = &csc->pdev->dev;
u32 read_reg(struct csc_data *csc, int offset)
{
return ioread32(csc->base + offset);
}
#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(csc, CSC_##r))
DUMPREG(CSC00);
DUMPREG(CSC01);
DUMPREG(CSC02);
DUMPREG(CSC03);
DUMPREG(CSC04);
DUMPREG(CSC05);
#undef DUMPREG
}
void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5)
{
*csc_reg5 |= CSC_BYPASS;
}
/*
* set the color space converter coefficient shadow register values
*/
void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
enum v4l2_colorspace src_colorspace,
enum v4l2_colorspace dst_colorspace)
{
u32 *csc_reg5 = csc_reg0 + 5;
u32 *shadow_csc = csc_reg0;
struct colorspace_coeffs *sd_hd_coeffs;
u16 *coeff, *end_coeff;
enum v4l2_colorspace yuv_colorspace;
int sel = 0;
/*
* support only graphics data range(full range) for now, a control ioctl
* would be nice here
*/
/* Y2R */
if (dst_colorspace == V4L2_COLORSPACE_SRGB &&
(src_colorspace == V4L2_COLORSPACE_SMPTE170M ||
src_colorspace == V4L2_COLORSPACE_REC709)) {
/* Y2R */
sel = 1;
yuv_colorspace = src_colorspace;
} else if ((dst_colorspace == V4L2_COLORSPACE_SMPTE170M ||
dst_colorspace == V4L2_COLORSPACE_REC709) &&
src_colorspace == V4L2_COLORSPACE_SRGB) {
/* R2Y */
sel = 3;
yuv_colorspace = dst_colorspace;
} else {
*csc_reg5 |= CSC_BYPASS;
return;
}
sd_hd_coeffs = &colorspace_coeffs[sel];
/* select between SD or HD coefficients */
if (yuv_colorspace == V4L2_COLORSPACE_SMPTE170M)
coeff = sd_hd_coeffs->sd;
else
coeff = sd_hd_coeffs->hd;
end_coeff = coeff + 12;
for (; coeff < end_coeff; coeff += 2)
*shadow_csc++ = (*(coeff + 1) << 16) | *coeff;
}
struct csc_data *csc_create(struct platform_device *pdev)
{
struct csc_data *csc;
dev_dbg(&pdev->dev, "csc_create\n");
csc = devm_kzalloc(&pdev->dev, sizeof(*csc), GFP_KERNEL);
if (!csc) {
dev_err(&pdev->dev, "couldn't alloc csc_data\n");
return ERR_PTR(-ENOMEM);
}
csc->pdev = pdev;
csc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM,
"csc");
if (csc->res == NULL) {
dev_err(&pdev->dev, "missing platform resources data\n");
return ERR_PTR(-ENODEV);
}
csc->base = devm_ioremap_resource(&pdev->dev, csc->res);
if (IS_ERR(csc->base)) {
dev_err(&pdev->dev, "failed to ioremap\n");
return csc->base;
}
return csc;
}

View file

@ -0,0 +1,68 @@
/*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef TI_CSC_H
#define TI_CSC_H
/* VPE color space converter regs */
#define CSC_CSC00 0x00
#define CSC_A0_MASK 0x1fff
#define CSC_A0_SHIFT 0
#define CSC_B0_MASK 0x1fff
#define CSC_B0_SHIFT 16
#define CSC_CSC01 0x04
#define CSC_C0_MASK 0x1fff
#define CSC_C0_SHIFT 0
#define CSC_A1_MASK 0x1fff
#define CSC_A1_SHIFT 16
#define CSC_CSC02 0x08
#define CSC_B1_MASK 0x1fff
#define CSC_B1_SHIFT 0
#define CSC_C1_MASK 0x1fff
#define CSC_C1_SHIFT 16
#define CSC_CSC03 0x0c
#define CSC_A2_MASK 0x1fff
#define CSC_A2_SHIFT 0
#define CSC_B2_MASK 0x1fff
#define CSC_B2_SHIFT 16
#define CSC_CSC04 0x10
#define CSC_C2_MASK 0x1fff
#define CSC_C2_SHIFT 0
#define CSC_D0_MASK 0x0fff
#define CSC_D0_SHIFT 16
#define CSC_CSC05 0x14
#define CSC_D1_MASK 0x0fff
#define CSC_D1_SHIFT 0
#define CSC_D2_MASK 0x0fff
#define CSC_D2_SHIFT 16
#define CSC_BYPASS (1 << 28)
struct csc_data {
void __iomem *base;
struct resource *res;
struct platform_device *pdev;
};
void csc_dump_regs(struct csc_data *csc);
void csc_set_coeff_bypass(struct csc_data *csc, u32 *csc_reg5);
void csc_set_coeff(struct csc_data *csc, u32 *csc_reg0,
enum v4l2_colorspace src_colorspace,
enum v4l2_colorspace dst_colorspace);
struct csc_data *csc_create(struct platform_device *pdev);
#endif

View file

@ -0,0 +1,311 @@
/*
* Scaler library
*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/err.h>
#include <linux/io.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include "sc.h"
#include "sc_coeff.h"
void sc_dump_regs(struct sc_data *sc)
{
struct device *dev = &sc->pdev->dev;
u32 read_reg(struct sc_data *sc, int offset)
{
return ioread32(sc->base + offset);
}
#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(sc, CFG_##r))
DUMPREG(SC0);
DUMPREG(SC1);
DUMPREG(SC2);
DUMPREG(SC3);
DUMPREG(SC4);
DUMPREG(SC5);
DUMPREG(SC6);
DUMPREG(SC8);
DUMPREG(SC9);
DUMPREG(SC10);
DUMPREG(SC11);
DUMPREG(SC12);
DUMPREG(SC13);
DUMPREG(SC17);
DUMPREG(SC18);
DUMPREG(SC19);
DUMPREG(SC20);
DUMPREG(SC21);
DUMPREG(SC22);
DUMPREG(SC23);
DUMPREG(SC24);
DUMPREG(SC25);
#undef DUMPREG
}
/*
* set the horizontal scaler coefficients according to the ratio of output to
* input widths, after accounting for up to two levels of decimation
*/
void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w,
unsigned int dst_w)
{
int sixteenths;
int idx;
int i, j;
u16 *coeff_h = addr;
const u16 *cp;
if (dst_w > src_w) {
idx = HS_UP_SCALE;
} else {
if ((dst_w << 1) < src_w)
dst_w <<= 1; /* first level decimation */
if ((dst_w << 1) < src_w)
dst_w <<= 1; /* second level decimation */
if (dst_w == src_w) {
idx = HS_LE_16_16_SCALE;
} else {
sixteenths = (dst_w << 4) / src_w;
if (sixteenths < 8)
sixteenths = 8;
idx = HS_LT_9_16_SCALE + sixteenths - 8;
}
}
if (idx == sc->hs_index)
return;
cp = scaler_hs_coeffs[idx];
for (i = 0; i < SC_NUM_PHASES * 2; i++) {
for (j = 0; j < SC_H_NUM_TAPS; j++)
*coeff_h++ = *cp++;
/*
* for each phase, the scaler expects space for 8 coefficients
* in it's memory. For the horizontal scaler, we copy the first
* 7 coefficients and skip the last slot to move to the next
* row to hold coefficients for the next phase
*/
coeff_h += SC_NUM_TAPS_MEM_ALIGN - SC_H_NUM_TAPS;
}
sc->hs_index = idx;
sc->load_coeff_h = true;
}
/*
* set the vertical scaler coefficients according to the ratio of output to
* input heights
*/
void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
unsigned int dst_h)
{
int sixteenths;
int idx;
int i, j;
u16 *coeff_v = addr;
const u16 *cp;
if (dst_h > src_h) {
idx = VS_UP_SCALE;
} else if (dst_h == src_h) {
idx = VS_1_TO_1_SCALE;
} else {
sixteenths = (dst_h << 4) / src_h;
if (sixteenths < 8)
sixteenths = 8;
idx = VS_LT_9_16_SCALE + sixteenths - 8;
}
if (idx == sc->vs_index)
return;
cp = scaler_vs_coeffs[idx];
for (i = 0; i < SC_NUM_PHASES * 2; i++) {
for (j = 0; j < SC_V_NUM_TAPS; j++)
*coeff_v++ = *cp++;
/*
* for the vertical scaler, we copy the first 5 coefficients and
* skip the last 3 slots to move to the next row to hold
* coefficients for the next phase
*/
coeff_v += SC_NUM_TAPS_MEM_ALIGN - SC_V_NUM_TAPS;
}
sc->vs_index = idx;
sc->load_coeff_v = true;
}
void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
unsigned int dst_w, unsigned int dst_h)
{
struct device *dev = &sc->pdev->dev;
u32 val;
int dcm_x, dcm_shift;
bool use_rav;
unsigned long lltmp;
u32 lin_acc_inc, lin_acc_inc_u;
u32 col_acc_offset;
u16 factor = 0;
int row_acc_init_rav = 0, row_acc_init_rav_b = 0;
u32 row_acc_inc = 0, row_acc_offset = 0, row_acc_offset_b = 0;
/*
* location of SC register in payload memory with respect to the first
* register in the mmr address data block
*/
u32 *sc_reg9 = sc_reg8 + 1;
u32 *sc_reg12 = sc_reg8 + 4;
u32 *sc_reg13 = sc_reg8 + 5;
u32 *sc_reg24 = sc_reg17 + 7;
val = sc_reg0[0];
/* clear all the features(they may get enabled elsewhere later) */
val &= ~(CFG_SELFGEN_FID | CFG_TRIM | CFG_ENABLE_SIN2_VER_INTP |
CFG_INTERLACE_I | CFG_DCM_4X | CFG_DCM_2X | CFG_AUTO_HS |
CFG_ENABLE_EV | CFG_USE_RAV | CFG_INVT_FID | CFG_SC_BYPASS |
CFG_INTERLACE_O | CFG_Y_PK_EN | CFG_HP_BYPASS | CFG_LINEAR);
if (src_w == dst_w && src_h == dst_h) {
val |= CFG_SC_BYPASS;
sc_reg0[0] = val;
return;
}
/* we only support linear scaling for now */
val |= CFG_LINEAR;
/* configure horizontal scaler */
/* enable 2X or 4X decimation */
dcm_x = src_w / dst_w;
if (dcm_x > 4) {
val |= CFG_DCM_4X;
dcm_shift = 2;
} else if (dcm_x > 2) {
val |= CFG_DCM_2X;
dcm_shift = 1;
} else {
dcm_shift = 0;
}
lltmp = dst_w - 1;
lin_acc_inc = div64_u64(((u64)(src_w >> dcm_shift) - 1) << 24, lltmp);
lin_acc_inc_u = 0;
col_acc_offset = 0;
dev_dbg(dev, "hs config: src_w = %d, dst_w = %d, decimation = %s, lin_acc_inc = %08x\n",
src_w, dst_w, dcm_shift == 2 ? "4x" :
(dcm_shift == 1 ? "2x" : "none"), lin_acc_inc);
/* configure vertical scaler */
/* use RAV for vertical scaler if vertical downscaling is > 4x */
if (dst_h < (src_h >> 2)) {
use_rav = true;
val |= CFG_USE_RAV;
} else {
use_rav = false;
}
if (use_rav) {
/* use RAV */
factor = (u16) ((dst_h << 10) / src_h);
row_acc_init_rav = factor + ((1 + factor) >> 1);
if (row_acc_init_rav >= 1024)
row_acc_init_rav -= 1024;
row_acc_init_rav_b = row_acc_init_rav +
(1 + (row_acc_init_rav >> 1)) -
(1024 >> 1);
if (row_acc_init_rav_b < 0) {
row_acc_init_rav_b += row_acc_init_rav;
row_acc_init_rav *= 2;
}
dev_dbg(dev, "vs config(RAV): src_h = %d, dst_h = %d, factor = %d, acc_init = %08x, acc_init_b = %08x\n",
src_h, dst_h, factor, row_acc_init_rav,
row_acc_init_rav_b);
} else {
/* use polyphase */
row_acc_inc = ((src_h - 1) << 16) / (dst_h - 1);
row_acc_offset = 0;
row_acc_offset_b = 0;
dev_dbg(dev, "vs config(POLY): src_h = %d, dst_h = %d,row_acc_inc = %08x\n",
src_h, dst_h, row_acc_inc);
}
sc_reg0[0] = val;
sc_reg0[1] = row_acc_inc;
sc_reg0[2] = row_acc_offset;
sc_reg0[3] = row_acc_offset_b;
sc_reg0[4] = ((lin_acc_inc_u & CFG_LIN_ACC_INC_U_MASK) <<
CFG_LIN_ACC_INC_U_SHIFT) | (dst_w << CFG_TAR_W_SHIFT) |
(dst_h << CFG_TAR_H_SHIFT);
sc_reg0[5] = (src_w << CFG_SRC_W_SHIFT) | (src_h << CFG_SRC_H_SHIFT);
sc_reg0[6] = (row_acc_init_rav_b << CFG_ROW_ACC_INIT_RAV_B_SHIFT) |
(row_acc_init_rav << CFG_ROW_ACC_INIT_RAV_SHIFT);
*sc_reg9 = lin_acc_inc;
*sc_reg12 = col_acc_offset << CFG_COL_ACC_OFFSET_SHIFT;
*sc_reg13 = factor;
*sc_reg24 = (src_w << CFG_ORG_W_SHIFT) | (src_h << CFG_ORG_H_SHIFT);
}
struct sc_data *sc_create(struct platform_device *pdev)
{
struct sc_data *sc;
dev_dbg(&pdev->dev, "sc_create\n");
sc = devm_kzalloc(&pdev->dev, sizeof(*sc), GFP_KERNEL);
if (!sc) {
dev_err(&pdev->dev, "couldn't alloc sc_data\n");
return ERR_PTR(-ENOMEM);
}
sc->pdev = pdev;
sc->res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "sc");
if (!sc->res) {
dev_err(&pdev->dev, "missing platform resources data\n");
return ERR_PTR(-ENODEV);
}
sc->base = devm_ioremap_resource(&pdev->dev, sc->res);
if (IS_ERR(sc->base)) {
dev_err(&pdev->dev, "failed to ioremap\n");
return sc->base;
}
return sc;
}

View file

@ -0,0 +1,208 @@
/*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef TI_SC_H
#define TI_SC_H
/* Scaler regs */
#define CFG_SC0 0x0
#define CFG_INTERLACE_O (1 << 0)
#define CFG_LINEAR (1 << 1)
#define CFG_SC_BYPASS (1 << 2)
#define CFG_INVT_FID (1 << 3)
#define CFG_USE_RAV (1 << 4)
#define CFG_ENABLE_EV (1 << 5)
#define CFG_AUTO_HS (1 << 6)
#define CFG_DCM_2X (1 << 7)
#define CFG_DCM_4X (1 << 8)
#define CFG_HP_BYPASS (1 << 9)
#define CFG_INTERLACE_I (1 << 10)
#define CFG_ENABLE_SIN2_VER_INTP (1 << 11)
#define CFG_Y_PK_EN (1 << 14)
#define CFG_TRIM (1 << 15)
#define CFG_SELFGEN_FID (1 << 16)
#define CFG_SC1 0x4
#define CFG_ROW_ACC_INC_MASK 0x07ffffff
#define CFG_ROW_ACC_INC_SHIFT 0
#define CFG_SC2 0x08
#define CFG_ROW_ACC_OFFSET_MASK 0x0fffffff
#define CFG_ROW_ACC_OFFSET_SHIFT 0
#define CFG_SC3 0x0c
#define CFG_ROW_ACC_OFFSET_B_MASK 0x0fffffff
#define CFG_ROW_ACC_OFFSET_B_SHIFT 0
#define CFG_SC4 0x10
#define CFG_TAR_H_MASK 0x07ff
#define CFG_TAR_H_SHIFT 0
#define CFG_TAR_W_MASK 0x07ff
#define CFG_TAR_W_SHIFT 12
#define CFG_LIN_ACC_INC_U_MASK 0x07
#define CFG_LIN_ACC_INC_U_SHIFT 24
#define CFG_NLIN_ACC_INIT_U_MASK 0x07
#define CFG_NLIN_ACC_INIT_U_SHIFT 28
#define CFG_SC5 0x14
#define CFG_SRC_H_MASK 0x07ff
#define CFG_SRC_H_SHIFT 0
#define CFG_SRC_W_MASK 0x07ff
#define CFG_SRC_W_SHIFT 12
#define CFG_NLIN_ACC_INC_U_MASK 0x07
#define CFG_NLIN_ACC_INC_U_SHIFT 24
#define CFG_SC6 0x18
#define CFG_ROW_ACC_INIT_RAV_MASK 0x03ff
#define CFG_ROW_ACC_INIT_RAV_SHIFT 0
#define CFG_ROW_ACC_INIT_RAV_B_MASK 0x03ff
#define CFG_ROW_ACC_INIT_RAV_B_SHIFT 10
#define CFG_SC8 0x20
#define CFG_NLIN_LEFT_MASK 0x07ff
#define CFG_NLIN_LEFT_SHIFT 0
#define CFG_NLIN_RIGHT_MASK 0x07ff
#define CFG_NLIN_RIGHT_SHIFT 12
#define CFG_SC9 0x24
#define CFG_LIN_ACC_INC CFG_SC9
#define CFG_SC10 0x28
#define CFG_NLIN_ACC_INIT CFG_SC10
#define CFG_SC11 0x2c
#define CFG_NLIN_ACC_INC CFG_SC11
#define CFG_SC12 0x30
#define CFG_COL_ACC_OFFSET_MASK 0x01ffffff
#define CFG_COL_ACC_OFFSET_SHIFT 0
#define CFG_SC13 0x34
#define CFG_SC_FACTOR_RAV_MASK 0xff
#define CFG_SC_FACTOR_RAV_SHIFT 0
#define CFG_CHROMA_INTP_THR_MASK 0x03ff
#define CFG_CHROMA_INTP_THR_SHIFT 12
#define CFG_DELTA_CHROMA_THR_MASK 0x0f
#define CFG_DELTA_CHROMA_THR_SHIFT 24
#define CFG_SC17 0x44
#define CFG_EV_THR_MASK 0x03ff
#define CFG_EV_THR_SHIFT 12
#define CFG_DELTA_LUMA_THR_MASK 0x0f
#define CFG_DELTA_LUMA_THR_SHIFT 24
#define CFG_DELTA_EV_THR_MASK 0x0f
#define CFG_DELTA_EV_THR_SHIFT 28
#define CFG_SC18 0x48
#define CFG_HS_FACTOR_MASK 0x03ff
#define CFG_HS_FACTOR_SHIFT 0
#define CFG_CONF_DEFAULT_MASK 0x01ff
#define CFG_CONF_DEFAULT_SHIFT 16
#define CFG_SC19 0x4c
#define CFG_HPF_COEFF0_MASK 0xff
#define CFG_HPF_COEFF0_SHIFT 0
#define CFG_HPF_COEFF1_MASK 0xff
#define CFG_HPF_COEFF1_SHIFT 8
#define CFG_HPF_COEFF2_MASK 0xff
#define CFG_HPF_COEFF2_SHIFT 16
#define CFG_HPF_COEFF3_MASK 0xff
#define CFG_HPF_COEFF3_SHIFT 23
#define CFG_SC20 0x50
#define CFG_HPF_COEFF4_MASK 0xff
#define CFG_HPF_COEFF4_SHIFT 0
#define CFG_HPF_COEFF5_MASK 0xff
#define CFG_HPF_COEFF5_SHIFT 8
#define CFG_HPF_NORM_SHIFT_MASK 0x07
#define CFG_HPF_NORM_SHIFT_SHIFT 16
#define CFG_NL_LIMIT_MASK 0x1ff
#define CFG_NL_LIMIT_SHIFT 20
#define CFG_SC21 0x54
#define CFG_NL_LO_THR_MASK 0x01ff
#define CFG_NL_LO_THR_SHIFT 0
#define CFG_NL_LO_SLOPE_MASK 0xff
#define CFG_NL_LO_SLOPE_SHIFT 16
#define CFG_SC22 0x58
#define CFG_NL_HI_THR_MASK 0x01ff
#define CFG_NL_HI_THR_SHIFT 0
#define CFG_NL_HI_SLOPE_SH_MASK 0x07
#define CFG_NL_HI_SLOPE_SH_SHIFT 16
#define CFG_SC23 0x5c
#define CFG_GRADIENT_THR_MASK 0x07ff
#define CFG_GRADIENT_THR_SHIFT 0
#define CFG_GRADIENT_THR_RANGE_MASK 0x0f
#define CFG_GRADIENT_THR_RANGE_SHIFT 12
#define CFG_MIN_GY_THR_MASK 0xff
#define CFG_MIN_GY_THR_SHIFT 16
#define CFG_MIN_GY_THR_RANGE_MASK 0x0f
#define CFG_MIN_GY_THR_RANGE_SHIFT 28
#define CFG_SC24 0x60
#define CFG_ORG_H_MASK 0x07ff
#define CFG_ORG_H_SHIFT 0
#define CFG_ORG_W_MASK 0x07ff
#define CFG_ORG_W_SHIFT 16
#define CFG_SC25 0x64
#define CFG_OFF_H_MASK 0x07ff
#define CFG_OFF_H_SHIFT 0
#define CFG_OFF_W_MASK 0x07ff
#define CFG_OFF_W_SHIFT 16
/* number of phases supported by the polyphase scalers */
#define SC_NUM_PHASES 32
/* number of taps used by horizontal polyphase scaler */
#define SC_H_NUM_TAPS 7
/* number of taps used by vertical polyphase scaler */
#define SC_V_NUM_TAPS 5
/* number of taps expected by the scaler in it's coefficient memory */
#define SC_NUM_TAPS_MEM_ALIGN 8
/*
* coefficient memory size in bytes:
* num phases x num sets(luma and chroma) x num taps(aligned) x coeff size
*/
#define SC_COEF_SRAM_SIZE (SC_NUM_PHASES * 2 * SC_NUM_TAPS_MEM_ALIGN * 2)
struct sc_data {
void __iomem *base;
struct resource *res;
dma_addr_t loaded_coeff_h; /* loaded h coeffs in SC */
dma_addr_t loaded_coeff_v; /* loaded v coeffs in SC */
bool load_coeff_h; /* have new h SC coeffs */
bool load_coeff_v; /* have new v SC coeffs */
unsigned int hs_index; /* h SC coeffs selector */
unsigned int vs_index; /* v SC coeffs selector */
struct platform_device *pdev;
};
void sc_dump_regs(struct sc_data *sc);
void sc_set_hs_coeffs(struct sc_data *sc, void *addr, unsigned int src_w,
unsigned int dst_w);
void sc_set_vs_coeffs(struct sc_data *sc, void *addr, unsigned int src_h,
unsigned int dst_h);
void sc_config_scaler(struct sc_data *sc, u32 *sc_reg0, u32 *sc_reg8,
u32 *sc_reg17, unsigned int src_w, unsigned int src_h,
unsigned int dst_w, unsigned int dst_h);
struct sc_data *sc_create(struct platform_device *pdev);
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,912 @@
/*
* VPDMA helper library
*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#include <linux/delay.h>
#include <linux/dma-mapping.h>
#include <linux/err.h>
#include <linux/firmware.h>
#include <linux/io.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/sched.h>
#include <linux/slab.h>
#include <linux/videodev2.h>
#include "vpdma.h"
#include "vpdma_priv.h"
#define VPDMA_FIRMWARE "vpdma-1b8.bin"
const struct vpdma_data_format vpdma_yuv_fmts[] = {
[VPDMA_DATA_FMT_Y444] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_Y444,
.depth = 8,
},
[VPDMA_DATA_FMT_Y422] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_Y422,
.depth = 8,
},
[VPDMA_DATA_FMT_Y420] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_Y420,
.depth = 8,
},
[VPDMA_DATA_FMT_C444] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_C444,
.depth = 8,
},
[VPDMA_DATA_FMT_C422] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_C422,
.depth = 8,
},
[VPDMA_DATA_FMT_C420] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_C420,
.depth = 4,
},
[VPDMA_DATA_FMT_YC422] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_YC422,
.depth = 16,
},
[VPDMA_DATA_FMT_YC444] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_YC444,
.depth = 24,
},
[VPDMA_DATA_FMT_CY422] = {
.type = VPDMA_DATA_FMT_TYPE_YUV,
.data_type = DATA_TYPE_CY422,
.depth = 16,
},
};
const struct vpdma_data_format vpdma_rgb_fmts[] = {
[VPDMA_DATA_FMT_RGB565] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGB16_565,
.depth = 16,
},
[VPDMA_DATA_FMT_ARGB16_1555] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ARGB_1555,
.depth = 16,
},
[VPDMA_DATA_FMT_ARGB16] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ARGB_4444,
.depth = 16,
},
[VPDMA_DATA_FMT_RGBA16_5551] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGBA_5551,
.depth = 16,
},
[VPDMA_DATA_FMT_RGBA16] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGBA_4444,
.depth = 16,
},
[VPDMA_DATA_FMT_ARGB24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ARGB24_6666,
.depth = 24,
},
[VPDMA_DATA_FMT_RGB24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGB24_888,
.depth = 24,
},
[VPDMA_DATA_FMT_ARGB32] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ARGB32_8888,
.depth = 32,
},
[VPDMA_DATA_FMT_RGBA24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGBA24_6666,
.depth = 24,
},
[VPDMA_DATA_FMT_RGBA32] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_RGBA32_8888,
.depth = 32,
},
[VPDMA_DATA_FMT_BGR565] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGR16_565,
.depth = 16,
},
[VPDMA_DATA_FMT_ABGR16_1555] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ABGR_1555,
.depth = 16,
},
[VPDMA_DATA_FMT_ABGR16] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ABGR_4444,
.depth = 16,
},
[VPDMA_DATA_FMT_BGRA16_5551] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGRA_5551,
.depth = 16,
},
[VPDMA_DATA_FMT_BGRA16] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGRA_4444,
.depth = 16,
},
[VPDMA_DATA_FMT_ABGR24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ABGR24_6666,
.depth = 24,
},
[VPDMA_DATA_FMT_BGR24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGR24_888,
.depth = 24,
},
[VPDMA_DATA_FMT_ABGR32] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_ABGR32_8888,
.depth = 32,
},
[VPDMA_DATA_FMT_BGRA24] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGRA24_6666,
.depth = 24,
},
[VPDMA_DATA_FMT_BGRA32] = {
.type = VPDMA_DATA_FMT_TYPE_RGB,
.data_type = DATA_TYPE_BGRA32_8888,
.depth = 32,
},
};
const struct vpdma_data_format vpdma_misc_fmts[] = {
[VPDMA_DATA_FMT_MV] = {
.type = VPDMA_DATA_FMT_TYPE_MISC,
.data_type = DATA_TYPE_MV,
.depth = 4,
},
};
struct vpdma_channel_info {
int num; /* VPDMA channel number */
int cstat_offset; /* client CSTAT register offset */
};
static const struct vpdma_channel_info chan_info[] = {
[VPE_CHAN_LUMA1_IN] = {
.num = VPE_CHAN_NUM_LUMA1_IN,
.cstat_offset = VPDMA_DEI_LUMA1_CSTAT,
},
[VPE_CHAN_CHROMA1_IN] = {
.num = VPE_CHAN_NUM_CHROMA1_IN,
.cstat_offset = VPDMA_DEI_CHROMA1_CSTAT,
},
[VPE_CHAN_LUMA2_IN] = {
.num = VPE_CHAN_NUM_LUMA2_IN,
.cstat_offset = VPDMA_DEI_LUMA2_CSTAT,
},
[VPE_CHAN_CHROMA2_IN] = {
.num = VPE_CHAN_NUM_CHROMA2_IN,
.cstat_offset = VPDMA_DEI_CHROMA2_CSTAT,
},
[VPE_CHAN_LUMA3_IN] = {
.num = VPE_CHAN_NUM_LUMA3_IN,
.cstat_offset = VPDMA_DEI_LUMA3_CSTAT,
},
[VPE_CHAN_CHROMA3_IN] = {
.num = VPE_CHAN_NUM_CHROMA3_IN,
.cstat_offset = VPDMA_DEI_CHROMA3_CSTAT,
},
[VPE_CHAN_MV_IN] = {
.num = VPE_CHAN_NUM_MV_IN,
.cstat_offset = VPDMA_DEI_MV_IN_CSTAT,
},
[VPE_CHAN_MV_OUT] = {
.num = VPE_CHAN_NUM_MV_OUT,
.cstat_offset = VPDMA_DEI_MV_OUT_CSTAT,
},
[VPE_CHAN_LUMA_OUT] = {
.num = VPE_CHAN_NUM_LUMA_OUT,
.cstat_offset = VPDMA_VIP_UP_Y_CSTAT,
},
[VPE_CHAN_CHROMA_OUT] = {
.num = VPE_CHAN_NUM_CHROMA_OUT,
.cstat_offset = VPDMA_VIP_UP_UV_CSTAT,
},
[VPE_CHAN_RGB_OUT] = {
.num = VPE_CHAN_NUM_RGB_OUT,
.cstat_offset = VPDMA_VIP_UP_Y_CSTAT,
},
};
static u32 read_reg(struct vpdma_data *vpdma, int offset)
{
return ioread32(vpdma->base + offset);
}
static void write_reg(struct vpdma_data *vpdma, int offset, u32 value)
{
iowrite32(value, vpdma->base + offset);
}
static int read_field_reg(struct vpdma_data *vpdma, int offset,
u32 mask, int shift)
{
return (read_reg(vpdma, offset) & (mask << shift)) >> shift;
}
static void write_field_reg(struct vpdma_data *vpdma, int offset, u32 field,
u32 mask, int shift)
{
u32 val = read_reg(vpdma, offset);
val &= ~(mask << shift);
val |= (field & mask) << shift;
write_reg(vpdma, offset, val);
}
void vpdma_dump_regs(struct vpdma_data *vpdma)
{
struct device *dev = &vpdma->pdev->dev;
#define DUMPREG(r) dev_dbg(dev, "%-35s %08x\n", #r, read_reg(vpdma, VPDMA_##r))
dev_dbg(dev, "VPDMA Registers:\n");
DUMPREG(PID);
DUMPREG(LIST_ADDR);
DUMPREG(LIST_ATTR);
DUMPREG(LIST_STAT_SYNC);
DUMPREG(BG_RGB);
DUMPREG(BG_YUV);
DUMPREG(SETUP);
DUMPREG(MAX_SIZE1);
DUMPREG(MAX_SIZE2);
DUMPREG(MAX_SIZE3);
/*
* dumping registers of only group0 and group3, because VPE channels
* lie within group0 and group3 registers
*/
DUMPREG(INT_CHAN_STAT(0));
DUMPREG(INT_CHAN_MASK(0));
DUMPREG(INT_CHAN_STAT(3));
DUMPREG(INT_CHAN_MASK(3));
DUMPREG(INT_CLIENT0_STAT);
DUMPREG(INT_CLIENT0_MASK);
DUMPREG(INT_CLIENT1_STAT);
DUMPREG(INT_CLIENT1_MASK);
DUMPREG(INT_LIST0_STAT);
DUMPREG(INT_LIST0_MASK);
/*
* these are registers specific to VPE clients, we can make this
* function dump client registers specific to VPE or VIP based on
* who is using it
*/
DUMPREG(DEI_CHROMA1_CSTAT);
DUMPREG(DEI_LUMA1_CSTAT);
DUMPREG(DEI_CHROMA2_CSTAT);
DUMPREG(DEI_LUMA2_CSTAT);
DUMPREG(DEI_CHROMA3_CSTAT);
DUMPREG(DEI_LUMA3_CSTAT);
DUMPREG(DEI_MV_IN_CSTAT);
DUMPREG(DEI_MV_OUT_CSTAT);
DUMPREG(VIP_UP_Y_CSTAT);
DUMPREG(VIP_UP_UV_CSTAT);
DUMPREG(VPI_CTL_CSTAT);
}
/*
* Allocate a DMA buffer
*/
int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size)
{
buf->size = size;
buf->mapped = false;
buf->addr = kzalloc(size, GFP_KERNEL);
if (!buf->addr)
return -ENOMEM;
WARN_ON(((unsigned long)buf->addr & VPDMA_DESC_ALIGN) != 0);
return 0;
}
void vpdma_free_desc_buf(struct vpdma_buf *buf)
{
WARN_ON(buf->mapped);
kfree(buf->addr);
buf->addr = NULL;
buf->size = 0;
}
/*
* map descriptor/payload DMA buffer, enabling DMA access
*/
int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf)
{
struct device *dev = &vpdma->pdev->dev;
WARN_ON(buf->mapped);
buf->dma_addr = dma_map_single(dev, buf->addr, buf->size,
DMA_TO_DEVICE);
if (dma_mapping_error(dev, buf->dma_addr)) {
dev_err(dev, "failed to map buffer\n");
return -EINVAL;
}
buf->mapped = true;
return 0;
}
/*
* unmap descriptor/payload DMA buffer, disabling DMA access and
* allowing the main processor to acces the data
*/
void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf)
{
struct device *dev = &vpdma->pdev->dev;
if (buf->mapped)
dma_unmap_single(dev, buf->dma_addr, buf->size, DMA_TO_DEVICE);
buf->mapped = false;
}
/*
* create a descriptor list, the user of this list will append configuration,
* control and data descriptors to this list, this list will be submitted to
* VPDMA. VPDMA's list parser will go through each descriptor and perform the
* required DMA operations
*/
int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type)
{
int r;
r = vpdma_alloc_desc_buf(&list->buf, size);
if (r)
return r;
list->next = list->buf.addr;
list->type = type;
return 0;
}
/*
* once a descriptor list is parsed by VPDMA, we reset the list by emptying it,
* to allow new descriptors to be added to the list.
*/
void vpdma_reset_desc_list(struct vpdma_desc_list *list)
{
list->next = list->buf.addr;
}
/*
* free the buffer allocated fot the VPDMA descriptor list, this should be
* called when the user doesn't want to use VPDMA any more.
*/
void vpdma_free_desc_list(struct vpdma_desc_list *list)
{
vpdma_free_desc_buf(&list->buf);
list->next = NULL;
}
static bool vpdma_list_busy(struct vpdma_data *vpdma, int list_num)
{
return read_reg(vpdma, VPDMA_LIST_STAT_SYNC) & BIT(list_num + 16);
}
/*
* submit a list of DMA descriptors to the VPE VPDMA, do not wait for completion
*/
int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list)
{
/* we always use the first list */
int list_num = 0;
int list_size;
if (vpdma_list_busy(vpdma, list_num))
return -EBUSY;
/* 16-byte granularity */
list_size = (list->next - list->buf.addr) >> 4;
write_reg(vpdma, VPDMA_LIST_ADDR, (u32) list->buf.dma_addr);
write_reg(vpdma, VPDMA_LIST_ATTR,
(list_num << VPDMA_LIST_NUM_SHFT) |
(list->type << VPDMA_LIST_TYPE_SHFT) |
list_size);
return 0;
}
static void dump_cfd(struct vpdma_cfd *cfd)
{
int class;
class = cfd_get_class(cfd);
pr_debug("config descriptor of payload class: %s\n",
class == CFD_CLS_BLOCK ? "simple block" :
"address data block");
if (class == CFD_CLS_BLOCK)
pr_debug("word0: dst_addr_offset = 0x%08x\n",
cfd->dest_addr_offset);
if (class == CFD_CLS_BLOCK)
pr_debug("word1: num_data_wrds = %d\n", cfd->block_len);
pr_debug("word2: payload_addr = 0x%08x\n", cfd->payload_addr);
pr_debug("word3: pkt_type = %d, direct = %d, class = %d, dest = %d, "
"payload_len = %d\n", cfd_get_pkt_type(cfd),
cfd_get_direct(cfd), class, cfd_get_dest(cfd),
cfd_get_payload_len(cfd));
}
/*
* append a configuration descriptor to the given descriptor list, where the
* payload is in the form of a simple data block specified in the descriptor
* header, this is used to upload scaler coefficients to the scaler module
*/
void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
struct vpdma_buf *blk, u32 dest_offset)
{
struct vpdma_cfd *cfd;
int len = blk->size;
WARN_ON(blk->dma_addr & VPDMA_DESC_ALIGN);
cfd = list->next;
WARN_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size));
cfd->dest_addr_offset = dest_offset;
cfd->block_len = len;
cfd->payload_addr = (u32) blk->dma_addr;
cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_BLOCK,
client, len >> 4);
list->next = cfd + 1;
dump_cfd(cfd);
}
/*
* append a configuration descriptor to the given descriptor list, where the
* payload is in the address data block format, this is used to a configure a
* discontiguous set of MMRs
*/
void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client,
struct vpdma_buf *adb)
{
struct vpdma_cfd *cfd;
unsigned int len = adb->size;
WARN_ON(len & VPDMA_ADB_SIZE_ALIGN);
WARN_ON(adb->dma_addr & VPDMA_DESC_ALIGN);
cfd = list->next;
BUG_ON((void *)(cfd + 1) > (list->buf.addr + list->buf.size));
cfd->w0 = 0;
cfd->w1 = 0;
cfd->payload_addr = (u32) adb->dma_addr;
cfd->ctl_payload_len = cfd_pkt_payload_len(CFD_INDIRECT, CFD_CLS_ADB,
client, len >> 4);
list->next = cfd + 1;
dump_cfd(cfd);
};
/*
* control descriptor format change based on what type of control descriptor it
* is, we only use 'sync on channel' control descriptors for now, so assume it's
* that
*/
static void dump_ctd(struct vpdma_ctd *ctd)
{
pr_debug("control descriptor\n");
pr_debug("word3: pkt_type = %d, source = %d, ctl_type = %d\n",
ctd_get_pkt_type(ctd), ctd_get_source(ctd), ctd_get_ctl(ctd));
}
/*
* append a 'sync on channel' type control descriptor to the given descriptor
* list, this descriptor stalls the VPDMA list till the time DMA is completed
* on the specified channel
*/
void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list,
enum vpdma_channel chan)
{
struct vpdma_ctd *ctd;
ctd = list->next;
WARN_ON((void *)(ctd + 1) > (list->buf.addr + list->buf.size));
ctd->w0 = 0;
ctd->w1 = 0;
ctd->w2 = 0;
ctd->type_source_ctl = ctd_type_source_ctl(chan_info[chan].num,
CTD_TYPE_SYNC_ON_CHANNEL);
list->next = ctd + 1;
dump_ctd(ctd);
}
static void dump_dtd(struct vpdma_dtd *dtd)
{
int dir, chan;
dir = dtd_get_dir(dtd);
chan = dtd_get_chan(dtd);
pr_debug("%s data transfer descriptor for channel %d\n",
dir == DTD_DIR_OUT ? "outbound" : "inbound", chan);
pr_debug("word0: data_type = %d, notify = %d, field = %d, 1D = %d, "
"even_ln_skp = %d, odd_ln_skp = %d, line_stride = %d\n",
dtd_get_data_type(dtd), dtd_get_notify(dtd), dtd_get_field(dtd),
dtd_get_1d(dtd), dtd_get_even_line_skip(dtd),
dtd_get_odd_line_skip(dtd), dtd_get_line_stride(dtd));
if (dir == DTD_DIR_IN)
pr_debug("word1: line_length = %d, xfer_height = %d\n",
dtd_get_line_length(dtd), dtd_get_xfer_height(dtd));
pr_debug("word2: start_addr = %pad\n", &dtd->start_addr);
pr_debug("word3: pkt_type = %d, mode = %d, dir = %d, chan = %d, "
"pri = %d, next_chan = %d\n", dtd_get_pkt_type(dtd),
dtd_get_mode(dtd), dir, chan, dtd_get_priority(dtd),
dtd_get_next_chan(dtd));
if (dir == DTD_DIR_IN)
pr_debug("word4: frame_width = %d, frame_height = %d\n",
dtd_get_frame_width(dtd), dtd_get_frame_height(dtd));
else
pr_debug("word4: desc_write_addr = 0x%08x, write_desc = %d, "
"drp_data = %d, use_desc_reg = %d\n",
dtd_get_desc_write_addr(dtd), dtd_get_write_desc(dtd),
dtd_get_drop_data(dtd), dtd_get_use_desc(dtd));
if (dir == DTD_DIR_IN)
pr_debug("word5: hor_start = %d, ver_start = %d\n",
dtd_get_h_start(dtd), dtd_get_v_start(dtd));
else
pr_debug("word5: max_width %d, max_height %d\n",
dtd_get_max_width(dtd), dtd_get_max_height(dtd));
pr_debug("word6: client specific attr0 = 0x%08x\n", dtd->client_attr0);
pr_debug("word7: client specific attr1 = 0x%08x\n", dtd->client_attr1);
}
/*
* append an outbound data transfer descriptor to the given descriptor list,
* this sets up a 'client to memory' VPDMA transfer for the given VPDMA channel
*
* @list: vpdma desc list to which we add this decriptor
* @width: width of the image in pixels in memory
* @c_rect: compose params of output image
* @fmt: vpdma data format of the buffer
* dma_addr: dma address as seen by VPDMA
* chan: VPDMA channel
* flags: VPDMA flags to configure some descriptor fileds
*/
void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
const struct v4l2_rect *c_rect,
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
enum vpdma_channel chan, u32 flags)
{
int priority = 0;
int field = 0;
int notify = 1;
int channel, next_chan;
struct v4l2_rect rect = *c_rect;
int depth = fmt->depth;
int stride;
struct vpdma_dtd *dtd;
channel = next_chan = chan_info[chan].num;
if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV &&
fmt->data_type == DATA_TYPE_C420) {
rect.height >>= 1;
rect.top >>= 1;
depth = 8;
}
stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN);
dma_addr += rect.top * stride + (rect.left * depth >> 3);
dtd = list->next;
WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size));
dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type,
notify,
field,
!!(flags & VPDMA_DATA_FRAME_1D),
!!(flags & VPDMA_DATA_EVEN_LINE_SKIP),
!!(flags & VPDMA_DATA_ODD_LINE_SKIP),
stride);
dtd->w1 = 0;
dtd->start_addr = (u32) dma_addr;
dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED),
DTD_DIR_OUT, channel, priority, next_chan);
dtd->desc_write_addr = dtd_desc_write_addr(0, 0, 0, 0);
dtd->max_width_height = dtd_max_width_height(MAX_OUT_WIDTH_1920,
MAX_OUT_HEIGHT_1080);
dtd->client_attr0 = 0;
dtd->client_attr1 = 0;
list->next = dtd + 1;
dump_dtd(dtd);
}
/*
* append an inbound data transfer descriptor to the given descriptor list,
* this sets up a 'memory to client' VPDMA transfer for the given VPDMA channel
*
* @list: vpdma desc list to which we add this decriptor
* @width: width of the image in pixels in memory(not the cropped width)
* @c_rect: crop params of input image
* @fmt: vpdma data format of the buffer
* dma_addr: dma address as seen by VPDMA
* chan: VPDMA channel
* field: top or bottom field info of the input image
* flags: VPDMA flags to configure some descriptor fileds
* frame_width/height: the complete width/height of the image presented to the
* client (this makes sense when multiple channels are
* connected to the same client, forming a larger frame)
* start_h, start_v: position where the given channel starts providing pixel
* data to the client (makes sense when multiple channels
* contribute to the client)
*/
void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width,
const struct v4l2_rect *c_rect,
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
enum vpdma_channel chan, int field, u32 flags, int frame_width,
int frame_height, int start_h, int start_v)
{
int priority = 0;
int notify = 1;
int depth = fmt->depth;
int channel, next_chan;
struct v4l2_rect rect = *c_rect;
int stride;
struct vpdma_dtd *dtd;
channel = next_chan = chan_info[chan].num;
if (fmt->type == VPDMA_DATA_FMT_TYPE_YUV &&
fmt->data_type == DATA_TYPE_C420) {
rect.height >>= 1;
rect.top >>= 1;
depth = 8;
}
stride = ALIGN((depth * width) >> 3, VPDMA_STRIDE_ALIGN);
dma_addr += rect.top * stride + (rect.left * depth >> 3);
dtd = list->next;
WARN_ON((void *)(dtd + 1) > (list->buf.addr + list->buf.size));
dtd->type_ctl_stride = dtd_type_ctl_stride(fmt->data_type,
notify,
field,
!!(flags & VPDMA_DATA_FRAME_1D),
!!(flags & VPDMA_DATA_EVEN_LINE_SKIP),
!!(flags & VPDMA_DATA_ODD_LINE_SKIP),
stride);
dtd->xfer_length_height = dtd_xfer_length_height(rect.width,
rect.height);
dtd->start_addr = (u32) dma_addr;
dtd->pkt_ctl = dtd_pkt_ctl(!!(flags & VPDMA_DATA_MODE_TILED),
DTD_DIR_IN, channel, priority, next_chan);
dtd->frame_width_height = dtd_frame_width_height(frame_width,
frame_height);
dtd->start_h_v = dtd_start_h_v(start_h, start_v);
dtd->client_attr0 = 0;
dtd->client_attr1 = 0;
list->next = dtd + 1;
dump_dtd(dtd);
}
/* set or clear the mask for list complete interrupt */
void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
bool enable)
{
u32 val;
val = read_reg(vpdma, VPDMA_INT_LIST0_MASK);
if (enable)
val |= (1 << (list_num * 2));
else
val &= ~(1 << (list_num * 2));
write_reg(vpdma, VPDMA_INT_LIST0_MASK, val);
}
/* clear previosuly occured list intterupts in the LIST_STAT register */
void vpdma_clear_list_stat(struct vpdma_data *vpdma)
{
write_reg(vpdma, VPDMA_INT_LIST0_STAT,
read_reg(vpdma, VPDMA_INT_LIST0_STAT));
}
/*
* configures the output mode of the line buffer for the given client, the
* line buffer content can either be mirrored(each line repeated twice) or
* passed to the client as is
*/
void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode,
enum vpdma_channel chan)
{
int client_cstat = chan_info[chan].cstat_offset;
write_field_reg(vpdma, client_cstat, line_mode,
VPDMA_CSTAT_LINE_MODE_MASK, VPDMA_CSTAT_LINE_MODE_SHIFT);
}
/*
* configures the event which should trigger VPDMA transfer for the given
* client
*/
void vpdma_set_frame_start_event(struct vpdma_data *vpdma,
enum vpdma_frame_start_event fs_event,
enum vpdma_channel chan)
{
int client_cstat = chan_info[chan].cstat_offset;
write_field_reg(vpdma, client_cstat, fs_event,
VPDMA_CSTAT_FRAME_START_MASK, VPDMA_CSTAT_FRAME_START_SHIFT);
}
static void vpdma_firmware_cb(const struct firmware *f, void *context)
{
struct vpdma_data *vpdma = context;
struct vpdma_buf fw_dma_buf;
int i, r;
dev_dbg(&vpdma->pdev->dev, "firmware callback\n");
if (!f || !f->data) {
dev_err(&vpdma->pdev->dev, "couldn't get firmware\n");
return;
}
/* already initialized */
if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK,
VPDMA_LIST_RDY_SHFT)) {
vpdma->cb(vpdma->pdev);
return;
}
r = vpdma_alloc_desc_buf(&fw_dma_buf, f->size);
if (r) {
dev_err(&vpdma->pdev->dev,
"failed to allocate dma buffer for firmware\n");
goto rel_fw;
}
memcpy(fw_dma_buf.addr, f->data, f->size);
vpdma_map_desc_buf(vpdma, &fw_dma_buf);
write_reg(vpdma, VPDMA_LIST_ADDR, (u32) fw_dma_buf.dma_addr);
for (i = 0; i < 100; i++) { /* max 1 second */
msleep_interruptible(10);
if (read_field_reg(vpdma, VPDMA_LIST_ATTR, VPDMA_LIST_RDY_MASK,
VPDMA_LIST_RDY_SHFT))
break;
}
if (i == 100) {
dev_err(&vpdma->pdev->dev, "firmware upload failed\n");
goto free_buf;
}
vpdma->cb(vpdma->pdev);
free_buf:
vpdma_unmap_desc_buf(vpdma, &fw_dma_buf);
vpdma_free_desc_buf(&fw_dma_buf);
rel_fw:
release_firmware(f);
}
static int vpdma_load_firmware(struct vpdma_data *vpdma)
{
int r;
struct device *dev = &vpdma->pdev->dev;
r = request_firmware_nowait(THIS_MODULE, 1,
(const char *) VPDMA_FIRMWARE, dev, GFP_KERNEL, vpdma,
vpdma_firmware_cb);
if (r) {
dev_err(dev, "firmware not available %s\n", VPDMA_FIRMWARE);
return r;
} else {
dev_info(dev, "loading firmware %s\n", VPDMA_FIRMWARE);
}
return 0;
}
struct vpdma_data *vpdma_create(struct platform_device *pdev,
void (*cb)(struct platform_device *pdev))
{
struct resource *res;
struct vpdma_data *vpdma;
int r;
dev_dbg(&pdev->dev, "vpdma_create\n");
vpdma = devm_kzalloc(&pdev->dev, sizeof(*vpdma), GFP_KERNEL);
if (!vpdma) {
dev_err(&pdev->dev, "couldn't alloc vpdma_dev\n");
return ERR_PTR(-ENOMEM);
}
vpdma->pdev = pdev;
vpdma->cb = cb;
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "vpdma");
if (res == NULL) {
dev_err(&pdev->dev, "missing platform resources data\n");
return ERR_PTR(-ENODEV);
}
vpdma->base = devm_ioremap(&pdev->dev, res->start, resource_size(res));
if (!vpdma->base) {
dev_err(&pdev->dev, "failed to ioremap\n");
return ERR_PTR(-ENOMEM);
}
r = vpdma_load_firmware(vpdma);
if (r) {
pr_err("failed to load firmware %s\n", VPDMA_FIRMWARE);
return ERR_PTR(r);
}
return vpdma;
}
MODULE_FIRMWARE(VPDMA_FIRMWARE);

View file

@ -0,0 +1,216 @@
/*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef __TI_VPDMA_H_
#define __TI_VPDMA_H_
/*
* A vpdma_buf tracks the size, DMA address and mapping status of each
* driver DMA area.
*/
struct vpdma_buf {
void *addr;
dma_addr_t dma_addr;
size_t size;
bool mapped;
};
struct vpdma_desc_list {
struct vpdma_buf buf;
void *next;
int type;
};
struct vpdma_data {
void __iomem *base;
struct platform_device *pdev;
/* callback to VPE driver when the firmware is loaded */
void (*cb)(struct platform_device *pdev);
};
enum vpdma_data_format_type {
VPDMA_DATA_FMT_TYPE_YUV,
VPDMA_DATA_FMT_TYPE_RGB,
VPDMA_DATA_FMT_TYPE_MISC,
};
struct vpdma_data_format {
enum vpdma_data_format_type type;
int data_type;
u8 depth;
};
#define VPDMA_DESC_ALIGN 16 /* 16-byte descriptor alignment */
#define VPDMA_STRIDE_ALIGN 16 /*
* line stride of source and dest
* buffers should be 16 byte aligned
*/
#define VPDMA_DTD_DESC_SIZE 32 /* 8 words */
#define VPDMA_CFD_CTD_DESC_SIZE 16 /* 4 words */
#define VPDMA_LIST_TYPE_NORMAL 0
#define VPDMA_LIST_TYPE_SELF_MODIFYING 1
#define VPDMA_LIST_TYPE_DOORBELL 2
enum vpdma_yuv_formats {
VPDMA_DATA_FMT_Y444 = 0,
VPDMA_DATA_FMT_Y422,
VPDMA_DATA_FMT_Y420,
VPDMA_DATA_FMT_C444,
VPDMA_DATA_FMT_C422,
VPDMA_DATA_FMT_C420,
VPDMA_DATA_FMT_YC422,
VPDMA_DATA_FMT_YC444,
VPDMA_DATA_FMT_CY422,
};
enum vpdma_rgb_formats {
VPDMA_DATA_FMT_RGB565 = 0,
VPDMA_DATA_FMT_ARGB16_1555,
VPDMA_DATA_FMT_ARGB16,
VPDMA_DATA_FMT_RGBA16_5551,
VPDMA_DATA_FMT_RGBA16,
VPDMA_DATA_FMT_ARGB24,
VPDMA_DATA_FMT_RGB24,
VPDMA_DATA_FMT_ARGB32,
VPDMA_DATA_FMT_RGBA24,
VPDMA_DATA_FMT_RGBA32,
VPDMA_DATA_FMT_BGR565,
VPDMA_DATA_FMT_ABGR16_1555,
VPDMA_DATA_FMT_ABGR16,
VPDMA_DATA_FMT_BGRA16_5551,
VPDMA_DATA_FMT_BGRA16,
VPDMA_DATA_FMT_ABGR24,
VPDMA_DATA_FMT_BGR24,
VPDMA_DATA_FMT_ABGR32,
VPDMA_DATA_FMT_BGRA24,
VPDMA_DATA_FMT_BGRA32,
};
enum vpdma_misc_formats {
VPDMA_DATA_FMT_MV = 0,
};
extern const struct vpdma_data_format vpdma_yuv_fmts[];
extern const struct vpdma_data_format vpdma_rgb_fmts[];
extern const struct vpdma_data_format vpdma_misc_fmts[];
enum vpdma_frame_start_event {
VPDMA_FSEVENT_HDMI_FID = 0,
VPDMA_FSEVENT_DVO2_FID,
VPDMA_FSEVENT_HDCOMP_FID,
VPDMA_FSEVENT_SD_FID,
VPDMA_FSEVENT_LM_FID0,
VPDMA_FSEVENT_LM_FID1,
VPDMA_FSEVENT_LM_FID2,
VPDMA_FSEVENT_CHANNEL_ACTIVE,
};
/*
* VPDMA channel numbers
*/
enum vpdma_channel {
VPE_CHAN_LUMA1_IN,
VPE_CHAN_CHROMA1_IN,
VPE_CHAN_LUMA2_IN,
VPE_CHAN_CHROMA2_IN,
VPE_CHAN_LUMA3_IN,
VPE_CHAN_CHROMA3_IN,
VPE_CHAN_MV_IN,
VPE_CHAN_MV_OUT,
VPE_CHAN_LUMA_OUT,
VPE_CHAN_CHROMA_OUT,
VPE_CHAN_RGB_OUT,
};
/* flags for VPDMA data descriptors */
#define VPDMA_DATA_ODD_LINE_SKIP (1 << 0)
#define VPDMA_DATA_EVEN_LINE_SKIP (1 << 1)
#define VPDMA_DATA_FRAME_1D (1 << 2)
#define VPDMA_DATA_MODE_TILED (1 << 3)
/*
* client identifiers used for configuration descriptors
*/
#define CFD_MMR_CLIENT 0
#define CFD_SC_CLIENT 4
/* Address data block header format */
struct vpdma_adb_hdr {
u32 offset;
u32 nwords;
u32 reserved0;
u32 reserved1;
};
/* helpers for creating ADB headers for config descriptors MMRs as client */
#define ADB_ADDR(dma_buf, str, fld) ((dma_buf)->addr + offsetof(str, fld))
#define MMR_ADB_ADDR(buf, str, fld) ADB_ADDR(&(buf), struct str, fld)
#define VPDMA_SET_MMR_ADB_HDR(buf, str, hdr, regs, offset_a) \
do { \
struct vpdma_adb_hdr *h; \
struct str *adb = NULL; \
h = MMR_ADB_ADDR(buf, str, hdr); \
h->offset = (offset_a); \
h->nwords = sizeof(adb->regs) >> 2; \
} while (0)
/* vpdma descriptor buffer allocation and management */
int vpdma_alloc_desc_buf(struct vpdma_buf *buf, size_t size);
void vpdma_free_desc_buf(struct vpdma_buf *buf);
int vpdma_map_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf);
void vpdma_unmap_desc_buf(struct vpdma_data *vpdma, struct vpdma_buf *buf);
/* vpdma descriptor list funcs */
int vpdma_create_desc_list(struct vpdma_desc_list *list, size_t size, int type);
void vpdma_reset_desc_list(struct vpdma_desc_list *list);
void vpdma_free_desc_list(struct vpdma_desc_list *list);
int vpdma_submit_descs(struct vpdma_data *vpdma, struct vpdma_desc_list *list);
/* helpers for creating vpdma descriptors */
void vpdma_add_cfd_block(struct vpdma_desc_list *list, int client,
struct vpdma_buf *blk, u32 dest_offset);
void vpdma_add_cfd_adb(struct vpdma_desc_list *list, int client,
struct vpdma_buf *adb);
void vpdma_add_sync_on_channel_ctd(struct vpdma_desc_list *list,
enum vpdma_channel chan);
void vpdma_add_out_dtd(struct vpdma_desc_list *list, int width,
const struct v4l2_rect *c_rect,
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
enum vpdma_channel chan, u32 flags);
void vpdma_add_in_dtd(struct vpdma_desc_list *list, int width,
const struct v4l2_rect *c_rect,
const struct vpdma_data_format *fmt, dma_addr_t dma_addr,
enum vpdma_channel chan, int field, u32 flags, int frame_width,
int frame_height, int start_h, int start_v);
/* vpdma list interrupt management */
void vpdma_enable_list_complete_irq(struct vpdma_data *vpdma, int list_num,
bool enable);
void vpdma_clear_list_stat(struct vpdma_data *vpdma);
/* vpdma client configuration */
void vpdma_set_line_mode(struct vpdma_data *vpdma, int line_mode,
enum vpdma_channel chan);
void vpdma_set_frame_start_event(struct vpdma_data *vpdma,
enum vpdma_frame_start_event fs_event, enum vpdma_channel chan);
void vpdma_dump_regs(struct vpdma_data *vpdma);
/* initialize vpdma, passed with VPE's platform device pointer */
struct vpdma_data *vpdma_create(struct platform_device *pdev,
void (*cb)(struct platform_device *pdev));
#endif

View file

@ -0,0 +1,641 @@
/*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef _TI_VPDMA_PRIV_H_
#define _TI_VPDMA_PRIV_H_
/*
* VPDMA Register offsets
*/
/* Top level */
#define VPDMA_PID 0x00
#define VPDMA_LIST_ADDR 0x04
#define VPDMA_LIST_ATTR 0x08
#define VPDMA_LIST_STAT_SYNC 0x0c
#define VPDMA_BG_RGB 0x18
#define VPDMA_BG_YUV 0x1c
#define VPDMA_SETUP 0x30
#define VPDMA_MAX_SIZE1 0x34
#define VPDMA_MAX_SIZE2 0x38
#define VPDMA_MAX_SIZE3 0x3c
/* Interrupts */
#define VPDMA_INT_CHAN_STAT(grp) (0x40 + grp * 8)
#define VPDMA_INT_CHAN_MASK(grp) (VPDMA_INT_CHAN_STAT(grp) + 4)
#define VPDMA_INT_CLIENT0_STAT 0x78
#define VPDMA_INT_CLIENT0_MASK 0x7c
#define VPDMA_INT_CLIENT1_STAT 0x80
#define VPDMA_INT_CLIENT1_MASK 0x84
#define VPDMA_INT_LIST0_STAT 0x88
#define VPDMA_INT_LIST0_MASK 0x8c
#define VPDMA_PERFMON(i) (0x200 + i * 4)
/* VPE specific client registers */
#define VPDMA_DEI_CHROMA1_CSTAT 0x0300
#define VPDMA_DEI_LUMA1_CSTAT 0x0304
#define VPDMA_DEI_LUMA2_CSTAT 0x0308
#define VPDMA_DEI_CHROMA2_CSTAT 0x030c
#define VPDMA_DEI_LUMA3_CSTAT 0x0310
#define VPDMA_DEI_CHROMA3_CSTAT 0x0314
#define VPDMA_DEI_MV_IN_CSTAT 0x0330
#define VPDMA_DEI_MV_OUT_CSTAT 0x033c
#define VPDMA_VIP_UP_Y_CSTAT 0x0390
#define VPDMA_VIP_UP_UV_CSTAT 0x0394
#define VPDMA_VPI_CTL_CSTAT 0x03d0
/* Reg field info for VPDMA_CLIENT_CSTAT registers */
#define VPDMA_CSTAT_LINE_MODE_MASK 0x03
#define VPDMA_CSTAT_LINE_MODE_SHIFT 8
#define VPDMA_CSTAT_FRAME_START_MASK 0xf
#define VPDMA_CSTAT_FRAME_START_SHIFT 10
#define VPDMA_LIST_NUM_MASK 0x07
#define VPDMA_LIST_NUM_SHFT 24
#define VPDMA_LIST_STOP_SHFT 20
#define VPDMA_LIST_RDY_MASK 0x01
#define VPDMA_LIST_RDY_SHFT 19
#define VPDMA_LIST_TYPE_MASK 0x03
#define VPDMA_LIST_TYPE_SHFT 16
#define VPDMA_LIST_SIZE_MASK 0xffff
/* VPDMA data type values for data formats */
#define DATA_TYPE_Y444 0x0
#define DATA_TYPE_Y422 0x1
#define DATA_TYPE_Y420 0x2
#define DATA_TYPE_C444 0x4
#define DATA_TYPE_C422 0x5
#define DATA_TYPE_C420 0x6
#define DATA_TYPE_YC422 0x7
#define DATA_TYPE_YC444 0x8
#define DATA_TYPE_CY422 0x27
#define DATA_TYPE_RGB16_565 0x0
#define DATA_TYPE_ARGB_1555 0x1
#define DATA_TYPE_ARGB_4444 0x2
#define DATA_TYPE_RGBA_5551 0x3
#define DATA_TYPE_RGBA_4444 0x4
#define DATA_TYPE_ARGB24_6666 0x5
#define DATA_TYPE_RGB24_888 0x6
#define DATA_TYPE_ARGB32_8888 0x7
#define DATA_TYPE_RGBA24_6666 0x8
#define DATA_TYPE_RGBA32_8888 0x9
#define DATA_TYPE_BGR16_565 0x10
#define DATA_TYPE_ABGR_1555 0x11
#define DATA_TYPE_ABGR_4444 0x12
#define DATA_TYPE_BGRA_5551 0x13
#define DATA_TYPE_BGRA_4444 0x14
#define DATA_TYPE_ABGR24_6666 0x15
#define DATA_TYPE_BGR24_888 0x16
#define DATA_TYPE_ABGR32_8888 0x17
#define DATA_TYPE_BGRA24_6666 0x18
#define DATA_TYPE_BGRA32_8888 0x19
#define DATA_TYPE_MV 0x3
/* VPDMA channel numbers(only VPE channels for now) */
#define VPE_CHAN_NUM_LUMA1_IN 0
#define VPE_CHAN_NUM_CHROMA1_IN 1
#define VPE_CHAN_NUM_LUMA2_IN 2
#define VPE_CHAN_NUM_CHROMA2_IN 3
#define VPE_CHAN_NUM_LUMA3_IN 4
#define VPE_CHAN_NUM_CHROMA3_IN 5
#define VPE_CHAN_NUM_MV_IN 12
#define VPE_CHAN_NUM_MV_OUT 15
#define VPE_CHAN_NUM_LUMA_OUT 102
#define VPE_CHAN_NUM_CHROMA_OUT 103
#define VPE_CHAN_NUM_RGB_OUT 106
/*
* a VPDMA address data block payload for a configuration descriptor needs to
* have each sub block length as a multiple of 16 bytes. Therefore, the overall
* size of the payload also needs to be a multiple of 16 bytes. The sub block
* lengths should be ensured to be aligned by the VPDMA user.
*/
#define VPDMA_ADB_SIZE_ALIGN 0x0f
/*
* data transfer descriptor
*/
struct vpdma_dtd {
u32 type_ctl_stride;
union {
u32 xfer_length_height;
u32 w1;
};
dma_addr_t start_addr;
u32 pkt_ctl;
union {
u32 frame_width_height; /* inbound */
dma_addr_t desc_write_addr; /* outbound */
};
union {
u32 start_h_v; /* inbound */
u32 max_width_height; /* outbound */
};
u32 client_attr0;
u32 client_attr1;
};
/* Data Transfer Descriptor specifics */
#define DTD_NO_NOTIFY 0
#define DTD_NOTIFY 1
#define DTD_PKT_TYPE 0xa
#define DTD_DIR_IN 0
#define DTD_DIR_OUT 1
/* type_ctl_stride */
#define DTD_DATA_TYPE_MASK 0x3f
#define DTD_DATA_TYPE_SHFT 26
#define DTD_NOTIFY_MASK 0x01
#define DTD_NOTIFY_SHFT 25
#define DTD_FIELD_MASK 0x01
#define DTD_FIELD_SHFT 24
#define DTD_1D_MASK 0x01
#define DTD_1D_SHFT 23
#define DTD_EVEN_LINE_SKIP_MASK 0x01
#define DTD_EVEN_LINE_SKIP_SHFT 20
#define DTD_ODD_LINE_SKIP_MASK 0x01
#define DTD_ODD_LINE_SKIP_SHFT 16
#define DTD_LINE_STRIDE_MASK 0xffff
#define DTD_LINE_STRIDE_SHFT 0
/* xfer_length_height */
#define DTD_LINE_LENGTH_MASK 0xffff
#define DTD_LINE_LENGTH_SHFT 16
#define DTD_XFER_HEIGHT_MASK 0xffff
#define DTD_XFER_HEIGHT_SHFT 0
/* pkt_ctl */
#define DTD_PKT_TYPE_MASK 0x1f
#define DTD_PKT_TYPE_SHFT 27
#define DTD_MODE_MASK 0x01
#define DTD_MODE_SHFT 26
#define DTD_DIR_MASK 0x01
#define DTD_DIR_SHFT 25
#define DTD_CHAN_MASK 0x01ff
#define DTD_CHAN_SHFT 16
#define DTD_PRI_MASK 0x0f
#define DTD_PRI_SHFT 9
#define DTD_NEXT_CHAN_MASK 0x01ff
#define DTD_NEXT_CHAN_SHFT 0
/* frame_width_height */
#define DTD_FRAME_WIDTH_MASK 0xffff
#define DTD_FRAME_WIDTH_SHFT 16
#define DTD_FRAME_HEIGHT_MASK 0xffff
#define DTD_FRAME_HEIGHT_SHFT 0
/* start_h_v */
#define DTD_H_START_MASK 0xffff
#define DTD_H_START_SHFT 16
#define DTD_V_START_MASK 0xffff
#define DTD_V_START_SHFT 0
#define DTD_DESC_START_SHIFT 5
#define DTD_WRITE_DESC_MASK 0x01
#define DTD_WRITE_DESC_SHIFT 2
#define DTD_DROP_DATA_MASK 0x01
#define DTD_DROP_DATA_SHIFT 1
#define DTD_USE_DESC_MASK 0x01
#define DTD_USE_DESC_SHIFT 0
/* max_width_height */
#define DTD_MAX_WIDTH_MASK 0x07
#define DTD_MAX_WIDTH_SHFT 4
#define DTD_MAX_HEIGHT_MASK 0x07
#define DTD_MAX_HEIGHT_SHFT 0
/* max width configurations */
/* unlimited width */
#define MAX_OUT_WIDTH_UNLIMITED 0
/* as specified in max_size1 reg */
#define MAX_OUT_WIDTH_REG1 1
/* as specified in max_size2 reg */
#define MAX_OUT_WIDTH_REG2 2
/* as specified in max_size3 reg */
#define MAX_OUT_WIDTH_REG3 3
/* maximum of 352 pixels as width */
#define MAX_OUT_WIDTH_352 4
/* maximum of 768 pixels as width */
#define MAX_OUT_WIDTH_768 5
/* maximum of 1280 pixels width */
#define MAX_OUT_WIDTH_1280 6
/* maximum of 1920 pixels as width */
#define MAX_OUT_WIDTH_1920 7
/* max height configurations */
/* unlimited height */
#define MAX_OUT_HEIGHT_UNLIMITED 0
/* as specified in max_size1 reg */
#define MAX_OUT_HEIGHT_REG1 1
/* as specified in max_size2 reg */
#define MAX_OUT_HEIGHT_REG2 2
/* as specified in max_size3 reg */
#define MAX_OUT_HEIGHT_REG3 3
/* maximum of 288 lines as height */
#define MAX_OUT_HEIGHT_288 4
/* maximum of 576 lines as height */
#define MAX_OUT_HEIGHT_576 5
/* maximum of 720 lines as height */
#define MAX_OUT_HEIGHT_720 6
/* maximum of 1080 lines as height */
#define MAX_OUT_HEIGHT_1080 7
static inline u32 dtd_type_ctl_stride(int type, bool notify, int field,
bool one_d, bool even_line_skip, bool odd_line_skip,
int line_stride)
{
return (type << DTD_DATA_TYPE_SHFT) | (notify << DTD_NOTIFY_SHFT) |
(field << DTD_FIELD_SHFT) | (one_d << DTD_1D_SHFT) |
(even_line_skip << DTD_EVEN_LINE_SKIP_SHFT) |
(odd_line_skip << DTD_ODD_LINE_SKIP_SHFT) |
line_stride;
}
static inline u32 dtd_xfer_length_height(int line_length, int xfer_height)
{
return (line_length << DTD_LINE_LENGTH_SHFT) | xfer_height;
}
static inline u32 dtd_pkt_ctl(bool mode, bool dir, int chan, int pri,
int next_chan)
{
return (DTD_PKT_TYPE << DTD_PKT_TYPE_SHFT) | (mode << DTD_MODE_SHFT) |
(dir << DTD_DIR_SHFT) | (chan << DTD_CHAN_SHFT) |
(pri << DTD_PRI_SHFT) | next_chan;
}
static inline u32 dtd_frame_width_height(int width, int height)
{
return (width << DTD_FRAME_WIDTH_SHFT) | height;
}
static inline u32 dtd_desc_write_addr(unsigned int addr, bool write_desc,
bool drop_data, bool use_desc)
{
return (addr << DTD_DESC_START_SHIFT) |
(write_desc << DTD_WRITE_DESC_SHIFT) |
(drop_data << DTD_DROP_DATA_SHIFT) |
use_desc;
}
static inline u32 dtd_start_h_v(int h_start, int v_start)
{
return (h_start << DTD_H_START_SHFT) | v_start;
}
static inline u32 dtd_max_width_height(int max_width, int max_height)
{
return (max_width << DTD_MAX_WIDTH_SHFT) | max_height;
}
static inline int dtd_get_data_type(struct vpdma_dtd *dtd)
{
return dtd->type_ctl_stride >> DTD_DATA_TYPE_SHFT;
}
static inline bool dtd_get_notify(struct vpdma_dtd *dtd)
{
return (dtd->type_ctl_stride >> DTD_NOTIFY_SHFT) & DTD_NOTIFY_MASK;
}
static inline int dtd_get_field(struct vpdma_dtd *dtd)
{
return (dtd->type_ctl_stride >> DTD_FIELD_SHFT) & DTD_FIELD_MASK;
}
static inline bool dtd_get_1d(struct vpdma_dtd *dtd)
{
return (dtd->type_ctl_stride >> DTD_1D_SHFT) & DTD_1D_MASK;
}
static inline bool dtd_get_even_line_skip(struct vpdma_dtd *dtd)
{
return (dtd->type_ctl_stride >> DTD_EVEN_LINE_SKIP_SHFT)
& DTD_EVEN_LINE_SKIP_MASK;
}
static inline bool dtd_get_odd_line_skip(struct vpdma_dtd *dtd)
{
return (dtd->type_ctl_stride >> DTD_ODD_LINE_SKIP_SHFT)
& DTD_ODD_LINE_SKIP_MASK;
}
static inline int dtd_get_line_stride(struct vpdma_dtd *dtd)
{
return dtd->type_ctl_stride & DTD_LINE_STRIDE_MASK;
}
static inline int dtd_get_line_length(struct vpdma_dtd *dtd)
{
return dtd->xfer_length_height >> DTD_LINE_LENGTH_SHFT;
}
static inline int dtd_get_xfer_height(struct vpdma_dtd *dtd)
{
return dtd->xfer_length_height & DTD_XFER_HEIGHT_MASK;
}
static inline int dtd_get_pkt_type(struct vpdma_dtd *dtd)
{
return dtd->pkt_ctl >> DTD_PKT_TYPE_SHFT;
}
static inline bool dtd_get_mode(struct vpdma_dtd *dtd)
{
return (dtd->pkt_ctl >> DTD_MODE_SHFT) & DTD_MODE_MASK;
}
static inline bool dtd_get_dir(struct vpdma_dtd *dtd)
{
return (dtd->pkt_ctl >> DTD_DIR_SHFT) & DTD_DIR_MASK;
}
static inline int dtd_get_chan(struct vpdma_dtd *dtd)
{
return (dtd->pkt_ctl >> DTD_CHAN_SHFT) & DTD_CHAN_MASK;
}
static inline int dtd_get_priority(struct vpdma_dtd *dtd)
{
return (dtd->pkt_ctl >> DTD_PRI_SHFT) & DTD_PRI_MASK;
}
static inline int dtd_get_next_chan(struct vpdma_dtd *dtd)
{
return (dtd->pkt_ctl >> DTD_NEXT_CHAN_SHFT) & DTD_NEXT_CHAN_MASK;
}
static inline int dtd_get_frame_width(struct vpdma_dtd *dtd)
{
return dtd->frame_width_height >> DTD_FRAME_WIDTH_SHFT;
}
static inline int dtd_get_frame_height(struct vpdma_dtd *dtd)
{
return dtd->frame_width_height & DTD_FRAME_HEIGHT_MASK;
}
static inline int dtd_get_desc_write_addr(struct vpdma_dtd *dtd)
{
return dtd->desc_write_addr >> DTD_DESC_START_SHIFT;
}
static inline bool dtd_get_write_desc(struct vpdma_dtd *dtd)
{
return (dtd->desc_write_addr >> DTD_WRITE_DESC_SHIFT) &
DTD_WRITE_DESC_MASK;
}
static inline bool dtd_get_drop_data(struct vpdma_dtd *dtd)
{
return (dtd->desc_write_addr >> DTD_DROP_DATA_SHIFT) &
DTD_DROP_DATA_MASK;
}
static inline bool dtd_get_use_desc(struct vpdma_dtd *dtd)
{
return dtd->desc_write_addr & DTD_USE_DESC_MASK;
}
static inline int dtd_get_h_start(struct vpdma_dtd *dtd)
{
return dtd->start_h_v >> DTD_H_START_SHFT;
}
static inline int dtd_get_v_start(struct vpdma_dtd *dtd)
{
return dtd->start_h_v & DTD_V_START_MASK;
}
static inline int dtd_get_max_width(struct vpdma_dtd *dtd)
{
return (dtd->max_width_height >> DTD_MAX_WIDTH_SHFT) &
DTD_MAX_WIDTH_MASK;
}
static inline int dtd_get_max_height(struct vpdma_dtd *dtd)
{
return (dtd->max_width_height >> DTD_MAX_HEIGHT_SHFT) &
DTD_MAX_HEIGHT_MASK;
}
/*
* configuration descriptor
*/
struct vpdma_cfd {
union {
u32 dest_addr_offset;
u32 w0;
};
union {
u32 block_len; /* in words */
u32 w1;
};
u32 payload_addr;
u32 ctl_payload_len; /* in words */
};
/* Configuration descriptor specifics */
#define CFD_PKT_TYPE 0xb
#define CFD_DIRECT 1
#define CFD_INDIRECT 0
#define CFD_CLS_ADB 0
#define CFD_CLS_BLOCK 1
/* block_len */
#define CFD__BLOCK_LEN_MASK 0xffff
#define CFD__BLOCK_LEN_SHFT 0
/* ctl_payload_len */
#define CFD_PKT_TYPE_MASK 0x1f
#define CFD_PKT_TYPE_SHFT 27
#define CFD_DIRECT_MASK 0x01
#define CFD_DIRECT_SHFT 26
#define CFD_CLASS_MASK 0x03
#define CFD_CLASS_SHFT 24
#define CFD_DEST_MASK 0xff
#define CFD_DEST_SHFT 16
#define CFD_PAYLOAD_LEN_MASK 0xffff
#define CFD_PAYLOAD_LEN_SHFT 0
static inline u32 cfd_pkt_payload_len(bool direct, int cls, int dest,
int payload_len)
{
return (CFD_PKT_TYPE << CFD_PKT_TYPE_SHFT) |
(direct << CFD_DIRECT_SHFT) |
(cls << CFD_CLASS_SHFT) |
(dest << CFD_DEST_SHFT) |
payload_len;
}
static inline int cfd_get_pkt_type(struct vpdma_cfd *cfd)
{
return cfd->ctl_payload_len >> CFD_PKT_TYPE_SHFT;
}
static inline bool cfd_get_direct(struct vpdma_cfd *cfd)
{
return (cfd->ctl_payload_len >> CFD_DIRECT_SHFT) & CFD_DIRECT_MASK;
}
static inline bool cfd_get_class(struct vpdma_cfd *cfd)
{
return (cfd->ctl_payload_len >> CFD_CLASS_SHFT) & CFD_CLASS_MASK;
}
static inline int cfd_get_dest(struct vpdma_cfd *cfd)
{
return (cfd->ctl_payload_len >> CFD_DEST_SHFT) & CFD_DEST_MASK;
}
static inline int cfd_get_payload_len(struct vpdma_cfd *cfd)
{
return cfd->ctl_payload_len & CFD_PAYLOAD_LEN_MASK;
}
/*
* control descriptor
*/
struct vpdma_ctd {
union {
u32 timer_value;
u32 list_addr;
u32 w0;
};
union {
u32 pixel_line_count;
u32 list_size;
u32 w1;
};
union {
u32 event;
u32 fid_ctl;
u32 w2;
};
u32 type_source_ctl;
};
/* control descriptor types */
#define CTD_TYPE_SYNC_ON_CLIENT 0
#define CTD_TYPE_SYNC_ON_LIST 1
#define CTD_TYPE_SYNC_ON_EXT 2
#define CTD_TYPE_SYNC_ON_LM_TIMER 3
#define CTD_TYPE_SYNC_ON_CHANNEL 4
#define CTD_TYPE_CHNG_CLIENT_IRQ 5
#define CTD_TYPE_SEND_IRQ 6
#define CTD_TYPE_RELOAD_LIST 7
#define CTD_TYPE_ABORT_CHANNEL 8
#define CTD_PKT_TYPE 0xc
/* timer_value */
#define CTD_TIMER_VALUE_MASK 0xffff
#define CTD_TIMER_VALUE_SHFT 0
/* pixel_line_count */
#define CTD_PIXEL_COUNT_MASK 0xffff
#define CTD_PIXEL_COUNT_SHFT 16
#define CTD_LINE_COUNT_MASK 0xffff
#define CTD_LINE_COUNT_SHFT 0
/* list_size */
#define CTD_LIST_SIZE_MASK 0xffff
#define CTD_LIST_SIZE_SHFT 0
/* event */
#define CTD_EVENT_MASK 0x0f
#define CTD_EVENT_SHFT 0
/* fid_ctl */
#define CTD_FID2_MASK 0x03
#define CTD_FID2_SHFT 4
#define CTD_FID1_MASK 0x03
#define CTD_FID1_SHFT 2
#define CTD_FID0_MASK 0x03
#define CTD_FID0_SHFT 0
/* type_source_ctl */
#define CTD_PKT_TYPE_MASK 0x1f
#define CTD_PKT_TYPE_SHFT 27
#define CTD_SOURCE_MASK 0xff
#define CTD_SOURCE_SHFT 16
#define CTD_CONTROL_MASK 0x0f
#define CTD_CONTROL_SHFT 0
static inline u32 ctd_pixel_line_count(int pixel_count, int line_count)
{
return (pixel_count << CTD_PIXEL_COUNT_SHFT) | line_count;
}
static inline u32 ctd_set_fid_ctl(int fid0, int fid1, int fid2)
{
return (fid2 << CTD_FID2_SHFT) | (fid1 << CTD_FID1_SHFT) | fid0;
}
static inline u32 ctd_type_source_ctl(int source, int control)
{
return (CTD_PKT_TYPE << CTD_PKT_TYPE_SHFT) |
(source << CTD_SOURCE_SHFT) | control;
}
static inline u32 ctd_get_pixel_count(struct vpdma_ctd *ctd)
{
return ctd->pixel_line_count >> CTD_PIXEL_COUNT_SHFT;
}
static inline int ctd_get_line_count(struct vpdma_ctd *ctd)
{
return ctd->pixel_line_count & CTD_LINE_COUNT_MASK;
}
static inline int ctd_get_event(struct vpdma_ctd *ctd)
{
return ctd->event & CTD_EVENT_MASK;
}
static inline int ctd_get_fid2_ctl(struct vpdma_ctd *ctd)
{
return (ctd->fid_ctl >> CTD_FID2_SHFT) & CTD_FID2_MASK;
}
static inline int ctd_get_fid1_ctl(struct vpdma_ctd *ctd)
{
return (ctd->fid_ctl >> CTD_FID1_SHFT) & CTD_FID1_MASK;
}
static inline int ctd_get_fid0_ctl(struct vpdma_ctd *ctd)
{
return ctd->fid_ctl & CTD_FID2_MASK;
}
static inline int ctd_get_pkt_type(struct vpdma_ctd *ctd)
{
return ctd->type_source_ctl >> CTD_PKT_TYPE_SHFT;
}
static inline int ctd_get_source(struct vpdma_ctd *ctd)
{
return (ctd->type_source_ctl >> CTD_SOURCE_SHFT) & CTD_SOURCE_MASK;
}
static inline int ctd_get_ctl(struct vpdma_ctd *ctd)
{
return ctd->type_source_ctl & CTD_CONTROL_MASK;
}
#endif

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,309 @@
/*
* Copyright (c) 2013 Texas Instruments Inc.
*
* David Griego, <dagriego@biglakesoftware.com>
* Dale Farnsworth, <dale@farnsworth.org>
* Archit Taneja, <archit@ti.com>
*
* This program is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 as published by
* the Free Software Foundation.
*/
#ifndef __TI_VPE_REGS_H
#define __TI_VPE_REGS_H
/* VPE register offsets and field selectors */
/* VPE top level regs */
#define VPE_PID 0x0000
#define VPE_PID_MINOR_MASK 0x3f
#define VPE_PID_MINOR_SHIFT 0
#define VPE_PID_CUSTOM_MASK 0x03
#define VPE_PID_CUSTOM_SHIFT 6
#define VPE_PID_MAJOR_MASK 0x07
#define VPE_PID_MAJOR_SHIFT 8
#define VPE_PID_RTL_MASK 0x1f
#define VPE_PID_RTL_SHIFT 11
#define VPE_PID_FUNC_MASK 0xfff
#define VPE_PID_FUNC_SHIFT 16
#define VPE_PID_SCHEME_MASK 0x03
#define VPE_PID_SCHEME_SHIFT 30
#define VPE_SYSCONFIG 0x0010
#define VPE_SYSCONFIG_IDLE_MASK 0x03
#define VPE_SYSCONFIG_IDLE_SHIFT 2
#define VPE_SYSCONFIG_STANDBY_MASK 0x03
#define VPE_SYSCONFIG_STANDBY_SHIFT 4
#define VPE_FORCE_IDLE_MODE 0
#define VPE_NO_IDLE_MODE 1
#define VPE_SMART_IDLE_MODE 2
#define VPE_SMART_IDLE_WAKEUP_MODE 3
#define VPE_FORCE_STANDBY_MODE 0
#define VPE_NO_STANDBY_MODE 1
#define VPE_SMART_STANDBY_MODE 2
#define VPE_SMART_STANDBY_WAKEUP_MODE 3
#define VPE_INT0_STATUS0_RAW_SET 0x0020
#define VPE_INT0_STATUS0_RAW VPE_INT0_STATUS0_RAW_SET
#define VPE_INT0_STATUS0_CLR 0x0028
#define VPE_INT0_STATUS0 VPE_INT0_STATUS0_CLR
#define VPE_INT0_ENABLE0_SET 0x0030
#define VPE_INT0_ENABLE0 VPE_INT0_ENABLE0_SET
#define VPE_INT0_ENABLE0_CLR 0x0038
#define VPE_INT0_LIST0_COMPLETE (1 << 0)
#define VPE_INT0_LIST0_NOTIFY (1 << 1)
#define VPE_INT0_LIST1_COMPLETE (1 << 2)
#define VPE_INT0_LIST1_NOTIFY (1 << 3)
#define VPE_INT0_LIST2_COMPLETE (1 << 4)
#define VPE_INT0_LIST2_NOTIFY (1 << 5)
#define VPE_INT0_LIST3_COMPLETE (1 << 6)
#define VPE_INT0_LIST3_NOTIFY (1 << 7)
#define VPE_INT0_LIST4_COMPLETE (1 << 8)
#define VPE_INT0_LIST4_NOTIFY (1 << 9)
#define VPE_INT0_LIST5_COMPLETE (1 << 10)
#define VPE_INT0_LIST5_NOTIFY (1 << 11)
#define VPE_INT0_LIST6_COMPLETE (1 << 12)
#define VPE_INT0_LIST6_NOTIFY (1 << 13)
#define VPE_INT0_LIST7_COMPLETE (1 << 14)
#define VPE_INT0_LIST7_NOTIFY (1 << 15)
#define VPE_INT0_DESCRIPTOR (1 << 16)
#define VPE_DEI_FMD_INT (1 << 18)
#define VPE_INT0_STATUS1_RAW_SET 0x0024
#define VPE_INT0_STATUS1_RAW VPE_INT0_STATUS1_RAW_SET
#define VPE_INT0_STATUS1_CLR 0x002c
#define VPE_INT0_STATUS1 VPE_INT0_STATUS1_CLR
#define VPE_INT0_ENABLE1_SET 0x0034
#define VPE_INT0_ENABLE1 VPE_INT0_ENABLE1_SET
#define VPE_INT0_ENABLE1_CLR 0x003c
#define VPE_INT0_CHANNEL_GROUP0 (1 << 0)
#define VPE_INT0_CHANNEL_GROUP1 (1 << 1)
#define VPE_INT0_CHANNEL_GROUP2 (1 << 2)
#define VPE_INT0_CHANNEL_GROUP3 (1 << 3)
#define VPE_INT0_CHANNEL_GROUP4 (1 << 4)
#define VPE_INT0_CHANNEL_GROUP5 (1 << 5)
#define VPE_INT0_CLIENT (1 << 7)
#define VPE_DEI_ERROR_INT (1 << 16)
#define VPE_DS1_UV_ERROR_INT (1 << 22)
#define VPE_INTC_EOI 0x00a0
#define VPE_CLK_ENABLE 0x0100
#define VPE_VPEDMA_CLK_ENABLE (1 << 0)
#define VPE_DATA_PATH_CLK_ENABLE (1 << 1)
#define VPE_CLK_RESET 0x0104
#define VPE_VPDMA_CLK_RESET_MASK 0x1
#define VPE_VPDMA_CLK_RESET_SHIFT 0
#define VPE_DATA_PATH_CLK_RESET_MASK 0x1
#define VPE_DATA_PATH_CLK_RESET_SHIFT 1
#define VPE_MAIN_RESET_MASK 0x1
#define VPE_MAIN_RESET_SHIFT 31
#define VPE_CLK_FORMAT_SELECT 0x010c
#define VPE_CSC_SRC_SELECT_MASK 0x03
#define VPE_CSC_SRC_SELECT_SHIFT 0
#define VPE_RGB_OUT_SELECT (1 << 8)
#define VPE_DS_SRC_SELECT_MASK 0x07
#define VPE_DS_SRC_SELECT_SHIFT 9
#define VPE_DS_BYPASS (1 << 16)
#define VPE_COLOR_SEPARATE_422 (1 << 18)
#define VPE_DS_SRC_DEI_SCALER (5 << VPE_DS_SRC_SELECT_SHIFT)
#define VPE_CSC_SRC_DEI_SCALER (3 << VPE_CSC_SRC_SELECT_SHIFT)
#define VPE_CLK_RANGE_MAP 0x011c
#define VPE_RANGE_RANGE_MAP_Y_MASK 0x07
#define VPE_RANGE_RANGE_MAP_Y_SHIFT 0
#define VPE_RANGE_RANGE_MAP_UV_MASK 0x07
#define VPE_RANGE_RANGE_MAP_UV_SHIFT 3
#define VPE_RANGE_MAP_ON (1 << 6)
#define VPE_RANGE_REDUCTION_ON (1 << 28)
/* VPE chrominance upsampler regs */
#define VPE_US1_R0 0x0304
#define VPE_US2_R0 0x0404
#define VPE_US3_R0 0x0504
#define VPE_US_C1_MASK 0x3fff
#define VPE_US_C1_SHIFT 2
#define VPE_US_C0_MASK 0x3fff
#define VPE_US_C0_SHIFT 18
#define VPE_US_MODE_MASK 0x03
#define VPE_US_MODE_SHIFT 16
#define VPE_ANCHOR_FID0_C1_MASK 0x3fff
#define VPE_ANCHOR_FID0_C1_SHIFT 2
#define VPE_ANCHOR_FID0_C0_MASK 0x3fff
#define VPE_ANCHOR_FID0_C0_SHIFT 18
#define VPE_US1_R1 0x0308
#define VPE_US2_R1 0x0408
#define VPE_US3_R1 0x0508
#define VPE_ANCHOR_FID0_C3_MASK 0x3fff
#define VPE_ANCHOR_FID0_C3_SHIFT 2
#define VPE_ANCHOR_FID0_C2_MASK 0x3fff
#define VPE_ANCHOR_FID0_C2_SHIFT 18
#define VPE_US1_R2 0x030c
#define VPE_US2_R2 0x040c
#define VPE_US3_R2 0x050c
#define VPE_INTERP_FID0_C1_MASK 0x3fff
#define VPE_INTERP_FID0_C1_SHIFT 2
#define VPE_INTERP_FID0_C0_MASK 0x3fff
#define VPE_INTERP_FID0_C0_SHIFT 18
#define VPE_US1_R3 0x0310
#define VPE_US2_R3 0x0410
#define VPE_US3_R3 0x0510
#define VPE_INTERP_FID0_C3_MASK 0x3fff
#define VPE_INTERP_FID0_C3_SHIFT 2
#define VPE_INTERP_FID0_C2_MASK 0x3fff
#define VPE_INTERP_FID0_C2_SHIFT 18
#define VPE_US1_R4 0x0314
#define VPE_US2_R4 0x0414
#define VPE_US3_R4 0x0514
#define VPE_ANCHOR_FID1_C1_MASK 0x3fff
#define VPE_ANCHOR_FID1_C1_SHIFT 2
#define VPE_ANCHOR_FID1_C0_MASK 0x3fff
#define VPE_ANCHOR_FID1_C0_SHIFT 18
#define VPE_US1_R5 0x0318
#define VPE_US2_R5 0x0418
#define VPE_US3_R5 0x0518
#define VPE_ANCHOR_FID1_C3_MASK 0x3fff
#define VPE_ANCHOR_FID1_C3_SHIFT 2
#define VPE_ANCHOR_FID1_C2_MASK 0x3fff
#define VPE_ANCHOR_FID1_C2_SHIFT 18
#define VPE_US1_R6 0x031c
#define VPE_US2_R6 0x041c
#define VPE_US3_R6 0x051c
#define VPE_INTERP_FID1_C1_MASK 0x3fff
#define VPE_INTERP_FID1_C1_SHIFT 2
#define VPE_INTERP_FID1_C0_MASK 0x3fff
#define VPE_INTERP_FID1_C0_SHIFT 18
#define VPE_US1_R7 0x0320
#define VPE_US2_R7 0x0420
#define VPE_US3_R7 0x0520
#define VPE_INTERP_FID0_C3_MASK 0x3fff
#define VPE_INTERP_FID0_C3_SHIFT 2
#define VPE_INTERP_FID0_C2_MASK 0x3fff
#define VPE_INTERP_FID0_C2_SHIFT 18
/* VPE de-interlacer regs */
#define VPE_DEI_FRAME_SIZE 0x0600
#define VPE_DEI_WIDTH_MASK 0x07ff
#define VPE_DEI_WIDTH_SHIFT 0
#define VPE_DEI_HEIGHT_MASK 0x07ff
#define VPE_DEI_HEIGHT_SHIFT 16
#define VPE_DEI_INTERLACE_BYPASS (1 << 29)
#define VPE_DEI_FIELD_FLUSH (1 << 30)
#define VPE_DEI_PROGRESSIVE (1 << 31)
#define VPE_MDT_BYPASS 0x0604
#define VPE_MDT_TEMPMAX_BYPASS (1 << 0)
#define VPE_MDT_SPATMAX_BYPASS (1 << 1)
#define VPE_MDT_SF_THRESHOLD 0x0608
#define VPE_MDT_SF_SC_THR1_MASK 0xff
#define VPE_MDT_SF_SC_THR1_SHIFT 0
#define VPE_MDT_SF_SC_THR2_MASK 0xff
#define VPE_MDT_SF_SC_THR2_SHIFT 0
#define VPE_MDT_SF_SC_THR3_MASK 0xff
#define VPE_MDT_SF_SC_THR3_SHIFT 0
#define VPE_EDI_CONFIG 0x060c
#define VPE_EDI_INP_MODE_MASK 0x03
#define VPE_EDI_INP_MODE_SHIFT 0
#define VPE_EDI_ENABLE_3D (1 << 2)
#define VPE_EDI_ENABLE_CHROMA_3D (1 << 3)
#define VPE_EDI_CHROMA3D_COR_THR_MASK 0xff
#define VPE_EDI_CHROMA3D_COR_THR_SHIFT 8
#define VPE_EDI_DIR_COR_LOWER_THR_MASK 0xff
#define VPE_EDI_DIR_COR_LOWER_THR_SHIFT 16
#define VPE_EDI_COR_SCALE_FACTOR_MASK 0xff
#define VPE_EDI_COR_SCALE_FACTOR_SHIFT 23
#define VPE_DEI_EDI_LUT_R0 0x0610
#define VPE_EDI_LUT0_MASK 0x1f
#define VPE_EDI_LUT0_SHIFT 0
#define VPE_EDI_LUT1_MASK 0x1f
#define VPE_EDI_LUT1_SHIFT 8
#define VPE_EDI_LUT2_MASK 0x1f
#define VPE_EDI_LUT2_SHIFT 16
#define VPE_EDI_LUT3_MASK 0x1f
#define VPE_EDI_LUT3_SHIFT 24
#define VPE_DEI_EDI_LUT_R1 0x0614
#define VPE_EDI_LUT0_MASK 0x1f
#define VPE_EDI_LUT0_SHIFT 0
#define VPE_EDI_LUT1_MASK 0x1f
#define VPE_EDI_LUT1_SHIFT 8
#define VPE_EDI_LUT2_MASK 0x1f
#define VPE_EDI_LUT2_SHIFT 16
#define VPE_EDI_LUT3_MASK 0x1f
#define VPE_EDI_LUT3_SHIFT 24
#define VPE_DEI_EDI_LUT_R2 0x0618
#define VPE_EDI_LUT4_MASK 0x1f
#define VPE_EDI_LUT4_SHIFT 0
#define VPE_EDI_LUT5_MASK 0x1f
#define VPE_EDI_LUT5_SHIFT 8
#define VPE_EDI_LUT6_MASK 0x1f
#define VPE_EDI_LUT6_SHIFT 16
#define VPE_EDI_LUT7_MASK 0x1f
#define VPE_EDI_LUT7_SHIFT 24
#define VPE_DEI_EDI_LUT_R3 0x061c
#define VPE_EDI_LUT8_MASK 0x1f
#define VPE_EDI_LUT8_SHIFT 0
#define VPE_EDI_LUT9_MASK 0x1f
#define VPE_EDI_LUT9_SHIFT 8
#define VPE_EDI_LUT10_MASK 0x1f
#define VPE_EDI_LUT10_SHIFT 16
#define VPE_EDI_LUT11_MASK 0x1f
#define VPE_EDI_LUT11_SHIFT 24
#define VPE_DEI_FMD_WINDOW_R0 0x0620
#define VPE_FMD_WINDOW_MINX_MASK 0x07ff
#define VPE_FMD_WINDOW_MINX_SHIFT 0
#define VPE_FMD_WINDOW_MAXX_MASK 0x07ff
#define VPE_FMD_WINDOW_MAXX_SHIFT 16
#define VPE_FMD_WINDOW_ENABLE (1 << 31)
#define VPE_DEI_FMD_WINDOW_R1 0x0624
#define VPE_FMD_WINDOW_MINY_MASK 0x07ff
#define VPE_FMD_WINDOW_MINY_SHIFT 0
#define VPE_FMD_WINDOW_MAXY_MASK 0x07ff
#define VPE_FMD_WINDOW_MAXY_SHIFT 16
#define VPE_DEI_FMD_CONTROL_R0 0x0628
#define VPE_FMD_ENABLE (1 << 0)
#define VPE_FMD_LOCK (1 << 1)
#define VPE_FMD_JAM_DIR (1 << 2)
#define VPE_FMD_BED_ENABLE (1 << 3)
#define VPE_FMD_CAF_FIELD_THR_MASK 0xff
#define VPE_FMD_CAF_FIELD_THR_SHIFT 16
#define VPE_FMD_CAF_LINE_THR_MASK 0xff
#define VPE_FMD_CAF_LINE_THR_SHIFT 24
#define VPE_DEI_FMD_CONTROL_R1 0x062c
#define VPE_FMD_CAF_THR_MASK 0x000fffff
#define VPE_FMD_CAF_THR_SHIFT 0
#define VPE_DEI_FMD_STATUS_R0 0x0630
#define VPE_FMD_CAF_MASK 0x000fffff
#define VPE_FMD_CAF_SHIFT 0
#define VPE_FMD_RESET (1 << 24)
#define VPE_DEI_FMD_STATUS_R1 0x0634
#define VPE_FMD_FIELD_DIFF_MASK 0x0fffffff
#define VPE_FMD_FIELD_DIFF_SHIFT 0
#define VPE_DEI_FMD_STATUS_R2 0x0638
#define VPE_FMD_FRAME_DIFF_MASK 0x000fffff
#define VPE_FMD_FRAME_DIFF_SHIFT 0
#endif