VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

More than 9999 Commits   30 Branches   50 Tags
author: zejian.su <zejian.su@starfivetech.com> 2023-08-07 10:38:36 +0800 committer: Andy Hu <andy.hu@starfivetech.com> 2023-11-01 15:04:54 +0800 commit: 7d7d284f7c210b2b722856a0f9dcf7870a20d4e9 parent: 5a0dc091ad05a0ea42cc293a4131c76cd9e86cf7
Commit Summary:
Expand 2 bytes after the SC buffer for the AE/AWB flag and copy the histogram data to the SC buffer.
Diffstat:
5 files changed, 82 insertions, 26 deletions
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
index 35e38efa238b..c836ba709788 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.c
@@ -323,6 +323,13 @@ FILL_ISP_REGS_FUNC(u16);
 #define FILL_ISP_REGS(type, ispbase, offset, value, size, mask, nbits)	\
 	fill_isp_regs_##type(ispbase, offset, value, size, mask, nbits)
 
+static void fill_regs_with_zero(void __iomem *ispbase, u32 offset, u32 size)
+{
+	u32 i;
+	for(i = 0; i < size; i++, offset += 4)
+		reg_write(ispbase, offset, 0);
+}
+
 static int isp_set_ctrl_wb(struct stf_isp_dev *isp_dev, const void * value)
 {
 	const struct module_register_info * reg_info = &mod_reg_info[imi_awb];
@@ -335,6 +342,8 @@ static int isp_set_ctrl_wb(struct stf_isp_dev *isp_dev, const void * value)
 	struct stf_vin_dev *vin = isp_dev->stfcamss->vin;
 	void __iomem *ispbase = vin->isp_base;
 
+	fill_regs_with_zero(ispbase, reg_info->cfg_reg, 16);
+
 	reg_write(ispbase, reg_addr, r_g);
 	reg_write(ispbase, reg_addr + 1 * 4, r_g);
 	reg_write(ispbase, reg_addr + 2 * 4, g_g);
@@ -370,8 +379,13 @@ static int isp_set_ctrl_ccm(struct stf_isp_dev *isp_dev, const void * value)
 	void __iomem *ispbase = vin->isp_base;
 
 	reg_write(ispbase, reg_info->cfg_reg, 6 << 16);
+	fill_regs_with_zero(ispbase, reg_info->cfg_reg + 4, 11);
+
 	FILL_ISP_REGS(u32, ispbase, reg_addr, (u32 *)ccm, 12, 0x7ff, 0);
 
+	reg_addr += 12 * 4;
+	fill_regs_with_zero(ispbase, reg_addr, 2);
+
 	reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
 
 	return 0;
@@ -640,6 +654,27 @@ static int isp_set_ctrl_sc(struct stf_isp_dev *isp_dev, const void * value)
 	u32 * w_diff = weight_cfg + 2;
 	s32 i;
 
+	// SC dumping axi id
+	reg_write(ispbase, 0x9c, 1 << 24);
+
+	// SC frame crop
+	reg_write(ispbase, 0xb8, ((u32)(setting->crop_config.v_start) << 16) | setting->crop_config.h_start);
+
+	// SC config1
+	reg_write(ispbase, 0xbc, ((u32)(setting->awb_config.sel) << 30) | ((u32)(setting->awb_config.awb_ps_grb_ba) << 16) | 
+		((u32)(setting->crop_config.sw_height) << 8) | setting->crop_config.sw_width);
+
+	// SC decimation config
+	reg_write(ispbase, 0xd8, ((u32)(setting->crop_config.vkeep) << 24) | ((u32)(setting->crop_config.vperiod) << 16) | 
+		((u32)(setting->crop_config.hkeep) << 8) | setting->crop_config.hperiod);
+
+	// SC AWB pixel sum config
+	reg_write(ispbase, 0xc4, CREATE_REG_VALUE(u8, &setting->awb_config.ws_ps_config.awb_ps_rl, 4, 0xff, 8));
+	reg_write(ispbase, 0xc8, CREATE_REG_VALUE(u8, &setting->awb_config.ws_ps_config.awb_ps_bl, 4, 0xff, 8));
+	reg_write(ispbase, 0xcc, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_grl, 2, 0xffff, 16));
+	reg_write(ispbase, 0xd0, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_gbl, 2, 0xffff, 16));
+	reg_write(ispbase, 0xd4, CREATE_REG_VALUE(u16, &setting->awb_config.ws_ps_config.awb_ps_grbl, 2, 0xffff, 16));
+
 	// AF register
 	reg_write(ispbase, 0xc0, 
 		((u32)(setting->af_config.es_hor_thr & 0x1ff) << 16) |
@@ -686,7 +721,7 @@ static int isp_set_ctrl_sc(struct stf_isp_dev *isp_dev, const void * value)
 	FILL_ISP_REGS(u32, ispbase, reg_addr, weight_cfg, 6, 0xffffffff, 0);
 
 	reg_set_bit(ispbase, reg_info->en_reg, 1 << reg_info->en_nbit, setting->enabled ? 1 << reg_info->en_nbit : 0);
-	
+
 	return 0;
 }
 
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_isp.h b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
index 5924503f536e..d740b1fe1aa1 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_isp.h
@@ -18,7 +18,7 @@
 
 #define ISP_SCD_BUFFER_SIZE     (19 * 256 * 4)  // align 128
 #define ISP_YHIST_BUFFER_SIZE   (64 * 4)
-#define ISP_SCD_Y_BUFFER_SIZE   (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)
+#define ISP_SCD_Y_BUFFER_SIZE   (ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE + 2)
 #define ISP_RAW_DATA_BITS       12
 #define SCALER_RATIO_MAX        1  // no compose function
 #define STF_ISP_REG_OFFSET_MAX  0x0FFF
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_video.c b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
index 53c7a6146b6c..8a5e5a846f96 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_video.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_video.c
@@ -1286,13 +1286,8 @@ static int stf_video_subscribe_event(struct v4l2_fh *fh,
 	switch (sub->type) {
 	case V4L2_EVENT_FRAME_SYNC:
 		return v4l2_event_subscribe(fh, sub, 2, NULL);
-		//int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
-		//pr_info("subscribe ret: %d\n", ret);
-		//return ret;
 	default:
 		return v4l2_ctrl_subscribe_event(fh, sub);
-		//st_debug(ST_VIN, "unsupport subscribe_event\n");
-		//return -EINVAL;
 	}
 }
 
diff --git a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
index 67e69565d179..dc30b018e684 100644
--- a/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
+++ b/drivers/media/platform/starfive/v4l2_driver/stf_vin.c
@@ -1147,6 +1147,17 @@ static void vin_buffer_done(struct vin_line *line, struct vin_params *params)
 	while ((ready_buf = vin_buf_get_ready(output))) {
 		//if (line->id >= VIN_LINE_ISP && line->id <= VIN_LINE_ISP_SS1) {
 		if (line->id == VIN_LINE_ISP_SCD_Y) {
+#define ADDR_REG_YHIST_ACC_0               0x0D00
+			struct stf_vin2_dev *vin_dev = line_to_vin2_dev(line);
+			struct stf_vin_dev *vin = vin_dev->stfcamss->vin;
+			void __iomem *ispbase = vin->isp_base;
+			u32 y_hist_reg_addr = ADDR_REG_YHIST_ACC_0;
+			u32 * y_hist_addr = (u32 *)ready_buf->vaddr_sc;
+			s32 i = 0;
+
+			for(i = 0; i < 64; i++, y_hist_reg_addr += 4)
+				y_hist_addr[i] = reg_read(ispbase, y_hist_reg_addr);
+
 			event.u.frame_sync.frame_sequence = output->sequence;
 			v4l2_event_queue(&(line->video_out.vdev), &event);
 			//v4l2_event_queue(line->subdev.devnode, &event);
@@ -1246,9 +1257,14 @@ static void vin_change_buffer(struct vin_line *line)
 			scd_type = vin_dev->hw_ops->vin_isp_get_scd_type(vin_dev);
 			ready_buf->vb.flags &= ~(V4L2_BUF_FLAG_PFRAME | V4L2_BUF_FLAG_BFRAME);
 			if (scd_type == AWB_TYPE)
+			{
 				ready_buf->vb.flags |= V4L2_BUF_FLAG_PFRAME;
-			else
+				*((u16 *)(ready_buf->vaddr_sc + ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)) = 0xffff;
+			}else{
 				ready_buf->vb.flags |= V4L2_BUF_FLAG_BFRAME;
+				*((u16 *)(ready_buf->vaddr_sc + ISP_SCD_BUFFER_SIZE + ISP_YHIST_BUFFER_SIZE)) = 0;
+			}
+
 			if (!output->frame_skip) {
 				output->frame_skip = ISP_AWB_OECF_SKIP_FRAME;
 				scd_type = scd_type == AWB_TYPE ? OECF_TYPE : AWB_TYPE;
@@ -1343,26 +1359,8 @@ static int vin_link_setup(struct media_entity *entity,
 	return 0;
 }
 
-static int stf_vin_subscribe_event(struct v4l2_subdev *sd,
-				   struct v4l2_fh *fh,
-				   struct v4l2_event_subscription *sub)
-{
-	switch (sub->type) {
-	case V4L2_EVENT_FRAME_SYNC:
-		//return v4l2_event_subscribe(fh, sub, 2, NULL);
-		int ret = v4l2_event_subscribe(fh, sub, 2, NULL);
-		pr_info("subscribe ret: %d\n", ret);
-		return ret;
-	default:
-		st_debug(ST_VIN, "unsupport subscribe_event\n");
-		return -EINVAL;
-	}
-}
-
 static const struct v4l2_subdev_core_ops vin_core_ops = {
 	.s_power = vin_set_power,
-	//.subscribe_event = stf_vin_subscribe_event,
-	//.unsubscribe_event = v4l2_event_subdev_unsubscribe,
 };
 
 static const struct v4l2_subdev_video_ops vin_video_ops = {
diff --git a/include/uapi/linux/jh7110-isp.h b/include/uapi/linux/jh7110-isp.h
index e20895bd881a..91254bb509a2 100644
--- a/include/uapi/linux/jh7110-isp.h
+++ b/include/uapi/linux/jh7110-isp.h
@@ -255,6 +255,17 @@ struct jh7110_isp_ycrv_setting {
 	struct jh7110_isp_ycrv_curve curve;
 };
 
+struct jh7110_isp_sc_config {
+	__u16 h_start;
+	__u16 v_start;
+	__u8 sw_width;
+	__u8 sw_height;
+	__u8 hperiod;
+	__u8 hkeep;
+	__u8 vperiod;
+	__u8 vkeep;
+};
+
 struct jh7110_isp_sc_af_config {
 	__u8 es_hor_mode;
 	__u8 es_sum_mode;
@@ -264,6 +275,23 @@ struct jh7110_isp_sc_af_config {
 	__u16 es_hor_thr;
 };
 
+struct jh7110_isp_sc_awb_ps {
+	__u8 awb_ps_rl;
+	__u8 awb_ps_ru;
+	__u8 awb_ps_gl;
+	__u8 awb_ps_gu;
+	__u8 awb_ps_bl;
+	__u8 awb_ps_bu;
+	__u8 awb_ps_yl;
+	__u8 awb_ps_yu;
+	__u16 awb_ps_grl;
+	__u16 awb_ps_gru;
+	__u16 awb_ps_gbl;
+	__u16 awb_ps_gbu;
+	__u16 awb_ps_grbl;
+	__u16 awb_ps_grbu;
+};
+
 struct jh7110_isp_sc_awb_ws {
 	__u8 awb_ws_rl;
 	__u8 awb_ws_ru;
@@ -275,12 +303,16 @@ struct jh7110_isp_sc_awb_ws {
 	__u8 awb_ws_bu;
 };
 
+
 struct jh7110_isp_sc_awb_point {
 	__u16 intensity;
 	__u8 weight;
 };
 
 struct jh7110_isp_sc_awb_config {
+	struct jh7110_isp_sc_awb_ps ws_ps_config;
+	__u8 awb_ps_grb_ba;
+	__u8 sel;
 	struct jh7110_isp_sc_awb_ws ws_config;
 	__u8 awb_cw[169];
 	struct jh7110_isp_sc_awb_point pts[17];
@@ -288,6 +320,7 @@ struct jh7110_isp_sc_awb_config {
 
 struct jh7110_isp_sc_setting {
 	__u32 enabled;
+	struct jh7110_isp_sc_config crop_config;
 	struct jh7110_isp_sc_af_config af_config;
 	struct jh7110_isp_sc_awb_config awb_config;
 };