media: rockchip: rv1106 vicap support dvp

Signed-off-by: Zefa Chen <zefa.chen@rock-chips.com>
Change-Id: I8c5b3db27d4fef1f486763cf2018729b9745b4ea
This commit is contained in:
Zefa Chen
2022-04-11 21:40:52 +08:00
committed by Tao Huang
parent 0a274564e9
commit 74aca7167d
7 changed files with 95 additions and 7 deletions

View File

@@ -2917,6 +2917,8 @@ static void rkcif_stream_stop(struct rkcif_stream *stream)
rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, 0x0); rkcif_write_register(cif_dev, CIF_REG_DVP_INTEN, 0x0);
rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, 0x3ff); rkcif_write_register(cif_dev, CIF_REG_DVP_INTSTAT, 0x3ff);
rkcif_write_register(cif_dev, CIF_REG_DVP_FRAME_STATUS, 0x0); rkcif_write_register(cif_dev, CIF_REG_DVP_FRAME_STATUS, 0x0);
if (IS_ENABLED(CONFIG_CPU_RV1106))
rkcif_config_dvp_pin(cif_dev, false);
} }
} }
stream->cifdev->id_use_cnt--; stream->cifdev->id_use_cnt--;
@@ -4183,6 +4185,9 @@ static int rkcif_stream_start(struct rkcif_stream *stream, unsigned int mode)
rkcif_enable_dvp_clk_dual_edge(dev, false); rkcif_enable_dvp_clk_dual_edge(dev, false);
} }
if (IS_ENABLED(CONFIG_CPU_RV1106))
rkcif_config_dvp_pin(dev, true);
if (mbus_flags & V4L2_MBUS_PCLK_SAMPLE_RISING) if (mbus_flags & V4L2_MBUS_PCLK_SAMPLE_RISING)
rkcif_config_dvp_clk_sampling_edge(dev, RKCIF_CLK_RISING); rkcif_config_dvp_clk_sampling_edge(dev, RKCIF_CLK_RISING);
else else

View File

@@ -27,6 +27,7 @@
#include "dev.h" #include "dev.h"
#include "procfs.h" #include "procfs.h"
#include <linux/kthread.h> #include <linux/kthread.h>
#include "../../../../phy/rockchip/phy-rockchip-csi2-dphy-common.h"
#define RKCIF_VERNO_LEN 10 #define RKCIF_VERNO_LEN 10
@@ -770,6 +771,12 @@ void rkcif_enable_dvp_clk_dual_edge(struct rkcif_device *dev, bool on)
else else
val = RK3588_CIF_PCLK_SINGLE_EDGE; val = RK3588_CIF_PCLK_SINGLE_EDGE;
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
} else if (dev->chip_id == CHIP_RV1106_CIF) {
if (on)
val = RV1106_CIF_PCLK_DUAL_EDGE;
else
val = RV1106_CIF_PCLK_SINGLE_EDGE;
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
} }
} }
@@ -804,10 +811,38 @@ void rkcif_config_dvp_clk_sampling_edge(struct rkcif_device *dev,
else else
val = RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING; val = RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING;
} }
if (dev->chip_id == CHIP_RV1106_CIF) {
if (dev->dphy_hw) {
if (edge == RKCIF_CLK_RISING)
val = RV1106_CIF_PCLK_EDGE_RISING_M0;
else
val = RV1106_CIF_PCLK_EDGE_FALLING_M0;
} else {
if (edge == RKCIF_CLK_RISING)
val = RV1106_CIF_PCLK_EDGE_RISING_M1;
else
val = RV1106_CIF_PCLK_EDGE_FALLING_M1;
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_VENC, val);
return;
}
}
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val); rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, val);
} }
} }
void rkcif_config_dvp_pin(struct rkcif_device *dev, bool on)
{
if (dev->dphy_hw && dev->dphy_hw->ttl_mode_enable && dev->dphy_hw->ttl_mode_disable) {
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, RV1106_CIF_GRF_SEL_M0);
if (on)
dev->dphy_hw->ttl_mode_enable(dev->dphy_hw);
else
dev->dphy_hw->ttl_mode_disable(dev->dphy_hw);
} else {
rkcif_write_grf_reg(dev, CIF_REG_GRF_CIFIO_CON, RV1106_CIF_GRF_SEL_M1);
}
}
/**************************** pipeline operations *****************************/ /**************************** pipeline operations *****************************/
static int __cif_pipeline_prepare(struct rkcif_pipeline *p, static int __cif_pipeline_prepare(struct rkcif_pipeline *p,
struct media_entity *me) struct media_entity *me)
@@ -1624,6 +1659,37 @@ static irqreturn_t rkcif_irq_lite_handler(int irq, struct rkcif_device *cif_dev)
return IRQ_HANDLED; return IRQ_HANDLED;
} }
static void rkcif_attach_dphy_hw(struct rkcif_device *cif_dev)
{
struct platform_device *plat_dev;
struct device *dev = cif_dev->dev;
struct device_node *np;
struct csi2_dphy_hw *dphy_hw;
np = of_parse_phandle(dev->of_node, "rockchip,dphy_hw", 0);
if (!np || !of_device_is_available(np)) {
dev_err(dev,
"failed to get dphy hw node\n");
return;
}
plat_dev = of_find_device_by_node(np);
of_node_put(np);
if (!plat_dev) {
dev_err(dev,
"failed to get dphy hw from node\n");
return;
}
dphy_hw = platform_get_drvdata(plat_dev);
if (!dphy_hw) {
dev_err(dev,
"failed attach dphy hw\n");
return;
}
cif_dev->dphy_hw = dphy_hw;
}
int rkcif_attach_hw(struct rkcif_device *cif_dev) int rkcif_attach_hw(struct rkcif_device *cif_dev)
{ {
struct device_node *np; struct device_node *np;
@@ -1658,6 +1724,8 @@ int rkcif_attach_hw(struct rkcif_device *cif_dev)
cif_dev->hw_dev = hw; cif_dev->hw_dev = hw;
cif_dev->chip_id = hw->chip_id; cif_dev->chip_id = hw->chip_id;
dev_info(cif_dev->dev, "attach to cif hw node\n"); dev_info(cif_dev->dev, "attach to cif hw node\n");
if (IS_ENABLED(CONFIG_CPU_RV1106))
rkcif_attach_dphy_hw(cif_dev);
return 0; return 0;
} }

View File

@@ -803,6 +803,7 @@ struct rkcif_device {
unsigned int wait_line_cache; unsigned int wait_line_cache;
struct rkcif_dummy_buffer dummy_buf; struct rkcif_dummy_buffer dummy_buf;
struct completion cmpl_ntf; struct completion cmpl_ntf;
struct csi2_dphy_hw *dphy_hw;
bool is_start_hdr; bool is_start_hdr;
bool reset_work_cancel; bool reset_work_cancel;
bool iommu_en; bool iommu_en;
@@ -883,4 +884,6 @@ void rkcif_do_soft_reset(struct rkcif_device *dev);
u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode); u32 rkcif_mbus_pixelcode_to_v4l2(u32 pixelcode);
void rkcif_config_dvp_pin(struct rkcif_device *dev, bool on);
#endif #endif

View File

@@ -862,6 +862,8 @@ static const struct cif_reg rv1106_cif_regs[] = {
[CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL), [CIF_REG_TOISP0_CTRL] = CIF_REG(TOISP0_CH_CTRL),
[CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE), [CIF_REG_TOISP0_SIZE] = CIF_REG(TOISP0_CROP_SIZE),
[CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP), [CIF_REG_TOISP0_CROP] = CIF_REG(TOISP0_CROP),
[CIF_REG_GRF_CIFIO_CON] = CIF_REG(RV1106_CIF_GRF_VI_CON),
[CIF_REG_GRF_CIFIO_VENC] = CIF_REG(RV1106_CIF_GRF_VENC_WRAPPER),
}; };
static const struct rkcif_hw_match_data px30_cif_match_data = { static const struct rkcif_hw_match_data px30_cif_match_data = {

View File

@@ -45,7 +45,7 @@ static inline struct csi2_dev *sd_to_dev(struct v4l2_subdev *sdev)
return container_of(sdev, struct csi2_dev, sd); return container_of(sdev, struct csi2_dev, sd);
} }
static struct csi2_sensor *sd_to_sensor(struct csi2_dev *csi2, static struct csi2_sensor_info *sd_to_sensor(struct csi2_dev *csi2,
struct v4l2_subdev *sd) struct v4l2_subdev *sd)
{ {
int i; int i;
@@ -106,8 +106,8 @@ static void get_remote_terminal_sensor(struct v4l2_subdev *sd,
static void csi2_update_sensor_info(struct csi2_dev *csi2) static void csi2_update_sensor_info(struct csi2_dev *csi2)
{ {
struct csi2_sensor *sensor = &csi2->sensors[0];
struct v4l2_subdev *terminal_sensor_sd = NULL; struct v4l2_subdev *terminal_sensor_sd = NULL;
struct csi2_sensor_info *sensor = &csi2->sensors[0];
struct v4l2_mbus_config mbus; struct v4l2_mbus_config mbus;
int ret = 0; int ret = 0;
@@ -659,7 +659,7 @@ csi2_notifier_bound(struct v4l2_async_notifier *notifier,
struct csi2_dev *csi2 = container_of(notifier, struct csi2_dev *csi2 = container_of(notifier,
struct csi2_dev, struct csi2_dev,
notifier); notifier);
struct csi2_sensor *sensor; struct csi2_sensor_info *sensor;
struct media_link *link; struct media_link *link;
unsigned int pad, ret; unsigned int pad, ret;
@@ -715,7 +715,7 @@ static void csi2_notifier_unbind(struct v4l2_async_notifier *notifier,
struct csi2_dev *csi2 = container_of(notifier, struct csi2_dev *csi2 = container_of(notifier,
struct csi2_dev, struct csi2_dev,
notifier); notifier);
struct csi2_sensor *sensor = sd_to_sensor(csi2, sd); struct csi2_sensor_info *sensor = sd_to_sensor(csi2, sd);
sensor->sd = NULL; sensor->sd = NULL;

View File

@@ -117,7 +117,7 @@ struct csi2_match_data {
int num_pads; int num_pads;
}; };
struct csi2_sensor { struct csi2_sensor_info {
struct v4l2_subdev *sd; struct v4l2_subdev *sd;
struct v4l2_mbus_config mbus; struct v4l2_mbus_config mbus;
int lanes; int lanes;
@@ -147,8 +147,8 @@ struct csi2_dev {
int stream_count; int stream_count;
struct v4l2_subdev *src_sd; struct v4l2_subdev *src_sd;
bool sink_linked[CSI2_NUM_SRC_PADS]; bool sink_linked[CSI2_NUM_SRC_PADS];
struct csi2_sensor sensors[MAX_CSI2_SENSORS];
bool is_check_sot_sync; bool is_check_sot_sync;
struct csi2_sensor_info sensors[MAX_CSI2_SENSORS];
const struct csi2_match_data *match_data; const struct csi2_match_data *match_data;
int num_sensors; int num_sensors;
atomic_t frm_sync_seq; atomic_t frm_sync_seq;

View File

@@ -162,6 +162,7 @@ enum cif_reg_index {
/* reg belowed is in grf */ /* reg belowed is in grf */
CIF_REG_GRF_CIFIO_CON, CIF_REG_GRF_CIFIO_CON,
CIF_REG_GRF_CIFIO_CON1, CIF_REG_GRF_CIFIO_CON1,
CIF_REG_GRF_CIFIO_VENC,
/* reg global control */ /* reg global control */
CIF_REG_GLB_CTRL, CIF_REG_GLB_CTRL,
CIF_REG_GLB_INTEN, CIF_REG_GLB_INTEN,
@@ -1042,7 +1043,16 @@ enum cif_reg_index {
#define RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING (0x00100010) #define RK3588_CIF_PCLK_SAMPLING_EDGE_FALLING (0x00100010)
#define RK3588_CIF_PCLK_SINGLE_EDGE (0x00200000) #define RK3588_CIF_PCLK_SINGLE_EDGE (0x00200000)
#define RK3588_CIF_PCLK_DUAL_EDGE (0x00200020) #define RK3588_CIF_PCLK_DUAL_EDGE (0x00200020)
#define RV1106_CIF_GRF_VI_CON (0x50038)
#define RV1106_CIF_GRF_VENC_WRAPPER (0x10008)
#define RV1106_CIF_PCLK_SINGLE_EDGE (0x00040000)
#define RV1106_CIF_PCLK_DUAL_EDGE (0x00040004)
#define RV1106_CIF_PCLK_EDGE_RISING_M0 (0x00020000)
#define RV1106_CIF_PCLK_EDGE_FALLING_M0 (0x00020002)
#define RV1106_CIF_PCLK_EDGE_RISING_M1 (0x00010000)
#define RV1106_CIF_PCLK_EDGE_FALLING_M1 (0x00010001)
#define RV1106_CIF_GRF_SEL_M0 (0x00010000)
#define RV1106_CIF_GRF_SEL_M1 (0x00010001)
/*toisp*/ /*toisp*/
#define TOISP_FS_CH0(index) (0x1 << (14 + index * 3)) #define TOISP_FS_CH0(index) (0x1 << (14 + index * 3))