media: rockchip: add procfs for avsp

Change-Id: I2bb91327df23dd62a0007ab9db2a35756d4917dc
Signed-off-by: Zhizhen Zheng <zhizhen.zheng@rock-chips.com>
This commit is contained in:
Zhizhen Zheng
2025-08-15 10:54:10 +08:00
committed by Tao Huang
parent 9823ea522b
commit 141729498a
7 changed files with 371 additions and 13 deletions

View File

@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0-only
video_rkavsp-objs := avsp.o
video_rkavsp-objs := avsp.o \
procfs.o
obj-$(CONFIG_VIDEO_ROCKCHIP_AVSP) += video_rkavsp.o

View File

@@ -5,6 +5,7 @@
#include "avsp.h"
#include "regs.h"
#include "procfs.h"
int rkavsp_log_level;
module_param_named(debug, rkavsp_log_level, int, 0644);
@@ -26,13 +27,12 @@ static void init_vb2(struct rkavsp_dev *avsp, struct rkavsp_buf *buf)
if (!buf)
return;
memset(&buf->vb, 0, sizeof(buf->vb));
memset(&buf->vb2_queue, 0, sizeof(buf->vb2_queue));
buf->vb2_queue.gfp_flags = GFP_KERNEL | GFP_DMA32;
buf->vb2_queue.dma_dir = DMA_BIDIRECTIONAL;
avsp->vb2_queue.gfp_flags = GFP_KERNEL | GFP_DMA32;
avsp->vb2_queue.dma_dir = DMA_BIDIRECTIONAL;
if (avsp->is_dma_config)
attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
buf->vb2_queue.dma_attrs = attrs;
buf->vb.vb2_queue = &buf->vb2_queue;
avsp->vb2_queue.dma_attrs = attrs;
buf->vb.vb2_queue = &avsp->vb2_queue;
}
#endif
@@ -149,8 +149,17 @@ static int avsp_dcp_run(struct file *file, struct rkavsp_dcp_in_out *buf)
u32 bandnum = buf->bandnum;
u32 wr_mode = buf->dcp_wr_mode, rd_mode = buf->dcp_rd_mode;
u32 dcp_rd_stride_y = buf->dcp_rd_stride_y, dcp_rd_stride_c = buf->dcp_rd_stride_c;
ktime_t t = 0;
s64 us = 0;
mutex_lock(&avsp->dcp_lock);
t = ktime_get();
avsp->dcp_prev_frame.fs_seq = avsp->dcp_curr_frame.fs_seq;
avsp->dcp_prev_frame.fs_timestamp = avsp->dcp_curr_frame.fs_timestamp;
avsp->dcp_curr_frame.fs_seq++;
avsp->dcp_curr_frame.fs_timestamp = ktime_to_ns(t);
avsp->dcp_state = RKAVSP_DCP_START;
if (rd_mode != AVSP_MODE_QUAD && rd_mode != AVSP_MODE_RASTER) {
RKAVSP_ERR("dcp rd_mode err.\n");
mutex_unlock(&avsp->dcp_lock);
@@ -173,7 +182,7 @@ static int avsp_dcp_run(struct file *file, struct rkavsp_dcp_in_out *buf)
val = SW_DCP_BYPASS(dcp_bypass) | SW_DCP_WR_MODE(wr_mode) |
SW_DCP_RD_MODE(rd_mode) | SW_DCP_BAND_NUM(bandnum);
writel(val, base + AVSP_DCP_CTRL);
val = SW_AVSP_SRC_WIDTH(in_w) | Sw_AVSP_SRC_HEIGHT(in_h);
val = SW_AVSP_SRC_WIDTH(in_w) | SW_AVSP_SRC_HEIGHT(in_h);
writel(val, base + AVSP_DCP_SIZE);
val = AVSP_RD_VIR_STRIDE_Y(dcp_rd_stride_y) | AVSP_RD_VIR_STRIDE_C(dcp_rd_stride_c);
writel(val, base + AVSP_DCP_RD_VIR_SIZE);
@@ -229,16 +238,38 @@ static int avsp_dcp_run(struct file *file, struct rkavsp_dcp_in_out *buf)
writel(AVSP_ST, base + AVSP_DCP_STRT);
RKAVSP_DBG("DCP: write start success.\n");
// add info for procfs
avsp->dcp_in_fmt.bandnum = bandnum;
avsp->dcp_in_fmt.width = in_w;
avsp->dcp_in_fmt.height = in_h;
avsp->dcp_in_fmt.mode = buf->dcp_rd_mode;
avsp->dcp_in_fmt.stride_y = dcp_rd_stride_y;
avsp->dcp_in_fmt.stride_c = dcp_rd_stride_y;
avsp->dcp_in_fmt.offset = in_offs;
avsp->dcp_out_fmt.mode = wr_mode;
for (i = 0; i < bandnum; i++) {
avsp->dcp_out_fmt.width[i] = buf->dcp_wr_stride_y[i];
avsp->dcp_out_fmt.height[i] = pry_h[i];
}
ret = wait_for_completion_timeout(&avsp->dcp_cmpl, msecs_to_jiffies(300));
if (!ret) {
RKAVSP_ERR("IOCTL AVSP_DCP work out time.\n");
avsp->dcp_debug.frame_timeout_cnt++;
ret = -EAGAIN;
rkavsp_soft_reset(avsp);
goto free_buf;
} else {
ret = 0;
}
us = ktime_us_delta(ktime_get(), t);
avsp->dcp_debug.interval = us;
avsp->dcp_state = RKAVSP_DCP_FRAME_END;
mutex_unlock(&avsp->dcp_lock);
return ret;
free_buf:
@@ -257,9 +288,12 @@ static int avsp_rcs_run(struct file *file, struct rkavsp_rcs_in_out *buf)
struct sg_table *sgt;
int ret = -EINVAL;
int i;
ktime_t t = 0;
s64 us = 0;
u32 rd_mode = AVSP_MODE_QUAD;
u32 out_offs, val, c_addr;
u32 out_offs = 0;
u32 val, c_addr;
u32 in_w = buf->in_width, in_h = buf->in_height;
u32 bandnum = buf->bandnum;
u32 wr_mode = buf->rcs_wr_mode;
@@ -267,12 +301,20 @@ static int avsp_rcs_run(struct file *file, struct rkavsp_rcs_in_out *buf)
u32 rcs_out_start_offset = buf->rcs_out_start_offset;
mutex_lock(&avsp->rcs_lock);
t = ktime_get();
avsp->rcs_prev_frame.fs_seq = avsp->rcs_curr_frame.fs_seq;
avsp->rcs_prev_frame.fs_timestamp = avsp->rcs_curr_frame.fs_timestamp;
avsp->rcs_curr_frame.fs_seq++;
avsp->rcs_curr_frame.fs_timestamp = ktime_to_ns(t);
avsp->rcs_state = RKAVSP_RCS_START;
val = SW_RCS_BAND_NUM(bandnum) | SW_RCS_RD_MODE(rd_mode) | SW_RCS_WR_MODE(wr_mode);
if (wr_mode == AVSP_MODE_FBCE)
val |= SW_RCS_FBCE_CTL;
writel(val, base + AVSP_RCS_CTRL);
val = SW_AVSP_SRC_WIDTH(in_w) | Sw_AVSP_SRC_HEIGHT(in_h);
val = SW_AVSP_SRC_WIDTH(in_w) | SW_AVSP_SRC_HEIGHT(in_h);
writel(val, base + AVSP_RCS_SIZE);
val = AVSP_WR_VIR_STRIDE_Y(rcs_wr_stride_y) | AVSP_WR_VIR_STRIDE_C(rcs_wr_stride_c);
writel(val, base + AVSP_RCS_WR_STRIDE);
@@ -359,16 +401,35 @@ static int avsp_rcs_run(struct file *file, struct rkavsp_rcs_in_out *buf)
writel(AVSP_FORCE_UPD, base + AVSP_RCS_UPDATE);
writel(AVSP_ST, base + AVSP_RCS_STRT);
// add info for procfs
avsp->rcs_state = RKAVSP_RCS_START;
avsp->rcs_in_fmt.bandnum = bandnum;
avsp->rcs_in_fmt.width = in_w;
avsp->rcs_in_fmt.height = in_h;
avsp->rcs_in_fmt.mode = rd_mode;
avsp->rcs_out_fmt.mode = wr_mode;
avsp->rcs_out_fmt.offset = out_offs;
avsp->rcs_out_fmt.stride_y = rcs_wr_stride_y;
avsp->rcs_out_fmt.stride_c = rcs_wr_stride_c;
ret = wait_for_completion_timeout(&avsp->rcs_cmpl, msecs_to_jiffies(300));
if (!ret) {
RKAVSP_ERR("IOCTL AVSP_RCS work out time.\n");
avsp->rcs_debug.frame_timeout_cnt++;
ret = -EAGAIN;
rkavsp_soft_reset(avsp);
goto free_buf;
} else {
ret = 0;
}
us = ktime_us_delta(ktime_get(), t);
avsp->rcs_debug.interval = us;
avsp->rcs_state = RKAVSP_RCS_FRAME_END;
mutex_unlock(&avsp->rcs_lock);
return ret;
free_buf:
@@ -455,12 +516,16 @@ static irqreturn_t avsp_dcp_irq_hdl(int irq, void *dev_id)
mis_val = readl(base + AVSP_DCP_INT_MSK);
writel(mis_val, base + AVSP_DCP_INT_CLR);
avsp->dcp_isr_cnt++;
if (mis_val & DCP_INT) {
mis_val &= (~DCP_INT);
if (!completion_done(&avsp->dcp_cmpl)) {
complete(&avsp->dcp_cmpl);
RKAVSP_DBG("misval: 0x%x\n", mis_val);
}
} else {
avsp->dcp_err_cnt++;
}
return IRQ_HANDLED;
}
@@ -476,12 +541,16 @@ static irqreturn_t avsp_rcs_irq_hdl(int irq, void *dev_id)
writel(mis_val, base + AVSP_RCS_INT_CLR0);
writel(mis_val, base + AVSP_RCS_INT_CLR1);
avsp->rcs_isr_cnt++;
if (mis_val & RCS_INT) {
mis_val &= (~RCS_INT);
if (!completion_done(&avsp->rcs_cmpl)) {
complete(&avsp->rcs_cmpl);
RKAVSP_DBG("misval: 0x%x\n", mis_val);
}
} else {
avsp->rcs_err_cnt++;
}
return IRQ_HANDLED;
}
@@ -565,8 +634,17 @@ static int avsp_probe(struct platform_device *pdev)
INIT_LIST_HEAD(&avsp->list);
init_completion(&avsp->dcp_cmpl);
init_completion(&avsp->rcs_cmpl);
memset(&avsp->vb2_queue, 0, sizeof(avsp->vb2_queue));
avsp->mem_ops = &vb2_cma_sg_memops;
rkavsp_proc_init(avsp);
avsp->dcp_state = RKAVSP_DCP_STOP;
avsp->rcs_state = RKAVSP_RCS_STOP;
memset(&avsp->dcp_curr_frame, 0, sizeof(avsp->dcp_curr_frame));
memset(&avsp->dcp_prev_frame, 0, sizeof(avsp->dcp_prev_frame));
memset(&avsp->rcs_curr_frame, 0, sizeof(avsp->rcs_curr_frame));
memset(&avsp->rcs_prev_frame, 0, sizeof(avsp->rcs_prev_frame));
/* get the irq */
for (i = 0; i < match_data->num_irqs; i++) {
irq = platform_get_irq_byname(pdev, match_data->irqs[i].name);
@@ -631,6 +709,7 @@ static int avsp_remove(struct platform_device *pdev)
/* misc device remove */
struct rkavsp_dev *avsp = platform_get_drvdata(pdev);
rkavsp_proc_cleanup(avsp);
pm_runtime_disable(&pdev->dev);
misc_deregister(&avsp->mdev);
mutex_destroy(&avsp->rcs_lock);

View File

@@ -53,13 +53,14 @@ extern int rkavsp_log_level;
#define AVSP_NAME "rockchip_avsp"
#define AVSP_MAX_BUS_CLK 3
#define RKAVSP_API_VERSION KERNEL_VERSION(0, 1, 0)
#define RKAVSP_PRY_MAX 6
struct rkavsp_buf {
int fd;
struct file *file;
struct list_head list;
struct vb2_buffer vb;
struct vb2_queue vb2_queue;
struct dma_buf *dbuf;
struct dma_buf_attachment *dba;
void *mem;
@@ -75,6 +76,45 @@ struct avsp_match_data {
int num_irqs;
};
struct rkavsp_pix_format {
u32 bandnum;
u32 width;
u32 height;
u32 mode;
u32 offset;
u32 stride_y;
u32 stride_c;
};
struct rkavsp_pix_format_pry {
u32 width[RKAVSP_PRY_MAX];
u32 height[RKAVSP_PRY_MAX];
u32 mode;
u32 offset;
u32 bytesperline;
};
struct rkavsp_frame_info {
u32 fs_seq;
u64 fs_timestamp;
};
struct rkavsp_debug_info {
u32 interval;
u32 frame_timeout_cnt;
};
enum rkfavsp_state {
RKAVSP_DCP_FRAME_END = BIT(1),
RKAVSP_DCP_STOP = BIT(16),
RKAVSP_DCP_START = BIT(17),
RKAVSP_DCP_ERROR = BIT(18),
RKAVSP_RCS_FRAME_END = BIT(1),
RKAVSP_RCS_STOP = BIT(16),
RKAVSP_RCS_START = BIT(17),
RKAVSP_RCS_ERROR = BIT(18),
};
struct rkavsp_dev {
struct device *dev;
struct regmap *grf;
@@ -82,6 +122,7 @@ struct rkavsp_dev {
struct completion rcs_cmpl;
struct list_head list;
const struct vb2_mem_ops *mem_ops;
struct vb2_queue vb2_queue;
void __iomem *base;
struct reset_control *reset;
const struct avsp_match_data *match_data;
@@ -90,13 +131,30 @@ struct rkavsp_dev {
int clk_rate_tbl_num;
int clks_num;
spinlock_t dcp_irq_lock;
spinlock_t rcs_irq_lock;
struct mutex dev_lock;
struct mutex dcp_lock;
struct mutex rcs_lock;
struct miscdevice mdev;
bool is_dma_config;
struct proc_dir_entry *procfs;
unsigned int dcp_isr_cnt;
unsigned int dcp_err_cnt;
unsigned int rcs_isr_cnt;
unsigned int rcs_err_cnt;
unsigned int in_seq;
unsigned int out_seq;
unsigned int dcp_state;
unsigned int rcs_state;
struct rkavsp_frame_info dcp_prev_frame;
struct rkavsp_frame_info dcp_curr_frame;
struct rkavsp_debug_info dcp_debug;
struct rkavsp_pix_format dcp_in_fmt;
struct rkavsp_pix_format_pry dcp_out_fmt;
struct rkavsp_frame_info rcs_prev_frame;
struct rkavsp_frame_info rcs_curr_frame;
struct rkavsp_debug_info rcs_debug;
struct rkavsp_pix_format rcs_in_fmt;
struct rkavsp_pix_format rcs_out_fmt;
};

View File

@@ -0,0 +1,183 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (c) Rockchip Electronics Co., Ltd. */
#include <linux/io.h>
#include "avsp.h"
#include "procfs.h"
#include "regs.h"
#include "version.h"
#ifdef CONFIG_PROC_FS
static const char * const mode[] = {
"raster(NV12)",
"til4x4",
"fbce",
"quad"
};
static void rkavsp_show_hw(struct seq_file *p, struct rkavsp_dev *hw)
{
u32 val;
int i, bandnum;
if (hw->dev->power.usage_count.counter <= 0) {
seq_printf(p, "\n%s\n", "HW close");
return;
}
// DCP
val = readl(hw->base + AVSP_DCP_CTRL);
bandnum = (val & 0x7);
seq_printf(p, "%-15s Bandnum: %d RD_mode: %s WR_mode: %s By_pass: %d\n",
"DCP_CTRL",
(val & 0x7),
mode[(val >> 3) & 0x3],
mode[(val >> 5) & 0x3],
(val >> 7) & 0x1);
val = readl(hw->base + AVSP_DCP_SIZE);
seq_printf(p, "%-15s Width: %d Height: %d\n", "DCP_SIZE",
(val & 0x07FF), (val >> 16) & 0x1FFF);
val = readl(hw->base + AVSP_DCP_RD_VIR_SIZE);
seq_printf(p, "%-15s Y:%d C:%d\n", "DCP_RD_VIR",
(val & 0x3FFF), (val >> 16) & 0x3FFF);
for (i = 0; i < bandnum; i++) {
val = readl(hw->base + AVSP_DCP_WR_LV0_VIR_SIZE + i * 4);
seq_printf(p, "%-15s Band: %d Y: %d C: %d\n", "DCP_WD_VIR",
i, (val & 0x3FFF), (val >> 16) & 0x3FFF);
}
for (i = 0; i < 5; i++) {
val = readl(hw->base + AVSP_DCP_STATUS0 + i * 4);
seq_printf(p, "%-15s %d 0x%x\n", "DCP_STATUS", i, val);
}
// RCS
val = readl(hw->base + AVSP_RCS_CTRL);
seq_printf(p, "%-15s Bandnum: %d RD_mode: %s WR_mode: %s FBCE_CTL: %x\n",
"RCS_CTRL",
(val & 0x7),
mode[(val >> 3) & 0x3],
mode[(val >> 5) & 0x3],
(val >> 9) & 0xF);
val = readl(hw->base + AVSP_RCS_SIZE);
seq_printf(p, "%-15s Width: %d Height: %d\n", "RCS_SIZE",
(val & 0x07FF), (val >> 16) & 0x1FFF);
val = readl(hw->base + AVSP_DCP_RD_VIR_SIZE);
seq_printf(p, "%-15s Y: %d C: %d\n", "RCS_WR_VIR",
(val & 0x3FFF), (val >> 16) & 0x3FFF);
for (i = 0; i < 5; i++) {
val = readl(hw->base + AVSP_RCS_STATUS0 + i * 4);
seq_printf(p, "%-15s %d 0x%x\n", "RCS_STATUS", i, val);
}
}
static int rkavsp_show(struct seq_file *p, void *v)
{
struct rkavsp_dev *ofl = p->private;
int i;
seq_printf(p, "%-20s Version:v%02x.%02x.%02x\n", AVSP_NAME,
RKAVSP_DRIVER_VERSION >> 16,
(RKAVSP_DRIVER_VERSION & 0xff00) >> 8,
RKAVSP_DRIVER_VERSION & 0xff);
for (i = 0; i < ofl->clks_num; i++) {
seq_printf(p, "%-15s %ld\n", ofl->match_data->clks[i],
clk_get_rate(ofl->clks[i]));
}
seq_printf(p, "%-15s DCP_Cnt:%d ErrCnt:%d\n", "DCP_INT", ofl->dcp_isr_cnt, ofl->dcp_err_cnt);
seq_printf(p, "%-15s RCS_Cnt:%d ErrCnt:%d\n", "RCS_INT", ofl->rcs_isr_cnt, ofl->rcs_err_cnt);
// DCP
seq_printf(p, "%-15s Bandnum: %d Rdmode: %x(%s) Size:%dx%d\n",
"DCP:Input",
ofl->dcp_in_fmt.bandnum, ofl->dcp_in_fmt.mode, mode[ofl->dcp_in_fmt.mode],
ofl->dcp_in_fmt.width, ofl->dcp_in_fmt.height);
seq_printf(p, "%-15s In_offset:%d(Byte) Stride_y: %d Stride_c: %d(Word)\n",
"DCP:Input",
ofl->dcp_in_fmt.offset, ofl->dcp_in_fmt.stride_y, ofl->dcp_in_fmt.stride_c);
seq_printf(p, "%-15s Wrmode: %x(%s)\n",
"DCP:Output", ofl->dcp_out_fmt.mode, mode[ofl->dcp_out_fmt.mode]);
for (i = 0; i < ofl->dcp_in_fmt.bandnum; i++) {
seq_printf(p, "%-15s band: %d Stride and Hgt: %d(Word) x %d(Byte)\n",
"DCP:Output", i, ofl->dcp_out_fmt.width[i], ofl->dcp_out_fmt.height[i]);
}
seq_printf(p, "%-15s (frame:%d rate:%dms state:%s time:%dms frm_timeout_cnt:%d)\n\n",
"AVSP_DCP",
ofl->dcp_curr_frame.fs_seq,
(u32)(ofl->dcp_curr_frame.fs_timestamp - ofl->dcp_prev_frame.fs_timestamp) /
1000 / 1000,
(ofl->rcs_state & RKAVSP_DCP_FRAME_END) ? "idle" : "working",
ofl->dcp_debug.interval / 1000,
ofl->dcp_debug.frame_timeout_cnt);
// RCS
seq_printf(p, "%-15s Bandnum: %d Rdmode: %x(%s) Size:%dx%d\n", "RCS:Input",
ofl->rcs_in_fmt.bandnum, ofl->rcs_in_fmt.mode, mode[ofl->rcs_in_fmt.mode],
ofl->rcs_in_fmt.width, ofl->rcs_in_fmt.height);
seq_printf(p, "%-15s Wrmode: %x(%s) Offsets %d(Byte) Stride_y: %d Stride_c: %d(Word)\n",
"RCS:Output",
ofl->rcs_out_fmt.mode, mode[ofl->rcs_out_fmt.mode], ofl->rcs_out_fmt.offset,
ofl->rcs_out_fmt.stride_y, ofl->rcs_out_fmt.stride_c);
seq_printf(p, "%-15s (frame:%d rate:%dms state:%s time:%dms frm_timeout_cnt:%d)\n\n",
"AVSP_RCS",
ofl->rcs_curr_frame.fs_seq,
(u32)(ofl->rcs_curr_frame.fs_timestamp - ofl->rcs_prev_frame.fs_timestamp) /
1000 / 1000,
(ofl->rcs_state & RKAVSP_RCS_FRAME_END) ? "idle" : "working",
ofl->rcs_debug.interval / 1000,
ofl->rcs_debug.frame_timeout_cnt);
rkavsp_show_hw(p, ofl);
return 0;
}
static int rkavsp_open(struct inode *inode, struct file *file)
{
#if IS_LINUX_VERSION_AT_LEAST_6_1
struct rkavsp_dev *data = pde_data(inode);
#else
struct rkavsp_dev *data = PDE_DATA(inode);
#endif
return single_open(file, rkavsp_show, data);
}
static const struct proc_ops rkavsp_ops = {
.proc_open = rkavsp_open,
.proc_read = seq_read,
.proc_lseek = seq_lseek,
.proc_release = single_release,
};
int rkavsp_proc_init(struct rkavsp_dev *dev)
{
dev->procfs = proc_create_data(AVSP_NAME, 0, NULL, &rkavsp_ops, dev);
if (!dev->procfs)
return -EINVAL;
return 0;
}
void rkavsp_proc_cleanup(struct rkavsp_dev *dev)
{
if (dev->procfs)
remove_proc_entry(AVSP_NAME, NULL);
dev->procfs = NULL;
}
#endif /* CONFIG_PROC_FS */

View File

@@ -0,0 +1,20 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKAVSP_PROCFS_H
#define _RKAVSP_PROCFS_H
#include <linux/clk.h>
#include <linux/proc_fs.h>
#include <linux/sem.h>
#include <linux/seq_file.h>
#ifdef CONFIG_PROC_FS
int rkavsp_proc_init(struct rkavsp_dev *dev);
void rkavsp_proc_cleanup(struct rkavsp_dev *dev);
#else
static inline int rkavsp_proc_init(struct rkavsp_dev *dev) { return 0; }
static inline void rkavsp_proc_cleanup(struct rkavsp_dev *dev) {}
#endif
#endif

View File

@@ -27,7 +27,7 @@
/* AVSP_SRC_SIZE */
#define SW_AVSP_SRC_WIDTH(x) ((x) & 0x07ff)
#define Sw_AVSP_SRC_HEIGHT(x) (((x) & 0x1fff) << 16)
#define SW_AVSP_SRC_HEIGHT(x) (((x) & 0x1fff) << 16)
/* AVSP_RD_VIR_STRIDE */
#define AVSP_RD_VIR_STRIDE_Y(x) ((x) & 0x3fff)

View File

@@ -0,0 +1,17 @@
/* SPDX-License-Identifier: GPL-2.0 */
/* Copyright (c) 2025 Rockchip Electronics Co., Ltd. */
#ifndef _RKAVSP_VERSION_H
#define _RKAVSP_VERSION_H
#include <linux/version.h>
/*
* RKAVSP DRIVER VERSION NOTE
*
* v0.1.0:
* 1. First version;
*/
#define RKAVSP_DRIVER_VERSION RKAVSP_API_VERSION
#endif