media: rockchip: ispp: init ispp

Change-Id: I20a6eee6157eccee6ac117b561a472474ce36b9f
Signed-off-by: Cai YiWei <cyw@rock-chips.com>
This commit is contained in:
Cai YiWei
2019-12-30 16:30:05 +08:00
committed by Tao Huang
parent b523f58386
commit b59278f203
18 changed files with 4229 additions and 0 deletions

View File

@@ -139,6 +139,7 @@ source "drivers/media/platform/rcar-vin/Kconfig"
source "drivers/media/platform/atmel/Kconfig"
source "drivers/media/platform/rockchip/cif/Kconfig"
source "drivers/media/platform/rockchip/isp/Kconfig"
source "drivers/media/platform/rockchip/ispp/Kconfig"
config VIDEO_TI_CAL
tristate "TI CAL (Camera Adaptation Layer) driver"

View File

@@ -69,6 +69,7 @@ obj-$(CONFIG_VIDEO_RENESAS_VSP1) += vsp1/
obj-$(CONFIG_VIDEO_ROCKCHIP_RGA) += rockchip/rga/
obj-$(CONFIG_VIDEO_ROCKCHIP_CIF) += rockchip/cif/
obj-$(CONFIG_VIDEO_ROCKCHIP_ISP) += rockchip/isp/
obj-$(CONFIG_VIDEO_ROCKCHIP_ISPP) += rockchip/ispp/
obj-y += omap/

View File

@@ -0,0 +1,10 @@
# SPDX-License-Identifier: GPL-2.0
config VIDEO_ROCKCHIP_ISPP
tristate "Rockchip Image Signal Post-Processing Unit driver"
depends on VIDEO_V4L2 && VIDEO_V4L2_SUBDEV_API
depends on ARCH_ROCKCHIP || COMPILE_TEST
select VIDEOBUF2_DMA_CONTIG
select VIDEOBUF2_VMALLOC
default n
help
Support for ISPP on the rockchip SoC.

View File

@@ -0,0 +1,8 @@
# SPDX-License-Identifier: GPL-2.0
obj-$(CONFIG_VIDEO_ROCKCHIP_ISPP) += video_rkispp.o
video_rkispp-objs += dev.o \
common.o \
ispp.o \
stream.o \
params.o

View File

@@ -0,0 +1,62 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 Rockchip Electronics Co., Ltd */
#include <linux/dma-mapping.h>
#include <media/v4l2-mc.h>
#include "dev.h"
#include "regs.h"
int rkispp_fh_open(struct file *filp)
{
struct rkispp_stream *stream = video_drvdata(filp);
struct rkispp_device *isppdev = stream->isppdev;
int ret;
ret = v4l2_fh_open(filp);
if (!ret) {
ret = v4l2_pipeline_pm_use(&stream->vnode.vdev.entity, 1);
if (ret < 0) {
v4l2_err(&isppdev->v4l2_dev,
"pipeline power on failed %d\n", ret);
vb2_fop_release(filp);
}
}
return ret;
}
int rkispp_fh_release(struct file *filp)
{
struct rkispp_stream *stream = video_drvdata(filp);
struct rkispp_device *isppdev = stream->isppdev;
int ret;
ret = vb2_fop_release(filp);
if (!ret) {
ret = v4l2_pipeline_pm_use(&stream->vnode.vdev.entity, 0);
if (ret < 0)
v4l2_err(&isppdev->v4l2_dev,
"pipeline power off failed %d\n", ret);
}
return ret;
}
int rkispp_allow_buffer(struct rkispp_device *dev,
struct rkispp_dummy_buffer *buf)
{
buf->vaddr = dma_alloc_coherent(dev->dev, buf->size,
&buf->dma_addr, GFP_KERNEL);
if (!buf->vaddr)
return -ENOMEM;
return 0;
}
void rkispp_free_buffer(struct rkispp_device *dev,
struct rkispp_dummy_buffer *buf)
{
if (buf && buf->vaddr && buf->size) {
dma_free_coherent(dev->dev, buf->size,
buf->vaddr, buf->dma_addr);
buf->size = 0;
buf->vaddr = NULL;
}
}

View File

@@ -0,0 +1,98 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_COMMON_H
#define _RKISPP_COMMON_H
#include <linux/mutex.h>
#include <media/media-device.h>
#include <media/media-entity.h>
#include <media/v4l2-ctrls.h>
#include <media/v4l2-device.h>
#include <media/videobuf2-v4l2.h>
#define RKISPP_PLANE_Y 0
#define RKISPP_PLANE_UV 1
struct rkispp_device;
/* One structure per video node */
struct rkispp_vdev_node {
struct vb2_queue buf_queue;
struct video_device vdev;
struct media_pad pad;
};
struct rkispp_buffer {
struct vb2_v4l2_buffer vb;
struct list_head queue;
union {
u32 buff_addr[VIDEO_MAX_PLANES];
void *vaddr[VIDEO_MAX_PLANES];
};
};
struct rkispp_dummy_buffer {
struct list_head queue;
dma_addr_t dma_addr;
void *vaddr;
u32 size;
};
extern int rkispp_tnr_3to1;
extern int rkispp_debug;
static inline struct rkispp_vdev_node *vdev_to_node(struct video_device *vdev)
{
return container_of(vdev, struct rkispp_vdev_node, vdev);
}
static inline struct rkispp_vdev_node *queue_to_node(struct vb2_queue *q)
{
return container_of(q, struct rkispp_vdev_node, buf_queue);
}
static inline struct rkispp_buffer *to_rkispp_buffer(struct vb2_v4l2_buffer *vb)
{
return container_of(vb, struct rkispp_buffer, vb);
}
static inline struct vb2_queue *to_vb2_queue(struct file *file)
{
struct rkispp_vdev_node *vnode = video_drvdata(file);
return &vnode->buf_queue;
}
static inline void rkispp_write(void __iomem *addr, u32 val)
{
writel(val, addr);
}
static inline u32 rkispp_read(void __iomem *addr)
{
return readl(addr);
}
static inline void rkispp_set_bits(void __iomem *addr, u32 bit_mask, u32 val)
{
u32 tmp = rkispp_read(addr) & ~bit_mask;
rkispp_write(addr, val | tmp);
}
static inline void rkispp_clear_bits(void __iomem *addr, u32 bit_mask)
{
u32 val = rkispp_read(addr);
rkispp_write(addr, val & ~bit_mask);
}
int rkispp_fh_open(struct file *filp);
int rkispp_fh_release(struct file *filp);
int rkispp_allow_buffer(struct rkispp_device *dev,
struct rkispp_dummy_buffer *buf);
void rkispp_free_buffer(struct rkispp_device *dev,
struct rkispp_dummy_buffer *buf);
#endif

View File

@@ -0,0 +1,416 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2019 Rockchip Electronics Co., Ltd */
#include <linux/clk.h>
#include <linux/delay.h>
#include <linux/interrupt.h>
#include <linux/module.h>
#include <linux/of.h>
#include <linux/of_graph.h>
#include <linux/of_platform.h>
#include <linux/of_reserved_mem.h>
#include <linux/pinctrl/consumer.h>
#include <linux/pm_runtime.h>
#include <linux/reset.h>
#include <linux/regmap.h>
#include <media/videobuf2-dma-contig.h>
#include <media/v4l2-fwnode.h>
#include "dev.h"
#include "regs.h"
#include "version.h"
#define RKISPP_VERNO_LEN 10
struct ispp_irqs_data {
const char *name;
irqreturn_t (*irq_hdl)(int irq, void *ctx);
};
struct ispp_match_data {
int clks_num;
const char * const *clks;
enum rkispp_ver ispp_ver;
struct ispp_irqs_data *irqs;
int num_irqs;
};
int rkispp_tnr_3to1;
module_param_named(tnr_3to1, rkispp_tnr_3to1, int, 0644);
MODULE_PARM_DESC(tnr_3to1, "tnr 3to1 mode");
int rkispp_debug;
module_param_named(debug, rkispp_debug, int, 0644);
MODULE_PARM_DESC(debug, "Debug level (0-3)");
static char rkispp_version[RKISPP_VERNO_LEN];
module_param_string(version, rkispp_version, RKISPP_VERNO_LEN, 0444);
MODULE_PARM_DESC(version, "version number");
static inline bool is_iommu_enable(struct device *dev)
{
struct device_node *iommu;
iommu = of_parse_phandle(dev->of_node, "iommus", 0);
if (!iommu) {
dev_info(dev, "no iommu attached, using non-iommu buffers\n");
return false;
} else if (!of_device_is_available(iommu)) {
dev_info(dev, "iommu is disabled, using non-iommu buffers\n");
of_node_put(iommu);
return false;
}
of_node_put(iommu);
return true;
}
#if defined(CONFIG_VIDEO_ROCKCHIP_ISP)
extern void
rkisp_get_mpfbc_sd(struct platform_device *dev, struct v4l2_subdev **sd);
#else
static void
rkisp_get_mpfbc_sd(struct platform_device *dev, struct v4l2_subdev **sd)
{
*sd = NULL;
}
#endif
static void get_remote_node_dev(struct rkispp_device *ispp_dev)
{
struct device *dev = ispp_dev->dev;
struct device_node *parent = dev->of_node;
struct platform_device *remote_dev = NULL;
struct device_node *remote = NULL;
struct v4l2_subdev *sd = NULL;
int i;
for (i = 0; i < 2; i++) {
remote = of_graph_get_remote_node(parent, 0, i);
if (!remote)
continue;
remote_dev = of_find_device_by_node(remote);
of_node_put(remote);
if (!remote_dev) {
dev_err(dev, "Failed to get remote device(%s)\n",
of_node_full_name(remote));
continue;
} else {
rkisp_get_mpfbc_sd(remote_dev, &sd);
if (!sd) {
dev_err(dev, "Failed to get remote mpfbc sd\n");
} else {
ispp_dev->ispp_sdev.remote_sd = sd;
dev_info(dev, "get remote mpfbc sd:%s\n",
sd->name);
break;
}
}
}
}
static int rkispp_create_links(struct rkispp_device *ispp_dev)
{
struct rkispp_stream_vdev *stream_vdev;
struct media_entity *source, *sink;
struct rkispp_stream *stream;
unsigned int flags = 0;
int ret;
stream_vdev = &ispp_dev->stream_vdev;
stream = &stream_vdev->stream[STREAM_II];
/* input stream links */
sink = &ispp_dev->ispp_sdev.sd.entity;
get_remote_node_dev(ispp_dev);
if (ispp_dev->ispp_sdev.remote_sd) {
ispp_dev->inp = INP_ISP;
} else {
flags = MEDIA_LNK_FL_ENABLED;
ispp_dev->inp = INP_DDR;
stream->linked = true;
}
source = &stream->vnode.vdev.entity;
ret = media_create_pad_link(source, 0, sink,
RKISPP_PAD_SINK, flags);
if (ret < 0)
return ret;
/* params links */
flags = MEDIA_LNK_FL_ENABLED;
source = &ispp_dev->params_vdev.vnode.vdev.entity;
ret = media_create_pad_link(source, 0, sink,
RKISPP_PAD_SINK_PARAMS, flags);
if (ret < 0)
return ret;
/* output stream links */
stream = &stream_vdev->stream[STREAM_MB];
stream->linked = flags;
source = &ispp_dev->ispp_sdev.sd.entity;
sink = &stream->vnode.vdev.entity;
ret = media_create_pad_link(source, RKISPP_PAD_SOURCE,
sink, 0, flags);
if (ret < 0)
return ret;
flags = 0;
stream = &stream_vdev->stream[STREAM_S0];
stream->linked = flags;
sink = &stream->vnode.vdev.entity;
ret = media_create_pad_link(source, RKISPP_PAD_SOURCE,
sink, 0, flags);
if (ret < 0)
return ret;
stream = &stream_vdev->stream[STREAM_S1];
stream->linked = flags;
sink = &stream->vnode.vdev.entity;
ret = media_create_pad_link(source, RKISPP_PAD_SOURCE,
sink, 0, flags);
if (ret < 0)
return ret;
stream = &stream_vdev->stream[STREAM_S2];
sink = &stream->vnode.vdev.entity;
ret = media_create_pad_link(source, RKISPP_PAD_SOURCE,
sink, 0, flags);
if (ret < 0)
return ret;
//TODO
ispp_dev->module_en[ISPP_3DNR] = true;
ispp_dev->module_en[ISPP_2DNR] = true;
ispp_dev->module_en[ISPP_SHP] = true;
ispp_dev->module_en[ISPP_FEC] = false;
ispp_dev->module_en[ISPP_SCL] = true;
return 0;
}
static int rkispp_register_platform_subdevs(struct rkispp_device *ispp_dev)
{
int ret;
ret = rkispp_register_stream_vdevs(ispp_dev);
if (ret < 0)
return ret;
ret = rkispp_register_params_vdev(ispp_dev);
if (ret < 0)
goto err_unreg_stream_vdevs;
ret = rkispp_register_subdev(ispp_dev, &ispp_dev->v4l2_dev);
if (ret < 0)
goto err_unreg_params_vdev;
ret = rkispp_create_links(ispp_dev);
if (ret < 0)
goto err_unreg_ispp_subdev;
return ret;
err_unreg_ispp_subdev:
rkispp_unregister_subdev(ispp_dev);
err_unreg_params_vdev:
rkispp_unregister_params_vdev(ispp_dev);
err_unreg_stream_vdevs:
rkispp_unregister_stream_vdevs(ispp_dev);
return ret;
}
static void rkispp_disable_sys_clk(struct rkispp_device *ispp_dev)
{
int i;
for (i = 0; i < ispp_dev->clks_num; i++)
clk_disable_unprepare(ispp_dev->clks[i]);
}
static int rkispp_enable_sys_clk(struct rkispp_device *ispp_dev)
{
int i, ret = -EINVAL;
for (i = 0; i < ispp_dev->clks_num; i++) {
ret = clk_prepare_enable(ispp_dev->clks[i]);
if (ret < 0)
goto err;
}
return 0;
err:
for (--i; i >= 0; --i)
clk_disable_unprepare(ispp_dev->clks[i]);
return ret;
}
static const struct of_device_id rkispp_plat_of_match[] = {
{},
};
static int rkispp_plat_probe(struct platform_device *pdev)
{
const struct of_device_id *match;
const struct ispp_match_data *match_data;
struct device_node *node = pdev->dev.of_node;
struct device *dev = &pdev->dev;
struct v4l2_device *v4l2_dev;
struct rkispp_device *ispp_dev;
struct resource *res;
int i, ret, irq;
sprintf(rkispp_version, "v%02x.%02x.%02x",
RKISPP_DRIVER_VERSION >> 16,
(RKISPP_DRIVER_VERSION & 0xff00) >> 8,
RKISPP_DRIVER_VERSION & 0x00ff);
dev_info(dev, "rkispp driver version: %s\n", rkispp_version);
match = of_match_node(rkispp_plat_of_match, node);
if (IS_ERR(match))
return PTR_ERR(match);
ispp_dev = devm_kzalloc(dev, sizeof(*ispp_dev), GFP_KERNEL);
if (!ispp_dev)
return -ENOMEM;
dev_set_drvdata(dev, ispp_dev);
ispp_dev->dev = dev;
match_data = match->data;
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
ispp_dev->base_addr = devm_ioremap_resource(dev, res);
if (IS_ERR(ispp_dev->base_addr)) {
dev_err(dev, "get resource failed\n");
return PTR_ERR(ispp_dev->base_addr);
}
res = platform_get_resource_byname(pdev, IORESOURCE_IRQ,
match_data->irqs[0].name);
if (res) {
/* there are irq names in dts */
for (i = 0; i < match_data->num_irqs; i++) {
irq = platform_get_irq_byname(pdev,
match_data->irqs[i].name);
if (irq < 0) {
dev_err(dev, "no irq %s in dts\n",
match_data->irqs[i].name);
return irq;
}
ret = devm_request_irq(dev, irq,
match_data->irqs[i].irq_hdl,
IRQF_SHARED,
dev_driver_string(dev),
dev);
if (ret < 0) {
dev_err(dev, "request %s failed: %d\n",
match_data->irqs[i].name, ret);
return ret;
}
}
}
for (i = 0; i < match_data->clks_num; i++) {
struct clk *clk = devm_clk_get(dev, match_data->clks[i]);
if (IS_ERR(clk))
dev_warn(dev, "failed to get %s\n",
match_data->clks[i]);
ispp_dev->clks[i] = clk;
}
ispp_dev->clks_num = match_data->clks_num;
ispp_dev->ispp_ver = match_data->ispp_ver;
mutex_init(&ispp_dev->apilock);
strlcpy(ispp_dev->media_dev.model, "rkispp",
sizeof(ispp_dev->media_dev.model));
ispp_dev->media_dev.dev = &pdev->dev;
v4l2_dev = &ispp_dev->v4l2_dev;
v4l2_dev->mdev = &ispp_dev->media_dev;
strlcpy(v4l2_dev->name, "rkispp", sizeof(v4l2_dev->name));
v4l2_ctrl_handler_init(&ispp_dev->ctrl_handler, 5);
v4l2_dev->ctrl_handler = &ispp_dev->ctrl_handler;
ret = v4l2_device_register(ispp_dev->dev, v4l2_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "register v4l2 device failed:%d\n", ret);
return ret;
}
media_device_init(&ispp_dev->media_dev);
ret = media_device_register(&ispp_dev->media_dev);
if (ret < 0) {
v4l2_err(v4l2_dev, "register media device failed:%d\n", ret);
goto err_unreg_v4l2_dev;
}
ret = rkispp_register_platform_subdevs(ispp_dev);
if (ret < 0)
goto err_unreg_media_dev;
if (!is_iommu_enable(dev)) {
ret = of_reserved_mem_device_init(dev);
if (ret)
v4l2_warn(v4l2_dev,
"No reserved memory region assign to ispp\n");
}
pm_runtime_enable(&pdev->dev);
return 0;
err_unreg_media_dev:
media_device_unregister(&ispp_dev->media_dev);
err_unreg_v4l2_dev:
v4l2_device_unregister(&ispp_dev->v4l2_dev);
return ret;
}
static int rkispp_plat_remove(struct platform_device *pdev)
{
struct rkispp_device *ispp_dev = platform_get_drvdata(pdev);
pm_runtime_disable(&pdev->dev);
rkispp_unregister_subdev(ispp_dev);
rkispp_unregister_params_vdev(ispp_dev);
rkispp_unregister_stream_vdevs(ispp_dev);
media_device_unregister(&ispp_dev->media_dev);
v4l2_device_unregister(&ispp_dev->v4l2_dev);
mutex_destroy(&ispp_dev->apilock);
return 0;
}
static int __maybe_unused rkispp_runtime_suspend(struct device *dev)
{
struct rkispp_device *ispp_dev = dev_get_drvdata(dev);
rkispp_disable_sys_clk(ispp_dev);
return 0;
}
static int __maybe_unused rkispp_runtime_resume(struct device *dev)
{
struct rkispp_device *ispp_dev = dev_get_drvdata(dev);
rkispp_enable_sys_clk(ispp_dev);
return 0;
}
static const struct dev_pm_ops rkispp_plat_pm_ops = {
SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
pm_runtime_force_resume)
SET_RUNTIME_PM_OPS(rkispp_runtime_suspend,
rkispp_runtime_resume, NULL)
};
static struct platform_driver rkispp_plat_drv = {
.driver = {
.name = DRIVER_NAME,
.of_match_table = of_match_ptr(rkispp_plat_of_match),
.pm = &rkispp_plat_pm_ops,
},
.probe = rkispp_plat_probe,
.remove = rkispp_plat_remove,
};
module_platform_driver(rkispp_plat_drv);
MODULE_AUTHOR("Rockchip Camera/ISP team");
MODULE_DESCRIPTION("Rockchip ISPP platform driver");
MODULE_LICENSE("GPL v2");

View File

@@ -0,0 +1,63 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_DEV_H
#define _RKISPP_DEV_H
#include "ispp.h"
#include "params.h"
#include "stream.h"
#define DRIVER_NAME "rkispp"
#define II_VDEV_NAME DRIVER_NAME "_input_image"
#define MB_VDEV_NAME DRIVER_NAME "_m_bypass"
#define S0_VDEV_NAME DRIVER_NAME "_scale0"
#define S1_VDEV_NAME DRIVER_NAME "_scale1"
#define S2_VDEV_NAME DRIVER_NAME "_scale2"
#define ISPP_MAX_BUS_CLK 4
enum rkispp_ver {
ISPP_V10 = 0x00,
};
enum rkispp_module_id {
ISPP_3DNR,
ISPP_2DNR,
ISPP_SHP,
ISPP_FEC,
ISPP_SCL,
ISPP_MD_MAX,
};
enum rkispp_input {
INP_INVAL = 0,
INP_ISP,
INP_DDR,
};
struct rkispp_device {
struct device *dev;
int irq;
int clks_num;
struct clk *clks[ISPP_MAX_BUS_CLK];
void __iomem *base_addr;
struct iommu_domain *domain;
struct vb2_alloc_ctx *alloc_ctx;
struct media_device media_dev;
struct v4l2_device v4l2_dev;
struct v4l2_ctrl_handler ctrl_handler;
struct rkispp_subdev ispp_sdev;
struct rkispp_stream_vdev stream_vdev;
struct rkispp_params_vdev params_vdev;
enum rkispp_ver ispp_ver;
/* mutex to serialize the calls from user */
struct mutex apilock;
u8 module_en[ISPP_MD_MAX];
enum rkispp_input inp;
};
#endif

View File

@@ -0,0 +1,319 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#include <linux/interrupt.h>
#include <linux/pm_runtime.h>
#include <linux/videodev2.h>
#include <media/media-entity.h>
#include "dev.h"
#include "regs.h"
u32 cal_fec_mesh(u32 width, u32 height, u32 mode)
{
u32 mesh_size, mesh_left_height;
u32 w = ALIGN(width, 32);
u32 h = ALIGN(height, 32);
u32 spb_num = (h + 127) >> 7;
u32 left_height = h & 127;
u32 mesh_width = mode ? (w / 32 + 1) : (w / 16 + 1);
u32 mesh_height = mode ? 9 : 17;
if (!left_height)
left_height = 128;
mesh_left_height = mode ? (left_height / 16 + 1) :
(left_height / 8 + 1);
mesh_size = (spb_num - 1) * mesh_width * mesh_height +
mesh_width * mesh_left_height;
return mesh_size;
}
static const struct isppsd_fmt rkispp_formats[] = {
{
.mbus_code = MEDIA_BUS_FMT_YUYV8_2X8,
.fourcc = V4L2_PIX_FMT_NV16,
.wr_fmt = FMT_YUV422,
},
};
static const struct isppsd_fmt *find_fmt(u32 mbus_code)
{
const struct isppsd_fmt *fmt;
int i, array_size = ARRAY_SIZE(rkispp_formats);
for (i = 0; i < array_size; i++) {
fmt = &rkispp_formats[i];
if (fmt->mbus_code == mbus_code)
return fmt;
}
return NULL;
}
static int rkispp_subdev_link_setup(struct media_entity *entity,
const struct media_pad *local,
const struct media_pad *remote,
u32 flags)
{
struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity);
struct rkispp_subdev *ispp_sdev;
struct rkispp_device *dev;
struct rkispp_stream_vdev *vdev;
struct rkispp_stream *stream = NULL;
if (!sd)
return -ENODEV;
ispp_sdev = v4l2_get_subdevdata(sd);
dev = ispp_sdev->dev;
vdev = &dev->stream_vdev;
if (!strcmp(remote->entity->name, II_VDEV_NAME)) {
stream = &vdev->stream[STREAM_II];
if (flags & MEDIA_LNK_FL_ENABLED)
dev->inp = INP_DDR;
else if (ispp_sdev->remote_sd)
dev->inp = INP_ISP;
else
dev->inp = INP_INVAL;
} else if (!strcmp(remote->entity->name, MB_VDEV_NAME)) {
stream = &vdev->stream[STREAM_MB];
} else if (!strcmp(remote->entity->name, S0_VDEV_NAME)) {
stream = &vdev->stream[STREAM_S0];
} else if (!strcmp(remote->entity->name, S1_VDEV_NAME)) {
stream = &vdev->stream[STREAM_S1];
} else if (!strcmp(remote->entity->name, S2_VDEV_NAME)) {
stream = &vdev->stream[STREAM_S2];
}
if (stream)
stream->linked = flags & MEDIA_LNK_FL_ENABLED;
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"input:%d\n", dev->inp);
return 0;
}
static int rkispp_sd_get_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct rkispp_device *dev = ispp_sdev->dev;
const struct isppsd_fmt *ispp_fmt;
int ret = 0;
if (dev->inp != INP_ISP)
return 0;
ret = v4l2_subdev_call(ispp_sdev->remote_sd,
pad, get_fmt, cfg, fmt);
if (ret == 0) {
ispp_fmt = find_fmt(fmt->format.code);
if (!ispp_fmt)
return -EINVAL;
ispp_sdev->in_fmt = *fmt;
ispp_sdev->out_fmt = *ispp_fmt;
ispp_sdev->out_fmt.width = fmt->format.width;
ispp_sdev->out_fmt.height = fmt->format.height;
}
return ret;
}
static int rkispp_sd_set_fmt(struct v4l2_subdev *sd,
struct v4l2_subdev_pad_config *cfg,
struct v4l2_subdev_format *fmt)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct rkispp_device *dev = ispp_sdev->dev;
const struct isppsd_fmt *ispp_fmt;
if (dev->inp != INP_ISP)
return 0;
ispp_fmt = find_fmt(fmt->format.code);
if (!ispp_fmt)
return -EINVAL;
ispp_sdev->out_fmt = *ispp_fmt;
ispp_sdev->in_fmt = *fmt;
return v4l2_subdev_call(ispp_sdev->remote_sd, pad,
set_fmt, NULL, fmt);
}
static int rkispp_sd_s_stream(struct v4l2_subdev *sd, int on)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct rkispp_device *dev = ispp_sdev->dev;
struct rkispp_stream_vdev *vdev;
v4l2_dbg(1, rkispp_debug, &dev->v4l2_dev,
"s_stream on:%d\n", on);
vdev = &dev->stream_vdev;
if (on) {
void *buf, *size;
if (dev->module_en[ISPP_3DNR]) {
buf = &vdev->tnr_buf.pic_cur.dma_addr;
size = &vdev->tnr_buf.pic_cur.size;
v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_rx_buffer, buf, size);
buf = &vdev->tnr_buf.gain_cur.dma_addr;
size = &vdev->tnr_buf.gain_cur.size;
if (rkispp_tnr_3to1) {
v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_rx_buffer, buf, size);
buf = &vdev->tnr_buf.pic_next.dma_addr;
size = &vdev->tnr_buf.pic_next.size;
v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_rx_buffer, buf, size);
buf = &vdev->tnr_buf.gain_next.dma_addr;
size = &vdev->tnr_buf.gain_next.size;
}
} else {
buf = &vdev->nr_buf.pic_cur.dma_addr;
size = &vdev->nr_buf.pic_cur.size;
v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_rx_buffer, buf, size);
buf = &vdev->nr_buf.gain_cur.dma_addr;
size = &vdev->nr_buf.gain_cur.size;
}
v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_rx_buffer, buf, size);
}
return v4l2_subdev_call(ispp_sdev->remote_sd,
video, s_stream, on);
}
static int rkispp_sd_s_power(struct v4l2_subdev *sd, int on)
{
struct rkispp_subdev *ispp_sdev = v4l2_get_subdevdata(sd);
struct rkispp_device *ispp_dev = ispp_sdev->dev;
int ret;
v4l2_dbg(1, rkispp_debug, &ispp_dev->v4l2_dev,
"s_power on:%d\n", on);
if (on) {
ret = pm_runtime_get_sync(ispp_dev->dev);
if (ret < 0) {
v4l2_err(&ispp_dev->v4l2_dev,
"%s runtime get failed:%d\n",
__func__, ret);
return ret;
}
atomic_set(&ispp_sdev->frm_sync_seq, 0);
rkispp_soft_reset(ispp_dev->base_addr);
writel(0xfffffff, ispp_dev->base_addr + RKISPP_CTRL_INT_MSK);
if (ispp_dev->inp == INP_ISP) {
struct v4l2_subdev_format *fmt = &ispp_sdev->in_fmt;
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
ret = v4l2_subdev_call(sd, pad, get_fmt, NULL, fmt);
if (ret < 0) {
v4l2_err(&ispp_dev->v4l2_dev,
"%s get format fail:%d\n",
__func__, ret);
goto err;
}
ret = v4l2_subdev_call(ispp_sdev->remote_sd,
core, s_power, 1);
if (ret < 0) {
v4l2_err(&ispp_dev->v4l2_dev,
"%s set isp power on fail:%d\n",
__func__, ret);
goto err;
}
}
} else {
writel(0, ispp_dev->base_addr + RKISPP_CTRL_INT_MSK);
if (ispp_dev->inp == INP_ISP)
v4l2_subdev_call(ispp_sdev->remote_sd, core, s_power, 0);
ret = pm_runtime_put(ispp_dev->dev);
if (ret < 0)
v4l2_err(&ispp_dev->v4l2_dev,
"%s runtime put failed:%d\n",
__func__, ret);
}
return ret;
err:
pm_runtime_put(ispp_dev->dev);
return ret;
}
static const struct media_entity_operations rkispp_sd_media_ops = {
.link_setup = rkispp_subdev_link_setup,
.link_validate = v4l2_subdev_link_validate,
};
static const struct v4l2_subdev_pad_ops rkispp_sd_pad_ops = {
.get_fmt = rkispp_sd_get_fmt,
.set_fmt = rkispp_sd_set_fmt,
};
static const struct v4l2_subdev_video_ops rkispp_sd_video_ops = {
.s_stream = rkispp_sd_s_stream,
};
static const struct v4l2_subdev_core_ops rkispp_sd_core_ops = {
.s_power = rkispp_sd_s_power,
};
static struct v4l2_subdev_ops rkispp_sd_ops = {
.core = &rkispp_sd_core_ops,
.video = &rkispp_sd_video_ops,
.pad = &rkispp_sd_pad_ops,
};
int rkispp_register_subdev(struct rkispp_device *dev,
struct v4l2_device *v4l2_dev)
{
struct rkispp_subdev *ispp_sdev = &dev->ispp_sdev;
struct v4l2_subdev *sd;
int ret;
memset(ispp_sdev, 0, sizeof(*ispp_sdev));
ispp_sdev->dev = dev;
sd = &ispp_sdev->sd;
v4l2_subdev_init(sd, &rkispp_sd_ops);
sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
sd->entity.ops = &rkispp_sd_media_ops;
snprintf(sd->name, sizeof(sd->name), "rkispp-subdev");
ispp_sdev->pads[RKISPP_PAD_SINK].flags =
MEDIA_PAD_FL_SINK | MEDIA_PAD_FL_MUST_CONNECT;
ispp_sdev->pads[RKISPP_PAD_SINK_PARAMS].flags = MEDIA_PAD_FL_SINK;
ispp_sdev->pads[RKISPP_PAD_SOURCE].flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&sd->entity, RKISPP_PAD_MAX,
ispp_sdev->pads);
if (ret < 0)
return ret;
sd->owner = THIS_MODULE;
v4l2_set_subdevdata(sd, ispp_sdev);
sd->grp_id = GRP_ID_ISPP;
ret = v4l2_device_register_subdev(v4l2_dev, sd);
if (ret < 0)
goto free_media;
ret = v4l2_device_register_subdev_nodes(v4l2_dev);
if (ret < 0)
goto free_subdev;
return ret;
free_subdev:
v4l2_device_unregister_subdev(sd);
free_media:
media_entity_cleanup(&sd->entity);
v4l2_err(sd, "Failed to register subdev, ret:%d\n", ret);
return ret;
}
void rkispp_unregister_subdev(struct rkispp_device *dev)
{
struct v4l2_subdev *sd = &dev->ispp_sdev.sd;
v4l2_device_unregister_subdev(sd);
media_entity_cleanup(&sd->entity);
}

View File

@@ -0,0 +1,41 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_ISPP_H
#define _RKISPP_ISPP_H
#include "common.h"
#define GRP_ID_ISPP BIT(0)
enum rkispp_pad {
RKISPP_PAD_SINK,
RKISPP_PAD_SINK_PARAMS,
RKISPP_PAD_SOURCE,
RKISPP_PAD_MAX
};
struct isppsd_fmt {
u32 mbus_code;
u32 fourcc;
u32 width;
u32 height;
u8 wr_fmt;
};
struct rkispp_subdev {
struct rkispp_device *dev;
struct v4l2_subdev sd;
struct v4l2_subdev *remote_sd;
struct media_pad pads[RKISPP_PAD_MAX];
struct v4l2_subdev_format in_fmt;
struct isppsd_fmt out_fmt;
atomic_t frm_sync_seq;
};
u32 cal_fec_mesh(u32 width, u32 height, u32 mode);
int rkispp_register_subdev(struct rkispp_device *dev,
struct v4l2_device *v4l2_dev);
void rkispp_unregister_subdev(struct rkispp_device *dev);
#endif

View File

@@ -0,0 +1,794 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#include <media/v4l2-common.h>
#include <media/v4l2-ioctl.h>
#include <media/videobuf2-core.h>
#include <media/videobuf2-vmalloc.h>
#include "dev.h"
#include "regs.h"
#define RKISP1_ISP_PARAMS_REQ_BUFS_MIN 2
#define RKISP1_ISP_PARAMS_REQ_BUFS_MAX 8
#define ISPP_PACK_4BIT(a, b, c, d, e, f, g, h) \
(((a) & 0xf) << 0 | ((b) & 0xf) << 4 | \
((c) & 0xf) << 8 | ((d) & 0xf) << 12 | \
((e) & 0xf) << 16 | ((f) & 0xf) << 20 | \
((g) & 0xf) << 24 | ((h) & 0xf) << 28)
#define ISPP_PACK_4BYTE(a, b, c, d) \
(((a) & 0xFF) << 0 | ((b) & 0xFF) << 8 | \
((c) & 0xFF) << 16 | ((d) & 0xFF) << 24)
#define ISPP_PACK_2SHORT(a, b) \
(((a) & 0xFFFF) << 0 | ((b) & 0xFFFF) << 16)
static void tnr_config(struct rkispp_params_vdev *params_vdev,
struct rkispp_tnr_config *arg)
{
void __iomem *base = params_vdev->dev->base_addr;
u32 i, val;
val = arg->opty_en << 2 | arg->optc_en << 3 |
arg->gain_en << 4;
rkispp_set_bits(base + RKISPP_TNR_CORE_CTRL,
SW_TNR_OPTY_EN | SW_TNR_OPTC_EN |
SW_TNR_GLB_GAIN_EN, val);
val = ISPP_PACK_4BYTE(arg->pk0_y, arg->pk1_y,
arg->pk0_c, arg->pk1_c);
rkispp_write(base + RKISPP_TNR_CORE_PK0, val);
val = ISPP_PACK_2SHORT(arg->glb_gain_cur, arg->glb_gain_nxt);
rkispp_write(base + RKISPP_TNR_CORE_GLB_GAIN, val);
val = ISPP_PACK_2SHORT(arg->glb_gain_cur_div, arg->glb_gain_cur_sqrt);
rkispp_write(base + RKISPP_TNR_CORE_GLB_GAIN_DIV, val);
for (i = 0; i < TNR_SIGMA_CURVE_SIZE - 1; i += 2)
rkispp_write(base + RKISPP_TNR_CORE_SIG_Y01 + i * 2,
ISPP_PACK_2SHORT(arg->sigma_curve[i].y,
arg->sigma_curve[i + 1].y));
rkispp_write(base + RKISPP_TNR_CORE_SIG_Y10, arg->sigma_curve[16].y);
rkispp_write(base + RKISPP_TNR_CORE_SIG_X18,
ISPP_PACK_4BIT(arg->sigma_curve[0].x, arg->sigma_curve[1].x,
arg->sigma_curve[2].x, arg->sigma_curve[3].x,
arg->sigma_curve[4].x, arg->sigma_curve[5].x,
arg->sigma_curve[6].x, arg->sigma_curve[7].x));
rkispp_write(base + RKISPP_TNR_CORE_SIG_X910,
ISPP_PACK_4BIT(arg->sigma_curve[8].x, arg->sigma_curve[9].x,
arg->sigma_curve[10].x, arg->sigma_curve[11].x,
arg->sigma_curve[12].x, arg->sigma_curve[13].x,
arg->sigma_curve[14].x, arg->sigma_curve[15].x));
for (i = 0; i < TNR_LUMA_CURVE_SIZE; i += 2) {
val = ISPP_PACK_2SHORT(arg->luma_curve[i], arg->luma_curve[i + 1]);
rkispp_write(base + RKISPP_TNR_CORE_LUMACURVE_Y01 + i * 2, val);
}
val = ISPP_PACK_2SHORT(arg->txt_th0_y, arg->txt_th1_y);
rkispp_write(base + RKISPP_TNR_CORE_TH_Y, val);
val = ISPP_PACK_2SHORT(arg->txt_th0_c, arg->txt_th1_c);
rkispp_write(base + RKISPP_TNR_CORE_TH_C, val);
val = ISPP_PACK_2SHORT(arg->txt_thy_dlt, arg->txt_thc_dlt);
rkispp_write(base + RKISPP_TNR_CORE_TH_DLT, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_y0[0], arg->gfcoef_y0[1],
arg->gfcoef_y0[2], arg->gfcoef_y0[3]);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_Y0_0, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_y0[4], arg->gfcoef_y0[5], 0, 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_Y0_1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_y1[0], arg->gfcoef_y1[1],
arg->gfcoef_y1[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_Y1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_y2[0], arg->gfcoef_y2[1],
arg->gfcoef_y2[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_Y2, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_y3[0], arg->gfcoef_y3[1],
arg->gfcoef_y3[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_Y3, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[0], arg->gfcoef_yg0[1],
arg->gfcoef_yg0[2], arg->gfcoef_yg0[3]);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YG0_0, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yg0[4], arg->gfcoef_yg0[5], 0, 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YG0_1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yg1[0], arg->gfcoef_yg1[1],
arg->gfcoef_yg1[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YG1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yg2[0], arg->gfcoef_yg2[1],
arg->gfcoef_yg2[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YG2, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yg3[0], arg->gfcoef_yg3[1],
arg->gfcoef_yg3[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YG3, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[0], arg->gfcoef_yl0[1],
arg->gfcoef_yl0[2], arg->gfcoef_yl0[3]);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YL0_0, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yl0[4], arg->gfcoef_yl0[5], 0, 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YL0_1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yl1[0], arg->gfcoef_yl1[1],
arg->gfcoef_yl1[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YL1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_yl2[0], arg->gfcoef_yl2[1],
arg->gfcoef_yl2[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_YL2, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[0], arg->gfcoef_cg0[1],
arg->gfcoef_cg0[2], arg->gfcoef_cg0[3]);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CG0_0, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cg0[4], arg->gfcoef_cg0[5], 0, 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CG0_1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cg1[0], arg->gfcoef_cg1[1],
arg->gfcoef_cg1[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CG1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cg2[0], arg->gfcoef_cg2[1],
arg->gfcoef_cg2[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CG2, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[0], arg->gfcoef_cl0[1],
arg->gfcoef_cl0[2], arg->gfcoef_cl0[3]);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CL0_0, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cl0[4], arg->gfcoef_cl0[5], 0, 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CL0_1, val);
val = ISPP_PACK_4BYTE(arg->gfcoef_cl1[0], arg->gfcoef_cl1[1],
arg->gfcoef_cl1[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_GFCOEF_CL1, val);
val = ISPP_PACK_2SHORT(arg->scale_yg[0], arg->scale_yg[1]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_YG01, val);
val = ISPP_PACK_2SHORT(arg->scale_yg[2], arg->scale_yg[3]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_YG23, val);
val = ISPP_PACK_2SHORT(arg->scale_yl[0], arg->scale_yl[1]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_YL01, val);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_YL2, arg->scale_yl[2]);
val = ISPP_PACK_2SHORT(arg->scale_cg[0], arg->scale_y2cg[0]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CG0, val);
val = ISPP_PACK_2SHORT(arg->scale_cg[1], arg->scale_y2cg[1]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CG1, val);
val = ISPP_PACK_2SHORT(arg->scale_cg[2], arg->scale_y2cg[2]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CG2, val);
val = ISPP_PACK_2SHORT(arg->scale_cl[0], arg->scale_y2cl[0]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CL0, val);
val = ISPP_PACK_2SHORT(arg->scale_cl[1], arg->scale_y2cl[1]);
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CL1, val);
val = arg->scale_y2cl[2] << 16;
rkispp_write(base + RKISPP_TNR_CORE_SCALE_CL2, val);
val = ISPP_PACK_4BYTE(arg->weight_y[0], arg->weight_y[1],
arg->weight_y[2], 0);
rkispp_write(base + RKISPP_TNR_CORE_WEIGHT, val);
}
static void tnr_enable(struct rkispp_params_vdev *params_vdev, bool en)
{
void __iomem *base = params_vdev->dev->base_addr;
rkispp_set_bits(base + RKISPP_TNR_CORE_CTRL, SW_TNR_EN, en);
}
static void nr_config(struct rkispp_params_vdev *params_vdev,
struct rkispp_nr_config *arg)
{
void __iomem *base = params_vdev->dev->base_addr;
u32 i, val;
val = arg->uvnr_step1_en << 1 | arg->uvnr_step2_en << 2 |
arg->nr_gain_en << 3 | arg->uvnr_nobig_en << 5 |
arg->uvnr_big_en << 6;
rkispp_set_bits(base + RKISPP_NR_UVNR_CTRL_PARA,
SW_UVNR_STEP1_ON | SW_UVNR_STEP2_ON |
SW_NR_GAIN_BYPASS | SW_UVNR_NOBIG_EN |
SW_UVNR_BIG_EN, val);
rkispp_write(base + RKISPP_NR_UVNR_GAIN_1SIGMA,
arg->uvnr_gain_1sigma);
rkispp_write(base + RKISPP_NR_UVNR_GAIN_OFFSET,
arg->uvnr_gain_offset);
val = ISPP_PACK_4BYTE(arg->uvnr_gain_uvgain[0],
arg->uvnr_gain_uvgain[1], arg->uvnr_gain_t2gen,
arg->uvnr_gain_iso);
rkispp_write(base + RKISPP_NR_UVNR_GAIN_GBLGAIN, val);
rkispp_write(base + RKISPP_NR_UVNR_T1GEN_M3ALPHA,
arg->uvnr_t1gen_m3alpha);
rkispp_write(base + RKISPP_NR_UVNR_T1FLT_MODE,
arg->uvnr_t1flt_mode);
rkispp_write(base + RKISPP_NR_UVNR_T1FLT_MSIGMA,
arg->uvnr_t1flt_msigma);
rkispp_write(base + RKISPP_NR_UVNR_T1FLT_WTP,
arg->uvnr_t1flt_wtp);
for (i = 0; i < NR_UVNR_T1FLT_WTQ_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->uvnr_t1flt_wtq[i],
arg->uvnr_t1flt_wtq[i + 1], arg->uvnr_t1flt_wtq[i + 2],
arg->uvnr_t1flt_wtq[i + 3]);
rkispp_write(base + RKISPP_NR_UVNR_T1FLT_WTQ0 + i, val);
}
rkispp_write(base + RKISPP_NR_UVNR_T2GEN_M3ALPHA,
arg->uvnr_t2gen_m3alpha);
rkispp_write(base + RKISPP_NR_UVNR_T2GEN_MSIGMA,
arg->uvnr_t2gen_msigma);
rkispp_write(base + RKISPP_NR_UVNR_T2GEN_WTP,
arg->uvnr_t2gen_wtp);
val = ISPP_PACK_4BYTE(arg->uvnr_t2gen_wtq[0],
arg->uvnr_t2gen_wtq[1], arg->uvnr_t2gen_wtq[2],
arg->uvnr_t2gen_wtq[3]);
rkispp_write(base + RKISPP_NR_UVNR_T2GEN_WTQ, val);
rkispp_write(base + RKISPP_NR_UVNR_T2FLT_MSIGMA,
arg->uvnr_t2flt_msigma);
val = ISPP_PACK_4BYTE(arg->uvnr_t2flt_wtp,
arg->uvnr_t2flt_wt[0], arg->uvnr_t2flt_wt[1],
arg->uvnr_t2flt_wt[2]);
rkispp_write(base + RKISPP_NR_UVNR_T2FLT_WT, val);
val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[0], arg->ynr_sgm_dx[1],
arg->ynr_sgm_dx[2], arg->ynr_sgm_dx[3],
arg->ynr_sgm_dx[4], arg->ynr_sgm_dx[5],
arg->ynr_sgm_dx[6], arg->ynr_sgm_dx[7]);
rkispp_write(base + RKISPP_NR_YNR_SGM_DX_1_8, val);
val = ISPP_PACK_4BIT(arg->ynr_sgm_dx[8], arg->ynr_sgm_dx[9],
arg->ynr_sgm_dx[10], arg->ynr_sgm_dx[11],
arg->ynr_sgm_dx[12], arg->ynr_sgm_dx[13],
arg->ynr_sgm_dx[14], arg->ynr_sgm_dx[15]);
rkispp_write(base + RKISPP_NR_YNR_SGM_DX_9_16, val);
for (i = 0; i < NR_YNR_SGM_Y_SIZE - 1; i += 2) {
rkispp_write(base + RKISPP_NR_YNR_LSGM_Y_0_1 + i * 2,
ISPP_PACK_2SHORT(arg->ynr_lsgm_y[i], arg->ynr_lsgm_y[i + 1]));
rkispp_write(base + RKISPP_NR_YNR_HSGM_Y_0_1 + i * 2,
ISPP_PACK_2SHORT(arg->ynr_hsgm_y[i], arg->ynr_hsgm_y[i + 1]));
}
rkispp_write(base + RKISPP_NR_YNR_LSGM_Y_16, arg->ynr_lsgm_y[16]);
rkispp_write(base + RKISPP_NR_YNR_HSGM_Y_16, arg->ynr_hsgm_y[16]);
val = ISPP_PACK_4BYTE(arg->ynr_lci[0], arg->ynr_lci[1],
arg->ynr_lci[2], arg->ynr_lci[3]);
rkispp_write(base + RKISPP_NR_YNR_LCI, val);
val = ISPP_PACK_4BYTE(arg->ynr_lgain_min[0], arg->ynr_lgain_min[1],
arg->ynr_lgain_min[2], arg->ynr_lgain_min[3]);
rkispp_write(base + RKISPP_NR_YNR_LGAIN_DIRE_MIN, val);
rkispp_write(base + RKISPP_NR_YNR_IGAIN_DIRE_MAX, arg->ynr_lgain_max);
val = ISPP_PACK_4BYTE(arg->ynr_lmerge_bound, arg->ynr_lmerge_ratio, 0, 0);
rkispp_write(base + RKISPP_NR_YNR_LMERGE, val);
val = ISPP_PACK_4BYTE(arg->ynr_lweit_flt[0], arg->ynr_lweit_flt[1],
arg->ynr_lweit_flt[2], arg->ynr_lweit_flt[3]);
rkispp_write(base + RKISPP_NR_YNR_LWEIT_FLT, val);
val = ISPP_PACK_4BYTE(arg->ynr_hlci[0], arg->ynr_hlci[1],
arg->ynr_hlci[2], arg->ynr_hlci[3]);
rkispp_write(base + RKISPP_NR_YNR_HLCI, val);
val = ISPP_PACK_4BYTE(arg->ynr_lhci[0], arg->ynr_lhci[1],
arg->ynr_lhci[2], arg->ynr_lhci[3]);
rkispp_write(base + RKISPP_NR_YNR_LHCI, val);
val = ISPP_PACK_4BYTE(arg->ynr_hhci[0], arg->ynr_hhci[1],
arg->ynr_hhci[2], arg->ynr_hhci[3]);
rkispp_write(base + RKISPP_NR_YNR_HHCI, val);
val = ISPP_PACK_4BYTE(arg->ynr_hgain_sgm[0], arg->ynr_hgain_sgm[1],
arg->ynr_hgain_sgm[2], arg->ynr_hgain_sgm[3]);
rkispp_write(base + RKISPP_NR_YNR_HGAIN_SGM, val);
for (i = 0; i < NR_YNR_HWEIT_D_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->ynr_hweit_d[i], arg->ynr_hweit_d[i + 1],
arg->ynr_hweit_d[i + 2], arg->ynr_hweit_d[i + 3]);
rkispp_write(base + RKISPP_NR_YNR_HWEIT_D0 + i, val);
}
for (i = 0; i < NR_YNR_HGRAD_Y_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->ynr_hgrad_y[0], arg->ynr_hgrad_y[1],
arg->ynr_hgrad_y[2], arg->ynr_hgrad_y[3]);
rkispp_write(base + RKISPP_NR_YNR_HGRAD_Y0 + i, val);
}
val = ISPP_PACK_2SHORT(arg->ynr_hweit[0], arg->ynr_hweit[1]);
rkispp_write(base + RKISPP_NR_YNR_HWEIT_1_2, val);
val = ISPP_PACK_2SHORT(arg->ynr_hweit[2], arg->ynr_hweit[3]);
rkispp_write(base + RKISPP_NR_YNR_HWEIT_3_4, val);
rkispp_write(base + RKISPP_NR_YNR_HADJUST_EXGAIN, arg->ynr_hmax_adjust);
rkispp_write(base + RKISPP_NR_YNR_HSTRENGTH, arg->ynr_hstrength);
val = ISPP_PACK_4BYTE(arg->ynr_lweit_cmp[0], arg->ynr_lweit_cmp[1], 0, 0);
rkispp_write(base + RKISPP_NR_YNR_LWEIT_CMP, val);
rkispp_write(base + RKISPP_NR_YNR_LMAXGAIN_LV4, arg->ynr_lmaxgain_lv4);
for (i = 0; i < NR_YNR_HSTV_Y_SIZE - 1; i += 2) {
val = ISPP_PACK_2SHORT(arg->ynr_hstv_y[i], arg->ynr_hstv_y[i + 1]);
rkispp_write(base + RKISPP_NR_YNR_HSTV_Y_0_1 + i * 2, val);
}
rkispp_write(base + RKISPP_NR_YNR_HSTV_Y_16, arg->ynr_hstv_y[16]);
val = ISPP_PACK_2SHORT(arg->ynr_st_scale[0], arg->ynr_st_scale[1]);
rkispp_write(base + RKISPP_NR_YNR_ST_SCALE_LV1_LV2, val);
rkispp_write(base + RKISPP_NR_YNR_ST_SCALE_LV3, arg->ynr_st_scale[2]);
}
static void nr_enable(struct rkispp_params_vdev *params_vdev, bool en)
{
void __iomem *base = params_vdev->dev->base_addr;
rkispp_set_bits(base + RKISPP_NR_UVNR_CTRL_PARA, SW_NR_EN, en);
}
static void shp_config(struct rkispp_params_vdev *params_vdev,
struct rkispp_sharp_config *arg)
{
void __iomem *base = params_vdev->dev->base_addr;
u32 i, val;
val = arg->alpha_adp_en << 1 | arg->yin_flt_en << 3 |
arg->edge_avg_en << 4;
rkispp_set_bits(base + RKISPP_SHARP_CORE_CTRL,
SW_SHP_ALPHA_ADP_EN | SW_SHP_YIN_FLT_EN |
SW_SHP_EDGE_AVG_EN, val);
rkispp_write(base + RKISPP_SHARP_HBF_FACTOR, arg->hbf_ratio |
arg->ehf_th << 16 | arg->pbf_ratio << 24);
rkispp_write(base + RKISPP_SHARP_EDGE_TH, arg->edge_thed |
arg->dir_min << 8 | arg->smoth_th4 << 16);
val = ISPP_PACK_2SHORT(arg->l_alpha, arg->g_alpha);
rkispp_write(base + RKISPP_SHARP_EDGE_ALPHA, val);
val = ISPP_PACK_4BYTE(arg->pbf_k[0], arg->pbf_k[1], arg->pbf_k[2], 0);
rkispp_write(base + RKISPP_SHARP_PBF_KERNEL, val);
val = ISPP_PACK_4BYTE(arg->mrf_k[0], arg->mrf_k[1], arg->mrf_k[2], arg->mrf_k[3]);
rkispp_write(base + RKISPP_SHARP_MRF_KERNEL0, val);
val = ISPP_PACK_4BYTE(arg->mrf_k[4], arg->mrf_k[5], 0, 0);
rkispp_write(base + RKISPP_SHARP_MRF_KERNEL1, val);
for (i = 0; i < SHP_MBF_KERNEL_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->mbf_k[i], arg->mbf_k[i + 1],
arg->mbf_k[i + 2], arg->mbf_k[i + 3]);
rkispp_write(base + RKISPP_SHARP_MBF_KERNEL0 + i, val);
}
val = ISPP_PACK_4BYTE(arg->hrf_k[0], arg->hrf_k[1], arg->hrf_k[2], arg->hrf_k[3]);
rkispp_write(base + RKISPP_SHARP_HRF_KERNEL0, val);
val = ISPP_PACK_4BYTE(arg->hrf_k[4], arg->hrf_k[5], 0, 0);
rkispp_write(base + RKISPP_SHARP_HRF_KERNEL1, val);
val = ISPP_PACK_4BYTE(arg->hbf_k[0], arg->hbf_k[1], arg->hbf_k[2], 0);
rkispp_write(base + RKISPP_SHARP_HBF_KERNEL, val);
val = ISPP_PACK_4BYTE(arg->eg_coef[0], arg->eg_coef[1], arg->eg_coef[2], 0);
rkispp_write(base + RKISPP_SHARP_EDGE_COEF, val);
val = ISPP_PACK_4BYTE(arg->eg_smoth[0], arg->eg_smoth[1], arg->eg_smoth[2], 0);
rkispp_write(base + RKISPP_SHARP_EDGE_SMOTH, val);
val = ISPP_PACK_4BYTE(arg->eg_gaus[0], arg->eg_gaus[1], arg->eg_gaus[2], arg->eg_gaus[3]);
rkispp_write(base + RKISPP_SHARP_EDGE_GAUS0, val);
val = ISPP_PACK_4BYTE(arg->eg_gaus[4], arg->eg_gaus[5], 0, 0);
rkispp_write(base + RKISPP_SHARP_EDGE_GAUS1, val);
val = ISPP_PACK_4BYTE(arg->dog_k[0], arg->dog_k[1], arg->dog_k[2], arg->dog_k[3]);
rkispp_write(base + RKISPP_SHARP_DOG_KERNEL0, val);
val = ISPP_PACK_4BYTE(arg->dog_k[4], arg->dog_k[5], 0, 0);
rkispp_write(base + RKISPP_SHARP_DOG_KERNEL1, val);
val = ISPP_PACK_4BYTE(arg->lum_point[0], arg->lum_point[1],
arg->lum_point[2], arg->lum_point[3]);
rkispp_write(base + RKISPP_SHARP_LUM_POINT0, val);
val = ISPP_PACK_4BYTE(arg->lum_point[4], arg->lum_point[5], 0, 0);
rkispp_write(base + RKISPP_SHARP_LUM_POINT1, val);
val = ISPP_PACK_4BYTE(arg->pbf_shf_bits, arg->mbf_shf_bits, arg->hbf_shf_bits, 0);
rkispp_write(base + RKISPP_SHARP_SHF_BITS, val);
for (i = 0; i < SHP_SIGMA_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->pbf_sigma[i], arg->pbf_sigma[i + 1],
arg->pbf_sigma[i + 2], arg->pbf_sigma[i + 3]);
rkispp_write(base + RKISPP_SHARP_PBF_SIGMA_INV0 + i, val);
val = ISPP_PACK_4BYTE(arg->mbf_sigma[i], arg->mbf_sigma[i + 1],
arg->mbf_sigma[i + 2], arg->mbf_sigma[i + 3]);
rkispp_write(base + RKISPP_SHARP_MBF_SIGMA_INV0 + i, val);
val = ISPP_PACK_4BYTE(arg->hbf_sigma[i], arg->hbf_sigma[i + 1],
arg->hbf_sigma[i + 2], arg->hbf_sigma[i + 3]);
rkispp_write(base + RKISPP_SHARP_HBF_SIGMA_INV0 + i, val);
}
for (i = 0; i < SHP_LUM_CLP_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->lum_clp_m[i], arg->lum_clp_m[i + 1],
arg->lum_clp_m[i + 2], arg->lum_clp_m[i + 3]);
rkispp_write(base + RKISPP_SHARP_LUM_CLP_M0 + i, val);
val = ISPP_PACK_4BYTE(arg->lum_clp_h[i], arg->lum_clp_h[i + 1],
arg->lum_clp_h[i + 2], arg->lum_clp_h[i + 3]);
rkispp_write(base + RKISPP_SHARP_LUM_CLP_H0 + i, val);
}
for (i = 0; i < SHP_LUM_MIN_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->lum_min_m[i], arg->lum_min_m[i + 1],
arg->lum_min_m[i + 2], arg->lum_min_m[i + 3]);
rkispp_write(base + RKISPP_SHARP_LUM_MIN_M0 + i, val);
}
for (i = 0; i < SHP_EDGE_LUM_THED_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->edge_lum_thed[i], arg->edge_lum_thed[i + 1],
arg->edge_lum_thed[i + 2], arg->edge_lum_thed[i + 3]);
rkispp_write(base + RKISPP_SHARP_EDGE_LUM_THED0 + i, val);
}
for (i = 0; i < SHP_CLAMP_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->clamp_pos[i], arg->clamp_pos[i + 1],
arg->clamp_pos[i + 2], arg->clamp_pos[i + 3]);
rkispp_write(base + RKISPP_SHARP_CLAMP_POS_DOG0 + i, val);
val = ISPP_PACK_4BYTE(arg->clamp_neg[i], arg->clamp_neg[i + 1],
arg->clamp_neg[i + 2], arg->clamp_neg[i + 3]);
rkispp_write(base + RKISPP_SHARP_CLAMP_NEG_DOG0 + i, val);
}
for (i = 0; i < SHP_DETAIL_ALPHA_SIZE; i += 4) {
val = ISPP_PACK_4BYTE(arg->detail_alpha[i], arg->detail_alpha[i + 1],
arg->detail_alpha[i + 2], arg->detail_alpha[i + 3]);
rkispp_write(base + RKISPP_SHARP_DETAIL_ALPHA_DOG0 + i, val);
}
val = ISPP_PACK_2SHORT(arg->rfl_ratio, arg->rfh_ratio);
rkispp_write(base + RKISPP_SHARP_RF_RATIO, val);
val = ISPP_PACK_4BYTE(arg->m_ratio, arg->h_ratio, 0, 0);
rkispp_write(base + RKISPP_SHARP_GRAD_RATIO, val);
}
static void shp_enable(struct rkispp_params_vdev *params_vdev, bool en)
{
void __iomem *base = params_vdev->dev->base_addr;
rkispp_set_bits(base + RKISPP_SHARP_CORE_CTRL, SW_SHP_EN, en);
}
static void fec_config(struct rkispp_params_vdev *params_vdev,
struct rkispp_fec_config *arg)
{
}
static void fec_enable(struct rkispp_params_vdev *params_vdev, bool en)
{
}
static int rkispp_params_enum_fmt_meta_out(struct file *file, void *priv,
struct v4l2_fmtdesc *f)
{
struct video_device *video = video_devdata(file);
struct rkispp_params_vdev *params_vdev = video_get_drvdata(video);
if (f->index > 0 || f->type != video->queue->type)
return -EINVAL;
f->pixelformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
return 0;
}
static int rkispp_params_g_fmt_meta_out(struct file *file, void *fh,
struct v4l2_format *f)
{
struct video_device *video = video_devdata(file);
struct rkispp_params_vdev *params_vdev = video_get_drvdata(video);
struct v4l2_meta_format *meta = &f->fmt.meta;
if (f->type != video->queue->type)
return -EINVAL;
memset(meta, 0, sizeof(*meta));
meta->dataformat = params_vdev->vdev_fmt.fmt.meta.dataformat;
meta->buffersize = params_vdev->vdev_fmt.fmt.meta.buffersize;
return 0;
}
static int rkispp_params_querycap(struct file *file,
void *priv, struct v4l2_capability *cap)
{
struct video_device *vdev = video_devdata(file);
struct rkispp_params_vdev *params_vdev = video_get_drvdata(vdev);
snprintf(cap->driver, sizeof(cap->driver),
"%s_v%d", DRIVER_NAME,
params_vdev->dev->ispp_ver >> 4);
strlcpy(cap->card, vdev->name, sizeof(cap->card));
strlcpy(cap->bus_info, "platform: " DRIVER_NAME, sizeof(cap->bus_info));
return 0;
}
static const struct v4l2_ioctl_ops rkispp_params_ioctl = {
.vidioc_reqbufs = vb2_ioctl_reqbufs,
.vidioc_querybuf = vb2_ioctl_querybuf,
.vidioc_create_bufs = vb2_ioctl_create_bufs,
.vidioc_qbuf = vb2_ioctl_qbuf,
.vidioc_dqbuf = vb2_ioctl_dqbuf,
.vidioc_prepare_buf = vb2_ioctl_prepare_buf,
.vidioc_expbuf = vb2_ioctl_expbuf,
.vidioc_streamon = vb2_ioctl_streamon,
.vidioc_streamoff = vb2_ioctl_streamoff,
.vidioc_enum_fmt_meta_out = rkispp_params_enum_fmt_meta_out,
.vidioc_g_fmt_meta_out = rkispp_params_g_fmt_meta_out,
.vidioc_s_fmt_meta_out = rkispp_params_g_fmt_meta_out,
.vidioc_try_fmt_meta_out = rkispp_params_g_fmt_meta_out,
.vidioc_querycap = rkispp_params_querycap
};
static int rkispp_params_vb2_queue_setup(struct vb2_queue *vq,
unsigned int *num_buffers,
unsigned int *num_planes,
unsigned int sizes[],
struct device *alloc_ctxs[])
{
struct rkispp_params_vdev *params_vdev = vq->drv_priv;
*num_buffers = clamp_t(u32, *num_buffers,
RKISP1_ISP_PARAMS_REQ_BUFS_MIN,
RKISP1_ISP_PARAMS_REQ_BUFS_MAX);
*num_planes = 1;
sizes[0] = sizeof(struct rkispp_params_cfg);
INIT_LIST_HEAD(&params_vdev->params);
params_vdev->first_params = true;
return 0;
}
static void rkispp_params_vb2_buf_queue(struct vb2_buffer *vb)
{
struct vb2_v4l2_buffer *vbuf = to_vb2_v4l2_buffer(vb);
struct rkispp_buffer *params_buf = to_rkispp_buffer(vbuf);
struct vb2_queue *vq = vb->vb2_queue;
struct rkispp_params_vdev *params_vdev = vq->drv_priv;
struct rkispp_params_cfg *new_params;
unsigned long flags;
if (params_vdev->first_params) {
new_params = (struct rkispp_params_cfg *)
(vb2_plane_vaddr(vb, 0));
vb2_buffer_done(&params_buf->vb.vb2_buf, VB2_BUF_STATE_DONE);
params_vdev->first_params = false;
params_vdev->cur_params = *new_params;
return;
}
params_buf->vaddr[0] = vb2_plane_vaddr(vb, 0);
spin_lock_irqsave(&params_vdev->config_lock, flags);
list_add_tail(&params_buf->queue, &params_vdev->params);
spin_unlock_irqrestore(&params_vdev->config_lock, flags);
}
static void rkispp_params_vb2_stop_streaming(struct vb2_queue *vq)
{
struct rkispp_params_vdev *params_vdev = vq->drv_priv;
struct rkispp_buffer *buf;
unsigned long flags;
int i;
/* stop params input firstly */
spin_lock_irqsave(&params_vdev->config_lock, flags);
params_vdev->streamon = false;
spin_unlock_irqrestore(&params_vdev->config_lock, flags);
for (i = 0; i < RKISP1_ISP_PARAMS_REQ_BUFS_MAX; i++) {
spin_lock_irqsave(&params_vdev->config_lock, flags);
if (!list_empty(&params_vdev->params)) {
buf = list_first_entry(&params_vdev->params,
struct rkispp_buffer, queue);
list_del(&buf->queue);
spin_unlock_irqrestore(&params_vdev->config_lock,
flags);
} else {
spin_unlock_irqrestore(&params_vdev->config_lock,
flags);
break;
}
if (buf)
vb2_buffer_done(&buf->vb.vb2_buf, VB2_BUF_STATE_ERROR);
buf = NULL;
}
/* clean module params */
params_vdev->cur_params.module_cfg_update = 0;
params_vdev->cur_params.module_en_update = 0;
}
static int
rkispp_params_vb2_start_streaming(struct vb2_queue *queue, unsigned int count)
{
struct rkispp_params_vdev *params_vdev = queue->drv_priv;
unsigned long flags;
spin_lock_irqsave(&params_vdev->config_lock, flags);
params_vdev->streamon = true;
spin_unlock_irqrestore(&params_vdev->config_lock, flags);
return 0;
}
static struct vb2_ops rkispp_params_vb2_ops = {
.queue_setup = rkispp_params_vb2_queue_setup,
.wait_prepare = vb2_ops_wait_prepare,
.wait_finish = vb2_ops_wait_finish,
.buf_queue = rkispp_params_vb2_buf_queue,
.start_streaming = rkispp_params_vb2_start_streaming,
.stop_streaming = rkispp_params_vb2_stop_streaming,
};
struct v4l2_file_operations rkispp_params_fops = {
.mmap = vb2_fop_mmap,
.unlocked_ioctl = video_ioctl2,
.poll = vb2_fop_poll,
.open = v4l2_fh_open,
.release = vb2_fop_release
};
static int
rkispp_params_init_vb2_queue(struct vb2_queue *q,
struct rkispp_params_vdev *params_vdev)
{
q->type = V4L2_BUF_TYPE_META_OUTPUT;
q->io_modes = VB2_MMAP | VB2_DMABUF | VB2_USERPTR;
q->drv_priv = params_vdev;
q->ops = &rkispp_params_vb2_ops;
q->mem_ops = &vb2_vmalloc_memops;
q->buf_struct_size = sizeof(struct rkispp_buffer);
q->timestamp_flags = V4L2_BUF_FLAG_TIMESTAMP_MONOTONIC;
q->lock = &params_vdev->dev->apilock;
q->dev = params_vdev->dev->dev;
return vb2_queue_init(q);
}
void rkispp_params_isr(struct rkispp_params_vdev *params_vdev, u32 mis)
{
struct rkispp_params_cfg *new_params = NULL;
u32 module_en_update, module_cfg_update, module_ens;
spin_lock(&params_vdev->config_lock);
if (!params_vdev->streamon) {
spin_unlock(&params_vdev->config_lock);
return;
}
if (!params_vdev->cur_buf &&
!list_empty(&params_vdev->params)) {
params_vdev->cur_buf = list_first_entry(&params_vdev->params,
struct rkispp_buffer, queue);
list_del(&params_vdev->cur_buf->queue);
}
if (!params_vdev->cur_buf) {
spin_unlock(&params_vdev->config_lock);
return;
}
new_params = (struct rkispp_params_cfg *)(params_vdev->cur_buf->vaddr[0]);
module_en_update = new_params->module_en_update;
module_cfg_update = new_params->module_cfg_update;
module_ens = new_params->module_ens;
if (module_cfg_update & ISPP_MODULE_TNR &&
mis & TNR_INT)
tnr_config(params_vdev,
&new_params->tnr_cfg);
if (module_en_update & ISPP_MODULE_TNR &&
mis & TNR_INT)
tnr_enable(params_vdev,
!!(module_ens & ISPP_MODULE_TNR));
if (module_cfg_update & ISPP_MODULE_NR &&
mis & NR_INT)
nr_config(params_vdev,
&new_params->nr_cfg);
if (module_en_update & ISPP_MODULE_NR &&
mis & NR_INT)
nr_enable(params_vdev,
!!(module_ens & ISPP_MODULE_NR));
if (module_cfg_update & ISPP_MODULE_SHP &&
mis & SHP_INT)
shp_config(params_vdev,
&new_params->shp_cfg);
if (module_en_update & ISPP_MODULE_SHP &&
mis & SHP_INT)
shp_enable(params_vdev,
!!(module_ens & ISPP_MODULE_SHP));
if (module_cfg_update & ISPP_MODULE_FEC)
fec_config(params_vdev,
&new_params->fec_cfg);
if (module_en_update & ISPP_MODULE_FEC)
fec_enable(params_vdev,
!!(module_ens & ISPP_MODULE_FEC));
//TODO diff mode to release buf
if (mis & SHP_INT) {
vb2_buffer_done(&params_vdev->cur_buf->vb.vb2_buf,
VB2_BUF_STATE_DONE);
params_vdev->cur_buf = NULL;
}
spin_unlock(&params_vdev->config_lock);
}
void rkispp_params_configure(struct rkispp_params_vdev *params_vdev)
{
u32 module_en_update = params_vdev->cur_params.module_en_update;
u32 module_cfg_update = params_vdev->cur_params.module_cfg_update;
u32 module_ens = params_vdev->cur_params.module_ens;
if (module_cfg_update & ISPP_MODULE_TNR)
tnr_config(params_vdev,
&params_vdev->cur_params.tnr_cfg);
if (module_en_update & ISPP_MODULE_TNR)
tnr_enable(params_vdev,
!!(module_ens & ISPP_MODULE_TNR));
if (module_cfg_update & ISPP_MODULE_NR)
nr_config(params_vdev,
&params_vdev->cur_params.nr_cfg);
if (module_en_update & ISPP_MODULE_NR)
nr_enable(params_vdev,
!!(module_ens & ISPP_MODULE_NR));
if (module_cfg_update & ISPP_MODULE_SHP)
shp_config(params_vdev,
&params_vdev->cur_params.shp_cfg);
if (module_en_update & ISPP_MODULE_SHP)
shp_enable(params_vdev,
!!(module_ens & ISPP_MODULE_SHP));
if (module_cfg_update & ISPP_MODULE_FEC)
fec_config(params_vdev,
&params_vdev->cur_params.fec_cfg);
if (module_en_update & ISPP_MODULE_FEC)
fec_enable(params_vdev,
!!(module_ens & ISPP_MODULE_FEC));
}
int rkispp_register_params_vdev(struct rkispp_device *dev)
{
struct rkispp_params_vdev *params_vdev = &dev->params_vdev;
struct rkispp_vdev_node *node = &params_vdev->vnode;
struct video_device *vdev = &node->vdev;
int ret;
params_vdev->dev = dev;
spin_lock_init(&params_vdev->config_lock);
strlcpy(vdev->name, "rkispp_input_params", sizeof(vdev->name));
video_set_drvdata(vdev, params_vdev);
vdev->ioctl_ops = &rkispp_params_ioctl;
vdev->fops = &rkispp_params_fops;
vdev->release = video_device_release_empty;
/*
* Provide a mutex to v4l2 core. It will be used
* to protect all fops and v4l2 ioctls.
*/
vdev->lock = &dev->apilock;
vdev->v4l2_dev = &dev->v4l2_dev;
vdev->queue = &node->buf_queue;
vdev->device_caps = V4L2_CAP_STREAMING | V4L2_CAP_META_OUTPUT;
vdev->vfl_dir = VFL_DIR_TX;
rkispp_params_init_vb2_queue(vdev->queue, params_vdev);
params_vdev->vdev_fmt.fmt.meta.dataformat =
V4L2_META_FMT_RK_ISPP_PARAMS;
node->pad.flags = MEDIA_PAD_FL_SOURCE;
ret = media_entity_pads_init(&vdev->entity, 1, &node->pad);
if (ret < 0)
goto err_release_queue;
ret = video_register_device(vdev, VFL_TYPE_GRABBER, -1);
if (ret < 0) {
dev_err(&vdev->dev,
"could not register Video for Linux device\n");
goto err_cleanup_media_entity;
}
return 0;
err_cleanup_media_entity:
media_entity_cleanup(&vdev->entity);
err_release_queue:
vb2_queue_release(vdev->queue);
return ret;
}
void rkispp_unregister_params_vdev(struct rkispp_device *dev)
{
struct rkispp_params_vdev *params_vdev = &dev->params_vdev;
struct rkispp_vdev_node *node = &params_vdev->vnode;
struct video_device *vdev = &node->vdev;
video_unregister_device(vdev);
media_entity_cleanup(&vdev->entity);
vb2_queue_release(vdev->queue);
}

View File

@@ -0,0 +1,34 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_PARAMS_H
#define _RKISPP_PARAMS_H
#include <linux/rkispp-config.h>
#include "common.h"
/* rkispp parameters device
* config_lock: lock to protect config
* params: queued buffer list
* cur_params: ispp params config
* cur_params: current buf of parameters
* first_params: the first params should take effect immediately
*/
struct rkispp_params_vdev {
struct rkispp_vdev_node vnode;
struct rkispp_device *dev;
spinlock_t config_lock;
struct list_head params;
struct rkispp_params_cfg cur_params;
struct rkispp_buffer *cur_buf;
struct v4l2_format vdev_fmt;
bool streamon;
bool first_params;
};
int rkispp_register_params_vdev(struct rkispp_device *dev);
void rkispp_unregister_params_vdev(struct rkispp_device *dev);
void rkispp_params_configure(struct rkispp_params_vdev *params_vdev);
void rkispp_params_isr(struct rkispp_params_vdev *params_vdev, u32 mis);
#endif

View File

@@ -0,0 +1,501 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_REGS_H
#define _RKISPP_REGS_H
/* registers */
#define RKISPP_CTRL 0x0000
#define RKISPP_CTRL_STRT (RKISPP_CTRL + 0x0000)
#define RKISPP_CTRL_UPDATE (RKISPP_CTRL + 0x0004)
#define RKISPP_CTRL_QUICK (RKISPP_CTRL + 0x0008)
#define RKISPP_CTRL_RESET (RKISPP_CTRL + 0x000C)
#define RKISPP_CTRL_CLKGATE (RKISPP_CTRL + 0x0010)
#define RKISPP_CTRL_SIZE (RKISPP_CTRL + 0x0014)
#define RKISPP_CTRL_TNR_SIZE (RKISPP_CTRL + 0x0018)
#define RKISPP_CTRL_IP_VERSION (RKISPP_CTRL + 0x001C)
#define RKISPP_CTRL_INT_MSK (RKISPP_CTRL + 0x0020)
#define RKISPP_CTRL_INT_RAW_STA (RKISPP_CTRL + 0x0024)
#define RKISPP_CTRL_INT_STA (RKISPP_CTRL + 0x0028)
#define RKISPP_CTRL_INT_SET (RKISPP_CTRL + 0x002C)
#define RKISPP_CTRL_INT_CLR (RKISPP_CTRL + 0x0030)
#define RKISPP_CTRL_SYS_STATUS (RKISPP_CTRL + 0x003C)
#define RKISPP_CTRL_QUICK_FRM_NUM (RKISPP_CTRL + 0x0040)
#define RKISPP_CTRL_SYS_CTL_STA0 (RKISPP_CTRL + 0x0054)
#define RKISPP_CTRL_SYS_CTL_STA1 (RKISPP_CTRL + 0x0058)
#define RKISPP_CTRL_SYS_CTL_STA2 (RKISPP_CTRL + 0x005C)
#define RKISPP_CTRL_SYS_FRM_CNT0 (RKISPP_CTRL + 0x0060)
#define RKISPP_CTRL_SYS_FRM_CNT1 (RKISPP_CTRL + 0x0064)
#define RKISPP_TNR 0x0200
#define RKISPP_TNR_CTRL (RKISPP_TNR + 0x0000)
#define RKISPP_TNR_CUR_VIR_STRIDE (RKISPP_TNR + 0x0004)
#define RKISPP_TNR_CUR_Y_BASE (RKISPP_TNR + 0x0008)
#define RKISPP_TNR_CUR_UV_BASE (RKISPP_TNR + 0x000C)
#define RKISPP_TNR_IIR_VIR_STRIDE (RKISPP_TNR + 0x0010)
#define RKISPP_TNR_IIR_Y_BASE (RKISPP_TNR + 0x0014)
#define RKISPP_TNR_IIR_UV_BASE (RKISPP_TNR + 0x0018)
#define RKISPP_TNR_NXT_VIR_STRIDE (RKISPP_TNR + 0x001C)
#define RKISPP_TNR_NXT_Y_BASE (RKISPP_TNR + 0x0020)
#define RKISPP_TNR_NXT_UV_BASE (RKISPP_TNR + 0x0024)
#define RKISPP_TNR_GAIN_CUR_VIR_STRIDE (RKISPP_TNR + 0x0028)
#define RKISPP_TNR_GAIN_CUR_Y_BASE (RKISPP_TNR + 0x002C)
#define RKISPP_TNR_GAIN_NXT_VIR_STRIDE (RKISPP_TNR + 0x0030)
#define RKISPP_TNR_GAIN_NXT_Y_BASE (RKISPP_TNR + 0x0034)
#define RKISPP_TNR_GAIN_KG_VIR_STRIDE (RKISPP_TNR + 0x0038)
#define RKISPP_TNR_GAIN_KG_Y_BASE (RKISPP_TNR + 0x003C)
#define RKISPP_TNR_WR_VIR_STRIDE (RKISPP_TNR + 0x0040)
#define RKISPP_TNR_WR_Y_BASE (RKISPP_TNR + 0x0044)
#define RKISPP_TNR_WR_UV_BASE (RKISPP_TNR + 0x0048)
#define RKISPP_TNR_GAIN_WR_VIR_STRIDE (RKISPP_TNR + 0x004C)
#define RKISPP_TNR_GAIN_WR_Y_BASE (RKISPP_TNR + 0x0050)
#define RKISPP_TNR_CUR_Y_BASE_SHD (RKISPP_TNR + 0x0054)
#define RKISPP_TNR_CUR_UV_BASE_SHD (RKISPP_TNR + 0x0058)
#define RKISPP_TNR_IIR_Y_BASE_SHD (RKISPP_TNR + 0x005C)
#define RKISPP_TNR_IIR_UV_BASE_SHD (RKISPP_TNR + 0x0060)
#define RKISPP_TNR_NXT_Y_BASE_SHD (RKISPP_TNR + 0x0064)
#define RKISPP_TNR_NXT_UV_BASE_SHD (RKISPP_TNR + 0x0068)
#define RKISPP_TNR_GAIN_CUR_Y_BASE_SHD (RKISPP_TNR + 0x006C)
#define RKISPP_TNR_GAIN_NXT_Y_BASE_SHD (RKISPP_TNR + 0x0070)
#define RKISPP_TNR_WR_Y_BASE_SHD (RKISPP_TNR + 0x0074)
#define RKISPP_TNR_WR_UV_BASE_SHD (RKISPP_TNR + 0x0078)
#define RKISPP_TNR_GAIN_WR_Y_BASE_SHD (RKISPP_TNR + 0x007C)
#define RKISPP_TNR_CORE_CTRL (RKISPP_TNR + 0x0080)
#define RKISPP_TNR_CORE_PK0 (RKISPP_TNR + 0x0088)
#define RKISPP_TNR_CORE_GLB_GAIN (RKISPP_TNR + 0x008C)
#define RKISPP_TNR_CORE_GLB_GAIN_DIV (RKISPP_TNR + 0x0090)
#define RKISPP_TNR_CORE_SIG_X18 (RKISPP_TNR + 0x0094)
#define RKISPP_TNR_CORE_SIG_X910 (RKISPP_TNR + 0x0098)
#define RKISPP_TNR_CORE_SIG_Y01 (RKISPP_TNR + 0x009C)
#define RKISPP_TNR_CORE_SIG_Y23 (RKISPP_TNR + 0x00A0)
#define RKISPP_TNR_CORE_SIG_Y45 (RKISPP_TNR + 0x00A4)
#define RKISPP_TNR_CORE_SIG_Y67 (RKISPP_TNR + 0x00A8)
#define RKISPP_TNR_CORE_SIG_Y89 (RKISPP_TNR + 0x00AC)
#define RKISPP_TNR_CORE_SIG_YAB (RKISPP_TNR + 0x00B0)
#define RKISPP_TNR_CORE_SIG_YCD (RKISPP_TNR + 0x00B4)
#define RKISPP_TNR_CORE_SIG_YEF (RKISPP_TNR + 0x00B8)
#define RKISPP_TNR_CORE_SIG_Y10 (RKISPP_TNR + 0x00BC)
#define RKISPP_TNR_CORE_LUMACURVE_Y01 (RKISPP_TNR + 0x00C4)
#define RKISPP_TNR_CORE_LUMACURVE_Y23 (RKISPP_TNR + 0x00C8)
#define RKISPP_TNR_CORE_LUMACURVE_Y45 (RKISPP_TNR + 0x00CC)
#define RKISPP_TNR_CORE_TH_Y (RKISPP_TNR + 0x00D0)
#define RKISPP_TNR_CORE_TH_C (RKISPP_TNR + 0x00D4)
#define RKISPP_TNR_CORE_TH_DLT (RKISPP_TNR + 0x00D8)
#define RKISPP_TNR_CORE_GFCOEF_Y0_0 (RKISPP_TNR + 0x00DC)
#define RKISPP_TNR_CORE_GFCOEF_Y0_1 (RKISPP_TNR + 0x00E0)
#define RKISPP_TNR_CORE_GFCOEF_Y1 (RKISPP_TNR + 0x00E4)
#define RKISPP_TNR_CORE_GFCOEF_Y2 (RKISPP_TNR + 0x00E8)
#define RKISPP_TNR_CORE_GFCOEF_Y3 (RKISPP_TNR + 0x00EC)
#define RKISPP_TNR_CORE_GFCOEF_YG0_0 (RKISPP_TNR + 0x00F0)
#define RKISPP_TNR_CORE_GFCOEF_YG0_1 (RKISPP_TNR + 0x00F4)
#define RKISPP_TNR_CORE_GFCOEF_YG1 (RKISPP_TNR + 0x00F8)
#define RKISPP_TNR_CORE_GFCOEF_YG2 (RKISPP_TNR + 0x00FC)
#define RKISPP_TNR_CORE_GFCOEF_YG3 (RKISPP_TNR + 0x0100)
#define RKISPP_TNR_CORE_GFCOEF_YL0_0 (RKISPP_TNR + 0x0104)
#define RKISPP_TNR_CORE_GFCOEF_YL0_1 (RKISPP_TNR + 0x0108)
#define RKISPP_TNR_CORE_GFCOEF_YL1 (RKISPP_TNR + 0x010C)
#define RKISPP_TNR_CORE_GFCOEF_YL2 (RKISPP_TNR + 0x0110)
#define RKISPP_TNR_CORE_GFCOEF_CG0_0 (RKISPP_TNR + 0x0114)
#define RKISPP_TNR_CORE_GFCOEF_CG0_1 (RKISPP_TNR + 0x0118)
#define RKISPP_TNR_CORE_GFCOEF_CG1 (RKISPP_TNR + 0x011C)
#define RKISPP_TNR_CORE_GFCOEF_CG2 (RKISPP_TNR + 0x0120)
#define RKISPP_TNR_CORE_GFCOEF_CL0_0 (RKISPP_TNR + 0x0124)
#define RKISPP_TNR_CORE_GFCOEF_CL0_1 (RKISPP_TNR + 0x0128)
#define RKISPP_TNR_CORE_GFCOEF_CL1 (RKISPP_TNR + 0x012C)
#define RKISPP_TNR_CORE_SCALE_YG01 (RKISPP_TNR + 0x0130)
#define RKISPP_TNR_CORE_SCALE_YG23 (RKISPP_TNR + 0x0134)
#define RKISPP_TNR_CORE_SCALE_YL01 (RKISPP_TNR + 0x0138)
#define RKISPP_TNR_CORE_SCALE_YL2 (RKISPP_TNR + 0x013c)
#define RKISPP_TNR_CORE_SCALE_CG0 (RKISPP_TNR + 0x0140)
#define RKISPP_TNR_CORE_SCALE_CG1 (RKISPP_TNR + 0x0144)
#define RKISPP_TNR_CORE_SCALE_CG2 (RKISPP_TNR + 0x0148)
#define RKISPP_TNR_CORE_SCALE_CL0 (RKISPP_TNR + 0x014C)
#define RKISPP_TNR_CORE_SCALE_CL1 (RKISPP_TNR + 0x0150)
#define RKISPP_TNR_CORE_SCALE_CL2 (RKISPP_TNR + 0x0154)
#define RKISPP_TNR_CORE_WEIGHT (RKISPP_TNR + 0x0158)
#define RKISPP_NR 0x0400
#define RKISPP_NR_CTRL (RKISPP_NR + 0x0000)
#define RKISPP_NR_VIR_STRIDE (RKISPP_NR + 0x0004)
#define RKISPP_NR_ADDR_BASE_Y (RKISPP_NR + 0x0008)
#define RKISPP_NR_ADDR_BASE_UV (RKISPP_NR + 0x000C)
#define RKISPP_NR_VIR_STRIDE_GAIN (RKISPP_NR + 0x001C)
#define RKISPP_NR_ADDR_BASE_GAIN (RKISPP_NR + 0x0020)
#define RKISPP_NR_ADDR_BASE_Y_SHD (RKISPP_NR + 0x0024)
#define RKISPP_NR_ADDR_BASE_UV_SHD (RKISPP_NR + 0x0028)
#define RKISPP_FBC_VIR_HEIGHT (RKISPP_NR + 0x002C)
#define RKISPP_NR_UVNR_CTRL_PARA (RKISPP_NR + 0x0080)
#define RKISPP_NR_UVNR_GAIN_1SIGMA (RKISPP_NR + 0x0084)
#define RKISPP_NR_UVNR_GAIN_OFFSET (RKISPP_NR + 0x0088)
#define RKISPP_NR_UVNR_GAIN_GBLGAIN (RKISPP_NR + 0x008C)
#define RKISPP_NR_UVNR_T1GEN_M3ALPHA (RKISPP_NR + 0x0090)
#define RKISPP_NR_UVNR_T1FLT_MODE (RKISPP_NR + 0x0094)
#define RKISPP_NR_UVNR_T1FLT_MSIGMA (RKISPP_NR + 0x0098)
#define RKISPP_NR_UVNR_T1FLT_WTP (RKISPP_NR + 0x009C)
#define RKISPP_NR_UVNR_T1FLT_WTQ0 (RKISPP_NR + 0x00A0)
#define RKISPP_NR_UVNR_T1FLT_WTQ1 (RKISPP_NR + 0x00A4)
#define RKISPP_NR_UVNR_T2GEN_M3ALPHA (RKISPP_NR + 0x00A8)
#define RKISPP_NR_UVNR_T2GEN_MSIGMA (RKISPP_NR + 0x00AC)
#define RKISPP_NR_UVNR_T2GEN_WTP (RKISPP_NR + 0x00B0)
#define RKISPP_NR_UVNR_T2GEN_WTQ (RKISPP_NR + 0x00B4)
#define RKISPP_NR_UVNR_T2FLT_MSIGMA (RKISPP_NR + 0x00B8)
#define RKISPP_NR_UVNR_T2FLT_WT (RKISPP_NR + 0x00BC)
#define RKISPP_NR_YNR_SGM_DX_1_8 (RKISPP_NR + 0x0104)
#define RKISPP_NR_YNR_SGM_DX_9_16 (RKISPP_NR + 0x0108)
#define RKISPP_NR_YNR_LSGM_Y_0_1 (RKISPP_NR + 0x010C)
#define RKISPP_NR_YNR_LSGM_Y_2_3 (RKISPP_NR + 0x0110)
#define RKISPP_NR_YNR_LSGM_Y_4_5 (RKISPP_NR + 0x0114)
#define RKISPP_NR_YNR_LSGM_Y_6_7 (RKISPP_NR + 0x0118)
#define RKISPP_NR_YNR_LSGM_Y_8_9 (RKISPP_NR + 0x011C)
#define RKISPP_NR_YNR_LSGM_Y_10_11 (RKISPP_NR + 0x0120)
#define RKISPP_NR_YNR_LSGM_Y_12_13 (RKISPP_NR + 0x0124)
#define RKISPP_NR_YNR_LSGM_Y_14_15 (RKISPP_NR + 0x0128)
#define RKISPP_NR_YNR_LSGM_Y_16 (RKISPP_NR + 0x012C)
#define RKISPP_NR_YNR_LCI (RKISPP_NR + 0x0130)
#define RKISPP_NR_YNR_LGAIN_DIRE_MIN (RKISPP_NR + 0x0134)
#define RKISPP_NR_YNR_IGAIN_DIRE_MAX (RKISPP_NR + 0x0138)
#define RKISPP_NR_YNR_LMERGE (RKISPP_NR + 0x013C)
#define RKISPP_NR_YNR_LWEIT_FLT (RKISPP_NR + 0x0140)
#define RKISPP_NR_YNR_HSGM_Y_0_1 (RKISPP_NR + 0x0144)
#define RKISPP_NR_YNR_HSGM_Y_2_3 (RKISPP_NR + 0x0148)
#define RKISPP_NR_YNR_HSGM_Y_4_5 (RKISPP_NR + 0x014C)
#define RKISPP_NR_YNR_HSGM_Y_6_7 (RKISPP_NR + 0x0150)
#define RKISPP_NR_YNR_HSGM_Y_8_9 (RKISPP_NR + 0x0154)
#define RKISPP_NR_YNR_HSGM_Y_10_11 (RKISPP_NR + 0x0158)
#define RKISPP_NR_YNR_HSGM_Y_12_13 (RKISPP_NR + 0x015C)
#define RKISPP_NR_YNR_HSGM_Y_14_15 (RKISPP_NR + 0x0160)
#define RKISPP_NR_YNR_HSGM_Y_16 (RKISPP_NR + 0x0164)
#define RKISPP_NR_YNR_HLCI (RKISPP_NR + 0x0168)
#define RKISPP_NR_YNR_LHCI (RKISPP_NR + 0x016C)
#define RKISPP_NR_YNR_HHCI (RKISPP_NR + 0x0170)
#define RKISPP_NR_YNR_HGAIN_SGM (RKISPP_NR + 0x0174)
#define RKISPP_NR_YNR_HWEIT_D0 (RKISPP_NR + 0x0178)
#define RKISPP_NR_YNR_HWEIT_D1 (RKISPP_NR + 0x017C)
#define RKISPP_NR_YNR_HWEIT_D2 (RKISPP_NR + 0x0180)
#define RKISPP_NR_YNR_HWEIT_D3 (RKISPP_NR + 0x0184)
#define RKISPP_NR_YNR_HWEIT_D4 (RKISPP_NR + 0x0188)
#define RKISPP_NR_YNR_HGRAD_Y0 (RKISPP_NR + 0x018C)
#define RKISPP_NR_YNR_HGRAD_Y1 (RKISPP_NR + 0x0190)
#define RKISPP_NR_YNR_HGRAD_Y2 (RKISPP_NR + 0x0194)
#define RKISPP_NR_YNR_HGRAD_Y3 (RKISPP_NR + 0x0198)
#define RKISPP_NR_YNR_HGRAD_Y4 (RKISPP_NR + 0x019C)
#define RKISPP_NR_YNR_HGRAD_Y5 (RKISPP_NR + 0x01A0)
#define RKISPP_NR_YNR_HWEIT_1_2 (RKISPP_NR + 0x01A4)
#define RKISPP_NR_YNR_HWEIT_3_4 (RKISPP_NR + 0x01A8)
#define RKISPP_NR_YNR_HADJUST_EXGAIN (RKISPP_NR + 0x01AC)
#define RKISPP_NR_YNR_HMAX_ADJUST (RKISPP_NR + 0x01B0)
#define RKISPP_NR_YNR_HSTRENGTH (RKISPP_NR + 0x01B4)
#define RKISPP_NR_YNR_LWEIT_CMP (RKISPP_NR + 0x01B8)
#define RKISPP_NR_YNR_LMAXGAIN_LV4 (RKISPP_NR + 0x01BC)
#define RKISPP_NR_YNR_HSTV_Y_0_1 (RKISPP_NR + 0x01C0)
#define RKISPP_NR_YNR_HSTV_Y_2_3 (RKISPP_NR + 0x01C4)
#define RKISPP_NR_YNR_HSTV_Y_4_5 (RKISPP_NR + 0x01C8)
#define RKISPP_NR_YNR_HSTV_Y_6_7 (RKISPP_NR + 0x01CC)
#define RKISPP_NR_YNR_HSTV_Y_8_9 (RKISPP_NR + 0x01D0)
#define RKISPP_NR_YNR_HSTV_Y_10_11 (RKISPP_NR + 0x01D4)
#define RKISPP_NR_YNR_HSTV_Y_12_13 (RKISPP_NR + 0x01D8)
#define RKISPP_NR_YNR_HSTV_Y_14_15 (RKISPP_NR + 0x01DC)
#define RKISPP_NR_YNR_HSTV_Y_16 (RKISPP_NR + 0x01E0)
#define RKISPP_NR_YNR_ST_SCALE_LV1_LV2 (RKISPP_NR + 0x01E4)
#define RKISPP_NR_YNR_ST_SCALE_LV3 (RKISPP_NR + 0x01E8)
#define RKISPP_SHARP 0x0600
#define RKISPP_SHARP_CTRL (RKISPP_SHARP + 0x0000)
#define RKISPP_SHARP_WR_VIR_STRIDE (RKISPP_SHARP + 0x0004)
#define RKISPP_SHARP_WR_Y_BASE (RKISPP_SHARP + 0x0008)
#define RKISPP_SHARP_WR_UV_BASE (RKISPP_SHARP + 0x000C)
#define RKISPP_SHARP_SC_DOWN (RKISPP_SHARP + 0x0010)
#define RKISPP_SHARP_TMP_YUV_BASE (RKISPP_SHARP + 0x0014)
#define RKISPP_SHARP_WR_Y_BASE_SHD (RKISPP_SHARP + 0x0024)
#define RKISPP_SHARP_WR_UV_BASE_SHD (RKISPP_SHARP + 0x0028)
#define RKISPP_SHARP_CORE_CTRL (RKISPP_SHARP + 0x0080)
#define RKISPP_SHARP_HBF_FACTOR (RKISPP_SHARP + 0x0084)
#define RKISPP_SHARP_EDGE_TH (RKISPP_SHARP + 0x0088)
#define RKISPP_SHARP_EDGE_ALPHA (RKISPP_SHARP + 0x008C)
#define RKISPP_SHARP_PBF_KERNEL (RKISPP_SHARP + 0x0090)
#define RKISPP_SHARP_MRF_KERNEL0 (RKISPP_SHARP + 0x0094)
#define RKISPP_SHARP_MRF_KERNEL1 (RKISPP_SHARP + 0x0098)
#define RKISPP_SHARP_MBF_KERNEL0 (RKISPP_SHARP + 0x009C)
#define RKISPP_SHARP_MBF_KERNEL1 (RKISPP_SHARP + 0x00A0)
#define RKISPP_SHARP_MBF_KERNEL2 (RKISPP_SHARP + 0x00A4)
#define RKISPP_SHARP_HRF_KERNEL0 (RKISPP_SHARP + 0x00A8)
#define RKISPP_SHARP_HRF_KERNEL1 (RKISPP_SHARP + 0x00AC)
#define RKISPP_SHARP_HBF_KERNEL (RKISPP_SHARP + 0x00B0)
#define RKISPP_SHARP_EDGE_COEF (RKISPP_SHARP + 0x00B4)
#define RKISPP_SHARP_EDGE_SMOTH (RKISPP_SHARP + 0x00B8)
#define RKISPP_SHARP_EDGE_GAUS0 (RKISPP_SHARP + 0x00BC)
#define RKISPP_SHARP_EDGE_GAUS1 (RKISPP_SHARP + 0x00C0)
#define RKISPP_SHARP_DOG_KERNEL0 (RKISPP_SHARP + 0x00C4)
#define RKISPP_SHARP_DOG_KERNEL1 (RKISPP_SHARP + 0x00C8)
#define RKISPP_SHARP_LUM_POINT0 (RKISPP_SHARP + 0x00CC)
#define RKISPP_SHARP_LUM_POINT1 (RKISPP_SHARP + 0x00D0)
#define RKISPP_SHARP_SHF_BITS (RKISPP_SHARP + 0x00D4)
#define RKISPP_SHARP_PBF_SIGMA_INV0 (RKISPP_SHARP + 0x00D8)
#define RKISPP_SHARP_PBF_SIGMA_INV1 (RKISPP_SHARP + 0x00DC)
#define RKISPP_SHARP_LUM_CLP_M0 (RKISPP_SHARP + 0x00E0)
#define RKISPP_SHARP_LUM_CLP_M1 (RKISPP_SHARP + 0x00E4)
#define RKISPP_SHARP_LUM_MIN_M0 (RKISPP_SHARP + 0x00E8)
#define RKISPP_SHARP_LUM_MIN_M1 (RKISPP_SHARP + 0x00EC)
#define RKISPP_SHARP_MBF_SIGMA_INV0 (RKISPP_SHARP + 0x00F0)
#define RKISPP_SHARP_MBF_SIGMA_INV1 (RKISPP_SHARP + 0x00F4)
#define RKISPP_SHARP_LUM_CLP_H0 (RKISPP_SHARP + 0x00F8)
#define RKISPP_SHARP_LUM_CLP_H1 (RKISPP_SHARP + 0x00FC)
#define RKISPP_SHARP_HBF_SIGMA_INV0 (RKISPP_SHARP + 0x0100)
#define RKISPP_SHARP_HBF_SIGMA_INV1 (RKISPP_SHARP + 0x0104)
#define RKISPP_SHARP_EDGE_LUM_THED0 (RKISPP_SHARP + 0x0108)
#define RKISPP_SHARP_EDGE_LUM_THED1 (RKISPP_SHARP + 0x010C)
#define RKISPP_SHARP_CLAMP_POS_DOG0 (RKISPP_SHARP + 0x0110)
#define RKISPP_SHARP_CLAMP_POS_DOG1 (RKISPP_SHARP + 0x0114)
#define RKISPP_SHARP_CLAMP_NEG_DOG0 (RKISPP_SHARP + 0x0118)
#define RKISPP_SHARP_CLAMP_NEG_DOG1 (RKISPP_SHARP + 0x011C)
#define RKISPP_SHARP_DETAIL_ALPHA_DOG0 (RKISPP_SHARP + 0x0120)
#define RKISPP_SHARP_DETAIL_ALPHA_DOG1 (RKISPP_SHARP + 0x0124)
#define RKISPP_SHARP_RF_RATIO (RKISPP_SHARP + 0x0128)
#define RKISPP_SHARP_GRAD_RATIO (RKISPP_SHARP + 0x012C)
#define RKISPP_SCL0 0x0800
#define RKISPP_SCL0_CTRL (RKISPP_SCL0 + 0x0000)
#define RKISPP_SCL0_CUR_VIR_STRIDE (RKISPP_SCL0 + 0x0004)
#define RKISPP_SCL0_CUR_Y_BASE (RKISPP_SCL0 + 0x0008)
#define RKISPP_SCL0_CUR_UV_BASE (RKISPP_SCL0 + 0x000C)
#define RKISPP_SCL0_CUR_Y_BASE_SHD (RKISPP_SCL0 + 0x0010)
#define RKISPP_SCL0_CUR_UV_BASE_SHD (RKISPP_SCL0 + 0x0014)
#define RKISPP_SCL0_FACTOR (RKISPP_SCL0 + 0x0018)
#define RKISPP_SCL1 0x0900
#define RKISPP_SCL1_CTRL (RKISPP_SCL1 + 0x0000)
#define RKISPP_SCL1_CUR_VIR_STRIDE (RKISPP_SCL1 + 0x0004)
#define RKISPP_SCL1_CUR_Y_BASE (RKISPP_SCL1 + 0x0008)
#define RKISPP_SCL1_CUR_UV_BASE (RKISPP_SCL1 + 0x000C)
#define RKISPP_SCL1_CUR_Y_BASE_SHD (RKISPP_SCL1 + 0x0010)
#define RKISPP_SCL1_CUR_UV_BASE_SHD (RKISPP_SCL1 + 0x0014)
#define RKISPP_SCL1_FACTOR (RKISPP_SCL1 + 0x0018)
#define RKISPP_SCL2 0x0A00
#define RKISPP_SCL2_CTRL (RKISPP_SCL2 + 0x0000)
#define RKISPP_SCL2_CUR_VIR_STRIDE (RKISPP_SCL2 + 0x0004)
#define RKISPP_SCL2_CUR_Y_BASE (RKISPP_SCL2 + 0x0008)
#define RKISPP_SCL2_CUR_UV_BASE (RKISPP_SCL2 + 0x000C)
#define RKISPP_SCL2_CUR_Y_BASE_SHD (RKISPP_SCL2 + 0x0010)
#define RKISPP_SCL2_CUR_UV_BASE_SHD (RKISPP_SCL2 + 0x0014)
#define RKISPP_SCL2_FACTOR (RKISPP_SCL2 + 0x0018)
#define RKISPP_FEC 0x0C00
#define RKISPP_FEC_CTRL (RKISPP_FEC + 0x0000)
#define RKISPP_FEC_RD_VIR_STRIDE (RKISPP_FEC + 0x0004)
#define RKISPP_FEC_RD_Y_BASE (RKISPP_FEC + 0x0008)
#define RKISPP_FEC_RD_UV_BASE (RKISPP_FEC + 0x000C)
#define RKISPP_FEC_MESH_XINT_BASE (RKISPP_FEC + 0x0010)
#define RKISPP_FEC_MESH_XFRA_BASE (RKISPP_FEC + 0x0014)
#define RKISPP_FEC_MESH_YINT_BASE (RKISPP_FEC + 0x0018)
#define RKISPP_FEC_MESH_YFRA_BASE (RKISPP_FEC + 0x001C)
#define RKISPP_FEC_WR_VIR_STRIDE (RKISPP_FEC + 0x0020)
#define RKISPP_FEC_WR_Y_BASE (RKISPP_FEC + 0x0024)
#define RKISPP_FEC_WR_UV_BASE (RKISPP_FEC + 0x0028)
#define RKISPP_FEC_RD_Y_BASE_SHD (RKISPP_FEC + 0x002C)
#define RKISPP_FEC_RD_UV_BASE_SHD (RKISPP_FEC + 0x0030)
#define RKISPP_FEC_MESH_XINT_BASE_SHD (RKISPP_FEC + 0x0034)
#define RKISPP_FEC_MESH_XFRA_BASE_SHD (RKISPP_FEC + 0x0038)
#define RKISPP_FEC_MESH_YINT_BASE_SHD (RKISPP_FEC + 0x003C)
#define RKISPP_FEC_MESH_YFRA_BASE_SHD (RKISPP_FEC + 0x0040)
#define RKISPP_FEC_WR_Y_BASE_SHD (RKISPP_FEC + 0x0044)
#define RKISPP_FEC_WR_UV_BASE_SHD (RKISPP_FEC + 0x0048)
#define RKISPP_FEC_CORE_CTRL (RKISPP_FEC + 0x0080)
#define RKISPP_FEC_PIC_SIZE (RKISPP_FEC + 0x0088)
#define RKISPP_FEC_MESH_SIZE (RKISPP_FEC + 0x008C)
#define RKISPP_FEC_DMA_STATUS (RKISPP_FEC + 0x0090)
#define RKISPP_FEC_CROP (RKISPP_FEC + 0x0094)
#define FMT_WR_MASK GENMASK(7, 5)
#define FMT_RD_MASK GENMASK(3, 1)
#define FMT_YC_SWAP BIT(3)
#define FMT_YUYV BIT(2)
#define FMT_YUV422 BIT(1)
#define FMT_YUV420 0
/* ISPP_STRT */
#define FEC_ST BIT(2)
#define NR_SHP_ST BIT(1)
#define TNR_ST BIT(0)
/* ISPP_UPDATE */
#define ALL_FORCE_UPD (FEC_FORCE_UPD | TNR_FORCE_UPD | OTHER_FORCE_UPD)
#define FEC_FORCE_UPD BIT(2)
#define TNR_FORCE_UPD BIT(1)
#define OTHER_FORCE_UPD BIT(0)
/* ISPP_CTRL_QUICK */
#define GLB_QUICK_MODE_MASK GENMASK(9, 8)
#define GLB_FEC2SCL_EN BIT(11)
#define GLB_NR_SD32_TNR BIT(10)
#define GLB_QUICK_MODE(a) (((a) & 0x3) << 8)
#define GLB_QUICK_EN BIT(0)
/* ISPP_CTRL_RESET */
#define FBCD_ERR_PROTECT_DIS BIT(12)
#define GLB_SOFT_RST_SCL BIT(11)
#define GLB_SOFT_RST_SHP BIT(10)
#define GLB_SOFT_RST_NR BIT(9)
#define GLB_SOFT_RST_TNR BIT(8)
#define RST_PROTECT_DIS BIT(1)
#define GLB_SOFT_RST_ALL BIT(0)
/* INT_MASK INT_RAW_STA INT_STA INT_SET INT_CLR */
#define INT_FRAME(stream) \
((stream)->config->frame_end_id)
#define NR_LOST_ERR BIT(26)
#define TNR_LOST_ERR BIT(25)
#define UVNR_MONITOR_ERR BIT(24)
#define FBCH_EMPTY_NR BIT(23)
#define FBCH_EMPTY_TNR BIT(22)
#define FBCD_DEC_ERR_NR BIT(21)
#define FBCD_DEC_ERR_TNR BIT(20)
#define BUS_ERR_NR BIT(17)
#define BUS_ERR_TNR BIT(16)
#define CMD_NR_SHP_ST_DONE BIT(12)
#define CMD_TNR_ST_DONE BIT(11)
#define SCL2_INT BIT(10)
#define SCL1_INT BIT(9)
#define SCL0_INT BIT(8)
#define FEC_INT BIT(7)
#define ORB_INT BIT(6)
#define SHP_INT BIT(4)
#define NR_INT BIT(3)
#define TNR_INT BIT(2)
#define FRAME_INT BIT(1)
#define QUICK_INT BIT(0)
/* TNR CTRL */
#define SW_TNR_WR_FORMAT_MASK GENMASK(7, 5)
#define SW_TNR_RD_FORMAT_MASK GENMASK(3, 1)
#define SW_TNR_THROUGH_MODE BIT(10)
#define SW_TNR_1ST_FRM BIT(9)
#define SW_TNR_RD_PINGPONG2TO1 BIT(8)
#define SW_TNR_WR_YUYV_YCSWAP BIT(7)
#define SW_TNR_WR_YUYV_FORMAT BIT(6)
#define SW_TNR_WR_YUV_FORMAT BIT(5)
#define SW_TNR_WR_FBCE_MODE BIT(4)
#define SW_TNR_RD_YUYV_YCSWAP BIT(3)
#define SW_TNR_RD_YUYV_FORMAT BIT(2)
#define SW_TNR_RD_YUV_FORMAT BIT(1)
#define SW_TNR_FBCD_MODE BIT(0)
/* CORE_CTRL */
#define SW_TNR_GLB_GAIN_EN_SHD BIT(28)
#define SW_TNR_OPTC_EN_SHD BIT(27)
#define SW_TNR_OPTY_EN_SHD BIT(26)
#define SW_TNR_MODE_SHD BIT(25)
#define SW_TNR_EN_SHD BIT(24)
#define SW_TNR_GLB_GAIN_EN BIT(4)
#define SW_TNR_OPTC_EN BIT(3)
#define SW_TNR_OPTY_EN BIT(2)
#define SW_TNR_MODE BIT(1)
#define SW_TNR_EN BIT(0)
/* NR CTRL */
#define SW_NR_RD_FBCD_READ_MODE BIT(31)
#define SW_NR_NEW_ALGORITHM BIT(16)
#define SW_UVNR_1ST_FRM_SELF_MODE BIT(10)
#define SW_UVNR_1ST_FRM_SELF BIT(9)
#define SW_NR_RD_YUYV_YCSWAP BIT(3)
#define SW_NR_RD_YUYV_FORMAT BIT(2)
#define SW_NR_RD_YUV_FORMAT BIT(1)
#define SW_NR_RD_FBCD_MODE BIT(0)
/* NR_CTRL_PARA */
#define SW_UVNR_BIG_EN BIT(6)
#define SW_UVNR_NOBIG_EN BIT(5)
#define SW_UVNR_SD32_SELF_EN BIT(4)
#define SW_NR_GAIN_BYPASS BIT(3)
#define SW_UVNR_STEP2_ON BIT(2)
#define SW_UVNR_STEP1_ON BIT(1)
#define SW_NR_EN BIT(0)
/* SHP CTRL*/
#define SW_SHP_WR_FORMAT_MASK GENMASK(3, 1)
#define SW_SHP_WR_ROT_MODE(a) (((a) & 0x3) << 5)
#define SW_SHP_WR_YUV_LIMIT BIT(4)
#define SW_SHP_WR_YUYV_YCSWAP BIT(3)
#define SW_SHP_WR_YUYV_FORMAT BIT(2)
#define SW_SHP_WR_YUY_FORMAT BIT(1)
#define SW_SHP_WR_FBCE_MODE BIT(0)
/* CORE_CTRL */
#define SW_SHP_EDGE_AVG_EN BIT(4)
#define SW_SHP_YIN_FLT_EN BIT(3)
#define SW_SHP_DMA_DIS BIT(2)
#define SW_SHP_ALPHA_ADP_EN BIT(1)
#define SW_SHP_EN BIT(0)
/* SCL_CTRL */
#define SW_SCL_BYPASS_SHD BIT(31)
#define SW_SCL_ENABLE_SHD BIT(30)
#define SW_SCL_RAM_CLK_ON BIT(8)
#define SW_SCL_WR_YUV_LIMIT BIT(7)
#define SW_SCL_WR_YUYV_YCSWAP BIT(6)
#define SW_SCL_WR_YUYV_FORMAT BIT(5)
#define SW_SCL_WR_YUV_FORMAT BIT(4)
#define SW_SCL_WR_UV_DIS BIT(3)
#define SW_SCL_FIRST_MODE BIT(2)
#define SW_SCL_BYPASS BIT(1)
#define SW_SCL_ENABLE BIT(0)
/* FEC_CTRL*/
#define SW_FEC_WR_YUV_LIMIT BIT(8)
#define SW_FEC_WR_YUYV_YC_SWAP BIT(7)
#define SW_FEC_WR_YUYV_FORMAT BIT(6)
#define SW_FEC_WR_YUV_FORMAT BIT(5)
#define SW_FEC_WR_FBCE_MODE BIT(4)
#define SW_FEC_RD_YUYV_YCSWAP BIT(3)
#define SW_FEC_RD_YUYV_FORMAT BIT(2)
#define SW_FEC_RD_YUV_FORMAT BIT(1)
/* FEC_CORE_CTRL */
#define SW_FEC_EN_SHD BIT(31)
#define SW_MINBUF_NON_UPDATE_SHD BIT(30)
#define SW_MINBUF_NON_UPDATE BIT(6)
#define SW_MESH_DDENSITY BIT(5)
#define SW_FEC2DDR_DIS BIT(1)
#define SW_FEC_EN BIT(0)
static inline void rkispp_soft_reset(void __iomem *base)
{
writel(GLB_SOFT_RST_ALL, base + RKISPP_CTRL_RESET);
}
static inline void set_y_addr(struct rkispp_stream *stream, u32 val)
{
void __iomem *base = stream->isppdev->base_addr;
writel(val, base + stream->config->reg.cur_y_base);
}
static inline void set_uv_addr(struct rkispp_stream *stream, u32 val)
{
void __iomem *base = stream->isppdev->base_addr;
writel(val, base + stream->config->reg.cur_uv_base);
}
static inline void set_vir_stride(struct rkispp_stream *stream, u32 val)
{
void __iomem *base = stream->isppdev->base_addr;
writel(val, base + stream->config->reg.cur_vir_stride);
}
static inline void set_scl_factor(struct rkispp_stream *stream, u32 val)
{
void __iomem *base = stream->isppdev->base_addr;
writel(val, base + stream->config->reg.factor);
}
static inline void set_ctrl(struct rkispp_stream *stream, u32 val)
{
void __iomem *base = stream->isppdev->base_addr;
writel(val, base + stream->config->reg.ctrl);
}
#endif /* _RKISPP_REGS_H */

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,143 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_STREAM_H
#define _RKISPP_STREAM_H
#include "common.h"
struct rkispp_stream;
/*
* STREAM_II: input image data
* STREAM_MB: module bypass output, no scale
* STREAM_S0: scale0 output
* STREAM_S1: scale1 output
* STREAM_S2: scale2 output
*/
enum rkispp_stream_id {
STREAM_II = 0,
STREAM_MB,
STREAM_S0,
STREAM_S1,
STREAM_S2,
STREAM_MAX
};
/*
* fourcc: pixel format
* cplanes: number of colour planes
* mplanes: number of stored memory planes
* wr_fmt: defines format for reg
* bpp: bits per pixel
*/
struct capture_fmt {
u32 fourcc;
u8 cplanes;
u8 mplanes;
u8 wr_fmt;
u8 bpp[VIDEO_MAX_PLANES];
};
/* Different config for stream */
struct stream_config {
const struct capture_fmt *fmts;
unsigned int fmt_size;
u32 frame_end_id;
/* registers */
struct {
u32 ctrl;
u32 factor;
u32 cur_y_base;
u32 cur_uv_base;
u32 cur_vir_stride;
u32 cur_y_base_shd;
u32 cur_uv_base_shd;
} reg;
};
/* Different reg ops for stream */
struct streams_ops {
int (*config)(struct rkispp_stream *stream);
void (*update)(struct rkispp_stream *stream);
void (*stop)(struct rkispp_stream *stream);
int (*start)(struct rkispp_stream *stream);
int (*is_stopped)(struct rkispp_stream *stream);
};
/* stream input/out flag */
enum stream_type {
STREAM_INPUT,
STREAM_OUTPUT,
};
/* tnr internal using buf */
struct in_tnr_buf {
struct rkispp_dummy_buffer pic_cur;
struct rkispp_dummy_buffer pic_next;
struct rkispp_dummy_buffer gain_cur;
struct rkispp_dummy_buffer gain_next;
struct rkispp_dummy_buffer gain_kg;
struct rkispp_dummy_buffer iir;
struct rkispp_dummy_buffer pic_wr;
struct rkispp_dummy_buffer gain_wr;
};
/* nr internal using buf */
struct in_nr_buf {
struct rkispp_dummy_buffer pic_cur;
struct rkispp_dummy_buffer gain_cur;
struct rkispp_dummy_buffer pic_wr;
struct rkispp_dummy_buffer tmp_yuv;
};
/* struct rkispp_stream - ISPP stream video device
* id: stream video identify
* buf_queue: queued buffer list
* curr_buf: the buffer used for current frame
* next_buf: the buffer used for next frame
* dummy_buf: dummy space to store dropped data
* done: wait frame end event queue
* vbq_lock: lock to protect buf_queue
* out_cap_fmt: the output of ispp
* out_fmt: the output of v4l2 pix format
* last_module: last function module
* streaming: stream start flag
* stopping: stream stop flag
* linked: link enable flag
*/
struct rkispp_stream {
enum rkispp_stream_id id;
struct rkispp_device *isppdev;
struct rkispp_vdev_node vnode;
struct list_head buf_queue;
struct rkispp_buffer *curr_buf;
struct rkispp_buffer *next_buf;
struct rkispp_dummy_buffer dummy_buf;
wait_queue_head_t done;
spinlock_t vbq_lock;
enum stream_type type;
struct streams_ops *ops;
struct stream_config *config;
struct capture_fmt out_cap_fmt;
struct v4l2_pix_format_mplane out_fmt;
u8 last_module;
u8 streaming;
u8 stopping;
u8 linked;
};
/* rkispp stream device */
struct rkispp_stream_vdev {
struct rkispp_stream stream[STREAM_MAX];
struct in_tnr_buf tnr_buf;
struct in_nr_buf nr_buf;
atomic_t refcnt;
};
void rkispp_isr(u32 mis_val, struct rkispp_device *dev);
void rkispp_unregister_stream_vdevs(struct rkispp_device *dev);
int rkispp_register_stream_vdevs(struct rkispp_device *dev);
#endif

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2019 Fuzhou Rockchip Electronics Co., Ltd. */
#ifndef _RKISPP_VERSION_H
#define _RKISPP_VERSION_H
#include <linux/version.h>
/*
* RKISPP DRIVER VERSION NOTE
*
* v0.1.0:
* 1. First version;
*/
#define RKISPP_DRIVER_VERSION KERNEL_VERSION(0, 1, 0x0)
#endif

View File

@@ -0,0 +1,254 @@
/* SPDX-License-Identifier: (GPL-2.0+ OR MIT)
*
* Copyright (C) 2019 Rockchip Electronics Co., Ltd.
*/
#ifndef _UAPI_RKISPP_CONFIG_H
#define _UAPI_RKISPP_CONFIG_H
#include <linux/types.h>
#include <linux/v4l2-controls.h>
#define ISPP_MODULE_TNR BIT(0)
#define ISPP_MODULE_NR BIT(1)
#define ISPP_MODULE_SHP BIT(2)
#define ISPP_MODULE_FEC BIT(3)
#define TNR_SIGMA_CURVE_SIZE 17
#define TNR_LUMA_CURVE_SIZE 6
#define TNR_GFCOEF5_SIZE 6
#define TNR_GFCOEF3_SIZE 3
#define TNR_SCALE_YG_SIZE 4
#define TNR_SCALE_YL_SIZE 3
#define TNR_SCALE_CG_SIZE 3
#define TNR_SCALE_Y2CG_SIZE 3
#define TNR_SCALE_CL_SIZE 2
#define TNR_SCALE_Y2CL_SIZE 3
#define TNR_WEIGHT_Y_SIZE 3
#define NR_UVNR_UVGAIN_SIZE 2
#define NR_UVNR_T1FLT_WTQ_SIZE 8
#define NR_UVNR_T2GEN_WTQ_SIZE 4
#define NR_UVNR_T2FLT_WT_SIZE 3
#define NR_YNR_SGM_DX_SIZE 16
#define NR_YNR_SGM_Y_SIZE 17
#define NR_YNR_HWEIT_D_SIZE 20
#define NR_YNR_HGRAD_Y_SIZE 24
#define NR_YNR_HSTV_Y_SIZE 17
#define NR_YNR_CI_SIZE 4
#define NR_YNR_LGAIN_MIN_SIZE 4
#define NR_YNR_LWEIT_FLT_SIZE 4
#define NR_YNR_HGAIN_SGM_SIZE 4
#define NR_YNR_HWEIT_SIZE 4
#define NR_YNR_LWEIT_CMP_SIZE 2
#define NR_YNR_ST_SCALE_SIZE 3
#define SHP_PBF_KERNEL_SIZE 3
#define SHP_MRF_KERNEL_SIZE 6
#define SHP_MBF_KERNEL_SIZE 12
#define SHP_HRF_KERNEL_SIZE 6
#define SHP_HBF_KERNEL_SIZE 3
#define SHP_EDGE_COEF_SIZE 3
#define SHP_EDGE_SMOTH_SIZE 3
#define SHP_EDGE_GAUS_SIZE 6
#define SHP_DOG_KERNEL_SIZE 6
#define SHP_LUM_POINT_SIZE 6
#define SHP_SIGMA_SIZE 8
#define SHP_LUM_CLP_SIZE 8
#define SHP_LUM_MIN_SIZE 8
#define SHP_EDGE_LUM_THED_SIZE 8
#define SHP_CLAMP_SIZE 8
#define SHP_DETAIL_ALPHA_SIZE 8
struct tnr_sigma_curve {
u8 x;
u16 y;
} __attribute__ ((packed));
struct rkispp_tnr_config {
u8 en;
u8 opty_en;
u8 optc_en;
u8 gain_en;
u8 pk0_y;
u8 pk1_y;
u8 pk0_c;
u8 pk1_c;
u16 glb_gain_cur;
u16 glb_gain_nxt;
u16 glb_gain_cur_div;
u8 glb_gain_cur_sqrt;
struct tnr_sigma_curve sigma_curve[TNR_SIGMA_CURVE_SIZE];
u16 luma_curve[TNR_LUMA_CURVE_SIZE];
u16 txt_th0_y;
u16 txt_th1_y;
u16 txt_th0_c;
u16 txt_th1_c;
u16 txt_thy_dlt;
u16 txt_thc_dlt;
u8 gfcoef_y0[TNR_GFCOEF5_SIZE];
u8 gfcoef_y1[TNR_GFCOEF3_SIZE];
u8 gfcoef_y2[TNR_GFCOEF5_SIZE];
u8 gfcoef_y3[TNR_GFCOEF3_SIZE];
u8 gfcoef_yg0[TNR_GFCOEF5_SIZE];
u8 gfcoef_yg1[TNR_GFCOEF3_SIZE];
u8 gfcoef_yg2[TNR_GFCOEF3_SIZE];
u8 gfcoef_yg3[TNR_GFCOEF3_SIZE];
u8 gfcoef_yl0[TNR_GFCOEF5_SIZE];
u8 gfcoef_yl1[TNR_GFCOEF3_SIZE];
u8 gfcoef_yl2[TNR_GFCOEF3_SIZE];
u8 gfcoef_cg0[TNR_GFCOEF5_SIZE];
u8 gfcoef_cg1[TNR_GFCOEF3_SIZE];
u8 gfcoef_cg2[TNR_GFCOEF3_SIZE];
u8 gfcoef_cl0[TNR_GFCOEF5_SIZE];
u8 gfcoef_cl1[TNR_GFCOEF3_SIZE];
u16 scale_yg[TNR_SCALE_YG_SIZE];
u16 scale_yl[TNR_SCALE_YL_SIZE];
u16 scale_cg[TNR_SCALE_CG_SIZE];
u16 scale_y2cg[TNR_SCALE_Y2CG_SIZE];
u16 scale_cl[TNR_SCALE_CL_SIZE];
u16 scale_y2cl[TNR_SCALE_Y2CL_SIZE];
u8 weight_y[TNR_WEIGHT_Y_SIZE];
} __attribute__ ((packed));
struct rkispp_nr_config {
u8 nr_en;
u8 uvnr_step1_en;
u8 uvnr_step2_en;
u8 nr_gain_en;
u8 uvnr_nobig_en;
u8 uvnr_big_en;
u8 uvnr_gain_1sigma;
u8 uvnr_gain_offset;
u8 uvnr_gain_uvgain[NR_UVNR_UVGAIN_SIZE];
u8 uvnr_gain_t2gen;
u8 uvnr_gain_iso;
u8 uvnr_t1gen_m3alpha;
u8 uvnr_t1flt_mode;
u16 uvnr_t1flt_msigma;
u8 uvnr_t1flt_wtp;
u8 uvnr_t1flt_wtq[NR_UVNR_T1FLT_WTQ_SIZE];
u8 uvnr_t2gen_m3alpha;
u16 uvnr_t2gen_msigma;
u8 uvnr_t2gen_wtp;
u8 uvnr_t2gen_wtq[NR_UVNR_T2GEN_WTQ_SIZE];
u16 uvnr_t2flt_msigma;
u8 uvnr_t2flt_wtp;
u8 uvnr_t2flt_wt[NR_UVNR_T2FLT_WT_SIZE];
u8 ynr_sgm_dx[NR_YNR_SGM_DX_SIZE];
u16 ynr_lsgm_y[NR_YNR_SGM_Y_SIZE];
u8 ynr_lci[NR_YNR_CI_SIZE];
u8 ynr_lgain_min[NR_YNR_LGAIN_MIN_SIZE];
u8 ynr_lgain_max;
u8 ynr_lmerge_bound;
u8 ynr_lmerge_ratio;
u8 ynr_lweit_flt[NR_YNR_LWEIT_FLT_SIZE];
u16 ynr_hsgm_y[NR_YNR_SGM_Y_SIZE];
u8 ynr_hlci[NR_YNR_CI_SIZE];
u8 ynr_lhci[NR_YNR_CI_SIZE];
u8 ynr_hhci[NR_YNR_CI_SIZE];
u8 ynr_hgain_sgm[NR_YNR_HGAIN_SGM_SIZE];
u8 ynr_hweit_d[NR_YNR_HWEIT_D_SIZE];
u8 ynr_hgrad_y[NR_YNR_HGRAD_Y_SIZE];
u16 ynr_hweit[NR_YNR_HWEIT_SIZE];
u8 ynr_hmax_adjust;
u8 ynr_hstrength;
u8 ynr_lweit_cmp[NR_YNR_LWEIT_CMP_SIZE];
u8 ynr_lmaxgain_lv4;
u16 ynr_hstv_y[NR_YNR_HSTV_Y_SIZE];
u16 ynr_st_scale[NR_YNR_ST_SCALE_SIZE];
} __attribute__ ((packed));
struct rkispp_sharp_config {
u8 en;
u8 alpha_adp_en;
u8 yin_flt_en;
u8 edge_avg_en;
u16 hbf_ratio;
u8 ehf_th;
u8 pbf_ratio;
u8 edge_thed;
u8 dir_min;
u8 smoth_th4;
u16 l_alpha;
u16 g_alpha;
u8 pbf_k[SHP_PBF_KERNEL_SIZE];
u8 mrf_k[SHP_MRF_KERNEL_SIZE];
u8 mbf_k[SHP_MBF_KERNEL_SIZE];
u8 hrf_k[SHP_HRF_KERNEL_SIZE];
u8 hbf_k[SHP_HBF_KERNEL_SIZE];
u8 eg_coef[SHP_EDGE_COEF_SIZE];
u8 eg_smoth[SHP_EDGE_SMOTH_SIZE];
u8 eg_gaus[SHP_EDGE_GAUS_SIZE];
u8 dog_k[SHP_DOG_KERNEL_SIZE];
u8 lum_point[SHP_LUM_POINT_SIZE];
u8 pbf_shf_bits;
u8 mbf_shf_bits;
u8 hbf_shf_bits;
u8 pbf_sigma[SHP_SIGMA_SIZE];
u8 lum_clp_m[SHP_LUM_CLP_SIZE];
u8 lum_min_m[SHP_LUM_MIN_SIZE];
u8 mbf_sigma[SHP_SIGMA_SIZE];
u8 lum_clp_h[SHP_LUM_CLP_SIZE];
u8 hbf_sigma[SHP_SIGMA_SIZE];
u8 edge_lum_thed[SHP_EDGE_LUM_THED_SIZE];
u8 clamp_pos[SHP_CLAMP_SIZE];
u8 clamp_neg[SHP_CLAMP_SIZE];
u8 detail_alpha[SHP_DETAIL_ALPHA_SIZE];
u16 rfl_ratio;
u16 rfh_ratio;
u8 m_ratio;
u8 h_ratio;
} __attribute__ ((packed));
struct rkispp_fec_config {
u8 en;
u8 mesh_density;
} __attribute__ ((packed));
/**
* struct rkispp_params_cfg - Rockchip ISPP Input Parameters Meta Data
*
* @module_en_update: mask the enable bits of which module should be updated
* @module_ens: mask the enable value of each module, only update the module
* which correspond bit was set in module_en_update
* @module_cfg_update: mask the config bits of which module should be updated
*/
struct rkispp_params_cfg {
unsigned int module_en_update;
unsigned int module_ens;
unsigned int module_cfg_update;
struct rkispp_tnr_config tnr_cfg;
struct rkispp_nr_config nr_cfg;
struct rkispp_sharp_config shp_cfg;
struct rkispp_fec_config fec_cfg;
} __attribute__ ((packed));
#endif

View File

@@ -722,6 +722,8 @@ struct v4l2_pix_format {
#define V4L2_META_FMT_RK_ISP1_PARAMS v4l2_fourcc('R', 'K', '1', 'P') /* Rockchip ISP1 params */
#define V4L2_META_FMT_RK_ISP1_STAT_3A v4l2_fourcc('R', 'K', '1', 'S') /* Rockchip ISP1 3A statistics */
#define V4L2_META_FMT_RK_ISPP_PARAMS v4l2_fourcc('R', 'K', 'P', 'P') /* Rockchip ISPP params */
/* priv field value to indicates that subsequent fields are valid. */
#define V4L2_PIX_FMT_PRIV_MAGIC 0xfeedcafe