media: platform: rockchip: cif: support bt656/bt1120 multi channels function

Signed-off-by: Allon Huang <allon.huang@rock-chips.com>
Change-Id: I0eb7c4d2a9d5d99eb69627741febedc09133ff21
Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
This commit is contained in:
Allon Huang
2021-03-04 20:02:23 +08:00
committed by Zefa Chen
parent 719446d5ff
commit 82cb10f7bc
8 changed files with 835 additions and 275 deletions

File diff suppressed because it is too large Load Diff

View File

@@ -224,6 +224,32 @@ u32 rkcif_read_grf_reg(struct rkcif_device *dev, enum cif_reg_index index)
return val;
}
void rkcif_enable_dvp_clk_dual_edge(struct rkcif_device *dev, bool on)
{
struct rkcif_hw *cif_hw = dev->hw_dev;
u32 val = 0x0;
if (!IS_ERR(cif_hw->grf)) {
if (dev->chip_id == CHIP_RK3568_CIF) {
if (on)
val = RK3568_CIF_PCLK_DUAL_EDGE;
else
val = RK3568_CIF_PCLK_SINGLE_EDGE;
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON1, val);
} else if (dev->chip_id == CHIP_RV1126_CIF) {
if (on)
val = CIF_SAMPLING_EDGE_DOUBLE;
else
val = CIF_SAMPLING_EDGE_SINGLE;
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
}
}
v4l2_info(&dev->v4l2_dev,
"set dual edge mode(%s,0x%x)!!!\n", on ? "on" : "off", val);
}
void rkcif_config_dvp_clk_sampling_edge(struct rkcif_device *dev,
enum rkcif_clk_edge edge)
{
@@ -431,10 +457,15 @@ static int rkcif_create_links(struct rkcif_device *dev)
unsigned int s, pad, id, stream_num = 0;
bool mipi_lvds_linked = false;
if (dev->inf_id == RKCIF_MIPI_LVDS)
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;
else
stream_num = RKCIF_SINGLE_STREAM;
}
/* sensor links(or mipi-phy) */
for (s = 0; s < dev->num_sensors; ++s) {
@@ -470,9 +501,7 @@ static int rkcif_create_links(struct rkcif_device *dev)
if ((linked_sensor.mbus.type == V4L2_MBUS_BT656 ||
linked_sensor.mbus.type == V4L2_MBUS_PARALLEL) &&
(dev->chip_id == CHIP_RK1808_CIF ||
dev->chip_id == CHIP_RV1126_CIF ||
dev->chip_id == CHIP_RK3568_CIF)) {
(dev->chip_id == CHIP_RK1808_CIF)) {
source_entity = &linked_sensor.sd->entity;
sink_entity = &dev->stream[RKCIF_STREAM_CIF].vnode.vdev.entity;
@@ -487,6 +516,23 @@ static int rkcif_create_links(struct rkcif_device *dev)
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;
@@ -704,14 +750,19 @@ static int rkcif_register_platform_subdevs(struct rkcif_device *cif_dev)
{
int stream_num = 0, ret;
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {
stream_num = RKCIF_MAX_STREAM_MIPI;
ret = rkcif_register_stream_vdevs(cif_dev, stream_num,
true);
if (cif_dev->chip_id < CHIP_RV1126_CIF) {
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {
stream_num = RKCIF_MAX_STREAM_MIPI;
ret = rkcif_register_stream_vdevs(cif_dev, stream_num,
true);
} else {
stream_num = RKCIF_SINGLE_STREAM;
ret = rkcif_register_stream_vdevs(cif_dev, stream_num,
false);
}
} else {
stream_num = RKCIF_SINGLE_STREAM;
ret = rkcif_register_stream_vdevs(cif_dev, stream_num,
false);
stream_num = RKCIF_MAX_STREAM_MIPI;
ret = rkcif_register_stream_vdevs(cif_dev, stream_num, true);
}
if (ret < 0) {
@@ -942,13 +993,21 @@ int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int
if (cif_dev->chip_id == CHIP_RV1126_CIF_LITE)
cif_dev->isr_hdl = rkcif_irq_lite_handler;
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {
if (cif_dev->chip_id < CHIP_RV1126_CIF) {
if (cif_dev->inf_id == RKCIF_MIPI_LVDS) {
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID0);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID1);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID2);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3);
} else {
rkcif_stream_init(cif_dev, RKCIF_STREAM_CIF);
}
} else {
/* for rv1126/rk356x, bt656/bt1120/mipi are multi channels */
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID0);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID1);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID2);
rkcif_stream_init(cif_dev, RKCIF_STREAM_MIPI_ID3);
} else {
rkcif_stream_init(cif_dev, RKCIF_STREAM_CIF);
}
#if defined(CONFIG_ROCKCHIP_CIF_WORKMODE_PINGPONG)
@@ -1007,16 +1066,22 @@ int rkcif_plat_uninit(struct rkcif_device *cif_dev)
if (cif_dev->active_sensor->mbus.type == V4L2_MBUS_CCP2)
rkcif_unregister_lvds_subdev(cif_dev);
if (cif_dev->active_sensor->mbus.type == V4L2_MBUS_BT656 ||
cif_dev->active_sensor->mbus.type == V4L2_MBUS_PARALLEL)
rkcif_unregister_dvp_sof_subdev(cif_dev);
media_device_unregister(&cif_dev->media_dev);
v4l2_device_unregister(&cif_dev->v4l2_dev);
if (cif_dev->inf_id == RKCIF_MIPI_LVDS)
if (cif_dev->chip_id < CHIP_RV1126_CIF) {
if (cif_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;
else
stream_num = RKCIF_SINGLE_STREAM;
}
rkcif_unregister_stream_vdevs(cif_dev, stream_num);
return 0;

View File

@@ -39,9 +39,15 @@
#define CIF_MIPI_ID2_VDEV_NAME CIF_VIDEODEVICE_NAME "_mipi_id2"
#define CIF_MIPI_ID3_VDEV_NAME CIF_VIDEODEVICE_NAME "_mipi_id3"
#define CIF_DVP_ID0_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id0"
#define CIF_DVP_ID1_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id1"
#define CIF_DVP_ID2_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id2"
#define CIF_DVP_ID3_VDEV_NAME CIF_VIDEODEVICE_NAME "_dvp_id3"
/*
* Rk1808 support 5 channel inputs simultaneously:
* dvp + 4 mipi virtual channels
* RK1808 support 5 channel inputs simultaneously:
* dvp + 4 mipi virtual channels;
* RV1126/RK356X support 4 channels of BT.656/BT.1120/MIPI
*/
#define RKCIF_MULTI_STREAMS_NUM 5
#define RKCIF_STREAM_MIPI_ID0 0
@@ -50,6 +56,7 @@
#define RKCIF_STREAM_MIPI_ID3 3
#define RKCIF_MAX_STREAM_MIPI 4
#define RKCIF_MAX_STREAM_LVDS 4
#define RKCIF_MAX_STREAM_DVP 4
#define RKCIF_STREAM_DVP 4
#define RKCIF_MAX_SENSOR 2
@@ -405,6 +412,7 @@ struct rkcif_stream {
struct v4l2_rect crop[CROP_SRC_MAX];
struct rkcif_fps_stats fps_stats;
struct rkcif_extend_info extend_line;
bool is_dvp_yuv_addr_init;
};
struct rkcif_lvds_subdev {
@@ -548,5 +556,6 @@ int rkcif_reset_notifier(struct notifier_block *nb, unsigned long action, void *
void rkcif_reset_watchdog_timer_handler(struct timer_list *t);
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);
#endif

View File

@@ -326,6 +326,18 @@ static const struct cif_reg rv1126_cif_regs[] = {
[CIF_REG_DVP_CUR_DST] = CIF_REG(RV1126_CIF_CUR_DST),
[CIF_REG_DVP_LAST_LINE] = CIF_REG(RV1126_CIF_LAST_LINE),
[CIF_REG_DVP_LAST_PIX] = CIF_REG(RV1126_CIF_LAST_PIX),
[CIF_REG_DVP_FRM0_ADDR_Y_ID1] = CIF_REG(CIF_FRM0_ADDR_Y_ID1),
[CIF_REG_DVP_FRM0_ADDR_UV_ID1] = CIF_REG(CIF_FRM0_ADDR_UV_ID1),
[CIF_REG_DVP_FRM1_ADDR_Y_ID1] = CIF_REG(CIF_FRM1_ADDR_Y_ID1),
[CIF_REG_DVP_FRM1_ADDR_UV_ID1] = CIF_REG(CIF_FRM1_ADDR_UV_ID1),
[CIF_REG_DVP_FRM0_ADDR_Y_ID2] = CIF_REG(CIF_FRM0_ADDR_Y_ID2),
[CIF_REG_DVP_FRM0_ADDR_UV_ID2] = CIF_REG(CIF_FRM0_ADDR_UV_ID2),
[CIF_REG_DVP_FRM1_ADDR_Y_ID2] = CIF_REG(CIF_FRM1_ADDR_Y_ID2),
[CIF_REG_DVP_FRM1_ADDR_UV_ID2] = CIF_REG(CIF_FRM1_ADDR_UV_ID2),
[CIF_REG_DVP_FRM0_ADDR_Y_ID3] = CIF_REG(CIF_FRM0_ADDR_Y_ID3),
[CIF_REG_DVP_FRM0_ADDR_UV_ID3] = CIF_REG(CIF_FRM0_ADDR_UV_ID3),
[CIF_REG_DVP_FRM1_ADDR_Y_ID3] = CIF_REG(CIF_FRM1_ADDR_Y_ID3),
[CIF_REG_DVP_FRM1_ADDR_UV_ID3] = CIF_REG(CIF_FRM1_ADDR_UV_ID3),
[CIF_REG_MIPI_LVDS_ID0_CTRL0] = CIF_REG(CIF_CSI_ID0_CTRL0),
[CIF_REG_MIPI_LVDS_ID0_CTRL1] = CIF_REG(CIF_CSI_ID0_CTRL1),
[CIF_REG_MIPI_LVDS_ID1_CTRL0] = CIF_REG(CIF_CSI_ID1_CTRL0),

View File

@@ -148,6 +148,7 @@ enum cif_reg_index {
CIF_REG_MMU_AUTO_GATING,
/* reg belowed is in grf */
CIF_REG_GRF_CIFIO_CON,
CIF_REG_GRF_CIFIO_CON1,
CIF_REG_INDEX_MAX
};
@@ -314,6 +315,9 @@ enum cif_reg_index {
#define PRE_INF_FRAME_END_EN (0x1 << 8)
#define PST_INF_FRAME_END_EN (0x1 << 9)
#define LINE_INT_EN (0x1 << 10)
#define DVP_CHANNEL1_FRM_END_EN (0x1 << 11)
#define DVP_CHANNEL2_FRM_END_EN (0x1 << 12)
#define DVP_CHANNEL3_FRM_END_EN (0x1 << 13)
/* CIF INTSTAT */
#define INTSTAT_CLS (0x3FF)
@@ -332,6 +336,39 @@ enum cif_reg_index {
#define INTSTAT_ERR (0xFC)
#define DVP_ALL_OVERFLOW (IFIFO_OVERFLOW | DFIFO_OVERFLOW)
#define DVP_DMA_END_INTEN(id) \
({ \
unsigned int mask; \
switch (id) { \
case 0: \
mask = 0x1 << 0; \
break; \
default: \
mask = 0x1 << (id + 10); \
break; \
} \
mask; \
})
#define DVP_LINE_INTEN (0x01 << 10)
#define DVP_DMA_END_INTSTAT(id) \
({ \
unsigned int mask; \
switch (id) { \
case 0: \
mask = 0x1 << 0; \
break; \
default: \
mask = 0x1 << (id + 10); \
break; \
} \
mask; \
})
#define DVP_PST_INTSTAT PST_INF_FRAME_END
#define DVP_LINE_INTSTAT (0x01 << 10)
/* FRAME STATUS */
#define FRAME_STAT_CLS 0x00
/* write 0 to clear frame 0 */
@@ -390,6 +427,10 @@ enum cif_reg_index {
#define BT656_1120_MULTI_ID_MODE_1 (0x00 << 30)
#define BT656_1120_MULTI_ID_MODE_2 (0x01 << 30)
#define BT656_1120_MULTI_ID_MODE_4 (0x02 << 30)
#define BT656_1120_MULTI_ID_0_MASK ~(0x03 << 4)
#define BT656_1120_MULTI_ID_1_MASK ~(0x03 << 12)
#define BT656_1120_MULTI_ID_2_MASK ~(0x03 << 20)
#define BT656_1120_MULTI_ID_3_MASK ~(0x03 << 28)
/* CIF_SCL_CTRL */
#define ENABLE_SCL_DOWN (0x01 << 0)
@@ -403,9 +444,52 @@ enum cif_reg_index {
#define ENABLE_32BIT_BYPASS (0x01 << 6)
#define DISABLE_32BIT_BYPASS (0x00 << 6)
/* CIF_INTSTAT */
/* CIF_FRAME_INTSTAT */
#define CIF_F0_READY (0x01 << 0)
#define CIF_F1_READY (0x01 << 1)
#define DVP_CHANNEL0_FRM_READ (CIF_F0_READY | CIF_F1_READY)
#define DVP_CHANNEL1_F0_READY (0x01 << 4)
#define DVP_CHANNEL1_F1_READY (0x01 << 5)
#define DVP_CHANNEL1_FRM_READ (DVP_CHANNEL1_F0_READY | DVP_CHANNEL1_F1_READY)
#define DVP_CHANNEL2_F0_READY (0x01 << 8)
#define DVP_CHANNEL2_F1_READY (0x01 << 9)
#define DVP_CHANNEL2_FRM_READ (DVP_CHANNEL2_F0_READY | DVP_CHANNEL2_F1_READY)
#define DVP_CHANNEL3_F0_READY (0x01 << 12)
#define DVP_CHANNEL3_F1_READY (0x01 << 13)
#define DVP_CHANNEL3_FRM_READ (DVP_CHANNEL3_F0_READY | DVP_CHANNEL3_F1_READY)
#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_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)
#define DVP_FRM_STS_ID3(x) (((x) & (0x3 << 12)) >> 12)
#define DVP_SW_MULTI_ID(channel, id, bits) \
({ \
unsigned int mask; \
switch (channel) { \
case 0: \
mask = ((bits) << 4) | ((id) << 0); \
break; \
case 1: \
mask = ((bits) << 12) | ((id) << 8); \
break; \
case 2: \
mask = ((bits) << 20) | ((id) << 16); \
break; \
case 3: \
mask = ((bits) << 28) | ((id) << 24); \
break; \
default: \
mask = ((bits) << 4) | ((id) << 0); \
break; \
} \
mask; \
})
/* CIF CROP */
#define CIF_CROP_Y_SHIFT 16
@@ -594,9 +678,12 @@ enum cif_reg_index {
#define CIF_PCLK_DELAY_DISABLE (0x02000000)
#define CIF_SAMPLING_EDGE_DOUBLE (0x01000100)
#define CIF_SAMPLING_EDGE_SINGLE (0x01000000)
#define CIF_PCLK_DELAY_NUM(num) (0x00ff0000 | ((num) & 0xff))
#define CIF_PCLK_DELAY_NUM(num) (0x00ff0000 | ((num) & 0xff))
#define CIF_GRF_VI_CON0 (0x340)
#define CIF_GRF_VI_CON1 (0x344)
#define RK3568_CIF_PCLK_SAMPLING_EDGE_RISING (0x10000000)
#define RK3568_CIF_PCLK_SAMPLING_EDGE_FALLING (0x10001000)
#define RK3568_CIF_PCLK_SINGLE_EDGE (0x02000000)
#define RK3568_CIF_PCLK_DUAL_EDGE (0x02000200)
#endif

View File

@@ -57,6 +57,8 @@
*5. modify reset mechanism drivered by real-time frame rate
*6. support rk356x iommu uses vb2 sg type
*7. register cif sd itf when pipeline completed
*v0.1.10
*1. rv1126/rk356x support bt656/bt1120 multi channels function
*/
#define RKCIF_DRIVER_VERSION RKCIF_API_VERSION

View File

@@ -25,6 +25,25 @@
#define RKMODULE_CAMERA_MODULE_NAME "rockchip,camera-module-name"
#define RKMODULE_CAMERA_LENS_NAME "rockchip,camera-module-lens-name"
/* BT.656 & BT.1120 multi channel
* On which channels it can send video data
* related with struct rkmodule_bt656_mbus_info
*/
#define RKMODULE_CAMERA_BT656_ID_EN_BITS_1 (0x1)
#define RKMODULE_CAMERA_BT656_ID_EN_BITS_2 (0x3)
#define RKMODULE_CAMERA_BT656_ID_EN_BITS_3 (0x7)
#define RKMODULE_CAMERA_BT656_ID_EN_BITS_4 (0xf)
#define RKMODULE_CAMERA_BT656_PARSE_ID_LSB BIT(0)
#define RKMODULE_CAMERA_BT656_PARSE_ID_MSB BIT(1)
#define RKMODULE_CAMERA_BT656_CHANNEL_0 BIT(2)
#define RKMODULE_CAMERA_BT656_CHANNEL_1 BIT(3)
#define RKMODULE_CAMERA_BT656_CHANNEL_2 BIT(4)
#define RKMODULE_CAMERA_BT656_CHANNEL_3 BIT(5)
#define RKMODULE_CAMERA_BT656_CHANNELS (RKMODULE_CAMERA_BT656_CHANNEL_0 | \
RKMODULE_CAMERA_BT656_CHANNEL_1 | \
RKMODULE_CAMERA_BT656_CHANNEL_2 | \
RKMODULE_CAMERA_BT656_CHANNEL_3)
#define RKMODULE_GET_MODULE_INFO \
_IOR('V', BASE_VIDIOC_PRIVATE + 0, struct rkmodule_inf)
@@ -76,6 +95,8 @@
#define RKMODULE_SET_VICAP_RST_INFO \
_IOR('V', BASE_VIDIOC_PRIVATE + 16, struct rkmodule_vicap_reset_info)
#define RKMODULE_GET_BT656_MBUS_INFO \
_IOR('V', BASE_VIDIOC_PRIVATE + 17, struct rkmodule_bt656_mbus_info)
/**
* struct rkmodule_base_inf - module base information
*
@@ -394,4 +415,10 @@ struct rkmodule_vicap_reset_info {
enum rkmodule_reset_src src;
} __attribute__ ((packed));
struct rkmodule_bt656_mbus_info {
__u32 flags;
__u32 id_en_bits;
} __attribute__ ((packed));
#endif /* _UAPI_RKMODULE_CAMERA_H */

View File

@@ -9,7 +9,7 @@
#include <linux/types.h>
#include <linux/v4l2-controls.h>
#define RKCIF_API_VERSION KERNEL_VERSION(0, 1, 0x9)
#define RKCIF_API_VERSION KERNEL_VERSION(0, 1, 0xa)
#define V4L2_CID_CIF_DATA_COMPACT (V4L2_CID_PRIVATE_BASE + 0)