Merge remote-tracking branch 'origin/capture/isi' into capture/next
* origin/capture/isi: (9 commits) staging: media: imx: add g_parm/s_parm for imx8 capture device staging: media: imx: enable ISI for imx8mn platform media: staging: imx: add V4L2 memory to memory driver for ISI of imx8qxp/qm media: staging: imx: add isi capture driver support for imx8qm/qxp media: staging: imx: add isi core driver support for imx8qm/qxp ...5.4-rM2-2.2.x-imx-squashed
commit
028cc80de9
|
@ -0,0 +1,33 @@
|
|||
NXP Image Sensor Interface
|
||||
========================
|
||||
|
||||
The Image Sensor Interface (ISI) is used to obtain the image data for
|
||||
processing in its pipeline channels. Each pipeline processes the image
|
||||
line from a configured source and performs one or more functions that
|
||||
are configured by software, such as down scaling, color space conversion,
|
||||
de-interlacing, alpha insertion, cropping and rotation (horizontal and
|
||||
vertical). The processed image is stored into programmable memory locations.
|
||||
|
||||
Required properties:
|
||||
- compatible: should be "fsl,imx8-isi", where SoC can be one of imx8qxp, imx8qm
|
||||
- reg: the register base and size for the device registers
|
||||
- interrupts: the ISI interrupt, high level active
|
||||
- clock-names: should be "per"
|
||||
- clocks: the ISI AXI clock
|
||||
- interface: specify ISI input, virtual channel and output,
|
||||
<Input MIPI_VCx Output>
|
||||
Input : 0-DC0, 1-DC1, 2-MIPI CSI0, 3-MIPI CSI1, 4-HDMI, 5-MEM
|
||||
VCx : 0-VC0, 1-VC1, 2-VC2, 3-VC3, MIPI CSI only
|
||||
Output: 0-DC0, 1-DC1, 2-MEM
|
||||
|
||||
Example:
|
||||
isi_0: isi@58100000 {
|
||||
compatible = "fsl,imx8-isi";
|
||||
reg = <0x58100000 0x10000>;
|
||||
interrupts = <GIC_SPI 297 IRQ_TYPE_LEVEL_HIGH>;
|
||||
interrupt-parent = <&gic>;
|
||||
clocks = <&img_lpcg IMX_IMG_LPCG_PDMA0_CLK>;
|
||||
clock-names = "per";
|
||||
power-domains = <&pd IMX_SC_R_ISI_CH0>;
|
||||
interface = <2 0 2>;
|
||||
};
|
|
@ -1,6 +1,6 @@
|
|||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_VIDEO_ALLEGRO_DVT) += allegro-dvt/
|
||||
obj-$(CONFIG_VIDEO_IMX_MEDIA) += imx/
|
||||
obj-$(CONFIG_VIDEO_IMX_CAPTURE) += imx/
|
||||
obj-$(CONFIG_VIDEO_MESON_VDEC) += meson/vdec/
|
||||
obj-$(CONFIG_VIDEO_OMAP4) += omap4iss/
|
||||
obj-$(CONFIG_VIDEO_SUNXI) += sunxi/
|
||||
|
|
|
@ -47,6 +47,23 @@ config VIDEO_IMX_CAPTURE
|
|||
if VIDEO_IMX_CAPTURE
|
||||
menu "i.MX8QXP/QM Camera ISI/MIPI Features support"
|
||||
|
||||
config IMX8_ISI_CORE
|
||||
bool "IMX8 Image Sensor Interface Core Driver"
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
default y
|
||||
|
||||
config IMX8_ISI_CAPTURE
|
||||
bool "IMX8 Image Sensor Interface Capture Device Driver"
|
||||
depends on IMX8_ISI_CORE
|
||||
select VIDEOBUF2_DMA_CONTIG
|
||||
default y
|
||||
|
||||
config IMX8_ISI_M2M
|
||||
bool "IMX8 Image Sensor Interface Memory to Memory Device Driver"
|
||||
select V4L2_MEM2MEM_DEV
|
||||
depends on IMX8_ISI_CORE
|
||||
default y
|
||||
|
||||
config IMX8_MIPI_CSI2
|
||||
tristate "IMX8 MIPI CSI2 Controller"
|
||||
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
|
||||
|
|
|
@ -3,6 +3,8 @@ imx6-media-objs := imx-media-dev.o imx-media-internal-sd.o \
|
|||
imx-ic-common.o imx-ic-prp.o imx-ic-prpencvf.o imx-media-vdic.o \
|
||||
imx-media-csc-scaler.o
|
||||
|
||||
imx8-capture-objs := imx8-isi-core.o imx8-isi-hw.o
|
||||
|
||||
imx-media-common-objs := imx-media-capture.o imx-media-dev-common.o \
|
||||
imx-media-of.o imx-media-utils.o
|
||||
|
||||
|
@ -16,5 +18,8 @@ obj-$(CONFIG_VIDEO_IMX_CSI) += imx6-mipi-csi2.o
|
|||
|
||||
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-media-csi.o
|
||||
obj-$(CONFIG_VIDEO_IMX7_CSI) += imx7-mipi-csis.o
|
||||
obj-$(CONFIG_IMX8_ISI_CORE) += imx8-capture.o
|
||||
obj-$(CONFIG_IMX8_ISI_CAPTURE) += imx8-isi-cap.o
|
||||
obj-$(CONFIG_IMX8_ISI_M2M) += imx8-isi-m2m.o
|
||||
obj-$(CONFIG_IMX8_MIPI_CSI2) += imx8-mipi-csi2.o
|
||||
obj-$(CONFIG_IMX8_MIPI_CSI2_SAM) += imx8-mipi-csi2-sam.o
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,513 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 NXP Semiconductor
|
||||
*
|
||||
*/
|
||||
|
||||
#include "imx8-isi-hw.h"
|
||||
|
||||
static const struct of_device_id mxc_isi_of_match[];
|
||||
|
||||
struct mxc_isi_dev *mxc_isi_get_hostdata(struct platform_device *pdev)
|
||||
{
|
||||
struct mxc_isi_dev *mxc_isi;
|
||||
|
||||
if (!pdev || !pdev->dev.parent)
|
||||
return NULL;
|
||||
|
||||
device_lock(pdev->dev.parent);
|
||||
mxc_isi = (struct mxc_isi_dev *)dev_get_drvdata(pdev->dev.parent);
|
||||
if (!mxc_isi) {
|
||||
dev_err(&pdev->dev, "Cann't get host data\n");
|
||||
device_unlock(pdev->dev.parent);
|
||||
return NULL;
|
||||
}
|
||||
device_unlock(pdev->dev.parent);
|
||||
|
||||
return mxc_isi;
|
||||
}
|
||||
|
||||
struct device *mxc_isi_dev_get_parent(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct device_node *parent;
|
||||
struct platform_device *parent_pdev;
|
||||
|
||||
if (!pdev)
|
||||
return NULL;
|
||||
|
||||
/* Get parent for isi capture device */
|
||||
parent = of_get_parent(dev->of_node);
|
||||
parent_pdev = of_find_device_by_node(parent);
|
||||
if (!parent_pdev) {
|
||||
of_node_put(parent);
|
||||
return NULL;
|
||||
}
|
||||
of_node_put(parent);
|
||||
|
||||
return &parent_pdev->dev;
|
||||
}
|
||||
|
||||
static irqreturn_t mxc_isi_irq_handler(int irq, void *priv)
|
||||
{
|
||||
struct mxc_isi_dev *mxc_isi = priv;
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
u32 status;
|
||||
|
||||
spin_lock(&mxc_isi->slock);
|
||||
|
||||
status = mxc_isi_get_irq_status(mxc_isi);
|
||||
mxc_isi->status = status;
|
||||
mxc_isi_clean_irq_status(mxc_isi, status);
|
||||
|
||||
if (status & CHNL_STS_FRM_STRD_MASK) {
|
||||
if (mxc_isi->m2m_enabled)
|
||||
mxc_isi_m2m_frame_write_done(mxc_isi);
|
||||
else
|
||||
mxc_isi_cap_frame_write_done(mxc_isi);
|
||||
}
|
||||
|
||||
if (status & (CHNL_STS_AXI_WR_ERR_Y_MASK |
|
||||
CHNL_STS_AXI_WR_ERR_U_MASK |
|
||||
CHNL_STS_AXI_WR_ERR_V_MASK))
|
||||
dev_dbg(dev, "%s, IRQ AXI Error stat=0x%X\n", __func__, status);
|
||||
|
||||
if (status & (CHNL_STS_OFLW_PANIC_Y_BUF_MASK |
|
||||
CHNL_STS_OFLW_PANIC_U_BUF_MASK |
|
||||
CHNL_STS_OFLW_PANIC_V_BUF_MASK))
|
||||
dev_dbg(dev, "%s, IRQ Panic OFLW Error stat=0x%X\n", __func__, status);
|
||||
|
||||
if (status & (CHNL_STS_OFLW_Y_BUF_MASK |
|
||||
CHNL_STS_OFLW_U_BUF_MASK |
|
||||
CHNL_STS_OFLW_V_BUF_MASK))
|
||||
dev_dbg(dev, "%s, IRQ OFLW Error stat=0x%X\n", __func__, status);
|
||||
|
||||
if (status & (CHNL_STS_EXCS_OFLW_Y_BUF_MASK |
|
||||
CHNL_STS_EXCS_OFLW_U_BUF_MASK |
|
||||
CHNL_STS_EXCS_OFLW_V_BUF_MASK))
|
||||
dev_dbg(dev, "%s, IRQ EXCS OFLW Error stat=0x%X\n", __func__, status);
|
||||
|
||||
spin_unlock(&mxc_isi->slock);
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int disp_mix_sft_rstn(struct reset_control *reset, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!reset)
|
||||
return 0;
|
||||
|
||||
ret = enable ? reset_control_assert(reset) :
|
||||
reset_control_deassert(reset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int disp_mix_clks_enable(struct reset_control *reset, bool enable)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!reset)
|
||||
return 0;
|
||||
|
||||
ret = enable ? reset_control_assert(reset) :
|
||||
reset_control_deassert(reset);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int mxc_imx8_clk_get(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
|
||||
mxc_isi->clk = devm_clk_get(dev, NULL);
|
||||
|
||||
if (IS_ERR(mxc_isi->clk)) {
|
||||
dev_err(dev, "failed to get isi clk\n");
|
||||
return PTR_ERR(mxc_isi->clk);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_imx8_clk_enable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(mxc_isi->clk);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "%s, enable clk error\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxc_imx8_clk_disable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
clk_disable_unprepare(mxc_isi->clk);
|
||||
}
|
||||
|
||||
static struct mxc_isi_dev_ops mxc_imx8_data = {
|
||||
.clk_get = mxc_imx8_clk_get,
|
||||
.clk_enable = mxc_imx8_clk_enable,
|
||||
.clk_disable = mxc_imx8_clk_disable,
|
||||
};
|
||||
|
||||
static int mxc_imx8mn_clk_get(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
|
||||
mxc_isi->clk_disp_axi = devm_clk_get(dev, "disp_axi");
|
||||
if (IS_ERR(mxc_isi->clk_disp_axi)) {
|
||||
dev_err(dev, "failed to get disp_axi clk\n");
|
||||
return PTR_ERR(mxc_isi->clk_disp_axi);
|
||||
}
|
||||
|
||||
mxc_isi->clk_disp_apb = devm_clk_get(dev, "disp_apb");
|
||||
if (IS_ERR(mxc_isi->clk_disp_apb)) {
|
||||
dev_err(dev, "failed to get disp_apb clk\n");
|
||||
return PTR_ERR(mxc_isi->clk_disp_apb);
|
||||
}
|
||||
|
||||
mxc_isi->clk_root_disp_axi = devm_clk_get(dev, "disp_axi_root");
|
||||
if (IS_ERR(mxc_isi->clk_root_disp_axi)) {
|
||||
dev_err(dev, "failed to get disp axi root clk\n");
|
||||
return PTR_ERR(mxc_isi->clk_root_disp_axi);
|
||||
}
|
||||
|
||||
mxc_isi->clk_root_disp_apb = devm_clk_get(dev, "disp_apb_root");
|
||||
if (IS_ERR(mxc_isi->clk_root_disp_apb)) {
|
||||
dev_err(dev, "failed to get disp apb root clk\n");
|
||||
return PTR_ERR(mxc_isi->clk_root_disp_apb);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_imx8mn_clk_enable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
int ret;
|
||||
|
||||
ret = clk_prepare_enable(mxc_isi->clk_disp_axi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "prepare and enable axi clk error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(mxc_isi->clk_disp_apb);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "prepare and enable abp clk error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(mxc_isi->clk_root_disp_axi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "prepare and enable axi root clk error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = clk_prepare_enable(mxc_isi->clk_root_disp_apb);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "prepare and enable apb root clk error\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void mxc_imx8mn_clk_disable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
clk_disable_unprepare(mxc_isi->clk_root_disp_axi);
|
||||
clk_disable_unprepare(mxc_isi->clk_root_disp_apb);
|
||||
clk_disable_unprepare(mxc_isi->clk_disp_axi);
|
||||
clk_disable_unprepare(mxc_isi->clk_disp_apb);
|
||||
}
|
||||
|
||||
static struct mxc_isi_dev_ops mxc_imx8mn_data = {
|
||||
.clk_get = mxc_imx8mn_clk_get,
|
||||
.clk_enable = mxc_imx8mn_clk_enable,
|
||||
.clk_disable = mxc_imx8mn_clk_disable,
|
||||
};
|
||||
|
||||
static int mxc_isi_parse_dt(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
struct device_node *node = dev->of_node;
|
||||
int ret = 0;
|
||||
|
||||
mxc_isi->id = of_alias_get_id(node, "isi");
|
||||
mxc_isi->chain_buf = of_property_read_bool(node, "fsl,chain_buf");
|
||||
|
||||
ret = of_property_read_u32_array(node, "interface", mxc_isi->interface, 3);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
dev_dbg(dev, "%s, isi_%d,interface(%d, %d, %d)\n", __func__,
|
||||
mxc_isi->id,
|
||||
mxc_isi->interface[0],
|
||||
mxc_isi->interface[1],
|
||||
mxc_isi->interface[2]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_isi_clk_get(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
const struct mxc_isi_dev_ops *ops = mxc_isi->ops;
|
||||
|
||||
if (!ops && !ops->clk_get)
|
||||
return -EINVAL;
|
||||
|
||||
return ops->clk_get(mxc_isi);
|
||||
}
|
||||
|
||||
static int mxc_isi_clk_enable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
const struct mxc_isi_dev_ops *ops = mxc_isi->ops;
|
||||
|
||||
if (!ops && !ops->clk_enable)
|
||||
return -EINVAL;
|
||||
|
||||
return ops->clk_enable(mxc_isi);
|
||||
}
|
||||
|
||||
static void mxc_isi_clk_disable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
const struct mxc_isi_dev_ops *ops = mxc_isi->ops;
|
||||
|
||||
if (!ops && !ops->clk_disable)
|
||||
return;
|
||||
|
||||
ops->clk_disable(mxc_isi);
|
||||
}
|
||||
|
||||
static int mxc_isi_of_parse_resets(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
int ret;
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
struct device_node *np = dev->of_node;
|
||||
struct device_node *parent, *child;
|
||||
struct of_phandle_args args;
|
||||
struct reset_control *rstc;
|
||||
const char *compat;
|
||||
uint32_t len, rstc_num = 0;
|
||||
|
||||
ret = of_parse_phandle_with_args(np, "resets", "#reset-cells",
|
||||
0, &args);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
parent = args.np;
|
||||
for_each_child_of_node(parent, child) {
|
||||
compat = of_get_property(child, "compatible", NULL);
|
||||
if (!compat)
|
||||
continue;
|
||||
|
||||
rstc = of_reset_control_array_get(child, false, false, true);
|
||||
if (IS_ERR(rstc))
|
||||
continue;
|
||||
|
||||
len = strlen(compat);
|
||||
if (!of_compat_cmp("isi,soft-resetn", compat, len)) {
|
||||
mxc_isi->soft_resetn = rstc;
|
||||
rstc_num++;
|
||||
} else if (!of_compat_cmp("isi,clk-enable", compat, len)) {
|
||||
mxc_isi->clk_enable = rstc;
|
||||
rstc_num++;
|
||||
} else {
|
||||
dev_warn(dev, "invalid isi reset node: %s\n", compat);
|
||||
}
|
||||
}
|
||||
|
||||
if (!rstc_num) {
|
||||
dev_err(dev, "no invalid reset control exists\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
of_node_put(parent);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_isi_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct mxc_isi_dev *mxc_isi;
|
||||
struct resource *res;
|
||||
const struct of_device_id *of_id;
|
||||
int ret = 0;
|
||||
|
||||
|
||||
mxc_isi = devm_kzalloc(dev, sizeof(*mxc_isi), GFP_KERNEL);
|
||||
if (!mxc_isi)
|
||||
return -ENOMEM;
|
||||
|
||||
mxc_isi->pdev = pdev;
|
||||
of_id = of_match_node(mxc_isi_of_match, dev->of_node);
|
||||
if (!of_id)
|
||||
return -EINVAL;
|
||||
|
||||
mxc_isi->ops = of_id->data;
|
||||
if (!mxc_isi->ops) {
|
||||
dev_err(dev, "Can't get platform device data\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
ret = mxc_isi_parse_dt(mxc_isi);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
if (mxc_isi->id >= MXC_ISI_MAX_DEVS || mxc_isi->id < 0) {
|
||||
dev_err(dev, "Invalid driver data or device id (%d)\n",
|
||||
mxc_isi->id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_lock_init(&mxc_isi->slock);
|
||||
mutex_init(&mxc_isi->lock);
|
||||
atomic_set(&mxc_isi->usage_count, 0);
|
||||
|
||||
if (of_device_is_compatible(dev->of_node, "fsl,imx8mn-isi")) {
|
||||
ret = mxc_isi_of_parse_resets(mxc_isi);
|
||||
if (ret) {
|
||||
dev_warn(dev, "Can not parse reset control\n");
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
ret = mxc_isi_clk_get(mxc_isi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ISI_%d get clocks fail\n", mxc_isi->id);
|
||||
return ret;
|
||||
}
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
mxc_isi->regs = devm_ioremap_resource(dev, res);
|
||||
if (IS_ERR(mxc_isi->regs)) {
|
||||
dev_err(dev, "Failed to get ISI register map\n");
|
||||
return PTR_ERR(mxc_isi->regs);
|
||||
}
|
||||
|
||||
ret = mxc_isi_clk_enable(mxc_isi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "ISI_%d enable clocks fail\n", mxc_isi->id);
|
||||
return ret;
|
||||
}
|
||||
disp_mix_sft_rstn(mxc_isi->soft_resetn, false);
|
||||
disp_mix_clks_enable(mxc_isi->clk_enable, true);
|
||||
|
||||
mxc_isi_clean_registers(mxc_isi);
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "Failed to get IRQ resource\n");
|
||||
goto err;
|
||||
}
|
||||
ret = devm_request_irq(dev, res->start, mxc_isi_irq_handler,
|
||||
0, dev_name(dev), mxc_isi);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "failed to install irq (%d)\n", ret);
|
||||
goto err;
|
||||
}
|
||||
|
||||
mxc_isi_channel_set_chain_buf(mxc_isi);
|
||||
|
||||
ret = of_platform_populate(dev->of_node, NULL, NULL, dev);
|
||||
if (ret < 0)
|
||||
dev_warn(dev, "Populate child platform device fail\n");
|
||||
|
||||
mxc_isi_clk_disable(mxc_isi);
|
||||
|
||||
platform_set_drvdata(pdev, mxc_isi);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
dev_info(dev, "mxc_isi.%d registered successfully\n", mxc_isi->id);
|
||||
return 0;
|
||||
|
||||
err:
|
||||
disp_mix_clks_enable(mxc_isi->clk_enable, false);
|
||||
disp_mix_sft_rstn(mxc_isi->soft_resetn, true);
|
||||
mxc_isi_clk_disable(mxc_isi);
|
||||
return -ENXIO;
|
||||
}
|
||||
|
||||
static int mxc_isi_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
|
||||
pm_runtime_disable(dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_isi_pm_suspend(struct device *dev)
|
||||
{
|
||||
struct mxc_isi_dev *mxc_isi = dev_get_drvdata(dev);
|
||||
|
||||
if (mxc_isi->is_streaming) {
|
||||
dev_warn(dev, "running, prevent entering suspend.\n");
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
return pm_runtime_force_suspend(dev);
|
||||
}
|
||||
|
||||
static int mxc_isi_pm_resume(struct device *dev)
|
||||
{
|
||||
return pm_runtime_force_resume(dev);
|
||||
}
|
||||
|
||||
static int mxc_isi_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct mxc_isi_dev *mxc_isi = dev_get_drvdata(dev);
|
||||
|
||||
disp_mix_clks_enable(mxc_isi->clk_enable, false);
|
||||
mxc_isi_clk_disable(mxc_isi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int mxc_isi_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct mxc_isi_dev *mxc_isi = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = mxc_isi_clk_enable(mxc_isi);
|
||||
if (ret) {
|
||||
dev_err(dev, "%s clk enable fail\n", __func__);
|
||||
return ret;
|
||||
}
|
||||
disp_mix_sft_rstn(mxc_isi->soft_resetn, false);
|
||||
disp_mix_clks_enable(mxc_isi->clk_enable, true);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops mxc_isi_pm_ops = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(mxc_isi_pm_suspend, mxc_isi_pm_resume)
|
||||
SET_RUNTIME_PM_OPS(mxc_isi_runtime_suspend, mxc_isi_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id mxc_isi_of_match[] = {
|
||||
{.compatible = "fsl,imx8-isi", .data = &mxc_imx8_data },
|
||||
{.compatible = "fsl,imx8mn-isi", .data = &mxc_imx8mn_data },
|
||||
{ /* sentinel */ },
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, mxc_isi_of_match);
|
||||
|
||||
static struct platform_driver mxc_isi_driver = {
|
||||
.probe = mxc_isi_probe,
|
||||
.remove = mxc_isi_remove,
|
||||
.driver = {
|
||||
.of_match_table = mxc_isi_of_match,
|
||||
.name = MXC_ISI_DRIVER_NAME,
|
||||
.pm = &mxc_isi_pm_ops,
|
||||
}
|
||||
};
|
||||
module_platform_driver(mxc_isi_driver);
|
||||
|
||||
MODULE_AUTHOR("Freescale Semiconductor, Inc.");
|
||||
MODULE_DESCRIPTION("IMX8 Image Subsystem driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
MODULE_ALIAS("ISI");
|
||||
MODULE_VERSION("1.0");
|
|
@ -0,0 +1,364 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2019 NXP Semiconductor
|
||||
*/
|
||||
|
||||
#ifndef __MXC_ISI_CORE_H__
|
||||
#define __MXC_ISI_CORE_H__
|
||||
|
||||
#include <linux/module.h>
|
||||
#include <linux/kernel.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/device.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_device.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/clk.h>
|
||||
#include <media/media-device.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/v4l2-mem2mem.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-subdev.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/reset.h>
|
||||
|
||||
#include "imx8-common.h"
|
||||
|
||||
#define MXC_ISI_DRIVER_NAME "mxc-isi"
|
||||
#define MXC_ISI_CAPTURE "mxc-isi-cap"
|
||||
#define MXC_ISI_M2M "mxc-isi-m2m"
|
||||
#define MXC_MAX_PLANES 3
|
||||
|
||||
struct mxc_isi_dev;
|
||||
|
||||
enum mxc_isi_out_fmt {
|
||||
MXC_ISI_OUT_FMT_RGBA32 = 0x0,
|
||||
MXC_ISI_OUT_FMT_ABGR32,
|
||||
MXC_ISI_OUT_FMT_ARGB32,
|
||||
MXC_ISI_OUT_FMT_RGBX32,
|
||||
MXC_ISI_OUT_FMT_XBGR32,
|
||||
MXC_ISI_OUT_FMT_XRGB32,
|
||||
MXC_ISI_OUT_FMT_RGB32P,
|
||||
MXC_ISI_OUT_FMT_BGR32P,
|
||||
MXC_ISI_OUT_FMT_A2BGR10,
|
||||
MXC_ISI_OUT_FMT_A2RGB10,
|
||||
MXC_ISI_OUT_FMT_RGB565,
|
||||
MXC_ISI_OUT_FMT_RAW8,
|
||||
MXC_ISI_OUT_FMT_RAW10,
|
||||
MXC_ISI_OUT_FMT_RAW10P,
|
||||
MXC_ISI_OUT_FMT_RAW12,
|
||||
MXC_ISI_OUT_FMT_RAW16,
|
||||
MXC_ISI_OUT_FMT_YUV444_1P8P,
|
||||
MXC_ISI_OUT_FMT_YUV444_2P8P,
|
||||
MXC_ISI_OUT_FMT_YUV444_3P8P,
|
||||
MXC_ISI_OUT_FMT_YUV444_1P8,
|
||||
MXC_ISI_OUT_FMT_YUV444_1P10,
|
||||
MXC_ISI_OUT_FMT_YUV444_2P10,
|
||||
MXC_ISI_OUT_FMT_YUV444_3P10,
|
||||
MXC_ISI_OUT_FMT_YUV444_1P10P = 0x18,
|
||||
MXC_ISI_OUT_FMT_YUV444_2P10P,
|
||||
MXC_ISI_OUT_FMT_YUV444_3P10P,
|
||||
MXC_ISI_OUT_FMT_YUV444_1P12 = 0x1C,
|
||||
MXC_ISI_OUT_FMT_YUV444_2P12,
|
||||
MXC_ISI_OUT_FMT_YUV444_3P12,
|
||||
MXC_ISI_OUT_FMT_YUV422_1P8P = 0x20,
|
||||
MXC_ISI_OUT_FMT_YUV422_2P8P,
|
||||
MXC_ISI_OUT_FMT_YUV422_3P8P,
|
||||
MXC_ISI_OUT_FMT_YUV422_1P10 = 0x24,
|
||||
MXC_ISI_OUT_FMT_YUV422_2P10,
|
||||
MXC_ISI_OUT_FMT_YUV422_3P10,
|
||||
MXC_ISI_OUT_FMT_YUV422_1P10P = 0x28,
|
||||
MXC_ISI_OUT_FMT_YUV422_2P10P,
|
||||
MXC_ISI_OUT_FMT_YUV422_3P10P,
|
||||
MXC_ISI_OUT_FMT_YUV422_1P12 = 0x2C,
|
||||
MXC_ISI_OUT_FMT_YUV422_2P12,
|
||||
MXC_ISI_OUT_FMT_YUV422_3P12,
|
||||
MXC_ISI_OUT_FMT_YUV420_2P8P = 0x31,
|
||||
MXC_ISI_OUT_FMT_YUV420_3P8P,
|
||||
MXC_ISI_OUT_FMT_YUV420_2P10 = 0x35,
|
||||
MXC_ISI_OUT_FMT_YUV420_3P10,
|
||||
MXC_ISI_OUT_FMT_YUV420_2P10P = 0x39,
|
||||
MXC_ISI_OUT_FMT_YUV420_3P10P,
|
||||
MXC_ISI_OUT_FMT_YUV420_2P12 = 0x3D,
|
||||
MXC_ISI_OUT_FMT_YUV420_3P12,
|
||||
};
|
||||
|
||||
enum mxc_isi_in_fmt {
|
||||
MXC_ISI_IN_FMT_BGR8P = 0x0,
|
||||
};
|
||||
|
||||
enum mxc_isi_m2m_in_fmt {
|
||||
MXC_ISI_M2M_IN_FMT_BGR8P = 0x0,
|
||||
MXC_ISI_M2M_IN_FMT_RGB8P,
|
||||
MXC_ISI_M2M_IN_FMT_XRGB8,
|
||||
MXC_ISI_M2M_IN_FMT_RGBX8,
|
||||
MXC_ISI_M2M_IN_FMT_XBGR8,
|
||||
MXC_ISI_M2M_IN_FMT_RGB565,
|
||||
MXC_ISI_M2M_IN_FMT_A2BGR10,
|
||||
MXC_ISI_M2M_IN_FMT_A2RGB10,
|
||||
MXC_ISI_M2M_IN_FMT_YUV444_1P8P,
|
||||
MXC_ISI_M2M_IN_FMT_YUV444_1P10,
|
||||
MXC_ISI_M2M_IN_FMT_YUV444_1P10P,
|
||||
MXC_ISI_M2M_IN_FMT_YUV444_1P12,
|
||||
MXC_ISI_M2M_IN_FMT_YUV444_1P8,
|
||||
MXC_ISI_M2M_IN_FMT_YUV422_1P8P,
|
||||
MXC_ISI_M2M_IN_FMT_YUV422_1P10,
|
||||
MXC_ISI_M2M_IN_FMT_YUV422_1P10P,
|
||||
};
|
||||
|
||||
struct mxc_isi_fmt {
|
||||
char *name;
|
||||
u32 mbus_code;
|
||||
u32 fourcc;
|
||||
u32 color;
|
||||
u16 memplanes;
|
||||
u16 colplanes;
|
||||
u8 colorspace;
|
||||
u8 depth[MXC_MAX_PLANES];
|
||||
u16 mdataplanes;
|
||||
u16 flags;
|
||||
};
|
||||
|
||||
struct mxc_isi_ctrls {
|
||||
struct v4l2_ctrl_handler handler;
|
||||
struct v4l2_ctrl *hflip;
|
||||
struct v4l2_ctrl *vflip;
|
||||
struct v4l2_ctrl *alpha;
|
||||
struct v4l2_ctrl *num_cap_buf;
|
||||
struct v4l2_ctrl *num_out_buf;
|
||||
bool ready;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct addr - physical address set for DMA
|
||||
* @y: luminance plane physical address
|
||||
* @cb: Cb plane physical address
|
||||
* @cr: Cr plane physical address
|
||||
*/
|
||||
struct frame_addr {
|
||||
u32 y;
|
||||
u32 cb;
|
||||
u32 cr;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct mxc_isi_frame - source/target frame properties
|
||||
* o_width: original image width from sensor
|
||||
* o_height: original image height from sensor
|
||||
* c_width: crop image width set by g_selection
|
||||
* c_height: crop image height set by g_selection
|
||||
* h_off: crop horizontal pixel offset
|
||||
* v_off: crop vertical pixel offset
|
||||
* width: out image pixel width
|
||||
* height: out image pixel weight
|
||||
* bytesperline: bytesperline value for each plane
|
||||
* paddr: image frame buffer physical addresses
|
||||
* fmt: color format pointer
|
||||
*/
|
||||
struct mxc_isi_frame {
|
||||
u32 o_width;
|
||||
u32 o_height;
|
||||
u32 c_width;
|
||||
u32 c_height;
|
||||
u32 h_off;
|
||||
u32 v_off;
|
||||
u32 width;
|
||||
u32 height;
|
||||
unsigned int sizeimage[MXC_MAX_PLANES];
|
||||
unsigned int bytesperline[MXC_MAX_PLANES];
|
||||
struct mxc_isi_fmt *fmt;
|
||||
};
|
||||
|
||||
struct mxc_isi_roi_alpha {
|
||||
u8 alpha;
|
||||
struct v4l2_rect rect;
|
||||
};
|
||||
|
||||
struct mxc_isi_buffer {
|
||||
struct vb2_v4l2_buffer v4l2_buf;
|
||||
struct list_head list;
|
||||
struct frame_addr paddr;
|
||||
enum mxc_isi_buf_id id;
|
||||
bool discard;
|
||||
};
|
||||
|
||||
struct mxc_isi_m2m_dev {
|
||||
struct platform_device *pdev;
|
||||
|
||||
struct video_device vdev;
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct v4l2_m2m_dev *m2m_dev;
|
||||
struct v4l2_fh fh;
|
||||
struct v4l2_pix_format_mplane pix;
|
||||
|
||||
struct list_head out_active;
|
||||
struct mxc_isi_ctrls ctrls;
|
||||
|
||||
struct mxc_isi_frame src_f;
|
||||
struct mxc_isi_frame dst_f;
|
||||
|
||||
struct mutex lock;
|
||||
spinlock_t slock;
|
||||
|
||||
unsigned int aborting;
|
||||
unsigned int frame_count;
|
||||
|
||||
u32 req_cap_buf_num;
|
||||
u32 req_out_buf_num;
|
||||
|
||||
u8 id;
|
||||
};
|
||||
|
||||
struct mxc_isi_ctx {
|
||||
struct mxc_isi_m2m_dev *isi_m2m;
|
||||
struct v4l2_fh fh;
|
||||
};
|
||||
|
||||
struct mxc_isi_dev_ops {
|
||||
int (*clk_get)(struct mxc_isi_dev *mxc_isi);
|
||||
int (*clk_enable)(struct mxc_isi_dev *mxc_isi);
|
||||
void (*clk_disable)(struct mxc_isi_dev *mxc_isi);
|
||||
};
|
||||
|
||||
struct mxc_isi_cap_dev {
|
||||
struct v4l2_subdev sd;
|
||||
struct video_device vdev;
|
||||
struct v4l2_fh fh;
|
||||
struct vb2_queue vb2_q;
|
||||
struct v4l2_pix_format_mplane pix;
|
||||
|
||||
struct mxc_isi_dev *mxc_isi;
|
||||
struct platform_device *pdev;
|
||||
struct mxc_isi_ctrls ctrls;
|
||||
struct mxc_isi_buffer buf_discard[2];
|
||||
|
||||
struct media_pad cap_pad;
|
||||
struct media_pad sd_pads[MXC_ISI_SD_PADS_NUM];
|
||||
|
||||
struct list_head out_pending;
|
||||
struct list_head out_active;
|
||||
struct list_head out_discard;
|
||||
|
||||
struct mxc_isi_frame src_f;
|
||||
struct mxc_isi_frame dst_f;
|
||||
|
||||
u32 frame_count;
|
||||
u32 id;
|
||||
|
||||
struct mutex lock;
|
||||
spinlock_t slock;
|
||||
|
||||
/* dirty buffer */
|
||||
size_t discard_size[MXC_MAX_PLANES];
|
||||
void *discard_buffer[MXC_MAX_PLANES];
|
||||
dma_addr_t discard_buffer_dma[MXC_MAX_PLANES];
|
||||
};
|
||||
|
||||
struct mxc_isi_dev {
|
||||
/* Pointer to isi capture child device driver data */
|
||||
struct mxc_isi_cap_dev *isi_cap;
|
||||
|
||||
/* Pointer to isi m2m child device driver data */
|
||||
struct mxc_isi_m2m_dev *isi_m2m;
|
||||
|
||||
struct platform_device *pdev;
|
||||
|
||||
/* clk for imx8qxp/qm platform */
|
||||
struct clk *clk;
|
||||
|
||||
/* clks for imx8mn platform */
|
||||
struct clk *clk_disp_axi;
|
||||
struct clk *clk_disp_apb;
|
||||
struct clk *clk_root_disp_axi;
|
||||
struct clk *clk_root_disp_apb;
|
||||
|
||||
const struct mxc_isi_dev_ops *ops;
|
||||
|
||||
struct reset_control *soft_resetn;
|
||||
struct reset_control *clk_enable;
|
||||
|
||||
struct mutex lock;
|
||||
spinlock_t slock;
|
||||
|
||||
void __iomem *regs;
|
||||
|
||||
u8 chain_buf;
|
||||
u8 alpha;
|
||||
bool m2m_enabled;
|
||||
|
||||
/* manage share ISI channel resource */
|
||||
atomic_t usage_count;
|
||||
|
||||
/* scale factor */
|
||||
u32 xfactor;
|
||||
u32 yfactor;
|
||||
u32 pre_dec_x;
|
||||
u32 pre_dec_y;
|
||||
|
||||
u32 status;
|
||||
|
||||
u32 interface[MAX_PORTS];
|
||||
int id;
|
||||
|
||||
unsigned int hflip:1;
|
||||
unsigned int vflip:1;
|
||||
unsigned int cscen:1;
|
||||
unsigned int scale:1;
|
||||
unsigned int alphaen:1;
|
||||
unsigned int crop:1;
|
||||
unsigned int deinterlace:1;
|
||||
unsigned int is_streaming:1;
|
||||
};
|
||||
|
||||
static inline void set_frame_bounds(struct mxc_isi_frame *f,
|
||||
u32 width, u32 height)
|
||||
{
|
||||
f->o_width = width;
|
||||
f->o_height = height;
|
||||
f->c_width = width;
|
||||
f->c_height = height;
|
||||
f->width = width;
|
||||
f->height = height;
|
||||
}
|
||||
|
||||
static inline void set_frame_out(struct mxc_isi_frame *f,
|
||||
u32 width, u32 height)
|
||||
{
|
||||
f->c_width = width;
|
||||
f->c_height = height;
|
||||
f->width = width;
|
||||
f->height = height;
|
||||
}
|
||||
|
||||
static inline void set_frame_crop(struct mxc_isi_frame *f,
|
||||
u32 left, u32 top, u32 width, u32 height)
|
||||
{
|
||||
f->h_off = left;
|
||||
f->v_off = top;
|
||||
f->c_width = width;
|
||||
f->c_height = height;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IMX8_ISI_CORE)
|
||||
struct mxc_isi_dev *mxc_isi_get_hostdata(struct platform_device *pdev);
|
||||
struct device *mxc_isi_dev_get_parent(struct platform_device *pdev);
|
||||
#else
|
||||
static inline struct mxc_isi_dev *mxc_isi_get_hostdata(struct platform_device *pdev) {}
|
||||
static inline struct struct device *mxc_isi_dev_get_parent(struct platform_device *pdev) {}
|
||||
#endif
|
||||
|
||||
#endif /* __MXC_ISI_CORE_H__ */
|
|
@ -0,0 +1,734 @@
|
|||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Copyright (c) 2019 NXP Semiconductor
|
||||
*
|
||||
*/
|
||||
|
||||
#include <dt-bindings/pinctrl/pads-imx8qxp.h>
|
||||
|
||||
#include "imx8-isi-hw.h"
|
||||
#include "imx8-common.h"
|
||||
|
||||
#define ISI_DOWNSCALE_THRESHOLD 0x4000
|
||||
|
||||
#ifdef DEBUG
|
||||
void dump_isi_regs(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct device *dev = &mxc_isi->pdev->dev;
|
||||
struct {
|
||||
u32 offset;
|
||||
const char *const name[64];
|
||||
} registers[] = {
|
||||
{ 0x00h, "CHNL_CTRL" },
|
||||
{ 0x04h, "CHNL_IMG_CTRL" },
|
||||
{ 0x08h, "CHNL_OUT_BUF_CTRL" },
|
||||
{ 0x0Ch, "CHNL_IMG_CFG" },
|
||||
{ 0x10h, "CHNL_IER" },
|
||||
{ 0x14h, "CHNL_STS" },
|
||||
{ 0x18h, "CHNL_SCALE_FACTOR" },
|
||||
{ 0x1Ch, "CHNL_SCALE_OFFSET" },
|
||||
{ 0x20h, "CHNL_CROP_ULC" },
|
||||
{ 0x24h, "CHNL_CROP_LRC" },
|
||||
{ 0x28h, "CHNL_CSC_COEFF0" },
|
||||
{ 0x2Ch, "CHNL_CSC_COEFF1" },
|
||||
{ 0x30h, "CHNL_CSC_COEFF2" },
|
||||
{ 0x34h, "CHNL_CSC_COEFF3" },
|
||||
{ 0x38h, "CHNL_CSC_COEFF4" },
|
||||
{ 0x3Ch, "CHNL_CSC_COEFF5" },
|
||||
{ 0x40h, "CHNL_ROI_0_ALPHA" },
|
||||
{ 0x44h, "CHNL_ROI_0_ULC" },
|
||||
{ 0x48h, "CHNL_ROI_0_LRC" },
|
||||
{ 0x4Ch, "CHNL_ROI_1_ALPHA" },
|
||||
{ 0x50h, "CHNL_ROI_1_ULC" },
|
||||
{ 0x54h, "CHNL_ROI_1_LRC" },
|
||||
{ 0x58h, "CHNL_ROI_2_ALPHA" },
|
||||
{ 0x5Ch, "CHNL_ROI_2_ULC" },
|
||||
{ 0x60h, "CHNL_ROI_2_LRC" },
|
||||
{ 0x64h, "CHNL_ROI_3_ALPHA" },
|
||||
{ 0x68h, "CHNL_ROI_3_ULC" },
|
||||
{ 0x6Ch, "CHNL_ROI_3_LRC" },
|
||||
{ 0x70h, "CHNL_OUT_BUF1_ADDR_Y" },
|
||||
{ 0x74h, "CHNL_OUT_BUF1_ADDR_U" },
|
||||
{ 0x78h, "CHNL_OUT_BUF1_ADDR_V" },
|
||||
{ 0x7Ch, "CHNL_OUT_BUF_PITCH" },
|
||||
{ 0x80h, "CHNL_IN_BUF_ADDR" },
|
||||
{ 0x84h, "CHNL_IN_BUF_PITCH" },
|
||||
{ 0x88h, "CHNL_MEM_RD_CTRL" },
|
||||
{ 0x8Ch, "CHNL_OUT_BUF2_ADDR_Y" },
|
||||
{ 0x90h, "CHNL_OUT_BUF2_ADDR_U" },
|
||||
{ 0x94h, "CHNL_OUT_BUF2_ADDR_V" },
|
||||
{ 0x98h, "CHNL_SCL_IMG_CFG" },
|
||||
{ 0x9Ch, "CHNL_FLOW_CTRL" },
|
||||
};
|
||||
u32 i;
|
||||
|
||||
dev_dbg(dev, "ISI CHNLC register dump, isi%d\n", mxc_isi->id);
|
||||
for (i = 0; i < ARRAY_SIZE(registers); i++) {
|
||||
u32 reg = readl(mxc_isi->regs + registers.offset);
|
||||
dev_dbg(dev, "%20s[0x%.2x]: %.2x\n",
|
||||
registers.name, registers.offset, reg);
|
||||
}
|
||||
}
|
||||
#else
|
||||
void dump_isi_regs(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* A2,A1, B1, A3, B3, B2,
|
||||
* C2, C1, D1, C3, D3, D2
|
||||
*/
|
||||
static const u32 coeffs[2][6] = {
|
||||
/* YUV2RGB */
|
||||
{ 0x0000012A, 0x012A0198, 0x0730079C,
|
||||
0x0204012A, 0x01F00000, 0x01800180 },
|
||||
|
||||
/* RGB->YUV */
|
||||
{ 0x00810041, 0x07db0019, 0x007007b6,
|
||||
0x07a20070, 0x001007ee, 0x00800080 },
|
||||
};
|
||||
|
||||
static void printk_pixelformat(char *prefix, int val)
|
||||
{
|
||||
pr_info("%s %c%c%c%c\n", prefix ? prefix : "pixelformat",
|
||||
val & 0xff,
|
||||
(val >> 8) & 0xff,
|
||||
(val >> 16) & 0xff,
|
||||
(val >> 24) & 0xff);
|
||||
}
|
||||
|
||||
static bool is_rgb(u32 pix_fmt)
|
||||
{
|
||||
if ((pix_fmt == V4L2_PIX_FMT_RGB565) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_RGB24) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_RGB32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_BGR32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_XRGB32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_XBGR32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_BGR24) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_RGBA) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_ABGR32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_ARGB32))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool is_yuv(u32 pix_fmt)
|
||||
{
|
||||
if ((pix_fmt == V4L2_PIX_FMT_YUYV) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_YUV32) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_YUV444M) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_YUV24) ||
|
||||
(pix_fmt == V4L2_PIX_FMT_NV12))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void chain_buf(struct mxc_isi_dev *mxc_isi, struct mxc_isi_frame *frm)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (frm->o_width > ISI_2K) {
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~CHNL_CTRL_CHAIN_BUF_MASK;
|
||||
val |= (CHNL_CTRL_CHAIN_BUF_2_CHAIN << CHNL_CTRL_CHAIN_BUF_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
} else if (!mxc_isi->chain_buf) {
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~CHNL_CTRL_CHAIN_BUF_MASK;
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_outbuf(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_buffer *buf)
|
||||
{
|
||||
struct vb2_buffer *vb2_buf = &buf->v4l2_buf.vb2_buf;
|
||||
u32 framecount = buf->v4l2_buf.sequence;
|
||||
struct frame_addr *paddr = &buf->paddr;
|
||||
struct mxc_isi_cap_dev *isi_cap;
|
||||
struct v4l2_pix_format_mplane *pix;
|
||||
int val = 0;
|
||||
|
||||
if (buf->discard) {
|
||||
isi_cap = mxc_isi->isi_cap;
|
||||
pix = &isi_cap->pix;
|
||||
paddr->y = isi_cap->discard_buffer_dma[0];
|
||||
if (pix->num_planes == 2)
|
||||
paddr->cb = isi_cap->discard_buffer_dma[1];
|
||||
if (pix->num_planes == 3) {
|
||||
paddr->cb = isi_cap->discard_buffer_dma[1];
|
||||
paddr->cr = isi_cap->discard_buffer_dma[2];
|
||||
}
|
||||
} else {
|
||||
paddr->y = vb2_dma_contig_plane_dma_addr(vb2_buf, 0);
|
||||
|
||||
if (vb2_buf->num_planes == 2)
|
||||
paddr->cb = vb2_dma_contig_plane_dma_addr(vb2_buf, 1);
|
||||
if (vb2_buf->num_planes == 3) {
|
||||
paddr->cb = vb2_dma_contig_plane_dma_addr(vb2_buf, 1);
|
||||
paddr->cr = vb2_dma_contig_plane_dma_addr(vb2_buf, 2);
|
||||
}
|
||||
}
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_OUT_BUF_CTRL);
|
||||
|
||||
if (framecount == 0 || ((mxc_isi->status & 0x100) && (framecount != 1))) {
|
||||
writel(paddr->y, mxc_isi->regs + CHNL_OUT_BUF1_ADDR_Y);
|
||||
writel(paddr->cb, mxc_isi->regs + CHNL_OUT_BUF1_ADDR_U);
|
||||
writel(paddr->cr, mxc_isi->regs + CHNL_OUT_BUF1_ADDR_V);
|
||||
val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR_MASK;
|
||||
buf->id = MXC_ISI_BUF1;
|
||||
} else if (framecount == 1 || mxc_isi->status & 0x200) {
|
||||
writel(paddr->y, mxc_isi->regs + CHNL_OUT_BUF2_ADDR_Y);
|
||||
writel(paddr->cb, mxc_isi->regs + CHNL_OUT_BUF2_ADDR_U);
|
||||
writel(paddr->cr, mxc_isi->regs + CHNL_OUT_BUF2_ADDR_V);
|
||||
val ^= CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR_MASK;
|
||||
buf->id = MXC_ISI_BUF2;
|
||||
}
|
||||
writel(val, mxc_isi->regs + CHNL_OUT_BUF_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_m2m_src_addr(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_buffer *buf)
|
||||
{
|
||||
struct vb2_buffer *vb2_buf = &buf->v4l2_buf.vb2_buf;
|
||||
struct frame_addr *paddr = &buf->paddr;
|
||||
|
||||
/* Only support one plane */
|
||||
paddr->y = vb2_dma_contig_plane_dma_addr(vb2_buf, 0);
|
||||
writel(paddr->y, mxc_isi->regs + CHNL_IN_BUF_ADDR);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_sw_reset(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val |= CHNL_CTRL_SW_RST;
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
mdelay(5);
|
||||
val &= ~CHNL_CTRL_SW_RST;
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_source_config(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~(CHNL_CTRL_MIPI_VC_ID_MASK |
|
||||
CHNL_CTRL_SRC_INPUT_MASK | CHNL_CTRL_SRC_TYPE_MASK);
|
||||
|
||||
switch (mxc_isi->interface[IN_PORT]) {
|
||||
case ISI_INPUT_INTERFACE_MIPI0_CSI2:
|
||||
val |= CHNL_CTRL_SRC_INPUT_MIPI0;
|
||||
if (mxc_isi->interface[SUB_IN_PORT] <= CHNL_CTRL_MIPI_VC_ID_VC3 &&
|
||||
mxc_isi->interface[SUB_IN_PORT] >= CHNL_CTRL_MIPI_VC_ID_VC0)
|
||||
val |= (mxc_isi->interface[SUB_IN_PORT] << CHNL_CTRL_MIPI_VC_ID_OFFSET);
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_MIPI1_CSI2:
|
||||
val |= CHNL_CTRL_SRC_INPUT_MIPI1;
|
||||
if (mxc_isi->interface[SUB_IN_PORT] <= CHNL_CTRL_MIPI_VC_ID_VC3 &&
|
||||
mxc_isi->interface[SUB_IN_PORT] >= CHNL_CTRL_MIPI_VC_ID_VC0)
|
||||
val |= (mxc_isi->interface[SUB_IN_PORT] << CHNL_CTRL_MIPI_VC_ID_OFFSET);
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_DC0:
|
||||
val |= CHNL_CTRL_SRC_INPUT_DC0;
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_DC1:
|
||||
val |= CHNL_CTRL_SRC_INPUT_DC1;
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_HDMI:
|
||||
val |= CHNL_CTRL_SRC_INPUT_HDMI;
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_PARALLEL_CSI:
|
||||
val |= CHNL_CTRL_SRC_INPUT_CSI;
|
||||
break;
|
||||
case ISI_INPUT_INTERFACE_MEM:
|
||||
val |= CHNL_CTRL_SRC_INPUT_MEMORY;
|
||||
val |= (CHNL_CTRL_SRC_TYPE_MEMORY << CHNL_CTRL_SRC_TYPE_OFFSET);
|
||||
break;
|
||||
default:
|
||||
dev_err(&mxc_isi->pdev->dev, "invalid interface\n");
|
||||
break;
|
||||
}
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_flip(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~(CHNL_IMG_CTRL_VFLIP_EN_MASK | CHNL_IMG_CTRL_HFLIP_EN_MASK);
|
||||
|
||||
if (mxc_isi->vflip)
|
||||
val |= (CHNL_IMG_CTRL_VFLIP_EN_ENABLE << CHNL_IMG_CTRL_VFLIP_EN_OFFSET);
|
||||
if (mxc_isi->hflip)
|
||||
val |= (CHNL_IMG_CTRL_HFLIP_EN_ENABLE << CHNL_IMG_CTRL_HFLIP_EN_OFFSET);
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_csc(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f)
|
||||
{
|
||||
struct mxc_isi_fmt *src_fmt = src_f->fmt;
|
||||
struct mxc_isi_fmt *dst_fmt = dst_f->fmt;
|
||||
u32 val, csc = 0;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~(CHNL_IMG_CTRL_FORMAT_MASK |
|
||||
CHNL_IMG_CTRL_YCBCR_MODE_MASK |
|
||||
CHNL_IMG_CTRL_CSC_BYPASS_MASK |
|
||||
CHNL_IMG_CTRL_CSC_MODE_MASK);
|
||||
|
||||
/* set outbuf format */
|
||||
val |= dst_fmt->color << CHNL_IMG_CTRL_FORMAT_OFFSET;
|
||||
|
||||
mxc_isi->cscen = 1;
|
||||
|
||||
if (is_yuv(src_fmt->fourcc) && is_rgb(dst_fmt->fourcc)) {
|
||||
/* YUV2RGB */
|
||||
csc = YUV2RGB;
|
||||
/* YCbCr enable??? */
|
||||
val |= (CHNL_IMG_CTRL_CSC_MODE_YCBCR2RGB << CHNL_IMG_CTRL_CSC_MODE_OFFSET);
|
||||
val |= (CHNL_IMG_CTRL_YCBCR_MODE_ENABLE << CHNL_IMG_CTRL_YCBCR_MODE_OFFSET);
|
||||
} else if (is_rgb(src_fmt->fourcc) && is_yuv(dst_fmt->fourcc)) {
|
||||
/* RGB2YUV */
|
||||
csc = RGB2YUV;
|
||||
val |= (CHNL_IMG_CTRL_CSC_MODE_RGB2YCBCR << CHNL_IMG_CTRL_CSC_MODE_OFFSET);
|
||||
} else {
|
||||
/* Bypass CSC */
|
||||
pr_info("bypass csc\n");
|
||||
mxc_isi->cscen = 0;
|
||||
val |= CHNL_IMG_CTRL_CSC_BYPASS_ENABLE;
|
||||
}
|
||||
|
||||
printk_pixelformat("input fmt", src_fmt->fourcc);
|
||||
printk_pixelformat("output fmt", dst_fmt->fourcc);
|
||||
|
||||
if (mxc_isi->cscen) {
|
||||
writel(coeffs[csc][0], mxc_isi->regs + CHNL_CSC_COEFF0);
|
||||
writel(coeffs[csc][1], mxc_isi->regs + CHNL_CSC_COEFF1);
|
||||
writel(coeffs[csc][2], mxc_isi->regs + CHNL_CSC_COEFF2);
|
||||
writel(coeffs[csc][3], mxc_isi->regs + CHNL_CSC_COEFF3);
|
||||
writel(coeffs[csc][4], mxc_isi->regs + CHNL_CSC_COEFF4);
|
||||
writel(coeffs[csc][5], mxc_isi->regs + CHNL_CSC_COEFF5);
|
||||
}
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_alpha_roi0(struct mxc_isi_dev *mxc_isi,
|
||||
struct v4l2_rect *rect)
|
||||
{
|
||||
u32 val0, val1;
|
||||
|
||||
val0 = (rect->left << 16) | rect->top;
|
||||
writel(val0, mxc_isi->regs + CHNL_ROI_0_ULC);
|
||||
val1 = (rect->width << 16) | rect->height;
|
||||
writel(val0 + val1, mxc_isi->regs + CHNL_ROI_0_LRC);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_alpha(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~(CHNL_IMG_CTRL_GBL_ALPHA_VAL_MASK | CHNL_IMG_CTRL_GBL_ALPHA_EN_MASK);
|
||||
|
||||
if (mxc_isi->alphaen)
|
||||
val |= ((mxc_isi->alpha << CHNL_IMG_CTRL_GBL_ALPHA_VAL_OFFSET) |
|
||||
(CHNL_IMG_CTRL_GBL_ALPHA_EN_ENABLE << CHNL_IMG_CTRL_GBL_ALPHA_EN_OFFSET));
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_chain_buf(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (mxc_isi->chain_buf) {
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~CHNL_CTRL_CHAIN_BUF_MASK;
|
||||
val |= (CHNL_CTRL_CHAIN_BUF_2_CHAIN << CHNL_CTRL_CHAIN_BUF_OFFSET);
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
}
|
||||
|
||||
void mxc_isi_channel_deinterlace_init(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
/* Config for Blending deinterlace */
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_deinterlace(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
/* de-interlacing method
|
||||
* Weaving-------------Yes
|
||||
* Line Doubling-------No
|
||||
* Blending -----------TODO
|
||||
*/
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~CHNL_IMG_CTRL_DEINT_MASK;
|
||||
if (mxc_isi->deinterlace)
|
||||
val |= mxc_isi->deinterlace << CHNL_IMG_CTRL_DEINT_OFFSET;
|
||||
if (mxc_isi->deinterlace == CHNL_IMG_CTRL_DEINT_LDOUBLE_ODD_EVEN ||
|
||||
mxc_isi->deinterlace == CHNL_IMG_CTRL_DEINT_LDOUBLE_EVEN_ODD)
|
||||
mxc_isi_channel_deinterlace_init(mxc_isi);
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_crop(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
struct mxc_isi_frame *src_f = &mxc_isi->isi_cap->src_f;
|
||||
struct v4l2_rect crop;
|
||||
u32 val, val0, val1, temp;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~CHNL_IMG_CTRL_CROP_EN_MASK;
|
||||
|
||||
if ((src_f->o_height == src_f->height) &&
|
||||
(src_f->o_width == src_f->width)) {
|
||||
mxc_isi->crop = 0;
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
return;
|
||||
}
|
||||
|
||||
if (mxc_isi->scale) {
|
||||
temp = (src_f->h_off << 12) / mxc_isi->xfactor;
|
||||
crop.left = temp >> mxc_isi->pre_dec_x;
|
||||
temp = (src_f->v_off << 12) / mxc_isi->yfactor;
|
||||
crop.top = temp >> mxc_isi->pre_dec_y;
|
||||
temp = (src_f->width << 12) / mxc_isi->xfactor;
|
||||
crop.width = temp >> mxc_isi->pre_dec_x;
|
||||
temp = (src_f->height << 12) / mxc_isi->yfactor;
|
||||
crop.height = temp >> mxc_isi->pre_dec_y;
|
||||
} else {
|
||||
crop.left = src_f->h_off;
|
||||
crop.top = src_f->v_off;
|
||||
crop.width = src_f->width;
|
||||
crop.height = src_f->height;
|
||||
}
|
||||
|
||||
mxc_isi->crop = 1;
|
||||
val |= (CHNL_IMG_CTRL_CROP_EN_ENABLE << CHNL_IMG_CTRL_CROP_EN_OFFSET);
|
||||
val0 = crop.top | (crop.left << CHNL_CROP_ULC_X_OFFSET);
|
||||
val1 = crop.height | (crop.width << CHNL_CROP_LRC_X_OFFSET);
|
||||
|
||||
writel(val0, mxc_isi->regs + CHNL_CROP_ULC);
|
||||
writel((val1 + val0), mxc_isi->regs + CHNL_CROP_LRC);
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
static void mxc_isi_channel_clear_scaling(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val0;
|
||||
|
||||
writel(0x10001000, mxc_isi->regs + CHNL_SCALE_FACTOR);
|
||||
|
||||
val0 = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val0 &= ~(CHNL_IMG_CTRL_DEC_X_MASK | CHNL_IMG_CTRL_DEC_Y_MASK);
|
||||
writel(val0, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_set_scaling(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f)
|
||||
{
|
||||
u32 decx, decy;
|
||||
u32 xscale, yscale;
|
||||
u32 xdec = 0, ydec = 0;
|
||||
u32 val0, val1;
|
||||
|
||||
if (dst_f->height == src_f->height ||
|
||||
dst_f->width == src_f->width) {
|
||||
mxc_isi->scale = 0;
|
||||
mxc_isi_channel_clear_scaling(mxc_isi);
|
||||
dev_dbg(&mxc_isi->pdev->dev, "%s: no scale\n", __func__);
|
||||
return;
|
||||
}
|
||||
|
||||
dev_info(&mxc_isi->pdev->dev, "input_size(%d,%d), output_size(%d,%d)\n",
|
||||
src_f->width, src_f->height, dst_f->width, dst_f->height);
|
||||
|
||||
mxc_isi->scale = 1;
|
||||
|
||||
decx = src_f->width / dst_f->width;
|
||||
decy = src_f->height / dst_f->height;
|
||||
|
||||
if (decx > 1) {
|
||||
/* Down */
|
||||
if (decx >= 2 && decx < 4) {
|
||||
decx = 2;
|
||||
xdec = 1;
|
||||
} else if (decx >= 4 && decx < 8) {
|
||||
decx = 4;
|
||||
xdec = 2;
|
||||
} else if (decx >= 8) {
|
||||
decx = 8;
|
||||
xdec = 3;
|
||||
}
|
||||
xscale = src_f->width * 0x1000 / (dst_f->width * decx);
|
||||
} else {
|
||||
/* Up */
|
||||
xscale = src_f->width * 0x1000 / dst_f->width;
|
||||
}
|
||||
|
||||
if (decy > 1) {
|
||||
if (decy >= 2 && decy < 4) {
|
||||
decy = 2;
|
||||
ydec = 1;
|
||||
} else if (decy >= 4 && decy < 8) {
|
||||
decy = 4;
|
||||
ydec = 2;
|
||||
} else if (decy >= 8) {
|
||||
decy = 8;
|
||||
ydec = 3;
|
||||
}
|
||||
yscale = src_f->height * 0x1000 / (dst_f->height * decy);
|
||||
} else {
|
||||
yscale = src_f->height * 0x1000 / dst_f->height;
|
||||
}
|
||||
|
||||
val0 = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val0 |= CHNL_IMG_CTRL_YCBCR_MODE_MASK;//YCbCr Sandor???
|
||||
val0 &= ~(CHNL_IMG_CTRL_DEC_X_MASK | CHNL_IMG_CTRL_DEC_Y_MASK);
|
||||
val0 |= (xdec << CHNL_IMG_CTRL_DEC_X_OFFSET) |
|
||||
(ydec << CHNL_IMG_CTRL_DEC_Y_OFFSET);
|
||||
writel(val0, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
|
||||
if (xscale > ISI_DOWNSCALE_THRESHOLD)
|
||||
xscale = ISI_DOWNSCALE_THRESHOLD;
|
||||
if (yscale > ISI_DOWNSCALE_THRESHOLD)
|
||||
yscale = ISI_DOWNSCALE_THRESHOLD;
|
||||
|
||||
val1 = xscale | (yscale << CHNL_SCALE_FACTOR_Y_SCALE_OFFSET);
|
||||
|
||||
writel(val1, mxc_isi->regs + CHNL_SCALE_FACTOR);
|
||||
|
||||
/* Update scale config if scaling enabled */
|
||||
val1 = dst_f->o_width | (dst_f->o_height << CHNL_SCL_IMG_CFG_HEIGHT_OFFSET);
|
||||
writel(val1, mxc_isi->regs + CHNL_SCL_IMG_CFG);
|
||||
|
||||
writel(0, mxc_isi->regs + CHNL_SCALE_OFFSET);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
void mxc_isi_channel_init(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* sw reset */
|
||||
mxc_isi_channel_sw_reset(mxc_isi);
|
||||
|
||||
/* Init channel clk first */
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val |= (CHNL_CTRL_CLK_EN_ENABLE << CHNL_CTRL_CLK_EN_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_deinit(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* sw reset */
|
||||
mxc_isi_channel_sw_reset(mxc_isi);
|
||||
|
||||
/* deinit channel clk first */
|
||||
val = (CHNL_CTRL_CLK_EN_ENABLE << CHNL_CTRL_CLK_EN_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_config(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* images having higher than 2048 horizontal resolution */
|
||||
chain_buf(mxc_isi, src_f);
|
||||
|
||||
/* config output frame size and format */
|
||||
val = src_f->o_width | (src_f->o_height << CHNL_IMG_CFG_HEIGHT_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CFG);
|
||||
|
||||
/* scale size need to equal input size when scaling disabled*/
|
||||
writel(val, mxc_isi->regs + CHNL_SCL_IMG_CFG);
|
||||
|
||||
/* check csc and scaling */
|
||||
mxc_isi_channel_set_csc(mxc_isi, src_f, dst_f);
|
||||
|
||||
mxc_isi_channel_set_scaling(mxc_isi, src_f, dst_f);
|
||||
|
||||
/* select the source input / src type / virtual channel for mipi*/
|
||||
mxc_isi_channel_source_config(mxc_isi);
|
||||
|
||||
/* line pitch */
|
||||
val = dst_f->bytesperline[0];
|
||||
writel(val, mxc_isi->regs + CHNL_OUT_BUF_PITCH);
|
||||
|
||||
/* TODO */
|
||||
mxc_isi_channel_set_flip(mxc_isi);
|
||||
|
||||
mxc_isi_channel_set_alpha(mxc_isi);
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~CHNL_CTRL_CHNL_BYPASS_MASK;
|
||||
|
||||
/* Bypass channel */
|
||||
if (!mxc_isi->cscen && !mxc_isi->scale)
|
||||
val |= (CHNL_CTRL_CHNL_BYPASS_ENABLE << CHNL_CTRL_CHNL_BYPASS_OFFSET);
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_clean_registers(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 status;
|
||||
|
||||
status = mxc_isi_get_irq_status(mxc_isi);
|
||||
mxc_isi_clean_irq_status(mxc_isi, status);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_enable(struct mxc_isi_dev *mxc_isi, bool m2m_enabled)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val |= 0xff << CHNL_CTRL_BLANK_PXL_OFFSET;
|
||||
|
||||
if (m2m_enabled) {
|
||||
val &= ~(CHNL_CTRL_SRC_TYPE_MASK | CHNL_CTRL_SRC_INPUT_MASK);
|
||||
val |= (CHNL_CTRL_SRC_INPUT_MEMORY << CHNL_CTRL_SRC_INPUT_OFFSET |
|
||||
CHNL_CTRL_SRC_TYPE_MEMORY << CHNL_CTRL_SRC_TYPE_OFFSET);
|
||||
}
|
||||
|
||||
val &= ~CHNL_CTRL_CHNL_EN_MASK;
|
||||
val |= CHNL_CTRL_CHNL_EN_ENABLE << CHNL_CTRL_CHNL_EN_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
|
||||
mxc_isi_clean_registers(mxc_isi);
|
||||
mxc_isi_enable_irq(mxc_isi);
|
||||
|
||||
if (m2m_enabled) {
|
||||
mxc_isi_m2m_start_read(mxc_isi);
|
||||
return;
|
||||
}
|
||||
|
||||
dump_isi_regs(mxc_isi);
|
||||
msleep(300);
|
||||
}
|
||||
|
||||
void mxc_isi_channel_disable(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
mxc_isi_disable_irq(mxc_isi);
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_CTRL);
|
||||
val &= ~(CHNL_CTRL_CHNL_EN_MASK | CHNL_CTRL_CLK_EN_MASK);
|
||||
val |= (CHNL_CTRL_CHNL_EN_DISABLE << CHNL_CTRL_CHNL_EN_OFFSET);
|
||||
val |= (CHNL_CTRL_CLK_EN_DISABLE << CHNL_CTRL_CLK_EN_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_CTRL);
|
||||
}
|
||||
|
||||
void mxc_isi_enable_irq(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = CHNL_IER_FRM_RCVD_EN_MASK |
|
||||
CHNL_IER_OFLW_Y_BUF_EN_MASK |
|
||||
CHNL_IER_AXI_WR_ERR_U_EN_MASK |
|
||||
CHNL_IER_AXI_WR_ERR_V_EN_MASK |
|
||||
CHNL_IER_AXI_WR_ERR_Y_EN_MASK |
|
||||
CHNL_IER_OFLW_PANIC_V_BUF_EN_MASK |
|
||||
CHNL_IER_EXCS_OFLW_V_BUF_EN_MASK |
|
||||
CHNL_IER_OFLW_V_BUF_EN_MASK |
|
||||
CHNL_IER_OFLW_PANIC_U_BUF_EN_MASK |
|
||||
CHNL_IER_EXCS_OFLW_U_BUF_EN_MASK |
|
||||
CHNL_IER_OFLW_U_BUF_EN_MASK |
|
||||
CHNL_IER_OFLW_PANIC_Y_BUF_EN_MASK |
|
||||
CHNL_IER_EXCS_OFLW_Y_BUF_EN_MASK |
|
||||
CHNL_IER_OFLW_Y_BUF_EN_MASK;
|
||||
|
||||
writel(val, mxc_isi->regs + CHNL_IER);
|
||||
}
|
||||
|
||||
void mxc_isi_disable_irq(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
writel(0, mxc_isi->regs + CHNL_IER);
|
||||
}
|
||||
|
||||
u32 mxc_isi_get_irq_status(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
return readl(mxc_isi->regs + CHNL_STS);
|
||||
}
|
||||
|
||||
void mxc_isi_clean_irq_status(struct mxc_isi_dev *mxc_isi, u32 val)
|
||||
{
|
||||
writel(val, mxc_isi->regs + CHNL_STS);
|
||||
}
|
||||
|
||||
void mxc_isi_m2m_config_src(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* source format */
|
||||
val = readl(mxc_isi->regs + CHNL_MEM_RD_CTRL);
|
||||
val &= ~CHNL_MEM_RD_CTRL_IMG_TYPE_MASK;
|
||||
val |= src_f->fmt->color << CHNL_MEM_RD_CTRL_IMG_TYPE_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_MEM_RD_CTRL);
|
||||
|
||||
/* source image width and height */
|
||||
val = (src_f->width << CHNL_IMG_CFG_WIDTH_OFFSET |
|
||||
src_f->height << CHNL_IMG_CFG_HEIGHT_OFFSET);
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CFG);
|
||||
|
||||
/* source pitch */
|
||||
val = src_f->bytesperline[0] << CHNL_IN_BUF_PITCH_LINE_PITCH_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_IN_BUF_PITCH);
|
||||
}
|
||||
|
||||
void mxc_isi_m2m_config_dst(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *dst_f)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
/* out format */
|
||||
val = readl(mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
val &= ~CHNL_IMG_CTRL_FORMAT_MASK;
|
||||
val |= dst_f->fmt->color << CHNL_IMG_CTRL_FORMAT_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_IMG_CTRL);
|
||||
|
||||
/* out pitch */
|
||||
val = readl(mxc_isi->regs + CHNL_OUT_BUF_PITCH);
|
||||
val &= ~CHNL_IN_BUF_PITCH_LINE_PITCH_MASK;
|
||||
val |= dst_f->bytesperline[0] << CHNL_OUT_BUF_PITCH_LINE_PITCH_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_OUT_BUF_PITCH);
|
||||
}
|
||||
|
||||
void mxc_isi_m2m_start_read(struct mxc_isi_dev *mxc_isi)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
val = readl(mxc_isi->regs + CHNL_MEM_RD_CTRL);
|
||||
val &= ~ CHNL_MEM_RD_CTRL_READ_MEM_MASK;
|
||||
writel(val, mxc_isi->regs + CHNL_MEM_RD_CTRL);
|
||||
udelay(300);
|
||||
|
||||
val |= CHNL_MEM_RD_CTRL_READ_MEM_ENABLE << CHNL_MEM_RD_CTRL_READ_MEM_OFFSET;
|
||||
writel(val, mxc_isi->regs + CHNL_MEM_RD_CTRL);
|
||||
}
|
|
@ -0,0 +1,521 @@
|
|||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/*
|
||||
* Copyright (c) 2019 NXP Semiconductor
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __MXC_ISI_HW_H__
|
||||
#define __MXC_ISI_HW_H__
|
||||
|
||||
#include <linux/delay.h>
|
||||
#include <linux/types.h>
|
||||
#include <linux/errno.h>
|
||||
#include <linux/bug.h>
|
||||
#include <linux/platform_device.h>
|
||||
#include <linux/videodev2.h>
|
||||
|
||||
#include "imx8-isi-core.h"
|
||||
|
||||
/* ISI Registers Define */
|
||||
/* Channel Control Register */
|
||||
#define CHNL_CTRL 0x0
|
||||
#define CHNL_CTRL_CHNL_EN_OFFSET 31
|
||||
#define CHNL_CTRL_CHNL_EN_MASK 0x80000000
|
||||
#define CHNL_CTRL_CHNL_EN_DISABLE 0
|
||||
#define CHNL_CTRL_CHNL_EN_ENABLE 1
|
||||
#define CHNL_CTRL_CLK_EN_OFFSET 30
|
||||
#define CHNL_CTRL_CLK_EN_MASK 0x40000000
|
||||
#define CHNL_CTRL_CLK_EN_DISABLE 0
|
||||
#define CHNL_CTRL_CLK_EN_ENABLE 1
|
||||
#define CHNL_CTRL_CHNL_BYPASS_OFFSET 29
|
||||
#define CHNL_CTRL_CHNL_BYPASS_MASK 0x20000000
|
||||
#define CHNL_CTRL_CHNL_BYPASS_ENABLE 1
|
||||
#define CHNL_CTRL_CHAIN_BUF_OFFSET 25
|
||||
#define CHNL_CTRL_CHAIN_BUF_MASK 0x60000
|
||||
#define CHNL_CTRL_CHAIN_BUF_NO_CHAIN 0
|
||||
#define CHNL_CTRL_CHAIN_BUF_2_CHAIN 1
|
||||
#define CHNL_CTRL_SW_RST_OFFSET 24
|
||||
#define CHNL_CTRL_SW_RST_MASK 0x1000000
|
||||
#define CHNL_CTRL_SW_RST 0x1000000
|
||||
#define CHNL_CTRL_BLANK_PXL_OFFSET 16
|
||||
#define CHNL_CTRL_MIPI_VC_ID_OFFSET 6
|
||||
#define CHNL_CTRL_MIPI_VC_ID_MASK 0xc0
|
||||
#define CHNL_CTRL_MIPI_VC_ID_VC0 0
|
||||
#define CHNL_CTRL_MIPI_VC_ID_VC1 1
|
||||
#define CHNL_CTRL_MIPI_VC_ID_VC2 2
|
||||
#define CHNL_CTRL_MIPI_VC_ID_VC3 3
|
||||
#define CHNL_CTRL_SRC_TYPE_OFFSET 4
|
||||
#define CHNL_CTRL_SRC_TYPE_MASK 0x10
|
||||
#define CHNL_CTRL_SRC_TYPE_DEVICE 0
|
||||
#define CHNL_CTRL_SRC_TYPE_MEMORY 1
|
||||
#define CHNL_CTRL_SRC_INPUT_OFFSET 0
|
||||
#define CHNL_CTRL_SRC_INPUT_MASK 0x7
|
||||
#define CHNL_CTRL_SRC_INPUT_DC0 0
|
||||
#define CHNL_CTRL_SRC_INPUT_DC1 1
|
||||
#define CHNL_CTRL_SRC_INPUT_MIPI0 2
|
||||
#define CHNL_CTRL_SRC_INPUT_MIPI1 3
|
||||
#define CHNL_CTRL_SRC_INPUT_HDMI 4
|
||||
#define CHNL_CTRL_SRC_INPUT_CSI 4
|
||||
#define CHNL_CTRL_SRC_INPUT_MEMORY 5
|
||||
|
||||
/* Channel Image Control Register */
|
||||
#define CHNL_IMG_CTRL 0x4
|
||||
#define CHNL_IMG_CTRL_FORMAT_OFFSET 24
|
||||
#define CHNL_IMG_CTRL_FORMAT_MASK 0x3F000000
|
||||
#define CHNL_IMG_CTRL_GBL_ALPHA_VAL_OFFSET 16
|
||||
#define CHNL_IMG_CTRL_GBL_ALPHA_VAL_MASK 0xFF0000
|
||||
#define CHNL_IMG_CTRL_GBL_ALPHA_EN_OFFSET 15
|
||||
#define CHNL_IMG_CTRL_GBL_ALPHA_EN_ENABLE 1
|
||||
#define CHNL_IMG_CTRL_GBL_ALPHA_EN_MASK 0x8000
|
||||
#define CHNL_IMG_CTRL_DEINT_OFFSET 12
|
||||
#define CHNL_IMG_CTRL_DEINT_MASK 0x7000
|
||||
#define CHNL_IMG_CTRL_DEINT_WEAVE_ODD_EVEN 2
|
||||
#define CHNL_IMG_CTRL_DEINT_WEAVE_EVEN_ODD 3
|
||||
#define CHNL_IMG_CTRL_DEINT_BLEND_ODD_EVEN 4
|
||||
#define CHNL_IMG_CTRL_DEINT_BLEND_EVEN_ODD 5
|
||||
#define CHNL_IMG_CTRL_DEINT_LDOUBLE_ODD_EVEN 6
|
||||
#define CHNL_IMG_CTRL_DEINT_LDOUBLE_EVEN_ODD 7
|
||||
#define CHNL_IMG_CTRL_DEC_X_OFFSET 10
|
||||
#define CHNL_IMG_CTRL_DEC_X_MASK 0xC00
|
||||
#define CHNL_IMG_CTRL_DEC_X_0 0
|
||||
#define CHNL_IMG_CTRL_DEC_X_2 1
|
||||
#define CHNL_IMG_CTRL_DEC_X_4 2
|
||||
#define CHNL_IMG_CTRL_DEC_X_8 3
|
||||
#define CHNL_IMG_CTRL_DEC_Y_OFFSET 8
|
||||
#define CHNL_IMG_CTRL_DEC_Y_MASK 0x300
|
||||
#define CHNL_IMG_CTRL_DEC_Y_0 0
|
||||
#define CHNL_IMG_CTRL_DEC_Y_2 1
|
||||
#define CHNL_IMG_CTRL_DEC_Y_4 2
|
||||
#define CHNL_IMG_CTRL_DEC_Y_8 3
|
||||
#define CHNL_IMG_CTRL_CROP_EN_OFFSET 7
|
||||
#define CHNL_IMG_CTRL_CROP_EN_MASK 0x80
|
||||
#define CHNL_IMG_CTRL_CROP_EN_ENABLE 1
|
||||
#define CHNL_IMG_CTRL_VFLIP_EN_OFFSET 6
|
||||
#define CHNL_IMG_CTRL_VFLIP_EN_MASK 0x40
|
||||
#define CHNL_IMG_CTRL_VFLIP_EN_ENABLE 1
|
||||
#define CHNL_IMG_CTRL_HFLIP_EN_OFFSET 5
|
||||
#define CHNL_IMG_CTRL_HFLIP_EN_MASK 0x20
|
||||
#define CHNL_IMG_CTRL_HFLIP_EN_ENABLE 1
|
||||
#define CHNL_IMG_CTRL_YCBCR_MODE_OFFSET 3
|
||||
#define CHNL_IMG_CTRL_YCBCR_MODE_MASK 0x8
|
||||
#define CHNL_IMG_CTRL_YCBCR_MODE_ENABLE 1
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_OFFSET 1
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_MASK 0x6
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_YUV2RGB 0
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_YCBCR2RGB 1
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_RGB2YUV 2
|
||||
#define CHNL_IMG_CTRL_CSC_MODE_RGB2YCBCR 3
|
||||
#define CHNL_IMG_CTRL_CSC_BYPASS_OFFSET 0
|
||||
#define CHNL_IMG_CTRL_CSC_BYPASS_MASK 0x1
|
||||
#define CHNL_IMG_CTRL_CSC_BYPASS_ENABLE 0x1
|
||||
|
||||
/* Channel Output Buffer Control Register */
|
||||
#define CHNL_OUT_BUF_CTRL 0x8
|
||||
#define CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR_OFFSET 15
|
||||
#define CHNL_OUT_BUF_CTRL_LOAD_BUF2_ADDR_MASK 0x8000
|
||||
#define CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR_OFFSET 14
|
||||
#define CHNL_OUT_BUF_CTRL_LOAD_BUF1_ADDR_MASK 0x4000
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_OFFSET 6
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_MASK 0xC0
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_NO_PANIC 0
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_25 1
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_50 2
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_V_PANIC_75 3
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_OFFSET 3
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_MASK 0x18
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_NO_PANIC 0
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_25 1
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_50 2
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_U_PANIC_75 3
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_OFFSET 0
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_MASK 0x3
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_NO_PANIC 0
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_25 1
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_50 2
|
||||
#define CHNL_OUT_BUF_CTRL_OFLW_PANIC_SET_THD_Y_PANIC_75 3
|
||||
|
||||
/* Channel Image Configuration */
|
||||
#define CHNL_IMG_CFG 0xC
|
||||
#define CHNL_IMG_CFG_HEIGHT_OFFSET 16
|
||||
#define CHNL_IMG_CFG_HEIGHT_MASK 0x1FFF0000
|
||||
#define CHNL_IMG_CFG_WIDTH_OFFSET 0
|
||||
#define CHNL_IMG_CFG_WIDTH_MASK 0x1FFF
|
||||
|
||||
/* Channel Interrupt Enable Register */
|
||||
#define CHNL_IER 0x10
|
||||
#define CHNL_IER_MEM_RD_DONE_EN_OFFSET 31
|
||||
#define CHNL_IER_MEM_RD_DONE_EN_MASK 0x80000000
|
||||
#define CHNL_IER_MEM_RD_DONE_EN_ENABLE 1
|
||||
#define CHNL_IER_LINE_RCVD_EN_OFFSET 30
|
||||
#define CHNL_IER_LINE_RCVD_EN_MASK 0x40000000
|
||||
#define CHNL_IER_LINE_RCVD_EN_ENABLE 1
|
||||
#define CHNL_IER_FRM_RCVD_EN_OFFSET 29
|
||||
#define CHNL_IER_FRM_RCVD_EN_MASK 0x20000000
|
||||
#define CHNL_IER_FRM_RCVD_EN_ENABLE 1
|
||||
#define CHNL_IER_AXI_WR_ERR_V_EN_OFFSET 28
|
||||
#define CHNL_IER_AXI_WR_ERR_V_EN_MASK 0x10000000
|
||||
#define CHNL_IER_AXI_WR_ERR_V_EN_ENABLE 1
|
||||
#define CHNL_IER_AXI_WR_ERR_U_EN_OFFSET 27
|
||||
#define CHNL_IER_AXI_WR_ERR_U_EN_MASK 0x8000000
|
||||
#define CHNL_IER_AXI_WR_ERR_U_EN_ENABLE 1
|
||||
#define CHNL_IER_AXI_WR_ERR_Y_EN_OFFSET 26
|
||||
#define CHNL_IER_AXI_WR_ERR_Y_EN_MASK 0x4000000
|
||||
#define CHNL_IER_AXI_WR_ERR_Y_EN_ENABLE 1
|
||||
#define CHNL_IER_AXI_RD_ERR_EN_OFFSET 25
|
||||
#define CHNL_IER_AXI_RD_ERR_EN_MASK 0x2000000
|
||||
#define CHNL_IER_AXI_RD_ERR_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_PANIC_V_BUF_EN_OFFSET 24
|
||||
#define CHNL_IER_OFLW_PANIC_V_BUF_EN_MASK 0x1000000
|
||||
#define CHNL_IER_OFLW_PANIC_V_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_EXCS_OFLW_V_BUF_EN_OFFSET 23
|
||||
#define CHNL_IER_EXCS_OFLW_V_BUF_EN_MASK 0x800000
|
||||
#define CHNL_IER_EXCS_OFLW_V_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_V_BUF_EN_OFFSET 22
|
||||
#define CHNL_IER_OFLW_V_BUF_EN_MASK 0x400000
|
||||
#define CHNL_IER_OFLW_V_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_PANIC_U_BUF_EN_OFFSET 21
|
||||
#define CHNL_IER_OFLW_PANIC_U_BUF_EN_MASK 0x200000
|
||||
#define CHNL_IER_OFLW_PANIC_U_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_EXCS_OFLW_U_BUF_EN_OFFSET 20
|
||||
#define CHNL_IER_EXCS_OFLW_U_BUF_EN_MASK 0x100000
|
||||
#define CHNL_IER_EXCS_OFLW_U_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_U_BUF_EN_OFFSET 19
|
||||
#define CHNL_IER_OFLW_U_BUF_EN_MASK 0x80000
|
||||
#define CHNL_IER_OFLW_U_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_PANIC_Y_BUF_EN_OFFSET 18
|
||||
#define CHNL_IER_OFLW_PANIC_Y_BUF_EN_MASK 0x40000
|
||||
#define CHNL_IER_OFLW_PANIC_Y_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_EXCS_OFLW_Y_BUF_EN_OFFSET 17
|
||||
#define CHNL_IER_EXCS_OFLW_Y_BUF_EN_MASK 0x20000
|
||||
#define CHNL_IER_EXCS_OFLW_Y_BUF_EN_ENABLE 1
|
||||
#define CHNL_IER_OFLW_Y_BUF_EN_OFFSET 16
|
||||
#define CHNL_IER_OFLW_Y_BUF_EN_MASK 0x10000
|
||||
#define CHNL_IER_OFLW_Y_BUF_EN_ENABLE 1
|
||||
|
||||
/* Channel Status Register */
|
||||
#define CHNL_STS 0x14
|
||||
#define CHNL_STS_MEM_RD_DONE_OFFSET 31
|
||||
#define CHNL_STS_MEM_RD_DONE_MASK 0x80000000
|
||||
#define CHNL_STS_MEM_RD_DONE_ENABLE 1
|
||||
#define CHNL_STS_LINE_STRD_OFFSET 30
|
||||
#define CHNL_STS_LINE_STRD_MASK 0x40000000
|
||||
#define CHNL_STS_LINE_STRD_ENABLE 1
|
||||
#define CHNL_STS_FRM_STRD_OFFSET 29
|
||||
#define CHNL_STS_FRM_STRD_MASK 0x20000000
|
||||
#define CHNL_STS_FRM_STRD_ENABLE 1
|
||||
#define CHNL_STS_AXI_WR_ERR_V_OFFSET 28
|
||||
#define CHNL_STS_AXI_WR_ERR_V_MASK 0x10000000
|
||||
#define CHNL_STS_AXI_WR_ERR_V_ENABLE 1
|
||||
#define CHNL_STS_AXI_WR_ERR_U_OFFSET 27
|
||||
#define CHNL_STS_AXI_WR_ERR_U_MASK 0x8000000
|
||||
#define CHNL_STS_AXI_WR_ERR_U_ENABLE 1
|
||||
#define CHNL_STS_AXI_WR_ERR_Y_OFFSET 26
|
||||
#define CHNL_STS_AXI_WR_ERR_Y_MASK 0x4000000
|
||||
#define CHNL_STS_AXI_WR_ERR_Y_ENABLE 1
|
||||
#define CHNL_STS_AXI_RD_ERR_OFFSET 25
|
||||
#define CHNL_STS_AXI_RD_ERR_MASK 0x2000000
|
||||
#define CHNL_STS_AXI_RD_ERR_ENABLE 1
|
||||
#define CHNL_STS_OFLW_PANIC_V_BUF_OFFSET 24
|
||||
#define CHNL_STS_OFLW_PANIC_V_BUF_MASK 0x1000000
|
||||
#define CHNL_STS_OFLW_PANIC_V_BUF_ENABLE 1
|
||||
#define CHNL_STS_EXCS_OFLW_V_BUF_OFFSET 23
|
||||
#define CHNL_STS_EXCS_OFLW_V_BUF_MASK 0x800000
|
||||
#define CHNL_STS_EXCS_OFLW_V_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_V_BUF_OFFSET 22
|
||||
#define CHNL_STS_OFLW_V_BUF_MASK 0x400000
|
||||
#define CHNL_STS_OFLW_V_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_PANIC_U_BUF_OFFSET 21
|
||||
#define CHNL_STS_OFLW_PANIC_U_BUF_MASK 0x200000
|
||||
#define CHNL_STS_OFLW_PANIC_U_BUF_ENABLE 1
|
||||
#define CHNL_STS_EXCS_OFLW_U_BUF_OFFSET 20
|
||||
#define CHNL_STS_EXCS_OFLW_U_BUF_MASK 0x100000
|
||||
#define CHNL_STS_EXCS_OFLW_U_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_U_BUF_OFFSET 19
|
||||
#define CHNL_STS_OFLW_U_BUF_MASK 0x80000
|
||||
#define CHNL_STS_OFLW_U_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_PANIC_Y_BUF_OFFSET 18
|
||||
#define CHNL_STS_OFLW_PANIC_Y_BUF_MASK 0x40000
|
||||
#define CHNL_STS_OFLW_PANIC_Y_BUF_ENABLE 1
|
||||
#define CHNL_STS_EXCS_OFLW_Y_BUF_OFFSET 17
|
||||
#define CHNL_STS_EXCS_OFLW_Y_BUF_MASK 0x20000
|
||||
#define CHNL_STS_EXCS_OFLW_Y_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_Y_BUF_OFFSET 16
|
||||
#define CHNL_STS_OFLW_Y_BUF_MASK 0x10000
|
||||
#define CHNL_STS_OFLW_Y_BUF_ENABLE 1
|
||||
#define CHNL_STS_OFLW_BYTES_OFFSET 0
|
||||
#define CHNL_STS_OFLW_BYTES_MASK 0xFF
|
||||
|
||||
/* Channel Scale Factor Register */
|
||||
#define CHNL_SCALE_FACTOR 0x18
|
||||
#define CHNL_SCALE_FACTOR_Y_SCALE_OFFSET 16
|
||||
#define CHNL_SCALE_FACTOR_Y_SCALE_MASK 0x3FFF0000
|
||||
#define CHNL_SCALE_FACTOR_X_SCALE_OFFSET 0
|
||||
#define CHNL_SCALE_FACTOR_X_SCALE_MASK 0x3FFF
|
||||
|
||||
/* Channel Scale Offset Register */
|
||||
#define CHNL_SCALE_OFFSET 0x1C
|
||||
#define CHNL_SCALE_OFFSET_Y_SCALE_OFFSET 16
|
||||
#define CHNL_SCALE_OFFSET_Y_SCALE_MASK 0xFFF0000
|
||||
#define CHNL_SCALE_OFFSET_X_SCALE_OFFSET 0
|
||||
#define CHNL_SCALE_OFFSET_X_SCALE_MASK 0xFFF
|
||||
|
||||
/* Channel Crop Upper Left Corner Coordinate Register */
|
||||
#define CHNL_CROP_ULC 0x20
|
||||
#define CHNL_CROP_ULC_X_OFFSET 16
|
||||
#define CHNL_CROP_ULC_X_MASK 0xFFF0000
|
||||
#define CHNL_CROP_ULC_Y_OFFSET 0
|
||||
#define CHNL_CROP_ULC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Crop Lower Right Corner Coordinate Register */
|
||||
#define CHNL_CROP_LRC 0x24
|
||||
#define CHNL_CROP_LRC_X_OFFSET 16
|
||||
#define CHNL_CROP_LRC_X_MASK 0xFFF0000
|
||||
#define CHNL_CROP_LRC_Y_OFFSET 0
|
||||
#define CHNL_CROP_LRC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 0 */
|
||||
#define CHNL_CSC_COEFF0 0x28
|
||||
#define CHNL_CSC_COEFF0_A2_OFFSET 16
|
||||
#define CHNL_CSC_COEFF0_A2_MASK 0x7FF0000
|
||||
#define CHNL_CSC_COEFF0_A1_OFFSET 0
|
||||
#define CHNL_CSC_COEFF0_A1_MASK 0x7FF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 1 */
|
||||
#define CHNL_CSC_COEFF1 0x2C
|
||||
#define CHNL_CSC_COEFF1_B1_OFFSET 16
|
||||
#define CHNL_CSC_COEFF1_B1_MASK 0x7FF0000
|
||||
#define CHNL_CSC_COEFF1_A3_OFFSET 0
|
||||
#define CHNL_CSC_COEFF1_A3_MASK 0x7FF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 2 */
|
||||
#define CHNL_CSC_COEFF2 0x30
|
||||
#define CHNL_CSC_COEFF2_B3_OFFSET 16
|
||||
#define CHNL_CSC_COEFF2_B3_MASK 0x7FF0000
|
||||
#define CHNL_CSC_COEFF2_B2_OFFSET 0
|
||||
#define CHNL_CSC_COEFF2_B2_MASK 0x7FF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 3 */
|
||||
#define CHNL_CSC_COEFF3 0x34
|
||||
#define CHNL_CSC_COEFF3_C2_OFFSET 16
|
||||
#define CHNL_CSC_COEFF3_C2_MASK 0x7FF0000
|
||||
#define CHNL_CSC_COEFF3_C1_OFFSET 0
|
||||
#define CHNL_CSC_COEFF3_C1_MASK 0x7FF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 4 */
|
||||
#define CHNL_CSC_COEFF4 0x38
|
||||
#define CHNL_CSC_COEFF4_D1_OFFSET 16
|
||||
#define CHNL_CSC_COEFF4_D1_MASK 0x1FF0000
|
||||
#define CHNL_CSC_COEFF4_C3_OFFSET 0
|
||||
#define CHNL_CSC_COEFF4_C3_MASK 0x7FF
|
||||
|
||||
/* Channel Color Space Conversion Coefficient Register 5 */
|
||||
#define CHNL_CSC_COEFF5 0x3C
|
||||
#define CHNL_CSC_COEFF5_D3_OFFSET 16
|
||||
#define CHNL_CSC_COEFF5_D3_MASK 0x1FF0000
|
||||
#define CHNL_CSC_COEFF5_D2_OFFSET 0
|
||||
#define CHNL_CSC_COEFF5_D2_MASK 0x1FF
|
||||
|
||||
/* Channel Alpha Value Register for ROI 0 */
|
||||
#define CHNL_ROI_0_ALPHA 0x40
|
||||
#define CHNL_ROI_0_ALPHA_OFFSET 24
|
||||
#define CHNL_ROI_0_ALPHA_MASK 0xFF000000
|
||||
#define CHNL_ROI_0_ALPHA_EN_OFFSET 16
|
||||
#define CHNL_ROI_0_ALPHA_EN_MASK 0x10000
|
||||
|
||||
/* Channel Upper Left Coordinate Register for ROI 0 */
|
||||
#define CHNL_ROI_0_ULC 0x44
|
||||
#define CHNL_ROI_0_ULC_X_OFFSET 16
|
||||
#define CHNL_ROI_0_ULC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_0_ULC_Y_OFFSET 0
|
||||
#define CHNL_ROI_0_ULC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Lower Right Coordinate Register for ROI 0 */
|
||||
#define CHNL_ROI_0_LRC 0x48
|
||||
#define CHNL_ROI_0_LRC_X_OFFSET 16
|
||||
#define CHNL_ROI_0_LRC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_0_LRC_Y_OFFSET 0
|
||||
#define CHNL_ROI_0_LRC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Alpha Value Register for ROI 1 */
|
||||
#define CHNL_ROI_1_ALPHA 0x4C
|
||||
#define CHNL_ROI_1_ALPHA_OFFSET 24
|
||||
#define CHNL_ROI_1_ALPHA_MASK 0xFF000000
|
||||
#define CHNL_ROI_1_ALPHA_EN_OFFSET 16
|
||||
#define CHNL_ROI_1_ALPHA_EN_MASK 0x10000
|
||||
|
||||
/* Channel Upper Left Coordinate Register for ROI 1 */
|
||||
#define CHNL_ROI_1_ULC 0x50
|
||||
#define CHNL_ROI_1_ULC_X_OFFSET 16
|
||||
#define CHNL_ROI_1_ULC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_1_ULC_Y_OFFSET 0
|
||||
#define CHNL_ROI_1_ULC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Lower Right Coordinate Register for ROI 1 */
|
||||
#define CHNL_ROI_1_LRC 0x54
|
||||
#define CHNL_ROI_1_LRC_X_OFFSET 16
|
||||
#define CHNL_ROI_1_LRC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_1_LRC_Y_OFFSET 0
|
||||
#define CHNL_ROI_1_LRC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Alpha Value Register for ROI 2 */
|
||||
#define CHNL_ROI_2_ALPHA 0x58
|
||||
#define CHNL_ROI_2_ALPHA_OFFSET 24
|
||||
#define CHNL_ROI_2_ALPHA_MASK 0xFF000000
|
||||
#define CHNL_ROI_2_ALPHA_EN_OFFSET 16
|
||||
#define CHNL_ROI_2_ALPHA_EN_MASK 0x10000
|
||||
|
||||
/* Channel Upper Left Coordinate Register for ROI 2 */
|
||||
#define CHNL_ROI_2_ULC 0x5C
|
||||
#define CHNL_ROI_2_ULC_X_OFFSET 16
|
||||
#define CHNL_ROI_2_ULC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_2_ULC_Y_OFFSET 0
|
||||
#define CHNL_ROI_2_ULC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Lower Right Coordinate Register for ROI 2 */
|
||||
#define CHNL_ROI_2_LRC 0x60
|
||||
#define CHNL_ROI_2_LRC_X_OFFSET 16
|
||||
#define CHNL_ROI_2_LRC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_2_LRC_Y_OFFSET 0
|
||||
#define CHNL_ROI_2_LRC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Alpha Value Register for ROI 3 */
|
||||
#define CHNL_ROI_3_ALPHA 0x64
|
||||
#define CHNL_ROI_3_ALPHA_OFFSET 24
|
||||
#define CHNL_ROI_3_ALPHA_MASK 0xFF000000
|
||||
#define CHNL_ROI_3_ALPHA_EN_OFFSET 16
|
||||
#define CHNL_ROI_3_ALPHA_EN_MASK 0x10000
|
||||
|
||||
/* Channel Upper Left Coordinate Register for ROI 3 */
|
||||
#define CHNL_ROI_3_ULC 0x68
|
||||
#define CHNL_ROI_3_ULC_X_OFFSET 16
|
||||
#define CHNL_ROI_3_ULC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_3_ULC_Y_OFFSET 0
|
||||
#define CHNL_ROI_3_ULC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel Lower Right Coordinate Register for ROI 3 */
|
||||
#define CHNL_ROI_3_LRC 0x6C
|
||||
#define CHNL_ROI_3_LRC_X_OFFSET 16
|
||||
#define CHNL_ROI_3_LRC_X_MASK 0xFFF0000
|
||||
#define CHNL_ROI_3_LRC_Y_OFFSET 0
|
||||
#define CHNL_ROI_3_LRC_Y_MASK 0xFFF
|
||||
|
||||
/* Channel RGB or Luma (Y) Output Buffer 1 Address */
|
||||
#define CHNL_OUT_BUF1_ADDR_Y 0x70
|
||||
|
||||
/* Channel Chroma (U/Cb/UV/CbCr) Output Buffer 1 Address */
|
||||
#define CHNL_OUT_BUF1_ADDR_U 0x74
|
||||
|
||||
/* Channel Chroma (V/Cr) Output Buffer 1 Address */
|
||||
#define CHNL_OUT_BUF1_ADDR_V 0x78
|
||||
|
||||
/* Channel Output Buffer Pitch */
|
||||
#define CHNL_OUT_BUF_PITCH 0x7C
|
||||
#define CHNL_OUT_BUF_PITCH_LINE_PITCH_OFFSET 0
|
||||
#define CHNL_OUT_BUF_PITCH_LINE_PITCH_MASK 0xFFFF
|
||||
|
||||
/* Channel Input Buffer Address */
|
||||
#define CHNL_IN_BUF_ADDR 0x80
|
||||
|
||||
/* Channel Input Buffer Pitch */
|
||||
#define CHNL_IN_BUF_PITCH 0x84
|
||||
#define CHNL_IN_BUF_PITCH_FRM_PITCH_OFFSET 16
|
||||
#define CHNL_IN_BUF_PITCH_FRM_PITCH_MASK 0xFFFF0000
|
||||
#define CHNL_IN_BUF_PITCH_LINE_PITCH_OFFSET 0
|
||||
#define CHNL_IN_BUF_PITCH_LINE_PITCH_MASK 0xFFFF
|
||||
|
||||
/* Channel Memory Read Control */
|
||||
#define CHNL_MEM_RD_CTRL 0x88
|
||||
#define CHNL_MEM_RD_CTRL_IMG_TYPE_OFFSET 28
|
||||
#define CHNL_MEM_RD_CTRL_IMG_TYPE_MASK 0xF0000000
|
||||
#define CHNL_MEM_RD_CTRL_READ_MEM_OFFSET 0
|
||||
#define CHNL_MEM_RD_CTRL_READ_MEM_MASK 1
|
||||
#define CHNL_MEM_RD_CTRL_READ_MEM_ENABLE 1
|
||||
|
||||
/* Channel RGB or Luma (Y) Output Buffer 2 Address */
|
||||
#define CHNL_OUT_BUF2_ADDR_Y 0x8C
|
||||
|
||||
/* Channel Chroma (U/Cb/UV/CbCr) Output Buffer 2 Address */
|
||||
#define CHNL_OUT_BUF2_ADDR_U 0x90
|
||||
|
||||
/* Channel Chroma (V/Cr) Output Buffer 2 Address */
|
||||
#define CHNL_OUT_BUF2_ADDR_V 0x94
|
||||
|
||||
/* Channel scale image config */
|
||||
#define CHNL_SCL_IMG_CFG 0x98
|
||||
#define CHNL_SCL_IMG_CFG_HEIGHT_OFFSET 16
|
||||
#define CHNL_SCL_IMG_CFG_HEIGHT_MASK 0x1FFF0000
|
||||
#define CHNL_SCL_IMG_CFG_WIDTH_OFFSET 0
|
||||
#define CHNL_SCL_IMG_CFG_WIDTH_MASK 0x1FFF
|
||||
|
||||
/* Channel Flow Control Register */
|
||||
#define CHNL_FLOW_CTRL 0x9C
|
||||
#define CHNL_FLOW_CTRL_FC_DENOM_MASK 0xFF
|
||||
#define CHNL_FLOW_CTRL_FC_DENOM_OFFSET 0
|
||||
#define CHNL_FLOW_CTRL_FC_NUMER_MASK 0xFF0000
|
||||
#define CHNL_FLOW_CTRL_FC_NUMER_OFFSET 0
|
||||
|
||||
enum isi_csi_coeff {
|
||||
YUV2RGB = 0,
|
||||
RGB2YUV,
|
||||
};
|
||||
|
||||
void mxc_isi_channel_init(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_deinit(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_enable(struct mxc_isi_dev *mxc_isi, bool m2m_enabled);
|
||||
void mxc_isi_channel_disable(struct mxc_isi_dev *mxc_isi);
|
||||
#if defined(CONFIG_IMX8_ISI_CAPTURE)
|
||||
void mxc_isi_cap_frame_write_done(struct mxc_isi_dev *mxc_isi);
|
||||
#else
|
||||
static inline void mxc_isi_cap_frame_write_done(struct mxc_isi_dev *mxc_isi) {}
|
||||
#endif
|
||||
void mxc_isi_channel_set_deinterlace(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_sw_reset(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_hw_reset(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_source_config(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_flip(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_alpha(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_chain_buf(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_deinterlace(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_crop(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_channel_set_memory_image(struct mxc_isi_dev *mxc_isi);
|
||||
|
||||
void mxc_isi_channel_set_scaling(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f);
|
||||
|
||||
void mxc_isi_channel_set_outbuf(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_buffer *buf);
|
||||
|
||||
void mxc_isi_channel_set_csc(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f);
|
||||
|
||||
void mxc_isi_channel_config(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f,
|
||||
struct mxc_isi_frame *dst_f);
|
||||
|
||||
void mxc_isi_channel_set_alpha_roi0(struct mxc_isi_dev *mxc_isi,
|
||||
struct v4l2_rect *rect);
|
||||
void mxc_isi_channel_set_m2m_src_addr(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_buffer *buf);
|
||||
|
||||
void mxc_isi_m2m_config_src(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *src_f);
|
||||
void mxc_isi_m2m_config_dst(struct mxc_isi_dev *mxc_isi,
|
||||
struct mxc_isi_frame *dst_f);
|
||||
|
||||
void mxc_isi_m2m_start_read(struct mxc_isi_dev *mxc_isi);
|
||||
#if defined(CONFIG_IMX8_ISI_M2M)
|
||||
void mxc_isi_m2m_frame_write_done(struct mxc_isi_dev *mxc_isi);
|
||||
#else
|
||||
static inline void mxc_isi_m2m_frame_write_done(struct mxc_isi_dev *mxc_isi) {}
|
||||
#endif
|
||||
void mxc_isi_clean_irq_status(struct mxc_isi_dev *mxc_isi, u32 val);
|
||||
void mxc_isi_clean_registers(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_enable_irq(struct mxc_isi_dev *mxc_isi);
|
||||
void mxc_isi_disable_irq(struct mxc_isi_dev *mxc_isi);
|
||||
void dump_isi_regs(struct mxc_isi_dev *mxc_isi);
|
||||
|
||||
u32 mxc_isi_get_irq_status(struct mxc_isi_dev *mxc_isi);
|
||||
|
||||
#endif /* __MXC_ISI_HW_H__ */
|
File diff suppressed because it is too large
Load Diff
Loading…
Reference in New Issue