1
0
Fork 0

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
Dong Aisheng 2019-12-02 18:00:47 +08:00
commit 028cc80de9
10 changed files with 5156 additions and 1 deletions

View File

@ -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>;
};

View File

@ -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/

View File

@ -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

View File

@ -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

View File

@ -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");

View File

@ -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__ */

View File

@ -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);
}

View File

@ -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