mirror of
https://github.com/hardkernel/linux.git
synced 2026-06-07 11:26:02 +09:00
media: rockchip: cif support rk3588
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com> Change-Id: I4398f9163b858c8f7dd32c88f2f2d37a9f464bcc
This commit is contained in:
@@ -6,4 +6,6 @@ video_rkcif-objs += dev.o \
|
||||
cif-luma.o \
|
||||
hw.o \
|
||||
subdev-itf.o \
|
||||
procfs.o
|
||||
procfs.o \
|
||||
cif-scale.o \
|
||||
common.o
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -289,7 +289,7 @@ static void rkcif_luma_readout_task(unsigned long data)
|
||||
|
||||
void rkcif_luma_isr(struct rkcif_luma_vdev *luma_vdev, int mipi_id, u32 frame_id)
|
||||
{
|
||||
u8 hdr_mode = luma_vdev->cifdev->hdr.mode;
|
||||
u8 hdr_mode = luma_vdev->cifdev->hdr.hdr_mode;
|
||||
enum rkcif_luma_frm_mode frm_mode;
|
||||
bool send_task;
|
||||
u32 i, value;
|
||||
|
||||
1171
drivers/media/platform/rockchip/cif/cif-scale.c
Normal file
1171
drivers/media/platform/rockchip/cif/cif-scale.c
Normal file
File diff suppressed because it is too large
Load Diff
187
drivers/media/platform/rockchip/cif/common.c
Normal file
187
drivers/media/platform/rockchip/cif/common.c
Normal file
@@ -0,0 +1,187 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/* Copyright (C) 2021 Rockchip Electronics Co., Ltd */
|
||||
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <linux/of_platform.h>
|
||||
#include "dev.h"
|
||||
#include "common.h"
|
||||
|
||||
static int rkcif_alloc_buffer(struct rkcif_device *dev,
|
||||
struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
unsigned long attrs = buf->is_need_vaddr ? 0 : DMA_ATTR_NO_KERNEL_MAPPING;
|
||||
const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
|
||||
struct sg_table *sg_tbl;
|
||||
void *mem_priv;
|
||||
int ret = 0;
|
||||
|
||||
if (!buf->size) {
|
||||
ret = -EINVAL;
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (dev->hw_dev->is_dma_contig)
|
||||
attrs |= DMA_ATTR_FORCE_CONTIGUOUS;
|
||||
buf->size = PAGE_ALIGN(buf->size);
|
||||
mem_priv = g_ops->alloc(dev->hw_dev->dev, attrs, buf->size,
|
||||
DMA_BIDIRECTIONAL, GFP_KERNEL | GFP_DMA32);
|
||||
if (IS_ERR_OR_NULL(mem_priv)) {
|
||||
ret = -ENOMEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
buf->mem_priv = mem_priv;
|
||||
if (dev->hw_dev->is_dma_sg_ops) {
|
||||
sg_tbl = (struct sg_table *)g_ops->cookie(mem_priv);
|
||||
buf->dma_addr = sg_dma_address(sg_tbl->sgl);
|
||||
g_ops->prepare(mem_priv);
|
||||
} else {
|
||||
buf->dma_addr = *((dma_addr_t *)g_ops->cookie(mem_priv));
|
||||
}
|
||||
if (buf->is_need_vaddr)
|
||||
buf->vaddr = g_ops->vaddr(mem_priv);
|
||||
if (buf->is_need_dbuf) {
|
||||
buf->dbuf = g_ops->get_dmabuf(mem_priv, O_RDWR);
|
||||
if (buf->is_need_dmafd) {
|
||||
buf->dma_fd = dma_buf_fd(buf->dbuf, O_CLOEXEC);
|
||||
if (buf->dma_fd < 0) {
|
||||
dma_buf_put(buf->dbuf);
|
||||
ret = buf->dma_fd;
|
||||
goto err;
|
||||
}
|
||||
get_dma_buf(buf->dbuf);
|
||||
}
|
||||
}
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"%s buf:0x%x~0x%x size:%d\n", __func__,
|
||||
(u32)buf->dma_addr, (u32)buf->dma_addr + buf->size, buf->size);
|
||||
return ret;
|
||||
err:
|
||||
dev_err(dev->dev, "%s failed ret:%d\n", __func__, ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rkcif_free_buffer(struct rkcif_device *dev,
|
||||
struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
const struct vb2_mem_ops *g_ops = dev->hw_dev->mem_ops;
|
||||
|
||||
if (buf && buf->mem_priv) {
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"%s buf:0x%x~0x%x\n", __func__,
|
||||
(u32)buf->dma_addr, (u32)buf->dma_addr + buf->size);
|
||||
if (buf->dbuf)
|
||||
dma_buf_put(buf->dbuf);
|
||||
g_ops->put(buf->mem_priv);
|
||||
buf->size = 0;
|
||||
buf->dbuf = NULL;
|
||||
buf->vaddr = NULL;
|
||||
buf->mem_priv = NULL;
|
||||
buf->is_need_dbuf = false;
|
||||
buf->is_need_vaddr = false;
|
||||
buf->is_need_dmafd = false;
|
||||
}
|
||||
}
|
||||
|
||||
static int rkcif_alloc_page_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
struct rkcif_hw *hw = dev->hw_dev;
|
||||
u32 i, n_pages = PAGE_ALIGN(buf->size) >> PAGE_SHIFT;
|
||||
struct page *page = NULL, **pages = NULL;
|
||||
struct sg_table *sg = NULL;
|
||||
int ret = -ENOMEM;
|
||||
|
||||
page = alloc_pages(GFP_KERNEL | GFP_DMA32, 0);
|
||||
if (!page)
|
||||
goto err;
|
||||
|
||||
pages = kvmalloc_array(n_pages, sizeof(struct page *), GFP_KERNEL);
|
||||
if (!pages)
|
||||
goto free_page;
|
||||
for (i = 0; i < n_pages; i++)
|
||||
pages[i] = page;
|
||||
|
||||
sg = kmalloc(sizeof(struct sg_table), GFP_KERNEL);
|
||||
if (!sg)
|
||||
goto free_pages;
|
||||
ret = sg_alloc_table_from_pages(sg, pages, n_pages, 0,
|
||||
n_pages << PAGE_SHIFT, GFP_KERNEL);
|
||||
if (ret)
|
||||
goto free_sg;
|
||||
|
||||
ret = dma_map_sg(hw->dev, sg->sgl, sg->nents, DMA_BIDIRECTIONAL);
|
||||
buf->dma_addr = sg_dma_address(sg->sgl);
|
||||
buf->mem_priv = sg;
|
||||
buf->pages = pages;
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"%s buf:0x%x map cnt:%d size:%d\n", __func__,
|
||||
(u32)buf->dma_addr, ret, buf->size);
|
||||
return 0;
|
||||
free_sg:
|
||||
kfree(sg);
|
||||
free_pages:
|
||||
kvfree(pages);
|
||||
free_page:
|
||||
__free_pages(page, 0);
|
||||
err:
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void rkcif_free_page_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
struct sg_table *sg = buf->mem_priv;
|
||||
|
||||
if (!sg)
|
||||
return;
|
||||
dma_unmap_sg(dev->hw_dev->dev, sg->sgl, sg->nents, DMA_BIDIRECTIONAL);
|
||||
sg_free_table(sg);
|
||||
kfree(sg);
|
||||
__free_pages(buf->pages[0], 0);
|
||||
kvfree(buf->pages);
|
||||
buf->mem_priv = NULL;
|
||||
buf->pages = NULL;
|
||||
}
|
||||
|
||||
int rkcif_alloc_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
struct rkcif_hw *hw = dev->hw_dev;
|
||||
int ret = 0;
|
||||
|
||||
mutex_lock(&hw->dev_lock);
|
||||
if (buf->mem_priv)
|
||||
goto end;
|
||||
|
||||
if (buf->size == 0)
|
||||
goto end;
|
||||
|
||||
if (hw->iommu_en) {
|
||||
ret = rkcif_alloc_page_dummy_buf(dev, buf);
|
||||
goto end;
|
||||
}
|
||||
|
||||
ret = rkcif_alloc_buffer(dev, buf);
|
||||
if (!ret)
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"%s buf:0x%x size:%d\n", __func__,
|
||||
(u32)buf->dma_addr, buf->size);
|
||||
end:
|
||||
if (ret < 0)
|
||||
v4l2_err(&dev->v4l2_dev, "%s failed:%d\n", __func__, ret);
|
||||
mutex_unlock(&hw->dev_lock);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void rkcif_free_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf)
|
||||
{
|
||||
struct rkcif_hw *hw = dev->hw_dev;
|
||||
|
||||
mutex_lock(&hw->dev_lock);
|
||||
|
||||
if (hw->iommu_en)
|
||||
rkcif_free_page_dummy_buf(dev, buf);
|
||||
else
|
||||
rkcif_free_buffer(dev, buf);
|
||||
mutex_unlock(&hw->dev_lock);
|
||||
}
|
||||
|
||||
22
drivers/media/platform/rockchip/cif/common.h
Normal file
22
drivers/media/platform/rockchip/cif/common.h
Normal file
@@ -0,0 +1,22 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Copyright (c) 2021 Rockchip Electronics Co., Ltd. */
|
||||
|
||||
#ifndef _RKCIF_COMMON_H
|
||||
#define _RKCIF_COMMON_H
|
||||
#include <linux/clk.h>
|
||||
#include <linux/mutex.h>
|
||||
#include <linux/media.h>
|
||||
#include <media/media-device.h>
|
||||
#include <media/media-entity.h>
|
||||
#include <media/v4l2-ctrls.h>
|
||||
#include <media/v4l2-device.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
#include <media/v4l2-mc.h>
|
||||
#include "dev.h"
|
||||
|
||||
int rkcif_alloc_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf);
|
||||
void rkcif_free_common_dummy_buf(struct rkcif_device *dev, struct rkcif_dummy_buffer *buf);
|
||||
|
||||
#endif /* _RKCIF_COMMON_H */
|
||||
|
||||
@@ -92,6 +92,9 @@ static ssize_t rkcif_store_compact_mode(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_compact_mode, rkcif_store_compact_mode);
|
||||
|
||||
static ssize_t rkcif_show_line_int_num(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -109,9 +112,15 @@ static ssize_t rkcif_store_line_int_num(struct device *dev,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
struct sditf_priv *priv = cif_dev->sditf;
|
||||
int val = 0;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->toisp_inf.link_mode != TOISP_NONE) {
|
||||
dev_info(cif_dev->dev,
|
||||
"current mode is on the fly, wake up mode wouldn't used\n");
|
||||
return len;
|
||||
}
|
||||
ret = kstrtoint(buf, 0, &val);
|
||||
if (!ret && val >= 0 && val <= 0x3fff)
|
||||
cif_dev->wait_line_cache = val;
|
||||
@@ -120,6 +129,9 @@ static ssize_t rkcif_store_line_int_num(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_line_int_num, rkcif_store_line_int_num);
|
||||
|
||||
static ssize_t rkcif_show_dummybuf_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
@@ -152,8 +164,11 @@ static ssize_t rkcif_store_dummybuf_mode(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
/* show the compact mode of each stream in stream index order,
|
||||
* 1 for compact, 0 for 16bit
|
||||
static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode);
|
||||
|
||||
/* show the memory mode of each stream in stream index order,
|
||||
* 1 for high align, 0 for low align
|
||||
*/
|
||||
static ssize_t rkcif_show_memory_mode(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
@@ -210,24 +225,303 @@ static ssize_t rkcif_store_memory_mode(struct device *dev,
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(compact_test, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_compact_mode, rkcif_store_compact_mode);
|
||||
|
||||
static DEVICE_ATTR(wait_line, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_line_int_num, rkcif_store_line_int_num);
|
||||
|
||||
static DEVICE_ATTR(is_use_dummybuf, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_dummybuf_mode, rkcif_store_dummybuf_mode);
|
||||
|
||||
static DEVICE_ATTR(is_high_align, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_memory_mode, rkcif_store_memory_mode);
|
||||
|
||||
static ssize_t rkcif_show_scale_ch0_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "ch0 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[0].blc.pattern00,
|
||||
cif_dev->scale_vdev[0].blc.pattern01,
|
||||
cif_dev->scale_vdev[0].blc.pattern02,
|
||||
cif_dev->scale_vdev[0].blc.pattern03);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_scale_ch0_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i = 0, index = 0;
|
||||
unsigned int val[4] = {0};
|
||||
unsigned int temp = 0;
|
||||
int ret = 0;
|
||||
int j = 0;
|
||||
char cha[2] = {0};
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
|
||||
index++;
|
||||
j = 0;
|
||||
if (index == 4)
|
||||
break;
|
||||
continue;
|
||||
} else {
|
||||
if (buf[i] < '0' || buf[i] > '9')
|
||||
continue;
|
||||
cha[0] = buf[i];
|
||||
cha[1] = '\0';
|
||||
ret = kstrtoint(cha, 0, &temp);
|
||||
if (!ret) {
|
||||
if (j)
|
||||
val[index] *= 10;
|
||||
val[index] += temp;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255)
|
||||
return -EINVAL;
|
||||
cif_dev->scale_vdev[0].blc.pattern00 = val[0];
|
||||
cif_dev->scale_vdev[0].blc.pattern01 = val[1];
|
||||
cif_dev->scale_vdev[0].blc.pattern02 = val[2];
|
||||
cif_dev->scale_vdev[0].blc.pattern03 = val[3];
|
||||
dev_info(cif_dev->dev,
|
||||
"set ch0 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[0].blc.pattern00,
|
||||
cif_dev->scale_vdev[0].blc.pattern01,
|
||||
cif_dev->scale_vdev[0].blc.pattern02,
|
||||
cif_dev->scale_vdev[0].blc.pattern03);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(scale_ch0_blc, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_scale_ch0_blc, rkcif_store_scale_ch0_blc);
|
||||
|
||||
static ssize_t rkcif_show_scale_ch1_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "ch1 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[1].blc.pattern00,
|
||||
cif_dev->scale_vdev[1].blc.pattern01,
|
||||
cif_dev->scale_vdev[1].blc.pattern02,
|
||||
cif_dev->scale_vdev[1].blc.pattern03);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_scale_ch1_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i = 0, index = 0;
|
||||
unsigned int val[4] = {0};
|
||||
unsigned int temp = 0;
|
||||
int ret = 0;
|
||||
int j = 0;
|
||||
char cha[2] = {0};
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
|
||||
index++;
|
||||
j = 0;
|
||||
if (index == 4)
|
||||
break;
|
||||
continue;
|
||||
} else {
|
||||
if (buf[i] < '0' || buf[i] > '9')
|
||||
continue;
|
||||
cha[0] = buf[i];
|
||||
cha[1] = '\0';
|
||||
ret = kstrtoint(cha, 0, &temp);
|
||||
if (!ret) {
|
||||
if (j)
|
||||
val[index] *= 10;
|
||||
val[index] += temp;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255)
|
||||
return -EINVAL;
|
||||
|
||||
cif_dev->scale_vdev[1].blc.pattern00 = val[0];
|
||||
cif_dev->scale_vdev[1].blc.pattern01 = val[1];
|
||||
cif_dev->scale_vdev[1].blc.pattern02 = val[2];
|
||||
cif_dev->scale_vdev[1].blc.pattern03 = val[3];
|
||||
|
||||
dev_info(cif_dev->dev,
|
||||
"set ch1 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[1].blc.pattern00,
|
||||
cif_dev->scale_vdev[1].blc.pattern01,
|
||||
cif_dev->scale_vdev[1].blc.pattern02,
|
||||
cif_dev->scale_vdev[1].blc.pattern03);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(scale_ch1_blc, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_scale_ch1_blc, rkcif_store_scale_ch1_blc);
|
||||
|
||||
static ssize_t rkcif_show_scale_ch2_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "ch2 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[2].blc.pattern00,
|
||||
cif_dev->scale_vdev[2].blc.pattern01,
|
||||
cif_dev->scale_vdev[2].blc.pattern02,
|
||||
cif_dev->scale_vdev[2].blc.pattern03);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_scale_ch2_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i = 0, index = 0;
|
||||
unsigned int val[4] = {0};
|
||||
unsigned int temp = 0;
|
||||
int ret = 0;
|
||||
int j = 0;
|
||||
char cha[2] = {0};
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
|
||||
index++;
|
||||
j = 0;
|
||||
if (index == 4)
|
||||
break;
|
||||
continue;
|
||||
} else {
|
||||
if (buf[i] < '0' || buf[i] > '9')
|
||||
continue;
|
||||
cha[0] = buf[i];
|
||||
cha[1] = '\0';
|
||||
ret = kstrtoint(cha, 0, &temp);
|
||||
if (!ret) {
|
||||
if (j)
|
||||
val[index] *= 10;
|
||||
val[index] += temp;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255)
|
||||
return -EINVAL;
|
||||
|
||||
cif_dev->scale_vdev[2].blc.pattern00 = val[0];
|
||||
cif_dev->scale_vdev[2].blc.pattern01 = val[1];
|
||||
cif_dev->scale_vdev[2].blc.pattern02 = val[2];
|
||||
cif_dev->scale_vdev[2].blc.pattern03 = val[3];
|
||||
|
||||
dev_info(cif_dev->dev,
|
||||
"set ch2 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[2].blc.pattern00,
|
||||
cif_dev->scale_vdev[2].blc.pattern01,
|
||||
cif_dev->scale_vdev[2].blc.pattern02,
|
||||
cif_dev->scale_vdev[2].blc.pattern03);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
static DEVICE_ATTR(scale_ch2_blc, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_scale_ch2_blc, rkcif_store_scale_ch2_blc);
|
||||
|
||||
static ssize_t rkcif_show_scale_ch3_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
char *buf)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int ret;
|
||||
|
||||
ret = snprintf(buf, PAGE_SIZE, "ch3 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[3].blc.pattern00,
|
||||
cif_dev->scale_vdev[3].blc.pattern01,
|
||||
cif_dev->scale_vdev[3].blc.pattern02,
|
||||
cif_dev->scale_vdev[3].blc.pattern03);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static ssize_t rkcif_store_scale_ch3_blc(struct device *dev,
|
||||
struct device_attribute *attr,
|
||||
const char *buf, size_t len)
|
||||
{
|
||||
struct rkcif_device *cif_dev = (struct rkcif_device *)dev_get_drvdata(dev);
|
||||
int i = 0, index = 0;
|
||||
unsigned int val[4] = {0};
|
||||
unsigned int temp = 0;
|
||||
int ret = 0;
|
||||
int j = 0;
|
||||
char cha[2] = {0};
|
||||
|
||||
if (buf) {
|
||||
index = 0;
|
||||
for (i = 0; i < len; i++) {
|
||||
if (((buf[i] == ' ') || (buf[i] == '\n')) && j) {
|
||||
index++;
|
||||
j = 0;
|
||||
if (index == 4)
|
||||
break;
|
||||
continue;
|
||||
} else {
|
||||
if (buf[i] < '0' || buf[i] > '9')
|
||||
continue;
|
||||
cha[0] = buf[i];
|
||||
cha[1] = '\0';
|
||||
ret = kstrtoint(cha, 0, &temp);
|
||||
if (!ret) {
|
||||
if (j)
|
||||
val[index] *= 10;
|
||||
val[index] += temp;
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (val[0] > 255 || val[1] > 255 || val[2] > 255 || val[3] > 255)
|
||||
return -EINVAL;
|
||||
|
||||
cif_dev->scale_vdev[3].blc.pattern00 = val[0];
|
||||
cif_dev->scale_vdev[3].blc.pattern01 = val[1];
|
||||
cif_dev->scale_vdev[3].blc.pattern02 = val[2];
|
||||
cif_dev->scale_vdev[3].blc.pattern03 = val[3];
|
||||
|
||||
dev_info(cif_dev->dev,
|
||||
"set ch3 pattern00: %d, pattern01: %d, pattern02: %d, pattern03: %d\n",
|
||||
cif_dev->scale_vdev[3].blc.pattern00,
|
||||
cif_dev->scale_vdev[3].blc.pattern01,
|
||||
cif_dev->scale_vdev[3].blc.pattern02,
|
||||
cif_dev->scale_vdev[3].blc.pattern03);
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
static DEVICE_ATTR(scale_ch3_blc, S_IWUSR | S_IRUSR,
|
||||
rkcif_show_scale_ch3_blc, rkcif_store_scale_ch3_blc);
|
||||
|
||||
static struct attribute *dev_attrs[] = {
|
||||
&dev_attr_compact_test.attr,
|
||||
&dev_attr_wait_line.attr,
|
||||
&dev_attr_is_use_dummybuf.attr,
|
||||
&dev_attr_is_high_align.attr,
|
||||
&dev_attr_scale_ch0_blc.attr,
|
||||
&dev_attr_scale_ch1_blc.attr,
|
||||
&dev_attr_scale_ch2_blc.attr,
|
||||
&dev_attr_scale_ch3_blc.attr,
|
||||
NULL,
|
||||
};
|
||||
|
||||
@@ -244,11 +538,17 @@ void rkcif_write_register(struct rkcif_device *dev,
|
||||
{
|
||||
void __iomem *base = dev->hw_dev->base_addr;
|
||||
const struct cif_reg *reg = &dev->hw_dev->cif_regs[index];
|
||||
int csi_offset = 0;
|
||||
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS &&
|
||||
dev->chip_id == CHIP_RK3588_CIF &&
|
||||
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
|
||||
index <= CIF_REG_MIPI_ON_PAD)
|
||||
csi_offset = dev->csi_host_idx * 0x100;
|
||||
if (index < CIF_REG_INDEX_MAX) {
|
||||
if (index == CIF_REG_DVP_CTRL ||
|
||||
(index != CIF_REG_DVP_CTRL && reg->offset != 0x0))
|
||||
write_cif_reg(base, reg->offset, val);
|
||||
write_cif_reg(base, reg->offset + csi_offset, val);
|
||||
else
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"write reg[%d]:0x%x failed, maybe useless!!!\n",
|
||||
@@ -262,13 +562,20 @@ void rkcif_write_register_or(struct rkcif_device *dev,
|
||||
unsigned int reg_val = 0x0;
|
||||
void __iomem *base = dev->hw_dev->base_addr;
|
||||
const struct cif_reg *reg = &dev->hw_dev->cif_regs[index];
|
||||
int csi_offset = 0;
|
||||
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS &&
|
||||
dev->chip_id == CHIP_RK3588_CIF &&
|
||||
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
|
||||
index <= CIF_REG_MIPI_ON_PAD)
|
||||
csi_offset = dev->csi_host_idx * 0x100;
|
||||
|
||||
if (index < CIF_REG_INDEX_MAX) {
|
||||
if (index == CIF_REG_DVP_CTRL ||
|
||||
(index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) {
|
||||
reg_val = read_cif_reg(base, reg->offset);
|
||||
reg_val = read_cif_reg(base, reg->offset + csi_offset);
|
||||
reg_val |= val;
|
||||
write_cif_reg(base, reg->offset, reg_val);
|
||||
write_cif_reg(base, reg->offset + csi_offset, reg_val);
|
||||
} else {
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"write reg[%d]:0x%x with OR failed, maybe useless!!!\n",
|
||||
@@ -283,13 +590,20 @@ void rkcif_write_register_and(struct rkcif_device *dev,
|
||||
unsigned int reg_val = 0x0;
|
||||
void __iomem *base = dev->hw_dev->base_addr;
|
||||
const struct cif_reg *reg = &dev->hw_dev->cif_regs[index];
|
||||
int csi_offset = 0;
|
||||
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS &&
|
||||
dev->chip_id == CHIP_RK3588_CIF &&
|
||||
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
|
||||
index <= CIF_REG_MIPI_ON_PAD)
|
||||
csi_offset = dev->csi_host_idx * 0x100;
|
||||
|
||||
if (index < CIF_REG_INDEX_MAX) {
|
||||
if (index == CIF_REG_DVP_CTRL ||
|
||||
(index != CIF_REG_DVP_CTRL && reg->offset != 0x0)) {
|
||||
reg_val = read_cif_reg(base, reg->offset);
|
||||
reg_val = read_cif_reg(base, reg->offset + csi_offset);
|
||||
reg_val &= val;
|
||||
write_cif_reg(base, reg->offset, reg_val);
|
||||
write_cif_reg(base, reg->offset + csi_offset, reg_val);
|
||||
} else {
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"write reg[%d]:0x%x with OR failed, maybe useless!!!\n",
|
||||
@@ -304,11 +618,18 @@ unsigned int rkcif_read_register(struct rkcif_device *dev,
|
||||
unsigned int val = 0x0;
|
||||
void __iomem *base = dev->hw_dev->base_addr;
|
||||
const struct cif_reg *reg = &dev->hw_dev->cif_regs[index];
|
||||
int csi_offset = 0;
|
||||
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS &&
|
||||
dev->chip_id == CHIP_RK3588_CIF &&
|
||||
index >= CIF_REG_MIPI_LVDS_ID0_CTRL0 &&
|
||||
index <= CIF_REG_MIPI_ON_PAD)
|
||||
csi_offset = dev->csi_host_idx * 0x100;
|
||||
|
||||
if (index < CIF_REG_INDEX_MAX) {
|
||||
if (index == CIF_REG_DVP_CTRL ||
|
||||
(index != CIF_REG_DVP_CTRL && reg->offset != 0x0))
|
||||
val = read_cif_reg(base, reg->offset);
|
||||
val = read_cif_reg(base, reg->offset + csi_offset);
|
||||
else
|
||||
v4l2_dbg(1, rkcif_debug, &dev->v4l2_dev,
|
||||
"read reg[%d] failed, maybe useless!!!\n",
|
||||
@@ -375,6 +696,12 @@ void rkcif_enable_dvp_clk_dual_edge(struct rkcif_device *dev, bool on)
|
||||
else
|
||||
val = CIF_SAMPLING_EDGE_SINGLE;
|
||||
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
|
||||
} else if (dev->chip_id == CHIP_RK3588_CIF) {
|
||||
if (on)
|
||||
val = RK3588_CIF_PCLK_DUAL_EDGE;
|
||||
else
|
||||
val = RK3588_CIF_PCLK_SINGLE_EDGE;
|
||||
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -402,6 +729,13 @@ void rkcif_config_dvp_clk_sampling_edge(struct rkcif_device *dev,
|
||||
else
|
||||
val = RK3568_CIF_PCLK_SAMPLING_EDGE_FALLING;
|
||||
}
|
||||
|
||||
if (dev->chip_id == CHIP_RK3588_CIF) {
|
||||
if (edge == RKCIF_CLK_RISING)
|
||||
val = RK3588_CIF_PCLK_SAMPLING_EDGE_RISING;
|
||||
else
|
||||
val = RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING;
|
||||
}
|
||||
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
|
||||
}
|
||||
}
|
||||
@@ -490,7 +824,7 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
|
||||
bool can_be_set = false;
|
||||
int i, ret;
|
||||
|
||||
if (cif_dev->hdr.mode == NO_HDR) {
|
||||
if (cif_dev->hdr.hdr_mode == NO_HDR) {
|
||||
if ((on && atomic_inc_return(&p->stream_cnt) > 1) ||
|
||||
(!on && atomic_dec_return(&p->stream_cnt) > 0))
|
||||
return 0;
|
||||
@@ -504,6 +838,9 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
|
||||
cif_dev->irq_stats.dvp_overflow_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_pix_err_cnt = 0;
|
||||
cif_dev->irq_stats.all_err_cnt = 0;
|
||||
cif_dev->irq_stats.csi_size_err_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_size_err_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_bwidth_lack_cnt = 0;
|
||||
cif_dev->irq_stats.all_frm_end_cnt = 0;
|
||||
cif_dev->reset_watchdog_timer.is_triggered = false;
|
||||
cif_dev->reset_watchdog_timer.is_running = false;
|
||||
@@ -524,14 +861,14 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
|
||||
|
||||
if (on) {
|
||||
atomic_inc(&p->stream_cnt);
|
||||
if (cif_dev->hdr.mode == HDR_X2) {
|
||||
if (cif_dev->hdr.hdr_mode == HDR_X2) {
|
||||
if (atomic_read(&p->stream_cnt) == 1) {
|
||||
rockchip_set_system_status(SYS_STATUS_CIF0);
|
||||
can_be_set = false;
|
||||
} else if (atomic_read(&p->stream_cnt) == 2) {
|
||||
can_be_set = true;
|
||||
}
|
||||
} else if (cif_dev->hdr.mode == HDR_X3) {
|
||||
} else if (cif_dev->hdr.hdr_mode == HDR_X3) {
|
||||
if (atomic_read(&p->stream_cnt) == 1) {
|
||||
rockchip_set_system_status(SYS_STATUS_CIF0);
|
||||
can_be_set = false;
|
||||
@@ -549,7 +886,10 @@ static int rkcif_pipeline_set_stream(struct rkcif_pipeline *p, bool on)
|
||||
cif_dev->irq_stats.dvp_line_err_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_overflow_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_pix_err_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_bwidth_lack_cnt = 0;
|
||||
cif_dev->irq_stats.all_err_cnt = 0;
|
||||
cif_dev->irq_stats.csi_size_err_cnt = 0;
|
||||
cif_dev->irq_stats.dvp_size_err_cnt = 0;
|
||||
cif_dev->irq_stats.all_frm_end_cnt = 0;
|
||||
cif_dev->is_start_hdr = true;
|
||||
cif_dev->reset_watchdog_timer.is_triggered = false;
|
||||
@@ -581,98 +921,104 @@ err_stream_off:
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************** media controller *******************************/
|
||||
static int rkcif_create_links(struct rkcif_device *dev)
|
||||
static int rkcif_create_link(struct rkcif_device *dev,
|
||||
struct rkcif_sensor_info *sensor,
|
||||
u32 stream_num,
|
||||
bool *mipi_lvds_linked)
|
||||
{
|
||||
int ret;
|
||||
u32 flags;
|
||||
unsigned int s, pad, id, stream_num = 0;
|
||||
bool mipi_lvds_linked = false;
|
||||
struct rkcif_sensor_info linked_sensor;
|
||||
struct media_entity *source_entity, *sink_entity;
|
||||
int ret = 0;
|
||||
u32 flags, pad, id;
|
||||
|
||||
if (dev->chip_id < CHIP_RV1126_CIF) {
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS)
|
||||
stream_num = RKCIF_MAX_STREAM_MIPI;
|
||||
else
|
||||
stream_num = RKCIF_SINGLE_STREAM;
|
||||
linked_sensor.lanes = sensor->lanes;
|
||||
|
||||
if (sensor->mbus.type == V4L2_MBUS_CCP2) {
|
||||
linked_sensor.sd = &dev->lvds_subdev.sd;
|
||||
dev->lvds_subdev.sensor_self.sd = &dev->lvds_subdev.sd;
|
||||
dev->lvds_subdev.sensor_self.lanes = sensor->lanes;
|
||||
memcpy(&dev->lvds_subdev.sensor_self.mbus, &sensor->mbus,
|
||||
sizeof(struct v4l2_mbus_config));
|
||||
} else {
|
||||
stream_num = RKCIF_MAX_STREAM_MIPI;
|
||||
linked_sensor.sd = sensor->sd;
|
||||
}
|
||||
|
||||
/* sensor links(or mipi-phy) */
|
||||
for (s = 0; s < dev->num_sensors; ++s) {
|
||||
struct rkcif_sensor_info *sensor = &dev->sensors[s];
|
||||
struct rkcif_sensor_info linked_sensor;
|
||||
struct media_entity *source_entity, *sink_entity;
|
||||
memcpy(&linked_sensor.mbus, &sensor->mbus,
|
||||
sizeof(struct v4l2_mbus_config));
|
||||
|
||||
linked_sensor.lanes = sensor->lanes;
|
||||
for (pad = 0; pad < linked_sensor.sd->entity.num_pads; pad++) {
|
||||
if (linked_sensor.sd->entity.pads[pad].flags &
|
||||
MEDIA_PAD_FL_SOURCE) {
|
||||
if (pad == linked_sensor.sd->entity.num_pads) {
|
||||
dev_err(dev->dev,
|
||||
"failed to find src pad for %s\n",
|
||||
linked_sensor.sd->name);
|
||||
|
||||
if (sensor->mbus.type == V4L2_MBUS_CCP2) {
|
||||
linked_sensor.sd = &dev->lvds_subdev.sd;
|
||||
dev->lvds_subdev.sensor_self.sd = &dev->lvds_subdev.sd;
|
||||
dev->lvds_subdev.sensor_self.lanes = sensor->lanes;
|
||||
memcpy(&dev->lvds_subdev.sensor_self.mbus, &sensor->mbus,
|
||||
sizeof(struct v4l2_mbus_config));
|
||||
} else {
|
||||
linked_sensor.sd = sensor->sd;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
memcpy(&linked_sensor.mbus, &sensor->mbus,
|
||||
sizeof(struct v4l2_mbus_config));
|
||||
if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 ||
|
||||
linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) &&
|
||||
(dev->chip_id == CHIP_RK1808_CIF)) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[RKCIF_STREAM_CIF].vnode.vdev.entity;
|
||||
|
||||
for (pad = 0; pad < linked_sensor.sd->entity.num_pads; pad++) {
|
||||
if (linked_sensor.sd->entity.pads[pad].flags &
|
||||
MEDIA_PAD_FL_SOURCE) {
|
||||
if (pad == linked_sensor.sd->entity.num_pads) {
|
||||
dev_err(dev->dev,
|
||||
"failed to find src pad for %s\n",
|
||||
ret = media_create_pad_link(source_entity,
|
||||
pad,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link for %s\n",
|
||||
linked_sensor.sd->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 ||
|
||||
linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) &&
|
||||
(dev->chip_id >= CHIP_RV1126_CIF)) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[pad].vnode.vdev.entity;
|
||||
|
||||
ret = media_create_pad_link(source_entity,
|
||||
pad,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link for %s pad[%d]\n",
|
||||
linked_sensor.sd->name, pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
for (id = 0; id < stream_num; id++) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[id].vnode.vdev.entity;
|
||||
|
||||
if ((dev->chip_id < CHIP_RK1808_CIF) ||
|
||||
(id == pad - 1 && !(*mipi_lvds_linked)))
|
||||
flags = MEDIA_LNK_FL_ENABLED;
|
||||
else
|
||||
flags = 0;
|
||||
|
||||
ret = media_create_pad_link(source_entity,
|
||||
pad,
|
||||
sink_entity,
|
||||
0,
|
||||
flags);
|
||||
if (ret) {
|
||||
dev_err(dev->dev,
|
||||
"failed to create link for %s\n",
|
||||
linked_sensor.sd->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 ||
|
||||
linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) &&
|
||||
(dev->chip_id == CHIP_RK1808_CIF)) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[RKCIF_STREAM_CIF].vnode.vdev.entity;
|
||||
|
||||
ret = media_create_pad_link(source_entity,
|
||||
pad,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link for %s\n",
|
||||
linked_sensor.sd->name);
|
||||
break;
|
||||
}
|
||||
|
||||
if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 ||
|
||||
linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) &&
|
||||
(dev->chip_id >= CHIP_RV1126_CIF)) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[pad].vnode.vdev.entity;
|
||||
|
||||
ret = media_create_pad_link(source_entity,
|
||||
pad,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link for %s pad[%d]\n",
|
||||
linked_sensor.sd->name, pad);
|
||||
continue;
|
||||
}
|
||||
|
||||
}
|
||||
if (dev->chip_id == CHIP_RK3588_CIF) {
|
||||
for (id = 0; id < stream_num; id++) {
|
||||
source_entity = &linked_sensor.sd->entity;
|
||||
sink_entity = &dev->stream[id].vnode.vdev.entity;
|
||||
sink_entity = &dev->scale_vdev[id].vnode.vdev.entity;
|
||||
|
||||
if ((dev->chip_id != CHIP_RK1808_CIF &&
|
||||
dev->chip_id != CHIP_RV1126_CIF &&
|
||||
dev->chip_id != CHIP_RV1126_CIF_LITE &&
|
||||
dev->chip_id != CHIP_RK3568_CIF) ||
|
||||
(id == pad - 1 && !mipi_lvds_linked))
|
||||
if ((id + stream_num) == pad - 1 && !(*mipi_lvds_linked))
|
||||
flags = MEDIA_LNK_FL_ENABLED;
|
||||
else
|
||||
flags = 0;
|
||||
@@ -691,24 +1037,49 @@ static int rkcif_create_links(struct rkcif_device *dev)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (sensor->mbus.type == V4L2_MBUS_CCP2) {
|
||||
source_entity = &sensor->sd->entity;
|
||||
sink_entity = &linked_sensor.sd->entity;
|
||||
ret = media_create_pad_link(source_entity,
|
||||
1,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link between %s and %s\n",
|
||||
linked_sensor.sd->name,
|
||||
sensor->sd->name);
|
||||
}
|
||||
if (sensor->mbus.type == V4L2_MBUS_CCP2) {
|
||||
source_entity = &sensor->sd->entity;
|
||||
sink_entity = &linked_sensor.sd->entity;
|
||||
ret = media_create_pad_link(source_entity,
|
||||
1,
|
||||
sink_entity,
|
||||
0,
|
||||
MEDIA_LNK_FL_ENABLED);
|
||||
if (ret)
|
||||
dev_err(dev->dev, "failed to create link between %s and %s\n",
|
||||
linked_sensor.sd->name,
|
||||
sensor->sd->name);
|
||||
}
|
||||
|
||||
if (linked_sensor.mbus.type != V4L2_MBUS_BT656 &&
|
||||
linked_sensor.mbus.type != V4L2_MBUS_PARALLEL)
|
||||
mipi_lvds_linked = true;
|
||||
if (linked_sensor.mbus.type != V4L2_MBUS_BT656 &&
|
||||
linked_sensor.mbus.type != V4L2_MBUS_PARALLEL)
|
||||
*mipi_lvds_linked = true;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***************************** media controller *******************************/
|
||||
static int rkcif_create_links(struct rkcif_device *dev)
|
||||
{
|
||||
u32 s = 0;
|
||||
u32 stream_num = 0;
|
||||
bool mipi_lvds_linked = false;
|
||||
|
||||
if (dev->chip_id < CHIP_RV1126_CIF) {
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS)
|
||||
stream_num = RKCIF_MAX_STREAM_MIPI;
|
||||
else
|
||||
stream_num = RKCIF_SINGLE_STREAM;
|
||||
} else {
|
||||
stream_num = RKCIF_MAX_STREAM_MIPI;
|
||||
}
|
||||
|
||||
/* sensor links(or mipi-phy) */
|
||||
for (s = 0; s < dev->num_sensors; ++s) {
|
||||
struct rkcif_sensor_info *sensor = &dev->sensors[s];
|
||||
|
||||
rkcif_create_link(dev, sensor, stream_num, &mipi_lvds_linked);
|
||||
}
|
||||
|
||||
return 0;
|
||||
@@ -762,7 +1133,8 @@ static int subdev_notifier_complete(struct v4l2_async_notifier *notifier)
|
||||
}
|
||||
|
||||
if (sensor->mbus.type == V4L2_MBUS_CCP2 ||
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_DPHY) {
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) {
|
||||
|
||||
switch (sensor->mbus.flags & V4L2_MBUS_CSI2_LANES) {
|
||||
case V4L2_MBUS_CSI2_1_LANE:
|
||||
@@ -870,12 +1242,14 @@ static int rkcif_fwnode_parse(struct device *dev,
|
||||
if (vep->bus_type != V4L2_MBUS_BT656 &&
|
||||
vep->bus_type != V4L2_MBUS_PARALLEL &&
|
||||
vep->bus_type != V4L2_MBUS_CSI2_DPHY &&
|
||||
vep->bus_type != V4L2_MBUS_CSI2_CPHY &&
|
||||
vep->bus_type != V4L2_MBUS_CCP2)
|
||||
return 0;
|
||||
|
||||
rk_asd->mbus.type = vep->bus_type;
|
||||
|
||||
if (vep->bus_type == V4L2_MBUS_CSI2_DPHY) {
|
||||
if (vep->bus_type == V4L2_MBUS_CSI2_DPHY ||
|
||||
vep->bus_type == V4L2_MBUS_CSI2_CPHY) {
|
||||
rk_asd->mbus.flags = vep->bus.mipi_csi2.flags;
|
||||
rk_asd->lanes = vep->bus.mipi_csi2.num_data_lanes;
|
||||
} else if (vep->bus_type == V4L2_MBUS_CCP2) {
|
||||
@@ -942,6 +1316,14 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
if (cif_dev->chip_id == CHIP_RK3588_CIF) {
|
||||
ret = rkcif_register_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH, true);
|
||||
|
||||
if (ret < 0) {
|
||||
dev_err(cif_dev->dev, "cif register scale_vdev[%d] failed!\n", stream_num);
|
||||
goto err_unreg_stream_vdev;
|
||||
}
|
||||
}
|
||||
ret = cif_subdev_notifier(cif_dev);
|
||||
if (ret < 0) {
|
||||
v4l2_err(&cif_dev->v4l2_dev,
|
||||
@@ -952,17 +1334,22 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
|
||||
return 0;
|
||||
err_unreg_stream_vdev:
|
||||
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
|
||||
if (cif_dev->chip_id == CHIP_RK3588_CIF)
|
||||
rkcif_unregister_scale_vdevs(cif_dev, RKCIF_MAX_SCALE_CH);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static irqreturn_t rkcif_irq_handler(int irq, struct rkcif_device *cif_dev)
|
||||
{
|
||||
if (cif_dev->workmode == RKCIF_WORKMODE_PINGPONG)
|
||||
rkcif_irq_pingpong(cif_dev);
|
||||
else
|
||||
if (cif_dev->workmode == RKCIF_WORKMODE_PINGPONG) {
|
||||
if (cif_dev->chip_id < CHIP_RK3588_CIF)
|
||||
rkcif_irq_pingpong(cif_dev);
|
||||
else
|
||||
rkcif_irq_pingpong_v1(cif_dev);
|
||||
} else {
|
||||
rkcif_irq_oneframe(cif_dev);
|
||||
|
||||
}
|
||||
return IRQ_HANDLED;
|
||||
}
|
||||
|
||||
@@ -1149,10 +1536,11 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
|
||||
struct v4l2_device *v4l2_dev;
|
||||
int ret;
|
||||
|
||||
cif_dev->hdr.mode = NO_HDR;
|
||||
cif_dev->hdr.hdr_mode = NO_HDR;
|
||||
cif_dev->inf_id = inf_id;
|
||||
|
||||
mutex_init(&cif_dev->stream_lock);
|
||||
mutex_init(&cif_dev->scale_lock);
|
||||
spin_lock_init(&cif_dev->hdr_lock);
|
||||
spin_lock_init(&cif_dev->reset_watchdog_timer.timer_lock);
|
||||
spin_lock_init(&cif_dev->reset_watchdog_timer.csi2_err_lock);
|
||||
@@ -1164,6 +1552,7 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
|
||||
cif_dev->pipe.close = rkcif_pipeline_close;
|
||||
cif_dev->pipe.set_stream = rkcif_pipeline_set_stream;
|
||||
cif_dev->isr_hdl = rkcif_irq_handler;
|
||||
cif_dev->id_use_cnt = 0;
|
||||
if (cif_dev->chip_id == CHIP_RV1126_CIF_LITE)
|
||||
cif_dev->isr_hdl = rkcif_irq_lite_handler;
|
||||
|
||||
@@ -1184,6 +1573,13 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
|
||||
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3);
|
||||
}
|
||||
|
||||
if (cif_dev->chip_id == CHIP_RK3588_CIF) {
|
||||
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH0);
|
||||
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH1);
|
||||
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH2);
|
||||
rkcif_init_scale_vdev(cif_dev, RKCIF_SCALE_CH3);
|
||||
}
|
||||
|
||||
#if defined(CONFIG_ROCKCHIP_CIF_WORKMODE_PINGPONG)
|
||||
cif_dev->workmode = RKCIF_WORKMODE_PINGPONG;
|
||||
#elif defined(CONFIG_ROCKCHIP_CIF_WORKMODE_ONEFRAME)
|
||||
@@ -1200,6 +1596,9 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
|
||||
|
||||
strlcpy(cif_dev->media_dev.model, dev_name(dev),
|
||||
sizeof(cif_dev->media_dev.model));
|
||||
cif_dev->csi_host_idx = of_alias_get_id(node, "rkcif_mipi_lvds");
|
||||
if (cif_dev->csi_host_idx < 0 || cif_dev->csi_host_idx > 5)
|
||||
cif_dev->csi_host_idx = 0;
|
||||
cif_dev->media_dev.dev = dev;
|
||||
v4l2_dev = &cif_dev->v4l2_dev;
|
||||
v4l2_dev->mdev = &cif_dev->media_dev;
|
||||
@@ -1328,6 +1727,9 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
dev_set_drvdata(dev, cif_dev);
|
||||
cif_dev->dev = dev;
|
||||
|
||||
if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp))
|
||||
return -ENODEV;
|
||||
|
||||
rkcif_attach_hw(cif_dev);
|
||||
|
||||
rkcif_parse_dts(cif_dev);
|
||||
@@ -1338,9 +1740,6 @@ static int rkcif_plat_probe(struct platform_device *pdev)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (sysfs_create_group(&pdev->dev.kobj, &dev_attr_grp))
|
||||
return -ENODEV;
|
||||
|
||||
if (rkcif_proc_init(cif_dev))
|
||||
dev_warn(dev, "dev:%s create proc failed\n", dev_name(dev));
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include <media/v4l2-mc.h>
|
||||
#include <linux/workqueue.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include <linux/rkcif-config.h>
|
||||
|
||||
#include "regs.h"
|
||||
#include "version.h"
|
||||
@@ -46,6 +47,9 @@
|
||||
#define CIF_DVP_ID2_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id2"
|
||||
#define CIF_DVP_ID3_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id3"
|
||||
|
||||
#define RKCIF_PLANE_Y 0
|
||||
#define RKCIF_PLANE_CBCR 1
|
||||
|
||||
/*
|
||||
* RK1808 support 5 channel inputs simultaneously:
|
||||
* dvp + 4 mipi virtual channels;
|
||||
@@ -69,10 +73,13 @@
|
||||
#define RKCIF_DEFAULT_HEIGHT 480
|
||||
#define RKCIF_FS_DETECTED_NUM 2
|
||||
|
||||
#define RKCIF_RX_BUF_MAX 8
|
||||
|
||||
/*
|
||||
* for HDR mode sync buf
|
||||
*/
|
||||
#define RDBK_MAX 3
|
||||
#define RDBK_TOISP_MAX 2
|
||||
#define RDBK_L 0
|
||||
#define RDBK_M 1
|
||||
#define RDBK_S 2
|
||||
@@ -89,6 +96,13 @@ enum rkcif_workmode {
|
||||
RKCIF_WORKMODE_LINELOOP = 0x02
|
||||
};
|
||||
|
||||
enum rkcif_stream_mode {
|
||||
RKCIF_STREAM_MODE_NONE = 0x0,
|
||||
RKCIF_STREAM_MODE_CAPTURE = 0x01,
|
||||
RKCIF_STREAM_MODE_TOISP = 0x02,
|
||||
RKCIF_STREAM_MODE_TOSCALE = 0x04
|
||||
};
|
||||
|
||||
enum rkcif_yuvaddr_state {
|
||||
RKCIF_YUV_ADDR_STATE_UPDATE = 0x0,
|
||||
RKCIF_YUV_ADDR_STATE_INIT = 0x1
|
||||
@@ -171,9 +185,17 @@ struct rkcif_buffer {
|
||||
};
|
||||
|
||||
struct rkcif_dummy_buffer {
|
||||
void *vaddr;
|
||||
struct list_head list;
|
||||
struct dma_buf *dbuf;
|
||||
dma_addr_t dma_addr;
|
||||
struct page **pages;
|
||||
void *mem_priv;
|
||||
void *vaddr;
|
||||
u32 size;
|
||||
int dma_fd;
|
||||
bool is_need_vaddr;
|
||||
bool is_need_dbuf;
|
||||
bool is_need_dmafd;
|
||||
};
|
||||
|
||||
extern int rkcif_debug;
|
||||
@@ -322,10 +344,13 @@ struct rkcif_readout_stats {
|
||||
struct rkcif_irq_stats {
|
||||
u64 csi_overflow_cnt;
|
||||
u64 csi_bwidth_lack_cnt;
|
||||
u64 csi_size_err_cnt;
|
||||
u64 dvp_bus_err_cnt;
|
||||
u64 dvp_overflow_cnt;
|
||||
u64 dvp_line_err_cnt;
|
||||
u64 dvp_pix_err_cnt;
|
||||
u64 dvp_size_err_cnt;
|
||||
u64 dvp_bwidth_lack_cnt;
|
||||
u64 all_frm_end_cnt;
|
||||
u64 all_err_cnt;
|
||||
};
|
||||
@@ -394,6 +419,22 @@ struct rkcif_extend_info {
|
||||
bool is_extended;
|
||||
};
|
||||
|
||||
enum rkcif_capture_mode {
|
||||
RKCIF_TO_DDR = 0,
|
||||
RKCIF_TO_ISP_DDR,
|
||||
RKCIF_TO_ISP_DMA,
|
||||
};
|
||||
|
||||
struct rkcif_rx_buffer {
|
||||
struct rkisp_rx_buf dbufs;
|
||||
struct rkcif_dummy_buffer dummy;
|
||||
};
|
||||
|
||||
enum rkcif_dma_en_mode {
|
||||
RKCIF_DMAEN_BY_VICAP = 0x1,
|
||||
RKCIF_DMAEN_BY_ISP = 0x2,
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rkcif_stream - Stream states TODO
|
||||
*
|
||||
@@ -421,6 +462,8 @@ struct rkcif_stream {
|
||||
struct list_head buf_head;
|
||||
struct rkcif_buffer *curr_buf;
|
||||
struct rkcif_buffer *next_buf;
|
||||
struct rkcif_rx_buffer *curr_buf_toisp;
|
||||
struct rkcif_rx_buffer *next_buf_toisp;
|
||||
|
||||
spinlock_t vbq_lock; /* vfd lock */
|
||||
spinlock_t fps_lock;
|
||||
@@ -435,6 +478,15 @@ struct rkcif_stream {
|
||||
struct rkcif_extend_info extend_line;
|
||||
struct rkcif_readout_stats readout;
|
||||
unsigned int fs_cnt_in_single_frame;
|
||||
unsigned int capture_mode;
|
||||
struct rkcif_scale_vdev *scale_vdev;
|
||||
int dma_en;
|
||||
int to_en_dma;
|
||||
int to_stop_dma;
|
||||
unsigned int cur_stream_mode;
|
||||
struct rkcif_rx_buffer rx_buf[RKCIF_RX_BUF_MAX];
|
||||
struct list_head rx_buf_head;
|
||||
int buf_num_toisp;
|
||||
u64 line_int_cnt;
|
||||
int vc;
|
||||
bool stopping;
|
||||
@@ -499,6 +551,110 @@ static inline struct vb2_queue *to_vb2_queue(struct file *file)
|
||||
return &vnode->buf_queue;
|
||||
}
|
||||
|
||||
#define SCALE_DRIVER_NAME "rkcif_scale"
|
||||
|
||||
#define RKCIF_SCALE_CH0 0
|
||||
#define RKCIF_SCALE_CH1 1
|
||||
#define RKCIF_SCALE_CH2 2
|
||||
#define RKCIF_SCALE_CH3 3
|
||||
#define RKCIF_MAX_SCALE_CH 4
|
||||
|
||||
#define CIF_SCALE_CH0_VDEV_NAME CIF_DRIVER_NAME "_scale_ch0"
|
||||
#define CIF_SCALE_CH1_VDEV_NAME CIF_DRIVER_NAME "_scale_ch1"
|
||||
#define CIF_SCALE_CH2_VDEV_NAME CIF_DRIVER_NAME "_scale_ch2"
|
||||
#define CIF_SCALE_CH3_VDEV_NAME CIF_DRIVER_NAME "_scale_ch3"
|
||||
|
||||
#define RKCIF_SCALE_ENUM_SIZE_MAX 3
|
||||
|
||||
enum scale_ch_sw {
|
||||
SCALE_MIPI0_ID0,
|
||||
SCALE_MIPI0_ID1,
|
||||
SCALE_MIPI0_ID2,
|
||||
SCALE_MIPI0_ID3,
|
||||
SCALE_MIPI1_ID0,
|
||||
SCALE_MIPI1_ID1,
|
||||
SCALE_MIPI1_ID2,
|
||||
SCALE_MIPI1_ID3,
|
||||
SCALE_MIPI2_ID0,
|
||||
SCALE_MIPI2_ID1,
|
||||
SCALE_MIPI2_ID2,
|
||||
SCALE_MIPI2_ID3,
|
||||
SCALE_MIPI3_ID0,
|
||||
SCALE_MIPI3_ID1,
|
||||
SCALE_MIPI3_ID2,
|
||||
SCALE_MIPI3_ID3,
|
||||
SCALE_MIPI4_ID0,
|
||||
SCALE_MIPI4_ID1,
|
||||
SCALE_MIPI4_ID2,
|
||||
SCALE_MIPI4_ID3,
|
||||
SCALE_MIPI5_ID0,
|
||||
SCALE_MIPI5_ID1,
|
||||
SCALE_MIPI5_ID2,
|
||||
SCALE_MIPI5_ID3,
|
||||
SCALE_DVP,
|
||||
SCALE_CH_MAX,
|
||||
};
|
||||
|
||||
enum scale_mode {
|
||||
SCALE_8TIMES,
|
||||
SCALE_16TIMES,
|
||||
SCALE_32TIMES,
|
||||
};
|
||||
|
||||
struct rkcif_scale_ch_info {
|
||||
u32 width;
|
||||
u32 height;
|
||||
u32 vir_width;
|
||||
};
|
||||
|
||||
struct rkcif_scale_src_res {
|
||||
u32 width;
|
||||
u32 height;
|
||||
};
|
||||
|
||||
/*
|
||||
* struct rkcif_scale_vdev - CIF Capture device
|
||||
*
|
||||
* @irq_lock: buffer queue lock
|
||||
* @stat: stats buffer list
|
||||
* @readout_wq: workqueue for statistics information read
|
||||
*/
|
||||
struct rkcif_scale_vdev {
|
||||
unsigned int ch:3;
|
||||
struct rkcif_device *cifdev;
|
||||
struct rkcif_vdev_node vnode;
|
||||
struct rkcif_stream *stream;
|
||||
struct list_head buf_head;
|
||||
spinlock_t vbq_lock; /* vfd lock */
|
||||
wait_queue_head_t wq_stopped;
|
||||
struct v4l2_pix_format_mplane pixm;
|
||||
const struct cif_output_fmt *scale_out_fmt;
|
||||
struct rkcif_scale_ch_info ch_info;
|
||||
struct rkcif_scale_src_res src_res;
|
||||
struct rkcif_buffer *curr_buf;
|
||||
struct rkcif_buffer *next_buf;
|
||||
struct bayer_blc blc;
|
||||
enum rkcif_state state;
|
||||
unsigned int ch_src;
|
||||
unsigned int scale_mode;
|
||||
int frame_phase;
|
||||
unsigned int frame_idx;
|
||||
bool stopping;
|
||||
};
|
||||
|
||||
static inline
|
||||
struct rkcif_scale_vdev *to_rkcif_scale_vdev(struct rkcif_vdev_node *vnode)
|
||||
{
|
||||
return container_of(vnode, struct rkcif_scale_vdev, vnode);
|
||||
}
|
||||
|
||||
void rkcif_init_scale_vdev(struct rkcif_device *cif_dev, u32 ch);
|
||||
int rkcif_register_scale_vdevs(struct rkcif_device *cif_dev,
|
||||
int stream_num,
|
||||
bool is_multi_input);
|
||||
void rkcif_unregister_scale_vdevs(struct rkcif_device *cif_dev,
|
||||
int stream_num);
|
||||
|
||||
/*
|
||||
* struct rkcif_device - ISP platform device
|
||||
* @base_addr: base register address
|
||||
@@ -518,6 +674,7 @@ struct rkcif_device {
|
||||
struct rkcif_sensor_info terminal_sensor;
|
||||
|
||||
struct rkcif_stream stream[RKCIF_MULTI_STREAMS_NUM];
|
||||
struct rkcif_scale_vdev scale_vdev[RKCIF_MULTI_STREAMS_NUM];
|
||||
struct rkcif_pipeline pipe;
|
||||
|
||||
struct csi_channel_info channels[RKCIF_MAX_CSI_CHANNEL];
|
||||
@@ -526,9 +683,10 @@ struct rkcif_device {
|
||||
atomic_t stream_cnt;
|
||||
atomic_t fh_cnt;
|
||||
struct mutex stream_lock; /* lock between streams */
|
||||
struct mutex scale_lock; /* lock between scale dev */
|
||||
enum rkcif_workmode workmode;
|
||||
bool can_be_reset;
|
||||
struct rkcif_hdr hdr;
|
||||
struct rkmodule_hdr_cfg hdr;
|
||||
struct rkcif_buffer *rdbk_buf[RDBK_MAX];
|
||||
struct rkcif_luma_vdev luma_vdev;
|
||||
struct rkcif_lvds_subdev lvds_subdev;
|
||||
@@ -545,6 +703,8 @@ struct rkcif_device {
|
||||
unsigned int buf_wake_up_cnt;
|
||||
struct notifier_block reset_notifier; /* reset for mipi csi crc err */
|
||||
struct rkcif_work_struct reset_work;
|
||||
int id_use_cnt;
|
||||
unsigned int csi_host_idx;
|
||||
unsigned int dvp_sof_in_oneframe;
|
||||
unsigned int wait_line;
|
||||
unsigned int wait_line_bak;
|
||||
@@ -557,6 +717,17 @@ struct rkcif_device {
|
||||
};
|
||||
|
||||
extern struct platform_driver rkcif_plat_drv;
|
||||
int rkcif_do_start_stream(struct rkcif_stream *stream,
|
||||
enum rkcif_stream_mode mode);
|
||||
void rkcif_do_stop_stream(struct rkcif_stream *stream,
|
||||
enum rkcif_stream_mode mode);
|
||||
void rkcif_irq_handle_scale(struct rkcif_device *cif_dev,
|
||||
unsigned int intstat_glb);
|
||||
|
||||
const struct
|
||||
cif_input_fmt *get_input_fmt(struct v4l2_subdev *sd,
|
||||
struct v4l2_rect *rect,
|
||||
u32 pad_id, int *vc);
|
||||
|
||||
void rkcif_write_register(struct rkcif_device *dev,
|
||||
enum cif_reg_index index, u32 val);
|
||||
@@ -579,6 +750,9 @@ void rkcif_stream_init(struct rkcif_device *dev, u32 id);
|
||||
void rkcif_set_default_fmt(struct rkcif_device *cif_dev);
|
||||
void rkcif_irq_oneframe(struct rkcif_device *cif_dev);
|
||||
void rkcif_irq_pingpong(struct rkcif_device *cif_dev);
|
||||
void rkcif_irq_pingpong_v1(struct rkcif_device *cif_dev);
|
||||
unsigned int rkcif_irq_global(struct rkcif_device *cif_dev);
|
||||
void rkcif_irq_handle_toisp(struct rkcif_device *cif_dev, unsigned int intstat_glb);
|
||||
void rkcif_soft_reset(struct rkcif_device *cif_dev,
|
||||
bool is_rst_iommu);
|
||||
int rkcif_register_lvds_subdev(struct rkcif_device *dev);
|
||||
@@ -597,4 +771,16 @@ void rkcif_config_dvp_clk_sampling_edge(struct rkcif_device *dev,
|
||||
enum rkcif_clk_edge edge);
|
||||
void rkcif_enable_dvp_clk_dual_edge(struct rkcif_device *dev, bool on);
|
||||
void rkcif_reset_work(struct work_struct *work);
|
||||
|
||||
int rkcif_init_rx_buf(struct rkcif_stream *stream, int buf_num);
|
||||
void rkcif_free_rx_buf(struct rkcif_stream *stream, int buf_num);
|
||||
|
||||
void rkcif_set_fmt(struct rkcif_stream *stream,
|
||||
struct v4l2_pix_format_mplane *pixm,
|
||||
bool try);
|
||||
|
||||
u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode);
|
||||
|
||||
extern const struct vb2_mem_ops vb2_rdma_sg_memops;
|
||||
|
||||
#endif
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include <linux/pinctrl/consumer.h>
|
||||
#include <linux/regmap.h>
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/videobuf2-dma-sg.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include <linux/iommu.h>
|
||||
#include <dt-bindings/soc/rockchip-system-status.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <linux/io.h>
|
||||
#include <linux/mfd/syscon.h>
|
||||
#include "dev.h"
|
||||
#include "common.h"
|
||||
|
||||
static const struct cif_reg px30_cif_regs[] = {
|
||||
[CIF_REG_DVP_CTRL] = CIF_REG(CIF_CTRL),
|
||||
@@ -597,6 +599,128 @@ static const struct cif_reg rk3568_cif_regs[] = {
|
||||
[CIF_REG_GRF_CIFIO_CON1] = CIF_REG(CIF_GRF_VI_CON1),
|
||||
};
|
||||
|
||||
static const char * const rk3588_cif_clks[] = {
|
||||
"aclk_cif",
|
||||
"hclk_cif",
|
||||
"dclk_cif",
|
||||
};
|
||||
|
||||
static const char * const rk3588_cif_rsts[] = {
|
||||
"rst_cif_a",
|
||||
"rst_cif_h",
|
||||
"rst_cif_d",
|
||||
};
|
||||
|
||||
static const struct cif_reg rk3588_cif_regs[] = {
|
||||
[CIF_REG_DVP_CTRL] = CIF_REG(DVP_CTRL),
|
||||
[CIF_REG_DVP_INTEN] = CIF_REG(DVP_INTEN),
|
||||
[CIF_REG_DVP_INTSTAT] = CIF_REG(DVP_INTSTAT),
|
||||
[CIF_REG_DVP_FOR] = CIF_REG(DVP_FOR),
|
||||
[CIF_REG_DVP_MULTI_ID] = CIF_REG(DVP_MULTI_ID),
|
||||
[CIF_REG_DVP_SAV_EAV] = CIF_REG(DVP_SAV_EAV),
|
||||
[CIF_REG_DVP_FRM0_ADDR_Y] = CIF_REG(DVP_FRM0_ADDR_Y_ID0),
|
||||
[CIF_REG_DVP_FRM0_ADDR_UV] = CIF_REG(DVP_FRM0_ADDR_UV_ID0),
|
||||
[CIF_REG_DVP_FRM1_ADDR_Y] = CIF_REG(DVP_FRM1_ADDR_Y_ID0),
|
||||
[CIF_REG_DVP_FRM1_ADDR_UV] = CIF_REG(DVP_FRM1_ADDR_UV_ID0),
|
||||
[CIF_REG_DVP_FRM0_ADDR_Y_ID1] = CIF_REG(DVP_FRM0_ADDR_Y_ID1),
|
||||
[CIF_REG_DVP_FRM0_ADDR_UV_ID1] = CIF_REG(DVP_FRM0_ADDR_UV_ID1),
|
||||
[CIF_REG_DVP_FRM1_ADDR_Y_ID1] = CIF_REG(DVP_FRM1_ADDR_Y_ID1),
|
||||
[CIF_REG_DVP_FRM1_ADDR_UV_ID1] = CIF_REG(DVP_FRM1_ADDR_UV_ID1),
|
||||
[CIF_REG_DVP_FRM0_ADDR_Y_ID2] = CIF_REG(DVP_FRM0_ADDR_Y_ID2),
|
||||
[CIF_REG_DVP_FRM0_ADDR_UV_ID2] = CIF_REG(DVP_FRM0_ADDR_UV_ID2),
|
||||
[CIF_REG_DVP_FRM1_ADDR_Y_ID2] = CIF_REG(DVP_FRM1_ADDR_Y_ID2),
|
||||
[CIF_REG_DVP_FRM1_ADDR_UV_ID2] = CIF_REG(DVP_FRM1_ADDR_UV_ID2),
|
||||
[CIF_REG_DVP_FRM0_ADDR_Y_ID3] = CIF_REG(DVP_FRM0_ADDR_Y_ID3),
|
||||
[CIF_REG_DVP_FRM0_ADDR_UV_ID3] = CIF_REG(DVP_FRM0_ADDR_UV_ID3),
|
||||
[CIF_REG_DVP_FRM1_ADDR_Y_ID3] = CIF_REG(DVP_FRM1_ADDR_Y_ID3),
|
||||
[CIF_REG_DVP_FRM1_ADDR_UV_ID3] = CIF_REG(DVP_FRM1_ADDR_UV_ID3),
|
||||
[CIF_REG_DVP_VIR_LINE_WIDTH] = CIF_REG(DVP_VIR_LINE_WIDTH),
|
||||
[CIF_REG_DVP_SET_SIZE] = CIF_REG(DVP_CROP_SIZE),
|
||||
[CIF_REG_DVP_LINE_INT_NUM] = CIF_REG(DVP_LINE_INT_NUM_01),
|
||||
[CIF_REG_DVP_LINE_INT_NUM1] = CIF_REG(DVP_LINE_INT_NUM_23),
|
||||
[CIF_REG_DVP_LINE_CNT] = CIF_REG(DVP_LINE_INT_NUM_01),
|
||||
[CIF_REG_DVP_LINE_CNT1] = CIF_REG(DVP_LINE_INT_NUM_23),
|
||||
|
||||
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG(CSI_MIPI0_ID0_CTRL0),
|
||||
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG(CSI_MIPI0_ID0_CTRL1),
|
||||
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG(CSI_MIPI0_ID1_CTRL0),
|
||||
[CIF_REG_MIPI_LVDS_ID1_CTRL1] = CIF_REG(CSI_MIPI0_ID1_CTRL1),
|
||||
[CIF_REG_MIPI_LVDS_ID2_CTRL0] = CIF_REG(CSI_MIPI0_ID2_CTRL0),
|
||||
[CIF_REG_MIPI_LVDS_ID2_CTRL1] = CIF_REG(CSI_MIPI0_ID2_CTRL1),
|
||||
[CIF_REG_MIPI_LVDS_ID3_CTRL0] = CIF_REG(CSI_MIPI0_ID3_CTRL0),
|
||||
[CIF_REG_MIPI_LVDS_ID3_CTRL1] = CIF_REG(CSI_MIPI0_ID3_CTRL1),
|
||||
[CIF_REG_MIPI_LVDS_CTRL] = CIF_REG(CSI_MIPI0_CTRL),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID0),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID0),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID0),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID0] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID0),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID0] = CIF_REG(CSI_MIPI0_VLW_ID0),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID1),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID1),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID1),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID1] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID1),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID1] = CIF_REG(CSI_MIPI0_VLW_ID1),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID2),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID2),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID2),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID2] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID2),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID2] = CIF_REG(CSI_MIPI0_VLW_ID2),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_Y_ID3),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_Y_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_Y_ID3),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM0_ADDR_UV_ID3),
|
||||
[CIF_REG_MIPI_LVDS_FRAME1_ADDR_UV_ID3] = CIF_REG(CSI_MIPI0_FRM1_ADDR_UV_ID3),
|
||||
[CIF_REG_MIPI_LVDS_FRAME0_VLW_Y_ID3] = CIF_REG(CSI_MIPI0_VLW_ID3),
|
||||
[CIF_REG_MIPI_LVDS_INTEN] = CIF_REG(CSI_MIPI0_INTEN),
|
||||
[CIF_REG_MIPI_LVDS_INTSTAT] = CIF_REG(CSI_MIPI0_INTSTAT),
|
||||
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID0_1] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID0_1),
|
||||
[CIF_REG_MIPI_LVDS_LINE_INT_NUM_ID2_3] = CIF_REG(CSI_MIPI0_LINE_INT_NUM_ID2_3),
|
||||
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID0_1] = CIF_REG(CSI_MIPI0_LINE_CNT_ID0_1),
|
||||
[CIF_REG_MIPI_LVDS_LINE_LINE_CNT_ID2_3] = CIF_REG(CSI_MIPI0_LINE_CNT_ID2_3),
|
||||
[CIF_REG_MIPI_LVDS_ID0_CROP_START] = CIF_REG(CSI_MIPI0_ID0_CROP_START),
|
||||
[CIF_REG_MIPI_LVDS_ID1_CROP_START] = CIF_REG(CSI_MIPI0_ID1_CROP_START),
|
||||
[CIF_REG_MIPI_LVDS_ID2_CROP_START] = CIF_REG(CSI_MIPI0_ID2_CROP_START),
|
||||
[CIF_REG_MIPI_LVDS_ID3_CROP_START] = CIF_REG(CSI_MIPI0_ID3_CROP_START),
|
||||
[CIF_REG_MIPI_FRAME_NUM_VC0] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC0),
|
||||
[CIF_REG_MIPI_FRAME_NUM_VC1] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC1),
|
||||
[CIF_REG_MIPI_FRAME_NUM_VC2] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC2),
|
||||
[CIF_REG_MIPI_FRAME_NUM_VC3] = CIF_REG(CSI_MIPI0_FRAME_NUM_VC3),
|
||||
[CIF_REG_MIPI_EFFECT_CODE_ID0] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID0),
|
||||
[CIF_REG_MIPI_EFFECT_CODE_ID1] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID1),
|
||||
[CIF_REG_MIPI_EFFECT_CODE_ID2] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID2),
|
||||
[CIF_REG_MIPI_EFFECT_CODE_ID3] = CIF_REG(CSI_MIPI0_EFFECT_CODE_ID3),
|
||||
[CIF_REG_MIPI_ON_PAD] = CIF_REG(CSI_MIPI0_ON_PAD),
|
||||
|
||||
[CIF_REG_GLB_CTRL] = CIF_REG(GLB_CTRL),
|
||||
[CIF_REG_GLB_INTEN] = CIF_REG(GLB_INTEN),
|
||||
[CIF_REG_GLB_INTST] = CIF_REG(GLB_INTST),
|
||||
|
||||
[CIF_REG_SCL_CH_CTRL] = CIF_REG(SCL_CH_CTRL),
|
||||
[CIF_REG_SCL_CTRL] = CIF_REG(SCL_CTRL),
|
||||
[CIF_REG_SCL_FRM0_ADDR_CH0] = CIF_REG(SCL_FRM0_ADDR_CH0),
|
||||
[CIF_REG_SCL_FRM1_ADDR_CH0] = CIF_REG(SCL_FRM1_ADDR_CH0),
|
||||
[CIF_REG_SCL_VLW_CH0] = CIF_REG(SCL_VLW_CH0),
|
||||
[CIF_REG_SCL_FRM0_ADDR_CH1] = CIF_REG(SCL_FRM0_ADDR_CH1),
|
||||
[CIF_REG_SCL_FRM1_ADDR_CH1] = CIF_REG(SCL_FRM1_ADDR_CH1),
|
||||
[CIF_REG_SCL_VLW_CH1] = CIF_REG(SCL_VLW_CH1),
|
||||
[CIF_REG_SCL_FRM0_ADDR_CH2] = CIF_REG(SCL_FRM0_ADDR_CH2),
|
||||
[CIF_REG_SCL_FRM1_ADDR_CH2] = CIF_REG(SCL_FRM1_ADDR_CH2),
|
||||
[CIF_REG_SCL_VLW_CH2] = CIF_REG(SCL_VLW_CH2),
|
||||
[CIF_REG_SCL_FRM0_ADDR_CH3] = CIF_REG(SCL_FRM0_ADDR_CH3),
|
||||
[CIF_REG_SCL_FRM1_ADDR_CH3] = CIF_REG(SCL_FRM1_ADDR_CH3),
|
||||
[CIF_REG_SCL_VLW_CH3] = CIF_REG(SCL_VLW_CH3),
|
||||
[CIF_REG_SCL_BLC_CH0] = CIF_REG(SCL_BLC_CH0),
|
||||
[CIF_REG_SCL_BLC_CH1] = CIF_REG(SCL_BLC_CH1),
|
||||
[CIF_REG_SCL_BLC_CH2] = CIF_REG(SCL_BLC_CH2),
|
||||
[CIF_REG_SCL_BLC_CH3] = CIF_REG(SCL_BLC_CH3),
|
||||
[CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL),
|
||||
[CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE),
|
||||
[CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP),
|
||||
[CIF_REG_TOISP1_CTRL] = CIF_REG(TOISP1_CH_CTRL),
|
||||
[CIF_REG_TOISP1_SIZE] = CIF_REG(TOISP1_CROP_SIZE),
|
||||
[CIF_REG_TOISP1_CROP] = CIF_REG(TOISP1_CROP),
|
||||
[CIF_REG_GRF_CIFIO_CON] = CIF_REG(CIF_GRF_SOC_CON2),
|
||||
};
|
||||
|
||||
static const struct rkcif_hw_match_data px30_cif_match_data = {
|
||||
.chip_id = CHIP_PX30_CIF,
|
||||
.clks = px30_cif_clks,
|
||||
@@ -678,6 +802,14 @@ static const struct rkcif_hw_match_data rk3568_cif_match_data = {
|
||||
.cif_regs = rk3568_cif_regs,
|
||||
};
|
||||
|
||||
static const struct rkcif_hw_match_data rk3588_cif_match_data = {
|
||||
.chip_id = CHIP_RK3588_CIF,
|
||||
.clks = rk3588_cif_clks,
|
||||
.clks_num = ARRAY_SIZE(rk3588_cif_clks),
|
||||
.rsts = rk3588_cif_rsts,
|
||||
.rsts_num = ARRAY_SIZE(rk3588_cif_rsts),
|
||||
.cif_regs = rk3588_cif_regs,
|
||||
};
|
||||
|
||||
static const struct of_device_id rkcif_plat_of_match[] = {
|
||||
{
|
||||
@@ -708,6 +840,10 @@ static const struct of_device_id rkcif_plat_of_match[] = {
|
||||
.compatible = "rockchip,rk3568-cif",
|
||||
.data = &rk3568_cif_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3588-cif",
|
||||
.data = &rk3588_cif_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rv1126-cif",
|
||||
.data = &rv1126_cif_match_data,
|
||||
@@ -723,11 +859,17 @@ static irqreturn_t rkcif_irq_handler(int irq, void *ctx)
|
||||
{
|
||||
struct device *dev = ctx;
|
||||
struct rkcif_hw *cif_hw = dev_get_drvdata(dev);
|
||||
unsigned int intstat_glb = 0;
|
||||
int i;
|
||||
|
||||
if (cif_hw->chip_id == CHIP_RK3588_CIF)
|
||||
intstat_glb = rkcif_irq_global(cif_hw->cif_dev[0]);
|
||||
for (i = 0; i < cif_hw->dev_num; i++) {
|
||||
if (cif_hw->cif_dev[i]->isr_hdl)
|
||||
if (cif_hw->cif_dev[i]->isr_hdl) {
|
||||
cif_hw->cif_dev[i]->isr_hdl(irq, cif_hw->cif_dev[i]);
|
||||
if (cif_hw->chip_id == CHIP_RK3588_CIF && intstat_glb)
|
||||
rkcif_irq_handle_toisp(cif_hw->cif_dev[i], intstat_glb);
|
||||
}
|
||||
}
|
||||
|
||||
return IRQ_HANDLED;
|
||||
@@ -825,6 +967,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
const struct rkcif_hw_match_data *data;
|
||||
struct resource *res;
|
||||
int i, ret, irq;
|
||||
bool is_mem_reserved = false;
|
||||
|
||||
match = of_match_node(rkcif_plat_of_match, node);
|
||||
if (IS_ERR(match))
|
||||
@@ -853,10 +996,7 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
cif_hw->irq = irq;
|
||||
cif_hw->match_data = data;
|
||||
cif_hw->chip_id = data->chip_id;
|
||||
if (data->chip_id == CHIP_RK1808_CIF ||
|
||||
data->chip_id == CHIP_RV1126_CIF ||
|
||||
data->chip_id == CHIP_RV1126_CIF_LITE ||
|
||||
data->chip_id == CHIP_RK3568_CIF) {
|
||||
if (data->chip_id >= CHIP_RK1808_CIF) {
|
||||
res = platform_get_resource_byname(pdev,
|
||||
IORESOURCE_MEM,
|
||||
"cif_regs");
|
||||
@@ -915,17 +1055,30 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
|
||||
cif_hw->cif_regs = data->cif_regs;
|
||||
|
||||
cif_hw->is_dma_contig = true;
|
||||
cif_hw->is_dma_sg_ops = false;
|
||||
mutex_init(&cif_hw->dev_lock);
|
||||
|
||||
cif_hw->iommu_en = is_iommu_enable(dev);
|
||||
if (!cif_hw->iommu_en) {
|
||||
ret = of_reserved_mem_device_init(dev);
|
||||
if (ret)
|
||||
ret = of_reserved_mem_device_init(dev);
|
||||
if (ret) {
|
||||
is_mem_reserved = false;
|
||||
if (!cif_hw->iommu_en)
|
||||
dev_info(dev, "No reserved memory region assign to CIF\n");
|
||||
else
|
||||
cif_hw->is_dma_contig = false;
|
||||
}
|
||||
if (is_mem_reserved) {
|
||||
cif_hw->mem_ops = &vb2_rdma_sg_memops;
|
||||
cif_hw->is_dma_sg_ops = true;
|
||||
} else if (cif_hw->iommu_en) {
|
||||
cif_hw->mem_ops = &vb2_dma_sg_memops;
|
||||
cif_hw->is_dma_sg_ops = true;
|
||||
} else {
|
||||
cif_hw->mem_ops = &vb2_dma_contig_memops;
|
||||
}
|
||||
|
||||
if (data->chip_id != CHIP_RK1808_CIF &&
|
||||
data->chip_id != CHIP_RV1126_CIF &&
|
||||
data->chip_id != CHIP_RV1126_CIF_LITE &&
|
||||
data->chip_id != CHIP_RK3568_CIF) {
|
||||
if (data->chip_id < CHIP_RK1808_CIF) {
|
||||
cif_dev = devm_kzalloc(dev, sizeof(*cif_dev), GFP_KERNEL);
|
||||
if (!cif_dev)
|
||||
return -ENOMEM;
|
||||
@@ -946,9 +1099,8 @@ static int rkcif_plat_hw_probe(struct platform_device *pdev)
|
||||
|
||||
pm_runtime_enable(&pdev->dev);
|
||||
|
||||
if (data->chip_id == CHIP_RK1808_CIF ||
|
||||
data->chip_id == CHIP_RV1126_CIF ||
|
||||
data->chip_id == CHIP_RK3568_CIF) {
|
||||
if (data->chip_id >= CHIP_RK1808_CIF &&
|
||||
data->chip_id != CHIP_RV1126_CIF_LITE) {
|
||||
platform_driver_register(&rkcif_plat_drv);
|
||||
platform_driver_register(&rkcif_subdev_driver);
|
||||
}
|
||||
@@ -965,10 +1117,7 @@ static int rkcif_plat_remove(struct platform_device *pdev)
|
||||
rkcif_iommu_cleanup(cif_hw);
|
||||
|
||||
mutex_destroy(&cif_hw->dev_lock);
|
||||
if (cif_hw->chip_id != CHIP_RK1808_CIF &&
|
||||
cif_hw->chip_id != CHIP_RV1126_CIF &&
|
||||
cif_hw->chip_id != CHIP_RV1126_CIF_LITE &&
|
||||
cif_hw->chip_id != CHIP_RK3568_CIF)
|
||||
if (cif_hw->chip_id < CHIP_RK1808_CIF)
|
||||
rkcif_plat_uninit(cif_hw->cif_dev[0]);
|
||||
|
||||
return 0;
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
#include "regs.h"
|
||||
#include "version.h"
|
||||
|
||||
#define RKCIF_DEV_MAX 2
|
||||
#define RKCIF_DEV_MAX 7
|
||||
#define RKCIF_HW_DRIVER_NAME "rkcifhw"
|
||||
#define RKCIF_MAX_BUS_CLK 8
|
||||
#define RKCIF_MAX_RESET 15
|
||||
@@ -47,6 +47,7 @@ enum rkcif_chip_id {
|
||||
CHIP_RV1126_CIF,
|
||||
CHIP_RV1126_CIF_LITE,
|
||||
CHIP_RK3568_CIF,
|
||||
CHIP_RK3588_CIF,
|
||||
};
|
||||
|
||||
struct rkcif_hw_match_data {
|
||||
@@ -72,17 +73,19 @@ struct rkcif_hw {
|
||||
struct regmap *grf;
|
||||
struct clk *clks[RKCIF_MAX_BUS_CLK];
|
||||
int clk_size;
|
||||
bool iommu_en;
|
||||
struct iommu_domain *domain;
|
||||
struct reset_control *cif_rst[RKCIF_MAX_RESET];
|
||||
int chip_id;
|
||||
const struct cif_reg *cif_regs;
|
||||
const struct vb2_mem_ops *mem_ops;
|
||||
bool iommu_en;
|
||||
bool can_be_reset;
|
||||
bool is_dma_sg_ops;
|
||||
bool is_dma_contig;
|
||||
struct rkcif_device *cif_dev[RKCIF_DEV_MAX];
|
||||
int dev_num;
|
||||
|
||||
struct rkcif_device *cif_dev[RKCIF_DEV_MAX];
|
||||
int dev_num;
|
||||
|
||||
atomic_t power_cnt;
|
||||
atomic_t power_cnt;
|
||||
const struct rkcif_hw_match_data *match_data;
|
||||
struct mutex dev_lock;
|
||||
};
|
||||
|
||||
@@ -31,9 +31,10 @@ MODULE_PARM_DESC(debug_csi2, "Debug level (0-1)");
|
||||
* the 4 virtual channel output pads
|
||||
*/
|
||||
#define CSI2_SINK_PAD 0
|
||||
#define CSI2_NUM_SINK_PADS 1
|
||||
#define CSI2_NUM_SRC_PADS 4
|
||||
#define CSI2_NUM_SINK_PADS 4
|
||||
#define CSI2_NUM_SRC_PADS 8
|
||||
#define CSI2_NUM_PADS 5
|
||||
#define CSI2_NUM_PADS_MAX 9
|
||||
#define CSI2_NUM_PADS_SINGLE_LINK 2
|
||||
#define MAX_CSI2_SENSORS 2
|
||||
|
||||
@@ -60,6 +61,7 @@ enum rkcsi2_chip_id {
|
||||
CHIP_RK3288_CSI2,
|
||||
CHIP_RV1126_CSI2,
|
||||
CHIP_RK3568_CSI2,
|
||||
CHIP_RK3588_CSI2,
|
||||
};
|
||||
|
||||
enum csi2_pads {
|
||||
@@ -103,7 +105,7 @@ struct csi2_err_stats {
|
||||
struct csi2_dev {
|
||||
struct device *dev;
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pad[CSI2_NUM_PADS];
|
||||
struct media_pad pad[CSI2_NUM_PADS_MAX];
|
||||
struct clk_bulk_data *clks_bulk;
|
||||
int clks_num;
|
||||
struct reset_control *rsts_bulk;
|
||||
@@ -277,25 +279,36 @@ static void csi2_disable(struct csi2_dev *csi2)
|
||||
write_csihost_reg(base, CSIHOST_MSK2, 0xffffffff);
|
||||
}
|
||||
|
||||
static int csi2_g_mbus_config(struct v4l2_subdev *sd, unsigned int pad_id,
|
||||
struct v4l2_mbus_config *mbus);
|
||||
|
||||
static void csi2_enable(struct csi2_dev *csi2,
|
||||
enum host_type_t host_type)
|
||||
{
|
||||
void __iomem *base = csi2->base;
|
||||
int lanes = csi2->bus.num_data_lanes;
|
||||
struct v4l2_mbus_config mbus;
|
||||
u32 val = 0;
|
||||
|
||||
csi2_g_mbus_config(&csi2->sd, 0, &mbus);
|
||||
if (mbus.type == V4L2_MBUS_CSI2_DPHY)
|
||||
val = SW_CPHY_EN(0);
|
||||
else if (mbus.type == V4L2_MBUS_CSI2_CPHY)
|
||||
val = SW_CPHY_EN(1);
|
||||
|
||||
write_csihost_reg(base, CSIHOST_N_LANES, lanes - 1);
|
||||
|
||||
if (host_type == RK_DSI_RXHOST) {
|
||||
write_csihost_reg(base, CSIHOST_CONTROL,
|
||||
SW_CPHY_EN(0) | SW_DSI_EN(1) |
|
||||
SW_DATATYPE_FS(0x01) | SW_DATATYPE_FE(0x11) |
|
||||
SW_DATATYPE_LS(0x21) | SW_DATATYPE_LE(0x31));
|
||||
val |= SW_DSI_EN(1) | SW_DATATYPE_FS(0x01) |
|
||||
SW_DATATYPE_FE(0x11) | SW_DATATYPE_LS(0x21) |
|
||||
SW_DATATYPE_LE(0x31);
|
||||
write_csihost_reg(base, CSIHOST_CONTROL, val);
|
||||
/* Disable some error interrupt when HOST work on DSI RX mode */
|
||||
write_csihost_reg(base, CSIHOST_MSK1, 0xe00000f0);
|
||||
write_csihost_reg(base, CSIHOST_MSK2, 0xff00);
|
||||
} else {
|
||||
write_csihost_reg(base, CSIHOST_CONTROL,
|
||||
SW_CPHY_EN(0) | SW_DSI_EN(0));
|
||||
val |= SW_DSI_EN(0);
|
||||
write_csihost_reg(base, CSIHOST_CONTROL, val);
|
||||
write_csihost_reg(base, CSIHOST_MSK1, 0);
|
||||
write_csihost_reg(base, CSIHOST_MSK2, 0xf000);
|
||||
}
|
||||
@@ -889,6 +902,11 @@ static const struct csi2_match_data rk3568_csi2_match_data = {
|
||||
.num_pads = CSI2_NUM_PADS,
|
||||
};
|
||||
|
||||
static const struct csi2_match_data rk3588_csi2_match_data = {
|
||||
.chip_id = CHIP_RK3588_CSI2,
|
||||
.num_pads = CSI2_NUM_PADS_MAX,
|
||||
};
|
||||
|
||||
static const struct of_device_id csi2_dt_ids[] = {
|
||||
{
|
||||
.compatible = "rockchip,rk1808-mipi-csi2",
|
||||
@@ -906,6 +924,10 @@ static const struct of_device_id csi2_dt_ids[] = {
|
||||
.compatible = "rockchip,rv1126-mipi-csi2",
|
||||
.data = &rv1126_csi2_match_data,
|
||||
},
|
||||
{
|
||||
.compatible = "rockchip,rk3588-mipi-csi2",
|
||||
.data = &rk3588_csi2_match_data,
|
||||
},
|
||||
{ /* sentinel */ }
|
||||
};
|
||||
MODULE_DEVICE_TABLE(of, csi2_dt_ids);
|
||||
|
||||
@@ -272,7 +272,8 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
|
||||
mbus_flags & V4L2_MBUS_VSYNC_ACTIVE_HIGH ? "high active" : "low active");
|
||||
} else {
|
||||
seq_printf(f, "\tinterface:%s\n",
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ? "mipi csi2" :
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ? "mipi csi2 dphy" :
|
||||
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY ? "mipi csi2 cphy" :
|
||||
sensor->mbus.type == V4L2_MBUS_CCP2 ? "lvds" : "unknown");
|
||||
seq_printf(f, "\tlanes:%d\n", sensor->lanes);
|
||||
seq_puts(f, "\tvc channel:");
|
||||
@@ -288,8 +289,8 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
|
||||
}
|
||||
|
||||
seq_printf(f, "\thdr mode: %s\n",
|
||||
dev->hdr.mode == NO_HDR ? "normal" :
|
||||
dev->hdr.mode == HDR_X2 ? "hdr_x2" : "hdr_x3");
|
||||
dev->hdr.hdr_mode == NO_HDR ? "normal" :
|
||||
dev->hdr.hdr_mode == HDR_X2 ? "hdr_x2" : "hdr_x3");
|
||||
|
||||
seq_printf(f, "\tformat:%s/%ux%u@%d\n",
|
||||
rkcif_pixelcode_to_string(stream->cif_fmt_in->mbus_code),
|
||||
@@ -318,7 +319,7 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
|
||||
if (dev->inf_id == RKCIF_MIPI_LVDS) {
|
||||
time_val = div_u64(stream->readout.early_time, 1000000);
|
||||
seq_printf(f, "\tearly:%u ms\n", time_val);
|
||||
if (dev->hdr.mode == NO_HDR) {
|
||||
if (dev->hdr.hdr_mode == NO_HDR) {
|
||||
time_val = div_u64(stream->readout.readout_time, 1000000);
|
||||
seq_printf(f, "\treadout:%u ms\n", time_val);
|
||||
} else {
|
||||
@@ -341,10 +342,12 @@ static void rkcif_show_format(struct rkcif_device *dev, struct seq_file *f)
|
||||
seq_printf(f, "\t\t\tdvp pix err:%llu\n", dev->irq_stats.dvp_pix_err_cnt);
|
||||
seq_printf(f, "\t\t\tdvp line err:%llu\n", dev->irq_stats.dvp_line_err_cnt);
|
||||
seq_printf(f, "\t\t\tdvp over flow:%llu\n", dev->irq_stats.dvp_overflow_cnt);
|
||||
seq_printf(f, "\t\t\tdvp bandwidth lack:%llu\n", dev->irq_stats.dvp_bwidth_lack_cnt);
|
||||
seq_printf(f, "\t\t\tdvp size err:%llu\n", dev->irq_stats.dvp_size_err_cnt);
|
||||
} else {
|
||||
seq_printf(f, "\t\t\tcsi over flow:%llu\n", dev->irq_stats.csi_overflow_cnt);
|
||||
seq_printf(f, "\t\t\tcsi bandwidth lack:%llu\n", dev->irq_stats.csi_bwidth_lack_cnt);
|
||||
|
||||
seq_printf(f, "\t\t\tcsi size err:%llu\n", dev->irq_stats.csi_size_err_cnt);
|
||||
}
|
||||
seq_printf(f, "\t\t\tall err count:%llu\n", dev->irq_stats.all_err_cnt);
|
||||
seq_printf(f, "\t\t\tframe dma end:%llu\n", dev->irq_stats.all_frm_end_cnt);
|
||||
|
||||
@@ -61,6 +61,9 @@ enum cif_reg_index {
|
||||
CIF_REG_DVP_FRM0_ADDR_UV_ID3,
|
||||
CIF_REG_DVP_FRM1_ADDR_Y_ID3,
|
||||
CIF_REG_DVP_FRM1_ADDR_UV_ID3,
|
||||
CIF_REG_DVP_SAV_EAV,
|
||||
CIF_REG_DVP_LINE_CNT1,
|
||||
CIF_REG_DVP_LINE_INT_NUM1,
|
||||
/* mipi & lvds registers index */
|
||||
CIF_REG_MIPI_LVDS_ID0_CTRL0,
|
||||
CIF_REG_MIPI_LVDS_ID0_CTRL1,
|
||||
@@ -134,6 +137,12 @@ enum cif_reg_index {
|
||||
CIF_REG_LVDS_SAV_EAV_BLK0_ID3,
|
||||
CIF_REG_LVDS_SAV_EAV_ACT1_ID3,
|
||||
CIF_REG_LVDS_SAV_EAV_BLK1_ID3,
|
||||
CIF_REG_MIPI_EFFECT_CODE_ID0,
|
||||
CIF_REG_MIPI_EFFECT_CODE_ID1,
|
||||
CIF_REG_MIPI_EFFECT_CODE_ID2,
|
||||
CIF_REG_MIPI_EFFECT_CODE_ID3,
|
||||
CIF_REG_MIPI_ON_PAD,
|
||||
|
||||
CIF_REG_Y_STAT_CONTROL,
|
||||
CIF_REG_Y_STAT_VALUE,
|
||||
CIF_REG_MMU_DTE_ADDR,
|
||||
@@ -149,6 +158,34 @@ enum cif_reg_index {
|
||||
/* reg belowed is in grf */
|
||||
CIF_REG_GRF_CIFIO_CON,
|
||||
CIF_REG_GRF_CIFIO_CON1,
|
||||
/* reg global control */
|
||||
CIF_REG_GLB_CTRL,
|
||||
CIF_REG_GLB_INTEN,
|
||||
CIF_REG_GLB_INTST,
|
||||
CIF_REG_SCL_CH_CTRL,
|
||||
CIF_REG_SCL_CTRL,
|
||||
CIF_REG_SCL_FRM0_ADDR_CH0,
|
||||
CIF_REG_SCL_FRM1_ADDR_CH0,
|
||||
CIF_REG_SCL_VLW_CH0,
|
||||
CIF_REG_SCL_FRM0_ADDR_CH1,
|
||||
CIF_REG_SCL_FRM1_ADDR_CH1,
|
||||
CIF_REG_SCL_VLW_CH1,
|
||||
CIF_REG_SCL_FRM0_ADDR_CH2,
|
||||
CIF_REG_SCL_FRM1_ADDR_CH2,
|
||||
CIF_REG_SCL_VLW_CH2,
|
||||
CIF_REG_SCL_FRM0_ADDR_CH3,
|
||||
CIF_REG_SCL_FRM1_ADDR_CH3,
|
||||
CIF_REG_SCL_VLW_CH3,
|
||||
CIF_REG_SCL_BLC_CH0,
|
||||
CIF_REG_SCL_BLC_CH1,
|
||||
CIF_REG_SCL_BLC_CH2,
|
||||
CIF_REG_SCL_BLC_CH3,
|
||||
CIF_REG_TOISP0_CTRL,
|
||||
CIF_REG_TOISP0_SIZE,
|
||||
CIF_REG_TOISP0_CROP,
|
||||
CIF_REG_TOISP1_CTRL,
|
||||
CIF_REG_TOISP1_SIZE,
|
||||
CIF_REG_TOISP1_CROP,
|
||||
CIF_REG_INDEX_MAX
|
||||
};
|
||||
|
||||
@@ -298,6 +335,116 @@ enum cif_reg_index {
|
||||
#define CIF_MMU_INT_STATUS 0x820
|
||||
#define CIF_MMU_AUTO_GATING 0x824
|
||||
|
||||
/* RK3588 DVP Registers Offset */
|
||||
#define DVP_CTRL 0x10
|
||||
#define DVP_INTEN 0x14
|
||||
#define DVP_INTSTAT 0x18
|
||||
#define DVP_FOR 0x1C
|
||||
#define DVP_MULTI_ID 0x20
|
||||
#define DVP_SAV_EAV 0x24
|
||||
#define DVP_CROP_SIZE 0x28
|
||||
#define DVP_CROP 0x2C
|
||||
#define DVP_FRM0_ADDR_Y_ID0 0x30
|
||||
#define DVP_FRM0_ADDR_UV_ID0 0x34
|
||||
#define DVP_FRM1_ADDR_Y_ID0 0x38
|
||||
#define DVP_FRM1_ADDR_UV_ID0 0x3C
|
||||
#define DVP_FRM0_ADDR_Y_ID1 0x40
|
||||
#define DVP_FRM0_ADDR_UV_ID1 0x44
|
||||
#define DVP_FRM1_ADDR_Y_ID1 0x48
|
||||
#define DVP_FRM1_ADDR_UV_ID1 0x4C
|
||||
#define DVP_FRM0_ADDR_Y_ID2 0x50
|
||||
#define DVP_FRM0_ADDR_UV_ID2 0x54
|
||||
#define DVP_FRM1_ADDR_Y_ID2 0x58
|
||||
#define DVP_FRM1_ADDR_UV_ID2 0x5C
|
||||
#define DVP_FRM0_ADDR_Y_ID3 0x60
|
||||
#define DVP_FRM0_ADDR_UV_ID3 0x64
|
||||
#define DVP_FRM1_ADDR_Y_ID3 0x68
|
||||
#define DVP_FRM1_ADDR_UV_ID3 0x6C
|
||||
#define DVP_VIR_LINE_WIDTH 0x70
|
||||
#define DVP_LINE_INT_NUM_01 0x74
|
||||
#define DVP_LINE_INT_NUM_23 0x78
|
||||
#define DVP_LINE_CNT_01 0x7C
|
||||
#define DVP_LINE_CNT_23 0x80
|
||||
|
||||
/* RK3588 CSI Registers Offset */
|
||||
#define CSI_MIPI0_ID0_CTRL0 0x100
|
||||
#define CSI_MIPI0_ID0_CTRL1 0x104
|
||||
#define CSI_MIPI0_ID1_CTRL0 0x108
|
||||
#define CSI_MIPI0_ID1_CTRL1 0x10C
|
||||
#define CSI_MIPI0_ID2_CTRL0 0x110
|
||||
#define CSI_MIPI0_ID2_CTRL1 0x114
|
||||
#define CSI_MIPI0_ID3_CTRL0 0x118
|
||||
#define CSI_MIPI0_ID3_CTRL1 0x11C
|
||||
#define CSI_MIPI0_CTRL 0x120
|
||||
#define CSI_MIPI0_FRM0_ADDR_Y_ID0 0x124
|
||||
#define CSI_MIPI0_FRM1_ADDR_Y_ID0 0x128
|
||||
#define CSI_MIPI0_FRM0_ADDR_UV_ID0 0x12C
|
||||
#define CSI_MIPI0_FRM1_ADDR_UV_ID0 0x130
|
||||
#define CSI_MIPI0_VLW_ID0 0x134
|
||||
#define CSI_MIPI0_FRM0_ADDR_Y_ID1 0x138
|
||||
#define CSI_MIPI0_FRM1_ADDR_Y_ID1 0x13C
|
||||
#define CSI_MIPI0_FRM0_ADDR_UV_ID1 0x140
|
||||
#define CSI_MIPI0_FRM1_ADDR_UV_ID1 0x144
|
||||
#define CSI_MIPI0_VLW_ID1 0x148
|
||||
#define CSI_MIPI0_FRM0_ADDR_Y_ID2 0x14C
|
||||
#define CSI_MIPI0_FRM1_ADDR_Y_ID2 0x150
|
||||
#define CSI_MIPI0_FRM0_ADDR_UV_ID2 0x154
|
||||
#define CSI_MIPI0_FRM1_ADDR_UV_ID2 0x158
|
||||
#define CSI_MIPI0_VLW_ID2 0x15C
|
||||
#define CSI_MIPI0_FRM0_ADDR_Y_ID3 0x160
|
||||
#define CSI_MIPI0_FRM1_ADDR_Y_ID3 0x164
|
||||
#define CSI_MIPI0_FRM0_ADDR_UV_ID3 0x168
|
||||
#define CSI_MIPI0_FRM1_ADDR_UV_ID3 0x16C
|
||||
#define CSI_MIPI0_VLW_ID3 0x170
|
||||
#define CSI_MIPI0_INTEN 0x174
|
||||
#define CSI_MIPI0_INTSTAT 0x178
|
||||
#define CSI_MIPI0_LINE_INT_NUM_ID0_1 0x17C
|
||||
#define CSI_MIPI0_LINE_INT_NUM_ID2_3 0x180
|
||||
#define CSI_MIPI0_LINE_CNT_ID0_1 0x184
|
||||
#define CSI_MIPI0_LINE_CNT_ID2_3 0x188
|
||||
#define CSI_MIPI0_ID0_CROP_START 0x18C
|
||||
#define CSI_MIPI0_ID1_CROP_START 0x190
|
||||
#define CSI_MIPI0_ID2_CROP_START 0x194
|
||||
#define CSI_MIPI0_ID3_CROP_START 0x198
|
||||
#define CSI_MIPI0_FRAME_NUM_VC0 0x19C
|
||||
#define CSI_MIPI0_FRAME_NUM_VC1 0x1A0
|
||||
#define CSI_MIPI0_FRAME_NUM_VC2 0x1A4
|
||||
#define CSI_MIPI0_FRAME_NUM_VC3 0x1A8
|
||||
#define CSI_MIPI0_EFFECT_CODE_ID0 0x1AC
|
||||
#define CSI_MIPI0_EFFECT_CODE_ID1 0x1B0
|
||||
#define CSI_MIPI0_EFFECT_CODE_ID2 0x1B4
|
||||
#define CSI_MIPI0_EFFECT_CODE_ID3 0x1B8
|
||||
#define CSI_MIPI0_ON_PAD 0x1BC
|
||||
|
||||
/* RK3588 CONTROL Registers Offset */
|
||||
#define GLB_CTRL 0X000
|
||||
#define GLB_INTEN 0X004
|
||||
#define GLB_INTST 0X008
|
||||
#define SCL_CH_CTRL 0x700
|
||||
#define SCL_CTRL 0x704
|
||||
#define SCL_FRM0_ADDR_CH0 0x708
|
||||
#define SCL_FRM1_ADDR_CH0 0x70C
|
||||
#define SCL_VLW_CH0 0x710
|
||||
#define SCL_FRM0_ADDR_CH1 0x714
|
||||
#define SCL_FRM1_ADDR_CH1 0x718
|
||||
#define SCL_VLW_CH1 0x71C
|
||||
#define SCL_FRM0_ADDR_CH2 0x720
|
||||
#define SCL_FRM1_ADDR_CH2 0x724
|
||||
#define SCL_VLW_CH2 0x728
|
||||
#define SCL_FRM0_ADDR_CH3 0x72C
|
||||
#define SCL_FRM1_ADDR_CH3 0x730
|
||||
#define SCL_VLW_CH3 0x734
|
||||
#define SCL_BLC_CH0 0x738
|
||||
#define SCL_BLC_CH1 0x73C
|
||||
#define SCL_BLC_CH2 0x740
|
||||
#define SCL_BLC_CH3 0x744
|
||||
#define TOISP0_CH_CTRL 0x780
|
||||
#define TOISP0_CROP_SIZE 0x784
|
||||
#define TOISP0_CROP 0x788
|
||||
#define TOISP1_CH_CTRL 0x78C
|
||||
#define TOISP1_CROP_SIZE 0x790
|
||||
#define TOISP1_CROP 0x794
|
||||
|
||||
/* The key register bit description */
|
||||
|
||||
/* CIF_CTRL Reg */
|
||||
@@ -307,6 +454,13 @@ enum cif_reg_index {
|
||||
#define MODE_PINGPONG (0x1 << 1)
|
||||
#define MODE_LINELOOP (0x2 << 1)
|
||||
#define AXI_BURST_16 (0xF << 12)
|
||||
#define DVP_PRESS_EN (0x1 << 12)
|
||||
#define DVP_HURRY_EN (0x1 << 8)
|
||||
#define DVP_DMA_EN (0x1 << 1)
|
||||
#define DVP_SW_WATER_LINE_75 (0x0 << 5)
|
||||
#define DVP_SW_WATER_LINE_50 (0x1 << 5)
|
||||
#define DVP_SW_WATER_LINE_25 (0x2 << 5)
|
||||
#define DVP_SW_WATER_LINE_00 (0x3 << 5)
|
||||
|
||||
/* CIF_INTEN */
|
||||
#define INTEN_DISABLE (0x0 << 0)
|
||||
@@ -337,6 +491,22 @@ enum cif_reg_index {
|
||||
#define INTSTAT_ERR (0xFC)
|
||||
#define DVP_ALL_OVERFLOW (IFIFO_OVERFLOW | DFIFO_OVERFLOW)
|
||||
|
||||
#define DVP_FIFO_OVERFLOW (0x01 << 16)
|
||||
#define DVP_BANDWIDTH_LACK (0x01 << 17)
|
||||
|
||||
#define DVP_SIZE_ERR_ID0 (0x1 << 22)
|
||||
#define DVP_SIZE_ERR_ID1 (0x1 << 23)
|
||||
#define DVP_SIZE_ERR_ID2 (0x1 << 24)
|
||||
#define DVP_SIZE_ERR_ID3 (0x1 << 25)
|
||||
|
||||
#define DVP_SIZE_ERR (DVP_SIZE_ERR_ID0 |\
|
||||
DVP_SIZE_ERR_ID1 |\
|
||||
DVP_SIZE_ERR_ID2 |\
|
||||
DVP_SIZE_ERR_ID3)
|
||||
|
||||
#define DVP_SW_PRESS_VALUE(val) (((val) & 0x7) << 13)
|
||||
#define DVP_SW_HURRY_VALUE(val) (((val) & 0x7) << 9)
|
||||
|
||||
#define DVP_DMA_END_INTEN(id) \
|
||||
({ \
|
||||
unsigned int mask; \
|
||||
@@ -351,7 +521,7 @@ enum cif_reg_index {
|
||||
mask; \
|
||||
})
|
||||
|
||||
#define DVP_LINE_INTEN (0x01 << 10)
|
||||
#define DVP_LINE_INTEN (0x01 << 10)
|
||||
|
||||
#define DVP_DMA_END_INTSTAT(id) \
|
||||
({ \
|
||||
@@ -367,8 +537,8 @@ enum cif_reg_index {
|
||||
mask; \
|
||||
})
|
||||
|
||||
#define DVP_PST_INTSTAT PST_INF_FRAME_END
|
||||
#define DVP_LINE_INTSTAT (0x01 << 10)
|
||||
#define DVP_PST_INTSTAT PST_INF_FRAME_END
|
||||
#define DVP_LINE_INTSTAT (0x01 << 10)
|
||||
|
||||
/* FRAME STATUS */
|
||||
#define FRAME_STAT_CLS 0x00
|
||||
@@ -433,6 +603,19 @@ enum cif_reg_index {
|
||||
#define BT656_1120_MULTI_ID_2_MASK ~(0x03 << 20)
|
||||
#define BT656_1120_MULTI_ID_3_MASK ~(0x03 << 28)
|
||||
#define CIF_HIGH_ALIGN (0x01 << 18)
|
||||
#define CIF_HIGH_ALIGN_RK3588 (0x01 << 21)
|
||||
|
||||
|
||||
#define BT1120_CLOCK_SINGLE_EDGES_RK3588 (0x00 << 11)
|
||||
#define BT1120_CLOCK_DOUBLE_EDGES_RK3588 (0x01 << 11)
|
||||
#define TRANSMIT_INTERFACE_RK3588 (0x01 << 9)
|
||||
#define TRANSMIT_PROGRESS_RK3588 (0x00 << 9)
|
||||
#define BT1120_YC_SWAP_RK3588 (0x01 << 12)
|
||||
#define INPUT_BT601_YUV422 (0x00 << 2)
|
||||
#define INPUT_BT601_RAW (0x01 << 2)
|
||||
#define INPUT_BT656_YUV422 (0x02 << 2)
|
||||
#define INPUT_BT1120_YUV422 (0x03 << 2)
|
||||
#define INPUT_SONY_RAW (0x04 << 2)
|
||||
|
||||
/* CIF_SCL_CTRL */
|
||||
#define ENABLE_SCL_DOWN (0x01 << 0)
|
||||
@@ -460,11 +643,33 @@ enum cif_reg_index {
|
||||
#define DVP_CHANNEL3_F1_READY (0x01 << 13)
|
||||
#define DVP_CHANNEL3_FRM_READ (DVP_CHANNEL3_F0_READY | DVP_CHANNEL3_F1_READY)
|
||||
|
||||
#define DVP_FRAME0_START_ID0 (0x1 << 0)
|
||||
#define DVP_FRAME1_START_ID0 (0x1 << 1)
|
||||
|
||||
#define DVP_FRAME_END_ID0 (0x1 << 0)
|
||||
#define DVP_FRAME_END_ID1 (0x1 << 11)
|
||||
#define DVP_FRAME_END_ID2 (0x1 << 12)
|
||||
#define DVP_FRAME_END_ID3 (0x1 << 13)
|
||||
|
||||
#define DVP_FRAME0_END_ID0 (0x1 << 8)
|
||||
#define DVP_FRAME1_END_ID0 (0x1 << 9)
|
||||
#define DVP_ALL_END_ID0 (DVP_FRAME0_END_ID0 | DVP_FRAME1_END_ID0)
|
||||
|
||||
#define DVP_FRAME0_END_ID1 (0x1 << 10)
|
||||
#define DVP_FRAME1_END_ID1 (0x1 << 11)
|
||||
#define DVP_ALL_END_ID1 (DVP_FRAME0_END_ID1 | DVP_FRAME1_END_ID1)
|
||||
|
||||
#define DVP_FRAME0_END_ID2 (0x1 << 12)
|
||||
#define DVP_FRAME1_END_ID2 (0x1 << 13)
|
||||
#define DVP_ALL_END_ID2 (DVP_FRAME0_END_ID2 | DVP_FRAME1_END_ID2)
|
||||
|
||||
#define DVP_FRAME0_END_ID3 (0x1 << 14)
|
||||
#define DVP_FRAME1_END_ID3 (0x1 << 15)
|
||||
#define DVP_ALL_END_ID3 (DVP_FRAME0_END_ID3 | DVP_FRAME1_END_ID3)
|
||||
|
||||
#define DVP_ALIGN_MSB (0x01 << 21)
|
||||
#define DVP_ALIGN_LSB (0x00 << 21)
|
||||
|
||||
#define DVP_FRM_STS_ID0(x) (((x) & (0x3 << 0)) >> 0)
|
||||
#define DVP_FRM_STS_ID1(x) (((x) & (0x3 << 4)) >> 4)
|
||||
#define DVP_FRM_STS_ID2(x) (((x) & (0x3 << 8)) >> 8)
|
||||
@@ -497,6 +702,21 @@ enum cif_reg_index {
|
||||
#define CIF_CROP_Y_SHIFT 16
|
||||
#define CIF_CROP_X_SHIFT 0
|
||||
|
||||
/* CIF SCALE*/
|
||||
#define SCALE_END_INTSTAT(ch) (0x3 << ((ch + 1) * 2))
|
||||
#define SCALE_FIFO_OVERFLOW(ch) (1 << (10 + ch))
|
||||
#define SCALE_TOISP_AXI0_ERR (1 << 0)
|
||||
#define SCALE_TOISP_AXI1_ERR (1 << 1)
|
||||
#define CIF_SCALE_SW_PRESS_VALUE(val) (((val) & 0x7) << 13)
|
||||
#define CIF_SCALE_SW_PRESS_ENABLE (0x1 << 12)
|
||||
#define CIF_SCALE_SW_HURRY_VALUE(val) (((val) & 0x7) << 5)
|
||||
#define CIF_SCALE_SW_HURRY_ENABLE (0x1 << 4)
|
||||
#define CIF_SCALE_SW_WATER_LINE(val) (val << 1)
|
||||
#define CIF_SCALE_SW_SRC_CH(val, ch) ((val & 0x1f) << (3 + ch * 8))
|
||||
#define CIF_SCALE_SW_MODE(val, ch) ((val & 0x3) << (1 + ch * 8))
|
||||
#define CIF_SCALE_EN(ch) (1 << (ch * 8))
|
||||
#define SW_SCALE_END(intstat, ch) ((intstat >> ((ch + 1) * 2)) & 0x3)
|
||||
|
||||
/* CIF_CSI_ID_CTRL0 */
|
||||
#define CSI_DISABLE_CAPTURE (0x0 << 0)
|
||||
#define CSI_ENABLE_CAPTURE (0x1 << 0)
|
||||
@@ -511,12 +731,38 @@ enum cif_reg_index {
|
||||
#define CSI_ENABLE_COMMAND_MODE (0x1 << 4)
|
||||
#define CSI_DISABLE_CROP (0x0 << 5)
|
||||
#define CSI_ENABLE_CROP (0x1 << 5)
|
||||
#define CSI_DISABLE_CROP_V1 (0x0 << 4)
|
||||
#define CSI_ENABLE_CROP_V1 (0x1 << 4)
|
||||
#define CSI_ENABLE_MIPI_COMPACT (0x1 << 6)
|
||||
#define CSI_YUV_INPUT_ORDER_UYVY (0x0 << 16)
|
||||
#define CSI_YUV_INPUT_ORDER_VYUY (0x1 << 16)
|
||||
#define CSI_YUV_INPUT_ORDER_YUYV (0x2 << 16)
|
||||
#define CSI_YUV_INPUT_ORDER_YVYU (0x3 << 16)
|
||||
#define CSI_ENABLE_MIPI_HIGH_ALIGN (0x1 << 31)
|
||||
#define CSI_HIGH_ALIGN (0x1 << 31)
|
||||
#define CSI_HIGH_ALIGN_RK3588 (0x1 << 27)
|
||||
|
||||
#define CSI_YUV_OUTPUT_ORDER_UYVY (0x0 << 18)
|
||||
#define CSI_YUV_OUTPUT_ORDER_VYUY (0x1 << 18)
|
||||
#define CSI_YUV_OUTPUT_ORDER_YUYV (0x2 << 18)
|
||||
#define CSI_YUV_OUTPUT_ORDER_YVYU (0x3 << 18)
|
||||
#define CSI_WRDDR_TYPE_RAW_COMPACT (0x0 << 5)
|
||||
#define CSI_WRDDR_TYPE_RAW_UNCOMPACT (0x1 << 5)
|
||||
#define CSI_WRDDR_TYPE_YUV_PACKET (0x2 << 5)
|
||||
#define CSI_WRDDR_TYPE_YUV400_RK3588 (0x3 << 5)
|
||||
#define CSI_WRDDR_TYPE_YUV422SP_RK3588 (0x4 << 5)
|
||||
#define CSI_WRDDR_TYPE_YUV420SP_RK3588 (0x5 << 5)
|
||||
#define CSI_ALIGN_MSB (0x01 << 27)
|
||||
#define CSI_ALIGN_LSB (0x0 << 27)
|
||||
#define CSI_DMA_ENABLE (0x1 << 28)
|
||||
|
||||
#define CSI_NO_HDR (0X0 << 22)
|
||||
#define CSI_HDR2 (0X1 << 22)
|
||||
#define CSI_HDR3 (0X2 << 22)
|
||||
|
||||
#define CSI_HDR_MODE_VC (0x0 << 20)
|
||||
#define CSI_HDR_MODE_LINE_CNT (0x1 << 20)
|
||||
#define CSI_HDR_MODE_LINE_INFO (0x2 << 20)
|
||||
#define CSI_HDR_VC_MODE_PROTECT (0x1 << 29)
|
||||
|
||||
#define LVDS_ENABLE_CAPTURE (0x1 << 16)
|
||||
#define LVDS_MODE(mode) (((mode) & 0x7) << 17)
|
||||
@@ -561,14 +807,17 @@ enum cif_reg_index {
|
||||
#define CSI_ALL_FRAME_START_INTEN (0xff << 0)
|
||||
#define CSI_ALL_FRAME_END_INTEN (0xff << 8)
|
||||
#define CSI_ALL_ERROR_INTEN (0x1f << 16)
|
||||
#define CSI_ALL_ERROR_INTEN_V1 (0xf0f << 16)
|
||||
|
||||
#define CSI_START_INTEN(id) (0x3 << ((id) * 2))
|
||||
#define CSI_DMA_END_INTEN(id) (0x3 << ((id) * 2 + 8))
|
||||
#define CSI_LINE_INTEN(id) (0x1 << ((id) + 21))
|
||||
#define CSI_LINE_INTEN_RK3588(id) (0x1 << ((id) + 20))
|
||||
|
||||
#define CSI_START_INTSTAT(id) (0x3 << ((id) * 2))
|
||||
#define CSI_DMA_END_INTSTAT(id) (0x3 << ((id) * 2 + 8))
|
||||
#define CSI_LINE_INTSTAT(id) (0x1 << ((id) + 21))
|
||||
#define CSI_LINE_INTSTAT_V1(id) (0x1 << ((id) + 20))
|
||||
|
||||
/* CIF_CSI_INTSTAT */
|
||||
#define CSI_FRAME0_START_ID0 (0x1 << 0)
|
||||
@@ -598,51 +847,72 @@ enum cif_reg_index {
|
||||
#define CSI_LINE_ID3_INTST (0x1 << 24)
|
||||
#define CSI_DMA_LVDS_ID2_FIFO_OVERFLOW (0x1 << 25)
|
||||
#define CSI_DMA_LVDS_ID3_FIFO_OVERFLOW (0x1 << 26)
|
||||
#define CSI_SIZE_ERR_ID0 (0x1 << 24)
|
||||
#define CSI_SIZE_ERR_ID1 (0x1 << 25)
|
||||
#define CSI_SIZE_ERR_ID2 (0x1 << 26)
|
||||
#define CSI_SIZE_ERR_ID3 (0x1 << 27)
|
||||
|
||||
#define CSI_FRAME_START_ID0 (CSI_FRAME0_START_ID0 |\
|
||||
CSI_FRAME1_START_ID0)
|
||||
#define CSI_FRAME_START_ID1 (CSI_FRAME0_START_ID1 |\
|
||||
CSI_FRAME1_START_ID1)
|
||||
#define CSI_FRAME_START_ID2 (CSI_FRAME0_START_ID2 |\
|
||||
CSI_FRAME1_START_ID2)
|
||||
#define CSI_FRAME_START_ID3 (CSI_FRAME0_START_ID3 |\
|
||||
CSI_FRAME1_START_ID3)
|
||||
#define CSI_FRAME_END_ID0 (CSI_FRAME0_END_ID0 |\
|
||||
CSI_FRAME1_END_ID0)
|
||||
#define CSI_FRAME_END_ID1 (CSI_FRAME0_END_ID1 |\
|
||||
CSI_FRAME1_END_ID1)
|
||||
#define CSI_FRAME_END_ID2 (CSI_FRAME0_END_ID2 |\
|
||||
CSI_FRAME1_END_ID2)
|
||||
#define CSI_FRAME_END_ID3 (CSI_FRAME0_END_ID3 |\
|
||||
CSI_FRAME1_END_ID3)
|
||||
#define CSI_FIFO_OVERFLOW (CSI_DMA_Y_FIFO_OVERFLOW |\
|
||||
CSI_DMA_UV_FIFO_OVERFLOW |\
|
||||
CSI_CONFIG_FIFO_OVERFLOW |\
|
||||
CSI_RX_FIFO_OVERFLOW |\
|
||||
CSI_DMA_LVDS_ID2_FIFO_OVERFLOW |\
|
||||
CSI_DMA_LVDS_ID3_FIFO_OVERFLOW)
|
||||
|
||||
/*mask for rk3588*/
|
||||
#define CSI_RX_FIFO_OVERFLOW_V1 (0x1 << 19)
|
||||
#define CSI_BANDWIDTH_LACK_V1 (0x1 << 18)
|
||||
#define CSI_ALL_ERROR_INTEN_V1 (0xf0f << 16)
|
||||
|
||||
|
||||
#define CSI_FIFO_OVERFLOW_V1 (CSI_DMA_Y_FIFO_OVERFLOW |\
|
||||
CSI_DMA_UV_FIFO_OVERFLOW |\
|
||||
CSI_RX_FIFO_OVERFLOW_V1)
|
||||
#define CSI_SIZE_ERR (CSI_SIZE_ERR_ID0 |\
|
||||
CSI_SIZE_ERR_ID1 |\
|
||||
CSI_SIZE_ERR_ID2 |\
|
||||
CSI_SIZE_ERR_ID3)
|
||||
|
||||
#define CSI_FRAME_START_ID0 (CSI_FRAME0_START_ID0 |\
|
||||
CSI_FRAME1_START_ID0)
|
||||
#define CSI_FRAME_START_ID1 (CSI_FRAME0_START_ID1 |\
|
||||
CSI_FRAME1_START_ID1)
|
||||
#define CSI_FRAME_START_ID2 (CSI_FRAME0_START_ID2 |\
|
||||
CSI_FRAME1_START_ID2)
|
||||
#define CSI_FRAME_START_ID3 (CSI_FRAME0_START_ID3 |\
|
||||
CSI_FRAME1_START_ID3)
|
||||
#define CSI_FRAME_END_ID0 (CSI_FRAME0_END_ID0 |\
|
||||
CSI_FRAME1_END_ID0)
|
||||
#define CSI_FRAME_END_ID1 (CSI_FRAME0_END_ID1 |\
|
||||
CSI_FRAME1_END_ID1)
|
||||
#define CSI_FRAME_END_ID2 (CSI_FRAME0_END_ID2 |\
|
||||
CSI_FRAME1_END_ID2)
|
||||
#define CSI_FRAME_END_ID3 (CSI_FRAME0_END_ID3 |\
|
||||
CSI_FRAME1_END_ID3)
|
||||
#define CSI_FIFO_OVERFLOW (CSI_DMA_Y_FIFO_OVERFLOW | \
|
||||
CSI_DMA_UV_FIFO_OVERFLOW | \
|
||||
CSI_CONFIG_FIFO_OVERFLOW | \
|
||||
CSI_RX_FIFO_OVERFLOW | \
|
||||
CSI_DMA_LVDS_ID2_FIFO_OVERFLOW | \
|
||||
CSI_DMA_LVDS_ID3_FIFO_OVERFLOW)
|
||||
/* CIF_MIPI_LVDS_CTRL */
|
||||
#define CIF_MIPI_LVDS_SW_DMA_IDLE (0x1 << 16)
|
||||
#define CIF_MIPI_LVDS_SW_PRESS_VALUE(val) (((val) & 0x3) << 13)
|
||||
#define CIF_MIPI_LVDS_SW_PRESS_ENABLE (0x1 << 12)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_8BITS (0x0 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_10BITS (0x1 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_12BITS (0x2 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_SEL_LVDS (0x1 << 8)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_VALUE(val) (((val) & 0x3) << 5)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_ENABLE (0x1 << 4)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_75 (0x0 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_50 (0x1 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_25 (0x2 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_00 (0x3 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE (0x1 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_DMA_IDLE_RK1808 (0x1 << 24)
|
||||
#define CIF_MIPI_LVDS_SW_DMA_IDLE (0x1 << 16)
|
||||
#define CIF_MIPI_LVDS_SW_PRESS_VALUE(val) (((val) & 0x3) << 13)
|
||||
#define CIF_MIPI_LVDS_SW_PRESS_VALUE_RK3588(val) (((val) & 0x7) << 13)
|
||||
#define CIF_MIPI_LVDS_SW_PRESS_ENABLE (0x1 << 12)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_8BITS (0x0 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_10BITS (0x1 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_LVDS_WIDTH_12BITS (0x2 << 9)
|
||||
#define CIF_MIPI_LVDS_SW_SEL_LVDS (0x1 << 8)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_VALUE(val) (((val) & 0x3) << 5)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_VALUE_RK3588(val) (((val) & 0x7) << 5)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_ENABLE (0x1 << 4)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_75 (0x0 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_50 (0x1 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_25 (0x2 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_00 (0x3 << 1)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE (0x1 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_DMA_IDLE_RK1808 (0x1 << 24)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_VALUE_RK1808(val) (((val) & 0x3) << 17)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_ENABLE_RK1808 (0x1 << 16)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_75_RK1808 (0x0 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_50_RK1808 (0x1 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_25_RK1808 (0x2 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_00_RK1808 (0x3 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_HURRY_ENABLE_RK1808 (0x1 << 16)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_75_RK1808 (0x0 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_50_RK1808 (0x1 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_25_RK1808 (0x2 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_00_RK1808 (0x3 << 0)
|
||||
#define CIF_MIPI_LVDS_SW_WATER_LINE_ENABLE_RK1808 (0x1 << 4)
|
||||
|
||||
/* CSI Host Registers Define */
|
||||
@@ -688,5 +958,16 @@ enum cif_reg_index {
|
||||
#define RK3568_CIF_PCLK_SAMPLING_EDGE_FALLING (0x10001000)
|
||||
#define RK3568_CIF_PCLK_SINGLE_EDGE (0x02000000)
|
||||
#define RK3568_CIF_PCLK_DUAL_EDGE (0x02000200)
|
||||
#define CIF_GRF_SOC_CON2 (0x308)
|
||||
#define RK3588_CIF_PCLK_SAMPLING_EDGE_RISING (0x00100000)
|
||||
#define RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING (0x00100010)
|
||||
#define RK3588_CIF_PCLK_SINGLE_EDGE (0x00200000)
|
||||
#define RK3588_CIF_PCLK_DUAL_EDGE (0x00200020)
|
||||
|
||||
|
||||
/*toisp*/
|
||||
#define TOISP_END_CH0(index) (0x1 << (20 + index * 3))
|
||||
#define TOISP_END_CH1(index) (0x1 << (21 + index * 3))
|
||||
#define TOISP_END_CH2(index) (0x1 << (22 + index * 3))
|
||||
|
||||
#endif
|
||||
|
||||
@@ -20,12 +20,36 @@
|
||||
#include <media/videobuf2-dma-contig.h>
|
||||
#include <media/v4l2-fwnode.h>
|
||||
#include "dev.h"
|
||||
#include <linux/regulator/consumer.h>
|
||||
|
||||
static inline struct sditf_priv *to_sditf_priv(struct v4l2_subdev *subdev)
|
||||
{
|
||||
return container_of(subdev, struct sditf_priv, sd);
|
||||
}
|
||||
|
||||
static void sditf_get_hdr_mode(struct sditf_priv *priv)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct rkmodule_hdr_cfg hdr_cfg;
|
||||
int ret = 0;
|
||||
|
||||
if (!cif_dev->terminal_sensor.sd)
|
||||
rkcif_update_sensor_info(&cif_dev->stream[0]);
|
||||
|
||||
if (cif_dev->terminal_sensor.sd) {
|
||||
ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
|
||||
core, ioctl,
|
||||
RKMODULE_GET_HDR_CFG,
|
||||
&hdr_cfg);
|
||||
if (!ret)
|
||||
priv->hdr_cfg = hdr_cfg;
|
||||
else
|
||||
priv->hdr_cfg.hdr_mode = NO_HDR;
|
||||
} else {
|
||||
priv->hdr_cfg.hdr_mode = NO_HDR;
|
||||
}
|
||||
}
|
||||
|
||||
static int sditf_g_frame_interval(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_frame_interval *fi)
|
||||
{
|
||||
@@ -69,12 +93,15 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd,
|
||||
struct sditf_priv *priv = to_sditf_priv(sd);
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct v4l2_subdev_selection input_sel;
|
||||
struct v4l2_pix_format_mplane pixm;
|
||||
int ret = -EINVAL;
|
||||
|
||||
if (!cif_dev->terminal_sensor.sd)
|
||||
rkcif_update_sensor_info(&cif_dev->stream[0]);
|
||||
|
||||
if (cif_dev->terminal_sensor.sd) {
|
||||
sditf_get_hdr_mode(priv);
|
||||
fmt->which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd, pad, get_fmt, NULL, fmt);
|
||||
if (ret) {
|
||||
v4l2_err(&priv->sd,
|
||||
@@ -83,6 +110,8 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd,
|
||||
}
|
||||
|
||||
input_sel.target = V4L2_SEL_TGT_CROP_BOUNDS;
|
||||
input_sel.which = V4L2_SUBDEV_FORMAT_ACTIVE;
|
||||
input_sel.pad = 0;
|
||||
ret = v4l2_subdev_call(cif_dev->terminal_sensor.sd,
|
||||
pad, get_selection, NULL,
|
||||
&input_sel);
|
||||
@@ -90,11 +119,57 @@ static int sditf_get_set_fmt(struct v4l2_subdev *sd,
|
||||
fmt->format.width = input_sel.r.width;
|
||||
fmt->format.height = input_sel.r.height;
|
||||
}
|
||||
priv->cap_info.width = fmt->format.width;
|
||||
priv->cap_info.height = fmt->format.height;
|
||||
pixm.pixelformat = rkcif_mbus_pixelcode_to_v4l2(fmt->format.code);
|
||||
pixm.width = priv->cap_info.width;
|
||||
pixm.height = priv->cap_info.height;
|
||||
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
|
||||
"%s, width %d, height %d, hdr mode %d\n",
|
||||
__func__, fmt->format.width, fmt->format.width, priv->hdr_cfg.hdr_mode);
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
|
||||
rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
|
||||
rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
rkcif_set_fmt(&cif_dev->stream[0], &pixm, false);
|
||||
rkcif_set_fmt(&cif_dev->stream[1], &pixm, false);
|
||||
rkcif_set_fmt(&cif_dev->stream[2], &pixm, false);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sditf_init_buf(struct sditf_priv *priv)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
int ret = 0;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
ret = rkcif_init_rx_buf(&cif_dev->stream[0], priv->buf_num);
|
||||
ret |= rkcif_init_rx_buf(&cif_dev->stream[1], priv->buf_num);
|
||||
} else {
|
||||
ret = -EINVAL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void sditf_free_buf(struct sditf_priv *priv)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
rkcif_free_rx_buf(&cif_dev->stream[0], priv->buf_num);
|
||||
rkcif_free_rx_buf(&cif_dev->stream[1], priv->buf_num);
|
||||
}
|
||||
}
|
||||
|
||||
static int sditf_get_selection(struct v4l2_subdev *sd,
|
||||
struct v4l2_subdev_pad_config *cfg,
|
||||
struct v4l2_subdev_selection *sel)
|
||||
@@ -102,18 +177,49 @@ static int sditf_get_selection(struct v4l2_subdev *sd,
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
static void sditf_reinit_mode(struct sditf_priv *priv, struct rkisp_vicap_mode *mode)
|
||||
{
|
||||
if (mode->is_rdbk) {
|
||||
priv->toisp_inf.link_mode = TOISP_NONE;
|
||||
} else {
|
||||
if (strstr(mode->name, RKISP0_DEVNAME))
|
||||
priv->toisp_inf.link_mode = TOISP0;
|
||||
else if (strstr(mode->name, RKISP1_DEVNAME))
|
||||
priv->toisp_inf.link_mode = TOISP1;
|
||||
else if (strstr(mode->name, RKISP_UNITE_DEVNAME))
|
||||
priv->toisp_inf.link_mode = TOISP_UNITE;
|
||||
else
|
||||
v4l2_err(&priv->cif_dev->v4l2_dev,
|
||||
"%s, mode name err, mode name: %s\n",
|
||||
__func__, mode->name);
|
||||
}
|
||||
v4l2_dbg(3, rkcif_debug, &priv->cif_dev->v4l2_dev,
|
||||
"%s, mode->is_rdbk %d, mode->name %s, link_mode %d\n",
|
||||
__func__, mode->is_rdbk, mode->name, priv->toisp_inf.link_mode);
|
||||
}
|
||||
|
||||
static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
{
|
||||
struct sditf_priv *priv = to_sditf_priv(sd);
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct v4l2_subdev *sensor_sd;
|
||||
struct rkisp_vicap_mode *mode;
|
||||
struct v4l2_subdev_format fmt;
|
||||
int *pbuf_num = NULL;
|
||||
int ret = 0;
|
||||
|
||||
if (!cif_dev->terminal_sensor.sd)
|
||||
rkcif_update_sensor_info(&cif_dev->stream[0]);
|
||||
|
||||
if (cif_dev->terminal_sensor.sd) {
|
||||
sensor_sd = cif_dev->terminal_sensor.sd;
|
||||
return v4l2_subdev_call(sensor_sd, core, ioctl, cmd, arg);
|
||||
switch (cmd) {
|
||||
case RKISP_VICAP_CMD_MODE:
|
||||
mode = (struct rkisp_vicap_mode *)arg;
|
||||
memcpy(&priv->mode, mode, sizeof(*mode));
|
||||
sditf_reinit_mode(priv, &priv->mode);
|
||||
return 0;
|
||||
case RKISP_VICAP_CMD_INIT_BUF:
|
||||
pbuf_num = (int *)arg;
|
||||
priv->buf_num = *pbuf_num;
|
||||
sditf_get_set_fmt(&priv->sd, NULL, &fmt);
|
||||
ret = sditf_init_buf(priv);
|
||||
return ret;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return -EINVAL;
|
||||
@@ -123,9 +229,36 @@ static long sditf_ioctl(struct v4l2_subdev *sd, unsigned int cmd, void *arg)
|
||||
static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
unsigned int cmd, unsigned long arg)
|
||||
{
|
||||
void __user *up = compat_ptr(arg);
|
||||
struct sditf_priv *priv = to_sditf_priv(sd);
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct v4l2_subdev *sensor_sd;
|
||||
struct rkisp_vicap_mode *mode;
|
||||
int buf_num;
|
||||
int ret = 0;
|
||||
|
||||
switch (cmd) {
|
||||
case RKISP_VICAP_CMD_MODE:
|
||||
mode = kzalloc(sizeof(*mode), GFP_KERNEL);
|
||||
if (!mode) {
|
||||
ret = -ENOMEM;
|
||||
return ret;
|
||||
}
|
||||
if (copy_from_user(mode, up, sizeof(*mode))) {
|
||||
kfree(mode);
|
||||
return -EFAULT;
|
||||
}
|
||||
ret = sditf_ioctl(sd, cmd, mode);
|
||||
kfree(mode);
|
||||
return ret;
|
||||
case RKISP_VICAP_CMD_INIT_BUF:
|
||||
if (copy_from_user(&buf_num, up, sizeof(int)))
|
||||
return -EFAULT;
|
||||
ret = sditf_ioctl(sd, cmd, &buf_num);
|
||||
return ret;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!cif_dev->terminal_sensor.sd)
|
||||
rkcif_update_sensor_info(&cif_dev->stream[0]);
|
||||
@@ -139,6 +272,180 @@ static long sditf_compat_ioctl32(struct v4l2_subdev *sd,
|
||||
}
|
||||
#endif
|
||||
|
||||
static int sditf_channel_enable(struct sditf_priv *priv, int user)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
unsigned int ch0 = 0, ch1 = 0, ch2 = 0;
|
||||
unsigned int ctrl_val = 0;
|
||||
unsigned int int_en = 0;
|
||||
unsigned int offset_x = 0;
|
||||
unsigned int offset_y = 0;
|
||||
unsigned int width = priv->cap_info.width;
|
||||
unsigned int height = priv->cap_info.height;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
|
||||
if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
|
||||
ch0 = cif_dev->csi_host_idx * 4;
|
||||
else
|
||||
ch0 = 24;//dvp
|
||||
ctrl_val = (ch0 << 3) | 0x1;
|
||||
if (user == 0)
|
||||
int_en = 0x04104003;
|
||||
else
|
||||
int_en = 0x08820003;
|
||||
priv->toisp_inf.ch_info[0].is_valid = true;
|
||||
priv->toisp_inf.ch_info[0].id = ch0;
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
ch0 = cif_dev->csi_host_idx * 4 + 1;
|
||||
ch1 = cif_dev->csi_host_idx * 4;
|
||||
ctrl_val = (ch0 << 3) | 0x1;
|
||||
ctrl_val |= (ch1 << 11) | 0x100;
|
||||
if (user == 0)
|
||||
int_en = 0x0430c003;
|
||||
else
|
||||
int_en = 0x09860003;
|
||||
priv->toisp_inf.ch_info[0].is_valid = true;
|
||||
priv->toisp_inf.ch_info[0].id = ch0;
|
||||
priv->toisp_inf.ch_info[1].is_valid = true;
|
||||
priv->toisp_inf.ch_info[1].id = ch1;
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
ch0 = cif_dev->csi_host_idx * 4 + 2;
|
||||
ch1 = cif_dev->csi_host_idx * 4 + 1;
|
||||
ch2 = cif_dev->csi_host_idx * 4;
|
||||
ctrl_val = (ch0 << 3) | 0x1;
|
||||
ctrl_val |= (ch1 << 11) | 0x100;
|
||||
ctrl_val |= (ch2 << 19) | 0x10000;
|
||||
if (user == 0)
|
||||
int_en = 0x0471c003;
|
||||
else
|
||||
int_en = 0x0b8e0003;
|
||||
priv->toisp_inf.ch_info[0].is_valid = true;
|
||||
priv->toisp_inf.ch_info[0].id = ch0;
|
||||
priv->toisp_inf.ch_info[1].is_valid = true;
|
||||
priv->toisp_inf.ch_info[1].id = ch1;
|
||||
priv->toisp_inf.ch_info[2].is_valid = true;
|
||||
priv->toisp_inf.ch_info[2].id = ch2;
|
||||
}
|
||||
if (user == 0) {
|
||||
if (priv->toisp_inf.link_mode == TOISP_UNITE)
|
||||
width = priv->cap_info.width / 2 + 256;
|
||||
rkcif_write_register_or(cif_dev, CIF_REG_TOISP0_CTRL, ctrl_val);
|
||||
if (width && height) {
|
||||
rkcif_write_register(cif_dev, CIF_REG_TOISP0_CROP,
|
||||
offset_x | (offset_y << 16));
|
||||
rkcif_write_register(cif_dev, CIF_REG_TOISP0_SIZE,
|
||||
width | (height << 16));
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
|
||||
} else {
|
||||
if (priv->toisp_inf.link_mode == TOISP_UNITE) {
|
||||
offset_x = priv->cap_info.width / 2 - 256;
|
||||
width = priv->cap_info.width / 2 + 256;
|
||||
}
|
||||
rkcif_write_register_or(cif_dev, CIF_REG_TOISP1_CTRL, ctrl_val);
|
||||
if (width && height) {
|
||||
rkcif_write_register(cif_dev, CIF_REG_TOISP1_CROP,
|
||||
offset_x | (offset_y << 16));
|
||||
rkcif_write_register(cif_dev, CIF_REG_TOISP1_SIZE,
|
||||
width | (height << 16));
|
||||
} else {
|
||||
return -EINVAL;
|
||||
}
|
||||
rkcif_write_register_or(cif_dev, CIF_REG_GLB_INTEN, int_en);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static __maybe_unused void sditf_channel_disable(struct sditf_priv *priv, int user)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
unsigned int ctrl_val = 0;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR)
|
||||
ctrl_val = 0x01;
|
||||
else if (priv->hdr_cfg.hdr_mode == HDR_X2)
|
||||
ctrl_val = 0x101;
|
||||
else if (priv->hdr_cfg.hdr_mode == HDR_X3)
|
||||
ctrl_val = 0x10101;
|
||||
if (user == 0)
|
||||
rkcif_write_register_and(cif_dev, CIF_REG_TOISP0_CTRL, ~ctrl_val);
|
||||
else
|
||||
rkcif_write_register_and(cif_dev, CIF_REG_TOISP1_CTRL, ~ctrl_val);
|
||||
priv->toisp_inf.ch_info[0].is_valid = false;
|
||||
priv->toisp_inf.ch_info[1].is_valid = false;
|
||||
priv->toisp_inf.ch_info[2].is_valid = false;
|
||||
}
|
||||
|
||||
static int sditf_start_stream(struct sditf_priv *priv)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
struct v4l2_subdev_format fmt;
|
||||
|
||||
sditf_get_set_fmt(&priv->sd, NULL, &fmt);
|
||||
if (priv->toisp_inf.link_mode == TOISP0) {
|
||||
sditf_channel_enable(priv, 0);
|
||||
} else if (priv->toisp_inf.link_mode == TOISP1) {
|
||||
sditf_channel_enable(priv, 1);
|
||||
} else if (priv->toisp_inf.link_mode == TOISP_UNITE) {
|
||||
sditf_channel_enable(priv, 0);
|
||||
sditf_channel_enable(priv, 1);
|
||||
}
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_start_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
rkcif_do_start_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_start_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_start_stream(&cif_dev->stream[2], RKCIF_STREAM_MODE_TOISP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sditf_stop_stream(struct sditf_priv *priv)
|
||||
{
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
|
||||
if (priv->hdr_cfg.hdr_mode == NO_HDR) {
|
||||
rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X2) {
|
||||
rkcif_do_stop_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
} else if (priv->hdr_cfg.hdr_mode == HDR_X3) {
|
||||
rkcif_do_stop_stream(&cif_dev->stream[2], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_stop_stream(&cif_dev->stream[1], RKCIF_STREAM_MODE_TOISP);
|
||||
rkcif_do_stop_stream(&cif_dev->stream[0], RKCIF_STREAM_MODE_TOISP);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sditf_s_stream(struct v4l2_subdev *sd, int on)
|
||||
{
|
||||
struct sditf_priv *priv = to_sditf_priv(sd);
|
||||
struct rkcif_device *cif_dev = priv->cif_dev;
|
||||
int ret = 0;
|
||||
|
||||
if (cif_dev->chip_id >= CHIP_RK3588_CIF) {
|
||||
if (priv->toisp_inf.link_mode == TOISP_NONE)
|
||||
return 0;
|
||||
v4l2_dbg(3, rkcif_debug, &cif_dev->v4l2_dev,
|
||||
"%s, toisp mode %d, hdr %d, stream on %d\n",
|
||||
__func__, priv->toisp_inf.link_mode, priv->hdr_cfg.hdr_mode, on);
|
||||
if (on) {
|
||||
ret = sditf_start_stream(priv);
|
||||
} else {
|
||||
ret = sditf_stop_stream(priv);
|
||||
sditf_free_buf(priv);
|
||||
}
|
||||
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
static const struct v4l2_subdev_pad_ops sditf_subdev_pad_ops = {
|
||||
.set_fmt = sditf_get_set_fmt,
|
||||
.get_fmt = sditf_get_set_fmt,
|
||||
@@ -148,6 +455,7 @@ static const struct v4l2_subdev_pad_ops sditf_subdev_pad_ops = {
|
||||
|
||||
static const struct v4l2_subdev_video_ops sditf_video_ops = {
|
||||
.g_frame_interval = sditf_g_frame_interval,
|
||||
.s_stream = sditf_s_stream,
|
||||
};
|
||||
|
||||
static const struct v4l2_subdev_core_ops sditf_core_ops = {
|
||||
@@ -206,7 +514,13 @@ static int rkcif_subdev_media_init(struct sditf_priv *priv)
|
||||
return ret;
|
||||
|
||||
strncpy(priv->sd.name, dev_name(cif_dev->dev), sizeof(priv->sd.name));
|
||||
|
||||
priv->cap_info.width = 0;
|
||||
priv->cap_info.height = 0;
|
||||
priv->mode.is_rdbk = 0;
|
||||
priv->toisp_inf.link_mode = TOISP_NONE;
|
||||
priv->toisp_inf.ch_info[0].is_valid = false;
|
||||
priv->toisp_inf.ch_info[1].is_valid = false;
|
||||
priv->toisp_inf.ch_info[2].is_valid = false;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@@ -17,12 +17,51 @@
|
||||
#include <media/v4l2-mc.h>
|
||||
#include <linux/rk-camera-module.h>
|
||||
#include "hw.h"
|
||||
#include "../isp/isp_external.h"
|
||||
|
||||
#define RKISP0_DEVNAME "rkisp0"
|
||||
#define RKISP1_DEVNAME "rkisp1"
|
||||
#define RKISP_UNITE_DEVNAME "rkisp_unite"
|
||||
|
||||
#define RKCIF_TOISP_CH0 0
|
||||
#define RKCIF_TOISP_CH1 1
|
||||
#define RKCIF_TOISP_CH2 2
|
||||
#define TOISP_CH_MAX 3
|
||||
|
||||
struct capture_info {
|
||||
unsigned int offset_x;
|
||||
unsigned int offset_y;
|
||||
unsigned int width;
|
||||
unsigned int height;
|
||||
};
|
||||
|
||||
enum toisp_link_mode {
|
||||
TOISP_NONE,
|
||||
TOISP0,
|
||||
TOISP1,
|
||||
TOISP_UNITE,
|
||||
};
|
||||
|
||||
struct toisp_ch_info {
|
||||
bool is_valid;
|
||||
int id;
|
||||
};
|
||||
|
||||
struct toisp_info {
|
||||
struct toisp_ch_info ch_info[TOISP_CH_MAX];
|
||||
enum toisp_link_mode link_mode;
|
||||
};
|
||||
|
||||
struct sditf_priv {
|
||||
struct device *dev;
|
||||
struct v4l2_subdev sd;
|
||||
struct media_pad pads;
|
||||
struct rkcif_device *cif_dev;
|
||||
struct rkmodule_hdr_cfg hdr_cfg;
|
||||
struct capture_info cap_info;
|
||||
struct rkisp_vicap_mode mode;
|
||||
struct toisp_info toisp_inf;
|
||||
int buf_num;
|
||||
};
|
||||
|
||||
extern struct platform_driver rkcif_subdev_driver;
|
||||
|
||||
@@ -17,6 +17,12 @@
|
||||
#define RKCIF_CMD_SET_CSI_MEMORY_MODE \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 1, int)
|
||||
|
||||
#define RKCIF_CMD_GET_SCALE_BLC \
|
||||
_IOR('V', BASE_VIDIOC_PRIVATE + 2, struct bayer_blc)
|
||||
|
||||
#define RKCIF_CMD_SET_SCALE_BLC \
|
||||
_IOW('V', BASE_VIDIOC_PRIVATE + 3, struct bayer_blc)
|
||||
|
||||
/* cif memory mode
|
||||
* 0: raw12/raw10/raw8 8bit memory compact
|
||||
* 1: raw12/raw10 16bit memory one pixel
|
||||
@@ -38,4 +44,14 @@ enum cif_csi_lvds_memory {
|
||||
CSI_LVDS_MEM_WORD_HIGH_ALIGN = 2,
|
||||
};
|
||||
|
||||
/* black level for scale image
|
||||
* The sequence of pattern00~03 is the same as the output of sensor bayer
|
||||
*/
|
||||
|
||||
struct bayer_blc {
|
||||
u8 pattern00;
|
||||
u8 pattern01;
|
||||
u8 pattern02;
|
||||
u8 pattern03;
|
||||
};
|
||||
#endif
|
||||
|
||||
Reference in New Issue
Block a user