mirror of
https://github.com/AetherDroid/android_kernel_samsung_on5xelte.git
synced 2025-10-29 15:28:50 +01:00
Fixed MTP to work with TWRP
This commit is contained in:
commit
f6dfaef42e
50820 changed files with 20846062 additions and 0 deletions
5
drivers/media/platform/ti-vpe/Makefile
Normal file
5
drivers/media/platform/ti-vpe/Makefile
Normal 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
|
||||
196
drivers/media/platform/ti-vpe/csc.c
Normal file
196
drivers/media/platform/ti-vpe/csc.c
Normal 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;
|
||||
}
|
||||
68
drivers/media/platform/ti-vpe/csc.h
Normal file
68
drivers/media/platform/ti-vpe/csc.h
Normal 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
|
||||
311
drivers/media/platform/ti-vpe/sc.c
Normal file
311
drivers/media/platform/ti-vpe/sc.c
Normal 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;
|
||||
}
|
||||
208
drivers/media/platform/ti-vpe/sc.h
Normal file
208
drivers/media/platform/ti-vpe/sc.h
Normal 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
|
||||
1342
drivers/media/platform/ti-vpe/sc_coeff.h
Normal file
1342
drivers/media/platform/ti-vpe/sc_coeff.h
Normal file
File diff suppressed because it is too large
Load diff
912
drivers/media/platform/ti-vpe/vpdma.c
Normal file
912
drivers/media/platform/ti-vpe/vpdma.c
Normal 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);
|
||||
216
drivers/media/platform/ti-vpe/vpdma.h
Normal file
216
drivers/media/platform/ti-vpe/vpdma.h
Normal 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
|
||||
641
drivers/media/platform/ti-vpe/vpdma_priv.h
Normal file
641
drivers/media/platform/ti-vpe/vpdma_priv.h
Normal 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
|
||||
2388
drivers/media/platform/ti-vpe/vpe.c
Normal file
2388
drivers/media/platform/ti-vpe/vpe.c
Normal file
File diff suppressed because it is too large
Load diff
309
drivers/media/platform/ti-vpe/vpe_regs.h
Normal file
309
drivers/media/platform/ti-vpe/vpe_regs.h
Normal 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
|
||||
Loading…
Add table
Add a link
Reference in a new issue