mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-05 10:31:46 +09:00
media: rockchip: add aiisp driver
Signed-off-by: Hu Kejun <william.hu@rock-chips.com> Change-Id: I11459fd2862411528c1fce4eb6fdd174c42325d8
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
comment "Rockchip media platform drivers"
|
||||
|
||||
source "drivers/media/platform/rockchip/aiisp/Kconfig"
|
||||
source "drivers/media/platform/rockchip/cif/Kconfig"
|
||||
source "drivers/media/platform/rockchip/fec/Kconfig"
|
||||
source "drivers/media/platform/rockchip/flexbus_cif/Kconfig"
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
# SPDX-License-Identifier: GPL-2.0-only
|
||||
obj-y += aiisp/
|
||||
obj-y += cif/
|
||||
obj-y += fec/
|
||||
obj-y += flexbus_cif/
|
||||
|
||||
11
drivers/media/platform/rockchip/aiisp/Kconfig
Normal file
11
drivers/media/platform/rockchip/aiisp/Kconfig
Normal file
@@ -0,0 +1,11 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
config VIDEO_ROCKCHIP_AIISP
|
||||
tristate "Rockchip AIISP driver"
|
||||
depends on V4L_PLATFORM_DRIVERS
|
||||
depends on VIDEO_DEV
|
||||
depends on ARCH_ROCKCHIP || COMPILE_TEST
|
||||
select VIDEOBUF2_CMA_SG
|
||||
select V4L2_FWNODE
|
||||
default n
|
||||
help
|
||||
Support for AIISP on the rockchip SoC.
|
||||
4
drivers/media/platform/rockchip/aiisp/Makefile
Normal file
4
drivers/media/platform/rockchip/aiisp/Makefile
Normal file
@@ -0,0 +1,4 @@
|
||||
# SPDX-License-Identifier: GPL-2.0
|
||||
obj-$(CONFIG_VIDEO_ROCKCHIP_AIISP) += video_rkaiisp.o
|
||||
|
||||
video_rkaiisp-objs += hw.o dev.o aiisp.o
|
||||
1685
drivers/media/platform/rockchip/aiisp/aiisp.c
Normal file
1685
drivers/media/platform/rockchip/aiisp/aiisp.c
Normal file
File diff suppressed because it is too large
Load Diff
179
drivers/media/platform/rockchip/aiisp/aiisp.h
Normal file
179
drivers/media/platform/rockchip/aiisp/aiisp.h
Normal file
@@ -0,0 +1,179 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef _RKAIISP_DEV_H
|
||||
#define _RKAIISP_DEV_H
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/media.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/rk-video-format.h>
|
||||
#include <linux/rk-aiisp-config.h>
|
||||
#include <linux/slab.h>
|
||||
#include <linux/kfifo.h>
|
||||
#include <media/media-device.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/v4l2-mc.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <media/v4l2-common.h>
|
||||
#include <media/v4l2-ioctl.h>
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/v4l2-event.h>
|
||||
#include "hw.h"
|
||||
|
||||
#define DRIVER_NAME "rkaiisp"
|
||||
|
||||
#define RKAIISP_SUBDEV_NAME DRIVER_NAME "-subdev"
|
||||
#define RKAIISP_V4L2_EVENT_ELEMS 4
|
||||
|
||||
#define RKAIISP_MAX_CHANNEL 7
|
||||
#define RKAIISP_TMP_BUF_CNT 2
|
||||
#define RKAIISP_DEFAULT_MAXRUNCNT 8
|
||||
#define RKAIISP_DEFAULT_PARASIZE (16 * 1024)
|
||||
#define RKAIISP_SW_REG_SIZE 0x3000
|
||||
#define RKAIISP_SW_MAX_SIZE (RKAIISP_SW_REG_SIZE * 2)
|
||||
|
||||
enum rkaiisp_irqhdl_ret {
|
||||
NOT_WREND = (0 << 0),
|
||||
CONTINUE_RUN = (1 << 0),
|
||||
RUN_COMPLETE = (2 << 0)
|
||||
};
|
||||
|
||||
enum rkaiisp_hwstate {
|
||||
HW_STOP,
|
||||
HW_RUNNING
|
||||
};
|
||||
|
||||
struct rkaiisp_vdev_node {
|
||||
struct vb2_queue buf_queue;
|
||||
struct video_device vdev;
|
||||
struct media_pad pad;
|
||||
};
|
||||
|
||||
struct rkaiisp_buffer {
|
||||
struct vb2_v4l2_buffer vb;
|
||||
struct list_head queue;
|
||||
u32 buff_addr[VIDEO_MAX_PLANES];
|
||||
void *vaddr[VIDEO_MAX_PLANES];
|
||||
};
|
||||
|
||||
struct rkaiisp_dummy_buffer {
|
||||
struct vb2_buffer vb;
|
||||
struct vb2_queue vb2_queue;
|
||||
s32 dma_fd;
|
||||
struct dma_buf *dmabuf;
|
||||
struct dma_buf_attachment *dba;
|
||||
struct sg_table *sgt;
|
||||
dma_addr_t dma_addr;
|
||||
void *vaddr;
|
||||
u32 size;
|
||||
void *mem_priv;
|
||||
};
|
||||
|
||||
struct rkaiisp_buffer_size {
|
||||
u32 height;
|
||||
u32 width;
|
||||
u32 channel;
|
||||
u32 stride;
|
||||
};
|
||||
|
||||
struct rkaiiisp_subdev {
|
||||
struct v4l2_subdev sd;
|
||||
bool is_subs_evt;
|
||||
};
|
||||
|
||||
struct rkaiisp_device {
|
||||
char name[128];
|
||||
void *sw_base_addr;
|
||||
struct v4l2_device v4l2_dev;
|
||||
struct media_device media_dev;
|
||||
struct device *dev;
|
||||
|
||||
const struct vb2_mem_ops *mem_ops;
|
||||
spinlock_t config_lock;
|
||||
struct mutex apilock;
|
||||
wait_queue_head_t sync_onoff;
|
||||
|
||||
struct rkaiisp_hw_dev *hw_dev;
|
||||
bool is_hw_link;
|
||||
int dev_id;
|
||||
|
||||
struct rkaiiisp_subdev subdev;
|
||||
|
||||
struct rkaiisp_ispbuf_info ispbuf;
|
||||
struct rkaiisp_dummy_buffer iirbuf[RKISP_BUFFER_MAX];
|
||||
struct rkaiisp_dummy_buffer aiprebuf[RKISP_BUFFER_MAX];
|
||||
struct rkaiisp_dummy_buffer vpslbuf[RKISP_BUFFER_MAX];
|
||||
struct rkaiisp_dummy_buffer aiispbuf[RKISP_BUFFER_MAX];
|
||||
struct rkaiisp_dummy_buffer temp_buf[RKAIISP_TMP_BUF_CNT];
|
||||
u32 outbuf_idx;
|
||||
|
||||
struct kfifo idxbuf_kfifo;
|
||||
struct rkisp_aiisp_st curr_idxbuf;
|
||||
|
||||
struct rkaiisp_vdev_node vnode;
|
||||
struct list_head params;
|
||||
struct rkaiisp_buffer *cur_params;
|
||||
struct v4l2_format vdev_fmt;
|
||||
|
||||
struct rkaiisp_buffer_size outbuf_size[RKAIISP_MAX_RUNCNT];
|
||||
struct rkaiisp_buffer_size chn_size[RKAIISP_MAX_CHANNEL];
|
||||
enum rkaiisp_exemode exemode;
|
||||
enum rkaiisp_model_mode model_mode;
|
||||
enum rkaiisp_hwstate hwstate;
|
||||
u32 para_size;
|
||||
u32 max_runcnt;
|
||||
u32 model_runcnt;
|
||||
u32 run_idx;
|
||||
u32 frame_id;
|
||||
|
||||
bool streamon;
|
||||
bool showreg;
|
||||
};
|
||||
|
||||
extern int rkaiisp_debug;
|
||||
extern int rkaiisp_showreg;
|
||||
|
||||
static inline struct rkaiisp_buffer *to_rkaiisp_buffer(struct vb2_v4l2_buffer *vb)
|
||||
{
|
||||
return container_of(vb, struct rkaiisp_buffer, vb);
|
||||
}
|
||||
|
||||
static inline void rkaiisp_write(struct rkaiisp_device *aidev, u32 reg, u32 val, bool is_direct)
|
||||
{
|
||||
u32 *mem = aidev->sw_base_addr + reg;
|
||||
u32 *flag = aidev->sw_base_addr + reg + RKAIISP_SW_REG_SIZE;
|
||||
|
||||
*mem = val;
|
||||
*flag = SW_REG_CACHE;
|
||||
if (aidev->hw_dev->is_single || is_direct) {
|
||||
*flag = SW_REG_CACHE_SYNC;
|
||||
writel(val, aidev->hw_dev->base_addr + reg);
|
||||
}
|
||||
}
|
||||
|
||||
static inline u32 rkaiisp_read(struct rkaiisp_device *aidev, u32 reg, bool is_direct)
|
||||
{
|
||||
u32 val;
|
||||
|
||||
if (aidev->hw_dev->is_single || is_direct)
|
||||
val = readl(aidev->hw_dev->base_addr + reg);
|
||||
else
|
||||
val = *(u32 *)(aidev->sw_base_addr + reg);
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
extern struct platform_driver rkaiisp_plat_drv;
|
||||
int rkaiisp_queue_ispbuf(struct rkaiisp_device *aidev, struct rkisp_aiisp_st *idxbuf);
|
||||
void rkaiisp_update_list_reg(struct rkaiisp_device *aidev);
|
||||
void rkaiisp_trigger(struct rkaiisp_device *aidev);
|
||||
int rkaiisp_get_idxbuf_len(struct rkaiisp_device *aidev);
|
||||
enum rkaiisp_irqhdl_ret rkaiisp_irq_hdl(struct rkaiisp_device *aidev, u32 mi_mis);
|
||||
int rkaiisp_register_vdev(struct rkaiisp_device *aidev, struct v4l2_device *v4l2_dev);
|
||||
void rkaiisp_unregister_vdev(struct rkaiisp_device *aidev);
|
||||
|
||||
#endif
|
||||
236
drivers/media/platform/rockchip/aiisp/dev.c
Normal file
236
drivers/media/platform/rockchip/aiisp/dev.c
Normal file
@@ -0,0 +1,236 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.h>
|
||||
#include <linux/of_gpio.h>
|
||||
#include <linux/of_graph.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include <linux/of_reserved_mem.h>
|
||||
#include <linux/pm_runtime.h>
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <linux/nospec.h>
|
||||
#include "regs.h"
|
||||
#include "hw.h"
|
||||
#include "aiisp.h"
|
||||
#include "version.h"
|
||||
|
||||
#define RKAIISP_VERNO_LEN 10
|
||||
|
||||
int rkaiisp_debug;
|
||||
module_param_named(debug, rkaiisp_debug, int, 0644);
|
||||
MODULE_PARM_DESC(debug, "Debug level (0-1)");
|
||||
|
||||
int rkaiisp_showreg;
|
||||
module_param_named(showreg, rkaiisp_showreg, int, 0644);
|
||||
MODULE_PARM_DESC(showreg, "show register (0-1)");
|
||||
|
||||
static char rkaiisp_version[RKAIISP_VERNO_LEN];
|
||||
module_param_string(version, rkaiisp_version, RKAIISP_VERNO_LEN, 0444);
|
||||
MODULE_PARM_DESC(version, "version number");
|
||||
|
||||
/***************************** platform deive *******************************/
|
||||
static int rkaiisp_attach_hw(struct rkaiisp_device *aidev)
|
||||
{
|
||||
struct device_node *np;
|
||||
struct platform_device *pdev;
|
||||
struct rkaiisp_hw_dev *hw_dev;
|
||||
const char *name;
|
||||
int ret, dev_id = -1;
|
||||
|
||||
of_property_read_string(aidev->dev->of_node, "name", &name);
|
||||
if (name) {
|
||||
ret = sscanf(name, "rkaiisp-vir%d", &dev_id);
|
||||
if ((dev_id >= RKAIISP_DEV_MAX) || ret != 1) {
|
||||
dev_err(aidev->dev, "dev_id %d, failed attach aidev hw, max dev:%d\n",
|
||||
dev_id, RKAIISP_DEV_MAX);
|
||||
return -EINVAL;
|
||||
}
|
||||
}
|
||||
|
||||
np = of_parse_phandle(aidev->dev->of_node, "rockchip,hw", 0);
|
||||
if (!np || !of_device_is_available(np)) {
|
||||
dev_err(aidev->dev, "failed to get isp hw node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
pdev = of_find_device_by_node(np);
|
||||
of_node_put(np);
|
||||
if (!pdev) {
|
||||
dev_err(aidev->dev, "failed to get aidev hw from node\n");
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
hw_dev = platform_get_drvdata(pdev);
|
||||
if (!hw_dev) {
|
||||
dev_err(aidev->dev, "failed attach aidev hw\n");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&hw_dev->dev_mutex);
|
||||
if (hw_dev->dev_num >= RKAIISP_DEV_MAX) {
|
||||
dev_err(aidev->dev, "failed attach aidev hw, max dev:%d\n", RKAIISP_DEV_MAX);
|
||||
mutex_unlock(&hw_dev->dev_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (dev_id == -1)
|
||||
dev_id = hw_dev->dev_num;
|
||||
|
||||
if (dev_id >= 0 && dev_id < RKAIISP_DEV_MAX) {
|
||||
dev_id = array_index_nospec(dev_id, RKAIISP_DEV_MAX);
|
||||
dev_info(aidev->dev, "dev_id %d\n", dev_id);
|
||||
aidev->dev_id = dev_id;
|
||||
hw_dev->aidev[dev_id] = aidev;
|
||||
hw_dev->dev_num++;
|
||||
aidev->hw_dev = hw_dev;
|
||||
aidev->is_hw_link = true;
|
||||
}
|
||||
|
||||
hw_dev->is_single = (hw_dev->dev_num > 1) ? false : true;
|
||||
mutex_unlock(&hw_dev->dev_mutex);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int rkaiisp_plat_probe(struct platform_device *pdev)
|
||||
{
|
||||
struct device *dev = &pdev->dev;
|
||||
struct v4l2_device *v4l2_dev;
|
||||
struct rkaiisp_device *aidev;
|
||||
int ret;
|
||||
|
||||
snprintf(rkaiisp_version, sizeof(rkaiisp_version),
|
||||
"v%02x.%02x.%02x",
|
||||
RKAIISP_DRIVER_VERSION >> 16,
|
||||
(RKAIISP_DRIVER_VERSION & 0xff00) >> 8,
|
||||
RKAIISP_DRIVER_VERSION & 0x00ff);
|
||||
|
||||
dev_info(dev, "rkaiisp driver version: %s\n", rkaiisp_version);
|
||||
|
||||
aidev = devm_kzalloc(dev, sizeof(*aidev), GFP_KERNEL);
|
||||
if (!aidev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, aidev);
|
||||
aidev->dev = dev;
|
||||
ret = rkaiisp_attach_hw(aidev);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
aidev->sw_base_addr = devm_kzalloc(dev, RKAIISP_SW_MAX_SIZE, GFP_KERNEL);
|
||||
if (!aidev->sw_base_addr)
|
||||
return -ENOMEM;
|
||||
|
||||
snprintf(aidev->media_dev.model, sizeof(aidev->media_dev.model),
|
||||
"%s%d", DRIVER_NAME, aidev->dev_id);
|
||||
strscpy(aidev->name, dev_name(dev), sizeof(aidev->name));
|
||||
strscpy(aidev->media_dev.driver_name, aidev->name,
|
||||
sizeof(aidev->media_dev.driver_name));
|
||||
|
||||
mutex_init(&aidev->apilock);
|
||||
aidev->media_dev.dev = dev;
|
||||
|
||||
v4l2_dev = &aidev->v4l2_dev;
|
||||
v4l2_dev->mdev = &aidev->media_dev;
|
||||
strscpy(v4l2_dev->name, aidev->name, sizeof(v4l2_dev->name));
|
||||
|
||||
ret = v4l2_device_register(aidev->dev, &aidev->v4l2_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(v4l2_dev, "Failed to register v4l2 device:%d\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
media_device_init(&aidev->media_dev);
|
||||
ret = media_device_register(&aidev->media_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(v4l2_dev, "Failed to register media device:%d\n", ret);
|
||||
goto err_unreg_v4l2_dev;
|
||||
}
|
||||
|
||||
pm_runtime_enable(dev);
|
||||
ret = rkaiisp_register_vdev(aidev, &aidev->v4l2_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(v4l2_dev, "Failed to register platform subdevs:%d\n", ret);
|
||||
goto err_unreg_media_dev;
|
||||
}
|
||||
|
||||
v4l2_info(v4l2_dev, "probe end.\n");
|
||||
return 0;
|
||||
|
||||
err_unreg_media_dev:
|
||||
media_device_unregister(&aidev->media_dev);
|
||||
err_unreg_v4l2_dev:
|
||||
v4l2_device_unregister(&aidev->v4l2_dev);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rkaiisp_plat_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rkaiisp_device *aidev = platform_get_drvdata(pdev);
|
||||
|
||||
aidev->is_hw_link = false;
|
||||
aidev->hw_dev->aidev[aidev->dev_id] = NULL;
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
|
||||
media_device_unregister(&aidev->media_dev);
|
||||
v4l2_device_unregister(&aidev->v4l2_dev);
|
||||
rkaiisp_unregister_vdev(aidev);
|
||||
media_device_cleanup(&aidev->media_dev);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused rkaiisp_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct rkaiisp_device *aidev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&aidev->hw_dev->dev_mutex);
|
||||
ret = pm_runtime_put_sync(aidev->hw_dev->dev);
|
||||
mutex_unlock(&aidev->hw_dev->dev_mutex);
|
||||
return (ret > 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
static int __maybe_unused rkaiisp_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct rkaiisp_device *aidev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
mutex_lock(&aidev->hw_dev->dev_mutex);
|
||||
ret = pm_runtime_get_sync(aidev->hw_dev->dev);
|
||||
mutex_unlock(&aidev->hw_dev->dev_mutex);
|
||||
return (ret > 0) ? 0 : ret;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rkaiisp_plat_pm_ops = {
|
||||
SET_RUNTIME_PM_OPS(rkaiisp_runtime_suspend, rkaiisp_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static const struct of_device_id rkaiisp_plat_of_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,rkaiisp-vir",
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
struct platform_driver rkaiisp_plat_drv = {
|
||||
.driver = {
|
||||
.name = DRIVER_NAME,
|
||||
.of_match_table = of_match_ptr(rkaiisp_plat_of_match),
|
||||
.pm = &rkaiisp_plat_pm_ops,
|
||||
},
|
||||
.probe = rkaiisp_plat_probe,
|
||||
.remove = rkaiisp_plat_remove,
|
||||
};
|
||||
|
||||
MODULE_AUTHOR("Rockchip Camera/ISP team");
|
||||
MODULE_DESCRIPTION("Rockchip ISP platform driver");
|
||||
MODULE_LICENSE("Dual BSD/GPL");
|
||||
MODULE_IMPORT_NS(DMA_BUF);
|
||||
MODULE_IMPORT_NS(VFS_internal_I_am_really_a_filesystem_and_am_NOT_a_driver);
|
||||
446
drivers/media/platform/rockchip/aiisp/hw.c
Normal file
446
drivers/media/platform/rockchip/aiisp/hw.c
Normal file
@@ -0,0 +1,446 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#define pr_fmt(fmt) "rkaiisp: %s:%d " fmt, __func__, __LINE__
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/delay.h>
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/io.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include <linux/module.h>
|
||||
#include <linux/of.h>
|
||||
#include <linux/of_address.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 <media/videobuf2-cma-sg.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <soc/rockchip/rockchip_iommu.h>
|
||||
|
||||
#include "regs.h"
|
||||
#include "hw.h"
|
||||
#include "aiisp.h"
|
||||
|
||||
static struct rkaiisp_hw_dev *rkaiisp_hwdev;
|
||||
|
||||
/*
|
||||
* rkaiisp_hw share hardware resource with rkaiisp virtual device
|
||||
* rkaiisp_device rkaiisp_device rkaiisp_device rkaiisp_device
|
||||
* | | | |
|
||||
* \ | | /
|
||||
* --------------------------------------
|
||||
* |
|
||||
* rkaiisp_hw
|
||||
*/
|
||||
|
||||
static irqreturn_t hw_irq_hdl(int irq, void *ctx)
|
||||
{
|
||||
struct device *dev = ctx;
|
||||
struct rkaiisp_hw_dev *hw_dev = dev_get_drvdata(dev);
|
||||
struct rkaiisp_device *aidev = hw_dev->aidev[hw_dev->cur_dev_id];
|
||||
void __iomem *base = hw_dev->base_addr;
|
||||
int i, max = 0, id = 0;
|
||||
int len[RKAIISP_DEV_MAX] = { 0 };
|
||||
enum rkaiisp_irqhdl_ret irq_hdl_ret;
|
||||
u32 mis_val;
|
||||
|
||||
mis_val = readl(base + AIISP_MI_MIS);
|
||||
if (mis_val) {
|
||||
irq_hdl_ret = rkaiisp_irq_hdl(aidev, mis_val);
|
||||
if (irq_hdl_ret == RUN_COMPLETE) {
|
||||
spin_lock(&hw_dev->hw_lock);
|
||||
for (i = 0; i < RKAIISP_DEV_MAX; i++) {
|
||||
aidev = hw_dev->aidev[i];
|
||||
if (!aidev)
|
||||
continue;
|
||||
|
||||
if (!aidev->streamon)
|
||||
continue;
|
||||
|
||||
len[i] = rkaiisp_get_idxbuf_len(aidev);
|
||||
if (max < len[i]) {
|
||||
max = len[i];
|
||||
id = i;
|
||||
}
|
||||
}
|
||||
spin_unlock(&hw_dev->hw_lock);
|
||||
|
||||
if (max > 0) {
|
||||
spin_lock(&hw_dev->hw_lock);
|
||||
hw_dev->is_idle = false;
|
||||
hw_dev->cur_dev_id = id;
|
||||
aidev = hw_dev->aidev[hw_dev->cur_dev_id];
|
||||
spin_unlock(&hw_dev->hw_lock);
|
||||
v4l2_dbg(1, rkaiisp_debug, &aidev->v4l2_dev,
|
||||
"trigger aidev: %d, idxbuf len: %d\n",
|
||||
hw_dev->cur_dev_id, max);
|
||||
rkaiisp_trigger(aidev);
|
||||
} else {
|
||||
spin_lock(&hw_dev->hw_lock);
|
||||
hw_dev->is_idle = true;
|
||||
spin_unlock(&hw_dev->hw_lock);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
static int rkaiisp_register_irq(struct rkaiisp_hw_dev *hw_dev)
|
||||
{
|
||||
const struct aiisp_match_data *match_data = hw_dev->match_data;
|
||||
struct platform_device *pdev = hw_dev->pdev;
|
||||
struct device *dev = &pdev->dev;
|
||||
int ret, irq;
|
||||
|
||||
irq = platform_get_irq_byname(pdev, "irq");
|
||||
if (irq < 0) {
|
||||
dev_err(dev, "no irq %s in dts\n",
|
||||
match_data->irqs[0].name);
|
||||
return irq;
|
||||
}
|
||||
|
||||
ret = devm_request_irq(dev, irq,
|
||||
match_data->irqs[0].irq_hdl,
|
||||
0,
|
||||
dev_driver_string(dev),
|
||||
dev);
|
||||
if (ret < 0) {
|
||||
dev_err(dev, "request %s failed: %d\n",
|
||||
match_data->irqs[0].name, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf)
|
||||
{
|
||||
struct rkaiisp_hw_dev *hw_dev = rkaiisp_hwdev;
|
||||
struct rkaiisp_device *aidev = NULL;
|
||||
int i;
|
||||
|
||||
if (!hw_dev) {
|
||||
pr_err("Can not find hwdev!");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
for (i = 0; i < hw_dev->dev_num; i++) {
|
||||
if (hw_dev->aidev[i]) {
|
||||
if ((hw_dev->aidev[i]->is_hw_link) && hw_dev->aidev[i]->dev_id == dev_id) {
|
||||
aidev = hw_dev->aidev[i];
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!aidev) {
|
||||
pr_err("Can not find aidev for dev_id %d!", dev_id);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (aidev->exemode != BOTHEVENT_TO_AIQ) {
|
||||
pr_err("aidev %d exemode(%d) is not right!", dev_id, aidev->exemode);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
return rkaiisp_queue_ispbuf(aidev, idxbuf);
|
||||
}
|
||||
EXPORT_SYMBOL(rkaiisp_ispidx_queue);
|
||||
|
||||
static const char * const rv1126b_clks[] = {
|
||||
"clk_aiisp_core",
|
||||
"aclk_aiisp",
|
||||
"hclk_aiisp",
|
||||
};
|
||||
|
||||
static const struct aiisp_clk_info rv1126b_clk_rate[] = {
|
||||
{
|
||||
.clk_rate = 400,
|
||||
.refer_data = 1920, //width
|
||||
}, {
|
||||
.clk_rate = 400,
|
||||
.refer_data = 2688,
|
||||
}, {
|
||||
.clk_rate = 500,
|
||||
.refer_data = 3072,
|
||||
}, {
|
||||
.clk_rate = 600,
|
||||
.refer_data = 3840,
|
||||
}, {
|
||||
.clk_rate = 702,
|
||||
.refer_data = 4672,
|
||||
}
|
||||
};
|
||||
|
||||
static struct aiisp_irqs_data rv1126b_irqs[] = {
|
||||
{"irq", hw_irq_hdl},
|
||||
};
|
||||
|
||||
static const struct aiisp_match_data rv1126b_match_data = {
|
||||
.clks = rv1126b_clks,
|
||||
.num_clks = ARRAY_SIZE(rv1126b_clks),
|
||||
.clk_rate_tbl = rv1126b_clk_rate,
|
||||
.num_clk_rate_tbl = ARRAY_SIZE(rv1126b_clk_rate),
|
||||
.irqs = rv1126b_irqs,
|
||||
.num_irqs = ARRAY_SIZE(rv1126b_irqs),
|
||||
};
|
||||
|
||||
static const struct of_device_id rkaiisp_hw_of_match[] = {
|
||||
{
|
||||
.compatible = "rockchip,rv1126b-rkaiisp",
|
||||
.data = &rv1126b_match_data,
|
||||
},
|
||||
{},
|
||||
};
|
||||
|
||||
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 iommu buffers\n");
|
||||
of_node_put(iommu);
|
||||
return false;
|
||||
}
|
||||
of_node_put(iommu);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void rkaiisp_soft_reset(struct rkaiisp_hw_dev *dev, bool is_secure)
|
||||
{
|
||||
void __iomem *base = dev->base_addr;
|
||||
|
||||
if (is_secure) {
|
||||
/* if aidev working, cru reset isn't secure.
|
||||
* aidev soft reset first to protect aidev reset.
|
||||
*/
|
||||
writel(0x1, base + AIISP_CORE_SOFT_RST);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
if (dev->reset) {
|
||||
reset_control_assert(dev->reset);
|
||||
udelay(10);
|
||||
reset_control_deassert(dev->reset);
|
||||
udelay(10);
|
||||
}
|
||||
|
||||
/* refresh iommu after reset */
|
||||
if (dev->is_mmu) {
|
||||
rockchip_iommu_disable(dev->dev);
|
||||
rockchip_iommu_enable(dev->dev);
|
||||
}
|
||||
}
|
||||
|
||||
static void disable_sys_clk(struct rkaiisp_hw_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = dev->num_clks - 1; i >= 0; i--)
|
||||
if (!IS_ERR(dev->clks[i]))
|
||||
clk_disable_unprepare(dev->clks[i]);
|
||||
}
|
||||
|
||||
static int enable_sys_clk(struct rkaiisp_hw_dev *dev)
|
||||
{
|
||||
int i, ret = -EINVAL;
|
||||
|
||||
for (i = 0; i < dev->num_clks; i++) {
|
||||
if (!IS_ERR(dev->clks[i])) {
|
||||
ret = clk_prepare_enable(dev->clks[i]);
|
||||
if (ret < 0)
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
rkaiisp_soft_reset(dev, false);
|
||||
return 0;
|
||||
err:
|
||||
for (--i; i >= 0; --i)
|
||||
if (!IS_ERR(dev->clks[i]))
|
||||
clk_disable_unprepare(dev->clks[i]);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rkaiisp_hw_probe(struct platform_device *pdev)
|
||||
{
|
||||
const struct aiisp_match_data *match_data;
|
||||
struct device_node *node = pdev->dev.of_node;
|
||||
struct device *dev = &pdev->dev;
|
||||
struct rkaiisp_hw_dev *hw_dev;
|
||||
struct resource *res;
|
||||
int i, ret;
|
||||
bool is_mem_reserved = true;
|
||||
|
||||
match_data = of_device_get_match_data(dev);
|
||||
hw_dev = devm_kzalloc(dev, sizeof(*hw_dev), GFP_KERNEL);
|
||||
if (!hw_dev)
|
||||
return -ENOMEM;
|
||||
|
||||
dev_set_drvdata(dev, hw_dev);
|
||||
hw_dev->dev = dev;
|
||||
|
||||
hw_dev->grf = syscon_regmap_lookup_by_phandle(node, "rockchip,grf");
|
||||
if (IS_ERR(hw_dev->grf))
|
||||
dev_warn(dev, "Missing rockchip,grf property\n");
|
||||
|
||||
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
|
||||
if (!res) {
|
||||
dev_err(dev, "get resource failed\n");
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
hw_dev->base_addr = devm_ioremap_resource(dev, res);
|
||||
if (PTR_ERR(hw_dev->base_addr) == -EBUSY) {
|
||||
resource_size_t offset = res->start;
|
||||
resource_size_t size = resource_size(res);
|
||||
|
||||
hw_dev->base_addr = devm_ioremap(dev, offset, size);
|
||||
}
|
||||
if (IS_ERR(hw_dev->base_addr)) {
|
||||
dev_err(dev, "ioremap failed\n");
|
||||
ret = PTR_ERR(hw_dev->base_addr);
|
||||
goto err;
|
||||
}
|
||||
|
||||
hw_dev->pdev = pdev;
|
||||
hw_dev->match_data = match_data;
|
||||
|
||||
for (i = 0; i < match_data->num_clks; i++) {
|
||||
struct clk *clk = devm_clk_get(dev, match_data->clks[i]);
|
||||
|
||||
if (IS_ERR(clk)) {
|
||||
dev_err(dev, "failed to get %s\n", match_data->clks[i]);
|
||||
ret = PTR_ERR(clk);
|
||||
goto err;
|
||||
}
|
||||
hw_dev->clks[i] = clk;
|
||||
}
|
||||
hw_dev->num_clks = match_data->num_clks;
|
||||
hw_dev->clk_rate_tbl = match_data->clk_rate_tbl;
|
||||
hw_dev->num_clk_rate_tbl = match_data->num_clk_rate_tbl;
|
||||
|
||||
hw_dev->reset = devm_reset_control_array_get(dev, false, false);
|
||||
if (IS_ERR(hw_dev->reset)) {
|
||||
dev_dbg(dev, "failed to get reset\n");
|
||||
hw_dev->reset = NULL;
|
||||
}
|
||||
|
||||
hw_dev->dev_num = 0;
|
||||
hw_dev->cur_dev_id = 0;
|
||||
mutex_init(&hw_dev->dev_mutex);
|
||||
spin_lock_init(&hw_dev->hw_lock);
|
||||
atomic_set(&hw_dev->refcnt, 0);
|
||||
|
||||
hw_dev->is_idle = true;
|
||||
hw_dev->is_single = true;
|
||||
hw_dev->is_dma_contig = true;
|
||||
hw_dev->is_dma_sg_ops = true;
|
||||
hw_dev->is_shutdown = false;
|
||||
hw_dev->is_mmu = is_iommu_enable(dev);
|
||||
ret = of_reserved_mem_device_init(dev);
|
||||
if (ret) {
|
||||
is_mem_reserved = false;
|
||||
if (!hw_dev->is_mmu)
|
||||
dev_info(dev, "No reserved memory region. default cma area!\n");
|
||||
}
|
||||
if (hw_dev->is_mmu && !is_mem_reserved)
|
||||
hw_dev->is_dma_contig = false;
|
||||
hw_dev->mem_ops = &vb2_cma_sg_memops;
|
||||
|
||||
rkaiisp_hwdev = hw_dev;
|
||||
rkaiisp_register_irq(hw_dev);
|
||||
pm_runtime_enable(dev);
|
||||
|
||||
dev_info(dev, "probe end.\n");
|
||||
return 0;
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int rkaiisp_hw_remove(struct platform_device *pdev)
|
||||
{
|
||||
struct rkaiisp_hw_dev *hw_dev = platform_get_drvdata(pdev);
|
||||
|
||||
pm_runtime_disable(&pdev->dev);
|
||||
mutex_destroy(&hw_dev->dev_mutex);
|
||||
rkaiisp_hwdev = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void rkaiisp_hw_shutdown(struct platform_device *pdev)
|
||||
{
|
||||
struct rkaiisp_hw_dev *hw_dev = platform_get_drvdata(pdev);
|
||||
|
||||
hw_dev->is_shutdown = true;
|
||||
}
|
||||
|
||||
static int __maybe_unused rkaiisp_runtime_suspend(struct device *dev)
|
||||
{
|
||||
struct rkaiisp_hw_dev *hw_dev = dev_get_drvdata(dev);
|
||||
|
||||
hw_dev->is_idle = true;
|
||||
disable_sys_clk(hw_dev);
|
||||
return pinctrl_pm_select_sleep_state(dev);
|
||||
}
|
||||
|
||||
static int __maybe_unused rkaiisp_runtime_resume(struct device *dev)
|
||||
{
|
||||
struct rkaiisp_hw_dev *hw_dev = dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = pinctrl_pm_select_default_state(dev);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
|
||||
enable_sys_clk(hw_dev);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops rkaiisp_hw_pm_ops = {
|
||||
SET_LATE_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, pm_runtime_force_resume)
|
||||
SET_RUNTIME_PM_OPS(rkaiisp_runtime_suspend, rkaiisp_runtime_resume, NULL)
|
||||
};
|
||||
|
||||
static struct platform_driver rkaiisp_hw_drv = {
|
||||
.driver = {
|
||||
.name = "rkaiisp_hw",
|
||||
.of_match_table = of_match_ptr(rkaiisp_hw_of_match),
|
||||
.pm = &rkaiisp_hw_pm_ops,
|
||||
},
|
||||
.probe = rkaiisp_hw_probe,
|
||||
.remove = rkaiisp_hw_remove,
|
||||
.shutdown = rkaiisp_hw_shutdown,
|
||||
};
|
||||
|
||||
static int __init rkaiisp_hw_drv_init(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = platform_driver_register(&rkaiisp_hw_drv);
|
||||
if (!ret)
|
||||
ret = platform_driver_register(&rkaiisp_plat_drv);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void __exit rkaiisp_hw_drv_exit(void)
|
||||
{
|
||||
platform_driver_unregister(&rkaiisp_plat_drv);
|
||||
platform_driver_unregister(&rkaiisp_hw_drv);
|
||||
}
|
||||
|
||||
module_init(rkaiisp_hw_drv_init);
|
||||
module_exit(rkaiisp_hw_drv_exit);
|
||||
80
drivers/media/platform/rockchip/aiisp/hw.h
Normal file
80
drivers/media/platform/rockchip/aiisp/hw.h
Normal file
@@ -0,0 +1,80 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef _RKAIISP_HW_H
|
||||
#define _RKAIISP_HW_H
|
||||
|
||||
#include <linux/interrupt.h>
|
||||
#include <linux/rk-aiisp-config.h>
|
||||
|
||||
#define RKAIISP_MAX_BUS_CLK 10
|
||||
|
||||
enum rkaiisp_dev {
|
||||
RKAIISP_DEV_ID0 = 0,
|
||||
RKAIISP_DEV_ID1,
|
||||
RKAIISP_DEV_ID2,
|
||||
RKAIISP_DEV_ID3,
|
||||
RKAIISP_DEV_ID4,
|
||||
RKAIISP_DEV_ID5,
|
||||
RKAIISP_DEV_ID6,
|
||||
RKAIISP_DEV_ID7,
|
||||
RKAIISP_DEV_MAX,
|
||||
};
|
||||
|
||||
enum rkaiisp_sw_reg {
|
||||
SW_REG_CACHE = 0xffffffff,
|
||||
SW_REG_CACHE_SYNC = 0xeeeeeeee,
|
||||
};
|
||||
|
||||
struct aiisp_irqs_data {
|
||||
const char *name;
|
||||
irqreturn_t (*irq_hdl)(int irq, void *ctx);
|
||||
};
|
||||
|
||||
struct aiisp_clk_info {
|
||||
u32 clk_rate;
|
||||
u32 refer_data;
|
||||
};
|
||||
|
||||
struct aiisp_match_data {
|
||||
const char * const *clks;
|
||||
int num_clks;
|
||||
const struct aiisp_clk_info *clk_rate_tbl;
|
||||
int num_clk_rate_tbl;
|
||||
struct aiisp_irqs_data *irqs;
|
||||
int num_irqs;
|
||||
};
|
||||
|
||||
struct rkaiisp_hw_dev {
|
||||
const struct aiisp_match_data *match_data;
|
||||
struct platform_device *pdev;
|
||||
struct device *dev;
|
||||
struct regmap *grf;
|
||||
void __iomem *base_addr;
|
||||
struct clk *clks[RKAIISP_MAX_BUS_CLK];
|
||||
int num_clks;
|
||||
const struct aiisp_clk_info *clk_rate_tbl;
|
||||
int num_clk_rate_tbl;
|
||||
struct reset_control *reset;
|
||||
|
||||
struct rkaiisp_device *aidev[RKAIISP_DEV_MAX];
|
||||
int dev_num;
|
||||
int cur_dev_id;
|
||||
|
||||
/* lock for multi dev */
|
||||
struct mutex dev_mutex;
|
||||
spinlock_t hw_lock;
|
||||
atomic_t refcnt;
|
||||
const struct vb2_mem_ops *mem_ops;
|
||||
|
||||
bool is_dma_contig;
|
||||
bool is_dma_sg_ops;
|
||||
bool is_mmu;
|
||||
bool is_idle;
|
||||
bool is_single;
|
||||
bool is_shutdown;
|
||||
};
|
||||
|
||||
int rkaiisp_ispidx_queue(int dev_id, struct rkisp_aiisp_st *idxbuf);
|
||||
|
||||
#endif
|
||||
136
drivers/media/platform/rockchip/aiisp/regs.h
Normal file
136
drivers/media/platform/rockchip/aiisp/regs.h
Normal file
@@ -0,0 +1,136 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef _RKAIISP_REGS_H
|
||||
#define _RKAIISP_REGS_H
|
||||
|
||||
#define AIISP_CORE_BASE 0x00000000
|
||||
#define AIISP_CORE_CTRL (AIISP_CORE_BASE + 0x00000)
|
||||
#define AIISP_CORE_SOFT_RST (AIISP_CORE_BASE + 0x00008)
|
||||
#define AIISP_CORE_LEVEL_CTRL0 (AIISP_CORE_BASE + 0x00020)
|
||||
#define AIISP_CORE_LEVEL_CTRL1 (AIISP_CORE_BASE + 0x00024)
|
||||
#define AIISP_CORE_LEVEL_CTRL2 (AIISP_CORE_BASE + 0x00028)
|
||||
#define AIISP_CORE_LEVEL_CTRL3 (AIISP_CORE_BASE + 0x0002c)
|
||||
#define AIISP_CORE_OUT_CTRL (AIISP_CORE_BASE + 0x00040)
|
||||
#define AIISP_CORE_NOISE_LMT (AIISP_CORE_BASE + 0x00044)
|
||||
#define AIISP_CORE_COMP0 (AIISP_CORE_BASE + 0x00200)
|
||||
#define AIISP_CORE_COMP1 (AIISP_CORE_BASE + 0x00204)
|
||||
#define AIISP_CORE_COMP2 (AIISP_CORE_BASE + 0x00208)
|
||||
#define AIISP_CORE_COMP3 (AIISP_CORE_BASE + 0x0020c)
|
||||
#define AIISP_CORE_COMP4 (AIISP_CORE_BASE + 0x00210)
|
||||
#define AIISP_CORE_COMP5 (AIISP_CORE_BASE + 0x00214)
|
||||
#define AIISP_CORE_COMP6 (AIISP_CORE_BASE + 0x00218)
|
||||
#define AIISP_CORE_COMP7 (AIISP_CORE_BASE + 0x0021c)
|
||||
#define AIISP_CORE_COMP8 (AIISP_CORE_BASE + 0x00220)
|
||||
#define AIISP_CORE_COMP9 (AIISP_CORE_BASE + 0x00224)
|
||||
#define AIISP_CORE_COMP10 (AIISP_CORE_BASE + 0x00228)
|
||||
#define AIISP_CORE_COMP11 (AIISP_CORE_BASE + 0x0022c)
|
||||
#define AIISP_CORE_COMP12 (AIISP_CORE_BASE + 0x00230)
|
||||
#define AIISP_CORE_COMP13 (AIISP_CORE_BASE + 0x00234)
|
||||
#define AIISP_CORE_COMP14 (AIISP_CORE_BASE + 0x00238)
|
||||
#define AIISP_CORE_COMP15 (AIISP_CORE_BASE + 0x0023c)
|
||||
#define AIISP_CORE_COMP16 (AIISP_CORE_BASE + 0x00240)
|
||||
#define AIISP_CORE_DECOMP0 (AIISP_CORE_BASE + 0x00280)
|
||||
#define AIISP_CORE_DECOMP1 (AIISP_CORE_BASE + 0x00284)
|
||||
#define AIISP_CORE_DECOMP2 (AIISP_CORE_BASE + 0x00288)
|
||||
#define AIISP_CORE_DECOMP3 (AIISP_CORE_BASE + 0x0028c)
|
||||
#define AIISP_CORE_DECOMP4 (AIISP_CORE_BASE + 0x00290)
|
||||
#define AIISP_CORE_DECOMP5 (AIISP_CORE_BASE + 0x00294)
|
||||
#define AIISP_CORE_DECOMP6 (AIISP_CORE_BASE + 0x00298)
|
||||
#define AIISP_CORE_DECOMP7 (AIISP_CORE_BASE + 0x0029c)
|
||||
#define AIISP_CORE_DECOMP8 (AIISP_CORE_BASE + 0x002a0)
|
||||
#define AIISP_CORE_DECOMP9 (AIISP_CORE_BASE + 0x002a4)
|
||||
#define AIISP_CORE_DECOMP10 (AIISP_CORE_BASE + 0x002a8)
|
||||
#define AIISP_CORE_DECOMP11 (AIISP_CORE_BASE + 0x002ac)
|
||||
#define AIISP_CORE_DECOMP12 (AIISP_CORE_BASE + 0x002b0)
|
||||
#define AIISP_CORE_DECOMP13 (AIISP_CORE_BASE + 0x002b4)
|
||||
#define AIISP_CORE_DECOMP14 (AIISP_CORE_BASE + 0x002b8)
|
||||
#define AIISP_CORE_DECOMP15 (AIISP_CORE_BASE + 0x002bc)
|
||||
#define AIISP_CORE_DECOMP16 (AIISP_CORE_BASE + 0x002c0)
|
||||
|
||||
#define AIISP_MI_BASE 0x00002000
|
||||
#define AIISP_MI_HURRY_CTRL (AIISP_MI_BASE + 0x00040)
|
||||
#define AIISP_MI_ARQOS_CTRL (AIISP_MI_BASE + 0x00044)
|
||||
#define AIISP_MI_AWQOS_CTRL (AIISP_MI_BASE + 0x00048)
|
||||
#define AIISP_MI_IMSC (AIISP_MI_BASE + 0x00050)
|
||||
#define AIISP_MI_RIS (AIISP_MI_BASE + 0x00054)
|
||||
#define AIISP_MI_MIS (AIISP_MI_BASE + 0x00058)
|
||||
#define AIISP_MI_ICR (AIISP_MI_BASE + 0x0005c)
|
||||
#define AIISP_MI_ISR (AIISP_MI_BASE + 0x00060)
|
||||
#define AIISP_MI_RD_START (AIISP_MI_BASE + 0x00100)
|
||||
#define AIISP_MI_CTRL (AIISP_MI_BASE + 0x00104)
|
||||
#define AIISP_MI_SLICE_CTRL (AIISP_MI_BASE + 0x00180)
|
||||
#define AIISP_MI_MANUAL_CTRL (AIISP_MI_BASE + 0x00184)
|
||||
#define AIISP_MI_CORE_WIDTH (AIISP_MI_BASE + 0x001a0)
|
||||
#define AIISP_MI_CORE_HEIGHT (AIISP_MI_BASE + 0x001a4)
|
||||
#define AIISP_MI_RD_CH0_CTRL (AIISP_MI_BASE + 0x00200)
|
||||
#define AIISP_MI_RD_CH0_BASE (AIISP_MI_BASE + 0x00204)
|
||||
#define AIISP_MI_RD_CH0_HEIGHT (AIISP_MI_BASE + 0x0020c)
|
||||
#define AIISP_MI_RD_CH0_STRIDE (AIISP_MI_BASE + 0x00210)
|
||||
#define AIISP_MI_RD_CH1_CTRL (AIISP_MI_BASE + 0x00300)
|
||||
#define AIISP_MI_RD_CH1_BASE (AIISP_MI_BASE + 0x00304)
|
||||
#define AIISP_MI_RD_CH1_HEIGHT (AIISP_MI_BASE + 0x0030c)
|
||||
#define AIISP_MI_RD_CH1_STRIDE (AIISP_MI_BASE + 0x00310)
|
||||
#define AIISP_MI_RD_CH2_CTRL (AIISP_MI_BASE + 0x00400)
|
||||
#define AIISP_MI_RD_CH2_BASE (AIISP_MI_BASE + 0x00404)
|
||||
#define AIISP_MI_RD_CH2_HEIGHT (AIISP_MI_BASE + 0x0040c)
|
||||
#define AIISP_MI_RD_CH2_STRIDE (AIISP_MI_BASE + 0x00410)
|
||||
#define AIISP_MI_RD_CH3_CTRL (AIISP_MI_BASE + 0x00500)
|
||||
#define AIISP_MI_RD_CH3_BASE (AIISP_MI_BASE + 0x00504)
|
||||
#define AIISP_MI_RD_CH3_HEIGHT (AIISP_MI_BASE + 0x0050c)
|
||||
#define AIISP_MI_RD_CH3_STRIDE (AIISP_MI_BASE + 0x00510)
|
||||
#define AIISP_MI_RD_CH4_CTRL (AIISP_MI_BASE + 0x00600)
|
||||
#define AIISP_MI_RD_CH4_BASE (AIISP_MI_BASE + 0x00604)
|
||||
#define AIISP_MI_RD_CH4_HEIGHT (AIISP_MI_BASE + 0x0060c)
|
||||
#define AIISP_MI_RD_CH4_STRIDE (AIISP_MI_BASE + 0x00610)
|
||||
#define AIISP_MI_RD_CH5_CTRL (AIISP_MI_BASE + 0x00700)
|
||||
#define AIISP_MI_RD_CH5_BASE (AIISP_MI_BASE + 0x00704)
|
||||
#define AIISP_MI_RD_CH5_HEIGHT (AIISP_MI_BASE + 0x0070c)
|
||||
#define AIISP_MI_RD_CH5_STRIDE (AIISP_MI_BASE + 0x00710)
|
||||
#define AIISP_MI_RD_CH6_CTRL (AIISP_MI_BASE + 0x00800)
|
||||
#define AIISP_MI_RD_CH6_BASE (AIISP_MI_BASE + 0x00804)
|
||||
#define AIISP_MI_RD_CH6_HEIGHT (AIISP_MI_BASE + 0x0080c)
|
||||
#define AIISP_MI_RD_CH6_STRIDE (AIISP_MI_BASE + 0x00810)
|
||||
#define AIISP_MI_RD_KWT_CTRL (AIISP_MI_BASE + 0x00900)
|
||||
#define AIISP_MI_RD_KWT_BASE (AIISP_MI_BASE + 0x00904)
|
||||
#define AIISP_MI_RD_KWT_WIDTH (AIISP_MI_BASE + 0x00908)
|
||||
#define AIISP_MI_RD_KWT_HEIGHT (AIISP_MI_BASE + 0x0090c)
|
||||
#define AIISP_MI_RD_KWT_STRIDE (AIISP_MI_BASE + 0x00910)
|
||||
#define AIISP_MI_WR_CTRL (AIISP_MI_BASE + 0x00a00)
|
||||
#define AIISP_MI_WR_INIT (AIISP_MI_BASE + 0x00a04)
|
||||
#define AIISP_MI_CHN0_WR_CRTL (AIISP_MI_BASE + 0x00a08)
|
||||
#define AIISP_MI_CHN0_WR_BASE (AIISP_MI_BASE + 0x00a10)
|
||||
#define AIISP_MI_CHN0_WR_SIZE (AIISP_MI_BASE + 0x00a24)
|
||||
#define AIISP_MI_CHN0_WR_STRIDE (AIISP_MI_BASE + 0x00a28)
|
||||
|
||||
|
||||
#define AIISP_MI_ISR_BUSERR BIT(0)
|
||||
#define AIISP_MI_ISR_WREND BIT(3)
|
||||
#define AIISP_MI_ISR_ALL (AIISP_MI_ISR_BUSERR | AIISP_MI_ISR_WREND)
|
||||
|
||||
#define AIISP_MI_RD_START_EN BIT(0)
|
||||
#define AIISP_MI_RD_KWT_EN BIT(0)
|
||||
#define AIISP_MI_RD_CH_EN BIT(0)
|
||||
|
||||
#define AIISP_MI_RD_CH0_GROUP_MODE 2
|
||||
#define AIISP_MI_RD_CH1_GROUP_MODE 2
|
||||
#define AIISP_MI_RD_CH2_GROUP_MODE 2
|
||||
#define AIISP_MI_RD_CH3_GROUP_MODE 0
|
||||
#define AIISP_MI_RD_CH4_GROUP_MODE 0
|
||||
#define AIISP_MI_RD_CH5_GROUP_MODE 0
|
||||
#define AIISP_MI_RD_CH6_GROUP_MODE 0
|
||||
#define AIISP_MI_RD_KWT_GROUP_MODE 0
|
||||
#define AIISP_MI_WR_GROUP_MODE 2
|
||||
|
||||
#define AIISP_MI_WR_INIT_BASE_EN BIT(4)
|
||||
#define AIISP_MI_WR_INIT_OFFSET_EN BIT(5)
|
||||
|
||||
#define AIISP_MI_CHN0_WR_EN BIT(0)
|
||||
#define AIISP_MI_CHN0_WR_AUTOUPD BIT(1)
|
||||
|
||||
#define AIISP_MI_CHN0SELF_FORCE_UPD BIT(4)
|
||||
|
||||
#define AIISP_MI_RD_ALWAYS_ON BIT(0)
|
||||
#define AIISP_MI_WR_ALWAYS_ON BIT(4)
|
||||
|
||||
#endif /* _RKAIISP_REGS_H */
|
||||
18
drivers/media/platform/rockchip/aiisp/version.h
Normal file
18
drivers/media/platform/rockchip/aiisp/version.h
Normal file
@@ -0,0 +1,18 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (C) 2025 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef _RKAIISP_VERSION_H
|
||||
#define _RKAIISP_VERSION_H
|
||||
#include <linux/version.h>
|
||||
|
||||
/*
|
||||
*RKAIISP DRIVER VERSION NOTE
|
||||
*
|
||||
*v0.1.1:
|
||||
*1. First version;
|
||||
*
|
||||
*/
|
||||
|
||||
#define RKAIISP_DRIVER_VERSION KERNEL_VERSION(0, 1, 0x1)
|
||||
|
||||
#endif
|
||||
140
include/uapi/linux/rk-aiisp-config.h
Normal file
140
include/uapi/linux/rk-aiisp-config.h
Normal file
@@ -0,0 +1,140 @@
|
||||
/* SPDX-License-Identifier: (GPL-2.0+ WITH Linux-syscall-note) OR MIT
|
||||
*
|
||||
* Rockchip AIISP
|
||||
* Copyright (C) 2025 Rockchip Electronics Co., Ltd.
|
||||
*/
|
||||
|
||||
#ifndef _UAPI_RK_AIISP_CONFIG_H
|
||||
#define _UAPI_RK_AIISP_CONFIG_H
|
||||
|
||||
#include <linux/rk-isp2-config.h>
|
||||
|
||||
#define RKAIISP_PYRAMID_LAYER_NUM 4
|
||||
#define RKAIISP_MAX_RUNCNT 8
|
||||
#define RKAIISP_MAX_ISPBUF 8
|
||||
#define RKAIISP_MODEL_UPDATE 0x01
|
||||
#define RKAIISP_OTHER_UPDATE 0x02
|
||||
|
||||
#define RKAIISP_CMD_SET_PARAM_INFO \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 0, struct rkaiisp_param_info)
|
||||
|
||||
#define RKAIISP_CMD_INIT_BUFPOOL \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 1, struct rkaiisp_ispbuf_info)
|
||||
|
||||
#define RKAIISP_CMD_FREE_BUFPOOL \
|
||||
_IO('V', BASE_VIDIOC_PRIVATE + 2)
|
||||
|
||||
#define RKAIISP_CMD_QUEUE_BUF \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 3, struct rkisp_aiisp_st)
|
||||
|
||||
/**********************EVENT_PRIVATE***************************/
|
||||
#define RKAIISP_V4L2_EVENT_AIISP_DONE (V4L2_EVENT_PRIVATE_START + 1)
|
||||
|
||||
enum rkaiisp_chn_src {
|
||||
ISP_IIR,
|
||||
VPSL_YRAW_CHN0,
|
||||
VPSL_YRAW_CHN1,
|
||||
VPSL_YRAW_CHN2,
|
||||
VPSL_YRAW_CHN3,
|
||||
VPSL_YRAW_CHN4,
|
||||
VPSL_YRAW_CHN5,
|
||||
VPSL_SIG_CHN0,
|
||||
VPSL_SIG_CHN1,
|
||||
VPSL_SIG_CHN2,
|
||||
VPSL_SIG_CHN3,
|
||||
VPSL_SIG_CHN4,
|
||||
ISP_AIPRE_NARMAP,
|
||||
AIISP_LAST_OUT
|
||||
};
|
||||
|
||||
enum rkaiisp_model_mode {
|
||||
SINGLE_MODE,
|
||||
COMBO_MODE,
|
||||
SINGLEX2_MODE
|
||||
};
|
||||
|
||||
enum rkaiisp_exemode {
|
||||
BOTHEVENT_TO_AIQ,
|
||||
ISPEVENT_IN_KERNEL,
|
||||
BOTHEVENT_IN_KERNEL
|
||||
};
|
||||
|
||||
struct rkaiisp_param_info {
|
||||
enum rkaiisp_exemode exemode;
|
||||
__u32 para_size;
|
||||
__u32 max_runcnt;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_ispbuf_info {
|
||||
struct rkisp_bnr_buf_info bnr_buf;
|
||||
__u32 iir_width;
|
||||
__u32 iir_height;
|
||||
__u32 raw_width[6];
|
||||
__u32 raw_height[6];
|
||||
__u32 sig_width[5];
|
||||
__u32 sig_height[5];
|
||||
__u32 narmap_width;
|
||||
__u32 narmap_height;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_other_cfg {
|
||||
__u16 sw_neg_noiselimit;
|
||||
__u16 sw_pos_noiselimit;
|
||||
|
||||
__u16 sw_prev_blacklvl;
|
||||
__u16 sw_post_blacklvl;
|
||||
|
||||
__u16 sw_in_comp_y[33];
|
||||
__u16 sw_out_decomp_y[33];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_model_cfg {
|
||||
enum rkaiisp_chn_src mi_chn_src[7];
|
||||
__u32 sw_aiisp_mode;
|
||||
__u32 sw_aiisp_level_num;
|
||||
__u32 sw_aiisp_l1_level_num;
|
||||
__u32 sw_aiisp_op_mode;
|
||||
__u32 sw_aiisp_drop_en;
|
||||
__u32 sw_aiisp_lv_active[16];
|
||||
__u32 sw_aiisp_lv_mode[16];
|
||||
__u32 sw_mi_chn_en[7];
|
||||
__u32 sw_mi_chn_mode[7];
|
||||
__u32 sw_mi_chn_num[7];
|
||||
__u32 sw_mi_chn_data_mode[7];
|
||||
__u32 sw_mi_chn1_sel;
|
||||
__u32 sw_mi_chn3_sel;
|
||||
__u32 sw_out_d2s_en;
|
||||
__u32 sw_out_mode;
|
||||
__u32 sw_lastlvlm1_clip8bit;
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_kwt_cfg {
|
||||
__u32 kwt_offet[RKAIISP_MAX_RUNCNT];
|
||||
__u32 kwt_size[RKAIISP_MAX_RUNCNT];
|
||||
__u32 kwt_pad_size[RKAIISP_MAX_RUNCNT];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_params {
|
||||
__u32 frame_id;
|
||||
__u32 module_update;
|
||||
__u32 model_runcnt;
|
||||
enum rkaiisp_model_mode model_mode;
|
||||
|
||||
struct rkaiisp_other_cfg other_cfg;
|
||||
struct rkaiisp_model_cfg model_cfg[RKAIISP_MAX_RUNCNT];
|
||||
struct rkaiisp_kwt_cfg kwt_cfg;
|
||||
__u8 reserved[36];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
struct rkaiisp_model_info {
|
||||
__u32 checksum;
|
||||
__u32 model_runcnt;
|
||||
float model_qr;
|
||||
enum rkaiisp_model_mode model_mode;
|
||||
|
||||
struct rkaiisp_model_cfg model_cfg[RKAIISP_MAX_RUNCNT];
|
||||
struct rkaiisp_kwt_cfg kwt_cfg;
|
||||
__u8 reserved[48];
|
||||
} __attribute__ ((packed));
|
||||
|
||||
#endif /* _UAPI_RK_AIISP_CONFIG_H */
|
||||
Reference in New Issue
Block a user