media: rockchip: cif fixes the problem of failure to get sof

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I5d76a221154809d7fa351e7f9ff0db8fe5b94bde
This commit is contained in:
Zefa Chen
2021-11-14 00:12:39 +08:00
committed by Tao Huang
parent d8e0afd6b2
commit 17df3150ec
4 changed files with 206 additions and 180 deletions

View File

@@ -5120,6 +5120,14 @@ static u32 rkcif_lvds_get_sof(struct rkcif_device *dev)
return 0;
}
static u32 rkcif_lvds_set_sof(struct rkcif_device *dev, u32 seq)
{
if (dev)
atomic_set(&dev->lvds_subdev.frm_sync_seq, seq);
return 0;
}
int rkcif_register_lvds_subdev(struct rkcif_device *dev)
{
struct v4l2_device *v4l2_dev = &dev->v4l2_dev;
@@ -5205,6 +5213,14 @@ static u32 rkcif_dvp_get_sof(struct rkcif_device *dev)
return 0;
}
static u32 rkcif_dvp_set_sof(struct rkcif_device *dev, u32 seq)
{
if (dev)
atomic_set(&dev->dvp_sof_subdev.frm_sync_seq, seq);
return 0;
}
static const struct v4l2_subdev_core_ops rkcif_dvp_sof_sd_core_ops = {
.subscribe_event = rkcif_sof_subscribe_event,
.unsubscribe_event = v4l2_event_subdev_unsubscribe,
@@ -6169,23 +6185,42 @@ static void rkcif_update_stream_toisp(struct rkcif_device *cif_dev,
stream->frame_idx++;
}
u32 rkcif_get_sof(struct rkcif_device *cif_dev)
static u32 rkcif_get_sof(struct rkcif_device *cif_dev)
{
u32 val = 0x0;
struct rkcif_sensor_info *sensor = cif_dev->active_sensor;
struct csi2_dev *csi;
if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY)
val = rkcif_csi2_get_sof();
else if (sensor->mbus.type == V4L2_MBUS_CCP2)
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) {
csi = container_of(sensor->sd, struct csi2_dev, sd);
val = rkcif_csi2_get_sof(csi);
} else if (sensor->mbus.type == V4L2_MBUS_CCP2) {
val = rkcif_lvds_get_sof(cif_dev);
else if (sensor->mbus.type == V4L2_MBUS_PARALLEL ||
sensor->mbus.type == V4L2_MBUS_BT656)
} else if (sensor->mbus.type == V4L2_MBUS_PARALLEL ||
sensor->mbus.type == V4L2_MBUS_BT656) {
val = rkcif_dvp_get_sof(cif_dev);
}
return val;
}
static void rkcif_set_sof(struct rkcif_device *cif_dev, u32 seq)
{
struct rkcif_sensor_info *sensor = cif_dev->active_sensor;
struct csi2_dev *csi;
if (sensor->mbus.type == V4L2_MBUS_CSI2_DPHY ||
sensor->mbus.type == V4L2_MBUS_CSI2_CPHY) {
csi = container_of(sensor->sd, struct csi2_dev, sd);
rkcif_csi2_set_sof(csi, seq);
} else if (sensor->mbus.type == V4L2_MBUS_CCP2) {
rkcif_lvds_set_sof(cif_dev, seq);
} else if (sensor->mbus.type == V4L2_MBUS_PARALLEL ||
sensor->mbus.type == V4L2_MBUS_BT656) {
rkcif_dvp_set_sof(cif_dev, seq);
}
}
static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
enum rkmodule_reset_src reset_src)
{
@@ -6247,7 +6282,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"%s stop stream[%d] in streaming, frm_id:%d, csi_sof:%d\n",
__func__, stream->id, stream->frame_idx, rkcif_csi2_get_sof());
__func__, stream->id, stream->frame_idx, rkcif_get_sof(cif_dev));
}
}
@@ -6317,7 +6352,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
v4l2_dbg(1, rkcif_debug, &cif_dev->v4l2_dev,
"resume stream[%d], frm_idx:%d, csi_sof:%d\n",
stream->id, stream->frame_idx,
rkcif_csi2_get_sof());
rkcif_get_sof(cif_dev));
}
rockchip_set_system_status(SYS_STATUS_CIF0);
@@ -6327,7 +6362,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
if (p->subdevs[i] == terminal_sensor->sd) {
rkcif_csi2_set_sof(resume_info->frm_sync_seq);
rkcif_set_sof(cif_dev, resume_info->frm_sync_seq);
if (reset_src == RKCIF_RESET_SRC_ERR_CSI2 ||
reset_src == RKCIF_RESET_SRC_ERR_HOTPLUG ||
@@ -6341,7 +6376,7 @@ static int rkcif_do_reset_work(struct rkcif_device *cif_dev,
}
} else {
if (p->subdevs[i] == terminal_sensor->sd)
rkcif_csi2_set_sof(resume_info->frm_sync_seq);
rkcif_set_sof(cif_dev, resume_info->frm_sync_seq);
ret = v4l2_subdev_call(p->subdevs[i], video, s_stream, on);
}
@@ -6948,15 +6983,18 @@ static void rkcif_deal_sof(struct rkcif_device *cif_dev)
{
struct rkcif_stream *detect_stream = &cif_dev->stream[0];
struct v4l2_mbus_config *mbus = &cif_dev->active_sensor->mbus;
struct csi2_dev *csi;
unsigned long flags;
if (mbus->type == V4L2_MBUS_CSI2_DPHY ||
mbus->type == V4L2_MBUS_CSI2_CPHY)
rkcif_csi2_event_inc_sof();
else if (mbus->type == V4L2_MBUS_CCP2)
mbus->type == V4L2_MBUS_CSI2_CPHY) {
csi = container_of(cif_dev->active_sensor->sd, struct csi2_dev, sd);
rkcif_csi2_event_inc_sof(csi);
} else if (mbus->type == V4L2_MBUS_CCP2) {
rkcif_lvds_event_inc_sof(cif_dev);
else
} else {
rkcif_dvp_event_inc_sof(cif_dev);
}
detect_stream->fs_cnt_in_single_frame++;
spin_lock_irqsave(&detect_stream->fps_lock, flags);

View File

@@ -115,11 +115,6 @@ enum rkcif_state {
RKCIF_STATE_RESET_IN_STREAMING,
};
enum host_type_t {
RK_CSI_RXHOST,
RK_DSI_RXHOST
};
enum rkcif_lvds_pad {
RKCIF_LVDS_PAD_SINK = 0x0,
RKCIF_LVDS_PAD_SRC_ID0,
@@ -760,7 +755,6 @@ void rkcif_unregister_lvds_subdev(struct rkcif_device *dev);
int rkcif_register_dvp_sof_subdev(struct rkcif_device *dev);
void rkcif_unregister_dvp_sof_subdev(struct rkcif_device *dev);
void rkcif_irq_lite_lvds(struct rkcif_device *cif_dev);
u32 rkcif_get_sof(struct rkcif_device *cif_dev);
int rkcif_plat_init(struct rkcif_device *cif_dev, struct device_node *node, int inf_id);
int rkcif_plat_uninit(struct rkcif_device *cif_dev);
int rkcif_attach_hw(struct rkcif_device *cif_dev);

View File

@@ -15,157 +15,15 @@
#include <linux/of_graph.h>
#include <linux/platform_device.h>
#include <linux/reset.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-event.h>
#include "mipi-csi2.h"
static int csi2_debug;
module_param_named(debug_csi2, csi2_debug, int, 0644);
MODULE_PARM_DESC(debug_csi2, "Debug level (0-1)");
/*
* there must be 5 pads: 1 input pad from sensor, and
* the 4 virtual channel output pads
*/
#define CSI2_SINK_PAD 0
#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
#define RKCIF_DEFAULT_WIDTH 640
#define RKCIF_DEFAULT_HEIGHT 480
/*
* The default maximum bit-rate per lane in Mbps, if the
* source subdev does not provide V4L2_CID_LINK_FREQ.
*/
#define CSI2_DEFAULT_MAX_MBPS 849
#define IMX_MEDIA_GRP_ID_CSI2 BIT(8)
#define CSIHOST_MAX_ERRINT_COUNT 10
/*
* add new chip id in tail in time order
* by increasing to distinguish csi2 host version
*/
enum rkcsi2_chip_id {
CHIP_PX30_CSI2,
CHIP_RK1808_CSI2,
CHIP_RK3128_CSI2,
CHIP_RK3288_CSI2,
CHIP_RV1126_CSI2,
CHIP_RK3568_CSI2,
CHIP_RK3588_CSI2,
};
enum csi2_pads {
RK_CSI2_PAD_SINK = 0,
RK_CSI2X_PAD_SOURCE0,
RK_CSI2X_PAD_SOURCE1,
RK_CSI2X_PAD_SOURCE2,
RK_CSI2X_PAD_SOURCE3
};
enum csi2_err {
RK_CSI2_ERR_SOTSYN = 0x0,
RK_CSI2_ERR_FS_FE_MIS,
RK_CSI2_ERR_FRM_SEQ_ERR,
RK_CSI2_ERR_CRC_ONCE,
RK_CSI2_ERR_CRC,
RK_CSI2_ERR_ALL,
RK_CSI2_ERR_MAX
};
enum host_type_t {
RK_CSI_RXHOST,
RK_DSI_RXHOST
};
struct csi2_match_data {
int chip_id;
int num_pads;
};
struct csi2_sensor {
struct v4l2_subdev *sd;
struct v4l2_mbus_config mbus;
int lanes;
};
struct csi2_err_stats {
unsigned int cnt;
};
struct csi2_dev {
struct device *dev;
struct v4l2_subdev sd;
struct media_pad pad[CSI2_NUM_PADS_MAX];
struct clk_bulk_data *clks_bulk;
int clks_num;
struct reset_control *rsts_bulk;
void __iomem *base;
struct v4l2_async_notifier notifier;
struct v4l2_fwnode_bus_mipi_csi2 bus;
/* lock to protect all members below */
struct mutex lock;
struct v4l2_mbus_framefmt format_mbus;
struct v4l2_rect crop;
int stream_count;
struct v4l2_subdev *src_sd;
bool sink_linked[CSI2_NUM_SRC_PADS];
struct csi2_sensor sensors[MAX_CSI2_SENSORS];
const struct csi2_match_data *match_data;
int num_sensors;
atomic_t frm_sync_seq;
struct csi2_err_stats err_list[RK_CSI2_ERR_MAX];
};
#define DEVICE_NAME "rockchip-mipi-csi2"
/* CSI Host Registers Define */
#define CSIHOST_N_LANES 0x04
#define CSIHOST_DPHY_SHUTDOWNZ 0x08
#define CSIHOST_PHY_RSTZ 0x0c
#define CSIHOST_RESETN 0x10
#define CSIHOST_PHY_STATE 0x14
#define CSIHOST_ERR1 0x20
#define CSIHOST_ERR2 0x24
#define CSIHOST_MSK1 0x28
#define CSIHOST_MSK2 0x2c
#define CSIHOST_CONTROL 0x40
#define CSIHOST_ERR1_PHYERR_SPTSYNCHS 0x0000000f
#define CSIHOST_ERR1_ERR_BNDRY_MATCH 0x000000f0
#define CSIHOST_ERR1_ERR_SEQ 0x00000f00
#define CSIHOST_ERR1_ERR_FRM_DATA 0x0000f000
#define CSIHOST_ERR1_ERR_CRC 0x1f000000
#define CSIHOST_ERR2_PHYERR_ESC 0x0000000f
#define CSIHOST_ERR2_PHYERR_SOTHS 0x000000f0
#define CSIHOST_ERR2_ECC_CORRECTED 0x00000f00
#define CSIHOST_ERR2_ERR_ID 0x0000f000
#define CSIHOST_ERR2_PHYERR_CODEHS 0x01000000
#define SW_CPHY_EN(x) ((x) << 0)
#define SW_DSI_EN(x) ((x) << 4)
#define SW_DATATYPE_FS(x) ((x) << 8)
#define SW_DATATYPE_FE(x) ((x) << 14)
#define SW_DATATYPE_LS(x) ((x) << 20)
#define SW_DATATYPE_LE(x) ((x) << 26)
#define write_csihost_reg(base, addr, val) writel(val, (addr) + (base))
#define read_csihost_reg(base, addr) readl((addr) + (base))
static struct csi2_dev *g_csi2_dev;
static ATOMIC_NOTIFIER_HEAD(g_csi_host_chain);
int rkcif_csi2_register_notifier(struct notifier_block *nb)
@@ -604,32 +462,30 @@ static const struct media_entity_operations csi2_entity_ops = {
.link_validate = v4l2_subdev_link_validate,
};
void rkcif_csi2_event_inc_sof(void)
void rkcif_csi2_event_inc_sof(struct csi2_dev *csi2_dev)
{
if (g_csi2_dev) {
if (csi2_dev) {
struct v4l2_event event = {
.type = V4L2_EVENT_FRAME_SYNC,
.u.frame_sync.frame_sequence =
atomic_inc_return(&g_csi2_dev->frm_sync_seq) - 1,
atomic_inc_return(&csi2_dev->frm_sync_seq) - 1,
};
v4l2_event_queue(g_csi2_dev->sd.devnode, &event);
v4l2_event_queue(csi2_dev->sd.devnode, &event);
}
}
u32 rkcif_csi2_get_sof(void)
u32 rkcif_csi2_get_sof(struct csi2_dev *csi2_dev)
{
if (g_csi2_dev) {
return atomic_read(&g_csi2_dev->frm_sync_seq) - 1;
}
if (csi2_dev)
return atomic_read(&csi2_dev->frm_sync_seq) - 1;
return 0;
}
void rkcif_csi2_set_sof(u32 seq)
void rkcif_csi2_set_sof(struct csi2_dev *csi2_dev, u32 seq)
{
if (g_csi2_dev) {
atomic_set(&g_csi2_dev->frm_sync_seq, seq);
}
if (csi2_dev)
atomic_set(&csi2_dev->frm_sync_seq, seq);
}
static int rkcif_csi2_subscribe_event(struct v4l2_subdev *sd, struct v4l2_fh *fh,
@@ -1029,8 +885,6 @@ static int csi2_probe(struct platform_device *pdev)
csi2_hw_do_reset(csi2);
g_csi2_dev = csi2;
v4l2_info(&csi2->sd, "probe success, v4l2_dev:%s!\n", csi2->sd.v4l2_dev->name);
return 0;

View File

@@ -4,13 +4,153 @@
#define _RKCIF_MIPI_CSI2_H_
#include <linux/notifier.h>
#include <media/v4l2-device.h>
#include <media/v4l2-fwnode.h>
#include <media/v4l2-subdev.h>
#include <media/v4l2-event.h>
#define CSI2_ERR_FSFE_MASK (0xff << 8)
#define CSI2_ERR_COUNT_ALL_MASK (0xff)
u32 rkcif_csi2_get_sof(void);
void rkcif_csi2_set_sof(u32 seq);
void rkcif_csi2_event_inc_sof(void);
/*
* there must be 5 pads: 1 input pad from sensor, and
* the 4 virtual channel output pads
*/
#define CSI2_SINK_PAD 0
#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
#define RKCIF_DEFAULT_WIDTH 640
#define RKCIF_DEFAULT_HEIGHT 480
/*
* The default maximum bit-rate per lane in Mbps, if the
* source subdev does not provide V4L2_CID_LINK_FREQ.
*/
#define CSI2_DEFAULT_MAX_MBPS 849
#define IMX_MEDIA_GRP_ID_CSI2 BIT(8)
#define CSIHOST_MAX_ERRINT_COUNT 10
#define DEVICE_NAME "rockchip-mipi-csi2"
/* CSI Host Registers Define */
#define CSIHOST_N_LANES 0x04
#define CSIHOST_DPHY_SHUTDOWNZ 0x08
#define CSIHOST_PHY_RSTZ 0x0c
#define CSIHOST_RESETN 0x10
#define CSIHOST_PHY_STATE 0x14
#define CSIHOST_ERR1 0x20
#define CSIHOST_ERR2 0x24
#define CSIHOST_MSK1 0x28
#define CSIHOST_MSK2 0x2c
#define CSIHOST_CONTROL 0x40
#define CSIHOST_ERR1_PHYERR_SPTSYNCHS 0x0000000f
#define CSIHOST_ERR1_ERR_BNDRY_MATCH 0x000000f0
#define CSIHOST_ERR1_ERR_SEQ 0x00000f00
#define CSIHOST_ERR1_ERR_FRM_DATA 0x0000f000
#define CSIHOST_ERR1_ERR_CRC 0x1f000000
#define CSIHOST_ERR2_PHYERR_ESC 0x0000000f
#define CSIHOST_ERR2_PHYERR_SOTHS 0x000000f0
#define CSIHOST_ERR2_ECC_CORRECTED 0x00000f00
#define CSIHOST_ERR2_ERR_ID 0x0000f000
#define CSIHOST_ERR2_PHYERR_CODEHS 0x01000000
#define SW_CPHY_EN(x) ((x) << 0)
#define SW_DSI_EN(x) ((x) << 4)
#define SW_DATATYPE_FS(x) ((x) << 8)
#define SW_DATATYPE_FE(x) ((x) << 14)
#define SW_DATATYPE_LS(x) ((x) << 20)
#define SW_DATATYPE_LE(x) ((x) << 26)
/*
* add new chip id in tail in time order
* by increasing to distinguish csi2 host version
*/
enum rkcsi2_chip_id {
CHIP_PX30_CSI2,
CHIP_RK1808_CSI2,
CHIP_RK3128_CSI2,
CHIP_RK3288_CSI2,
CHIP_RV1126_CSI2,
CHIP_RK3568_CSI2,
CHIP_RK3588_CSI2,
};
enum csi2_pads {
RK_CSI2_PAD_SINK = 0,
RK_CSI2X_PAD_SOURCE0,
RK_CSI2X_PAD_SOURCE1,
RK_CSI2X_PAD_SOURCE2,
RK_CSI2X_PAD_SOURCE3
};
enum csi2_err {
RK_CSI2_ERR_SOTSYN = 0x0,
RK_CSI2_ERR_FS_FE_MIS,
RK_CSI2_ERR_FRM_SEQ_ERR,
RK_CSI2_ERR_CRC_ONCE,
RK_CSI2_ERR_CRC,
RK_CSI2_ERR_ALL,
RK_CSI2_ERR_MAX
};
enum host_type_t {
RK_CSI_RXHOST,
RK_DSI_RXHOST
};
struct csi2_match_data {
int chip_id;
int num_pads;
};
struct csi2_sensor {
struct v4l2_subdev *sd;
struct v4l2_mbus_config mbus;
int lanes;
};
struct csi2_err_stats {
unsigned int cnt;
};
struct csi2_dev {
struct device *dev;
struct v4l2_subdev sd;
struct media_pad pad[CSI2_NUM_PADS_MAX];
struct clk_bulk_data *clks_bulk;
int clks_num;
struct reset_control *rsts_bulk;
void __iomem *base;
struct v4l2_async_notifier notifier;
struct v4l2_fwnode_bus_mipi_csi2 bus;
/* lock to protect all members below */
struct mutex lock;
struct v4l2_mbus_framefmt format_mbus;
struct v4l2_rect crop;
int stream_count;
struct v4l2_subdev *src_sd;
bool sink_linked[CSI2_NUM_SRC_PADS];
struct csi2_sensor sensors[MAX_CSI2_SENSORS];
const struct csi2_match_data *match_data;
int num_sensors;
atomic_t frm_sync_seq;
struct csi2_err_stats err_list[RK_CSI2_ERR_MAX];
};
u32 rkcif_csi2_get_sof(struct csi2_dev *csi2_dev);
void rkcif_csi2_set_sof(struct csi2_dev *csi2_dev, u32 seq);
void rkcif_csi2_event_inc_sof(struct csi2_dev *csi2_dev);
int __init rkcif_csi2_plat_drv_init(void);
void __exit rkcif_csi2_plat_drv_exit(void);
int rkcif_csi2_register_notifier(struct notifier_block *nb);