From 17df3150ecbed4ed954d48fcfb37cbd2cf31c375 Mon Sep 17 00:00:00 2001 From: Zefa Chen Date: Sun, 14 Nov 2021 00:12:39 +0800 Subject: [PATCH] media: rockchip: cif fixes the problem of failure to get sof Signed-off-by: Zefa Chen Change-Id: I5d76a221154809d7fa351e7f9ff0db8fe5b94bde --- drivers/media/platform/rockchip/cif/capture.c | 68 +++++-- drivers/media/platform/rockchip/cif/dev.h | 6 - .../media/platform/rockchip/cif/mipi-csi2.c | 166 ++---------------- .../media/platform/rockchip/cif/mipi-csi2.h | 146 ++++++++++++++- 4 files changed, 206 insertions(+), 180 deletions(-) diff --git a/drivers/media/platform/rockchip/cif/capture.c b/drivers/media/platform/rockchip/cif/capture.c index b1aa346d5e36..20d92c187904 100644 --- a/drivers/media/platform/rockchip/cif/capture.c +++ b/drivers/media/platform/rockchip/cif/capture.c @@ -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); diff --git a/drivers/media/platform/rockchip/cif/dev.h b/drivers/media/platform/rockchip/cif/dev.h index 6b2f66040272..6073c0ab3e18 100644 --- a/drivers/media/platform/rockchip/cif/dev.h +++ b/drivers/media/platform/rockchip/cif/dev.h @@ -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); diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.c b/drivers/media/platform/rockchip/cif/mipi-csi2.c index 449f45da8356..6f6b2d55faf0 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.c +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.c @@ -15,157 +15,15 @@ #include #include #include -#include -#include -#include -#include - #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; diff --git a/drivers/media/platform/rockchip/cif/mipi-csi2.h b/drivers/media/platform/rockchip/cif/mipi-csi2.h index d7b08f22144c..e04a7dd2eef3 100644 --- a/drivers/media/platform/rockchip/cif/mipi-csi2.h +++ b/drivers/media/platform/rockchip/cif/mipi-csi2.h @@ -4,13 +4,153 @@ #define _RKCIF_MIPI_CSI2_H_ #include +#include +#include +#include +#include #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);