From 65e773354de288401a6c498d006b47b7f87e0936 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Thu, 17 Feb 2022 17:00:27 +0000
Subject: [PATCH] media: i2c: ov7251: Separate modes from frame
 intervals

The modes and frame intervals are independent, therefore
separate them into 2 structures.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 drivers/media/i2c/ov7251.c | 85 ++++++++++++++++++--------------------
 1 file changed, 41 insertions(+), 44 deletions(-)

--- a/drivers/media/i2c/ov7251.c
+++ b/drivers/media/i2c/ov7251.c
@@ -79,14 +79,17 @@ struct reg_value {
 	u8 val;
 };
 
+struct ov7251_frame_ival_info {
+	u16 vts;
+	struct v4l2_fract timeperframe;
+};
+
 struct ov7251_mode_info {
 	u32 width;
 	u32 height;
 	const struct reg_value *data;
 	u32 data_size;
 	u16 exposure_def;
-	u16 vts;
-	struct v4l2_fract timeperframe;
 };
 
 struct ov7251_pll1_config {
@@ -128,6 +131,7 @@ struct ov7251 {
 	struct regulator *analog_regulator;
 
 	const struct ov7251_mode_info *current_mode;
+	const struct ov7251_frame_ival_info *current_ival;
 
 	struct v4l2_ctrl_handler ctrls;
 	struct v4l2_ctrl *exposure;
@@ -343,13 +347,8 @@ static const s64 link_freq[] = {
 	240000000,
 };
 
-static const struct ov7251_mode_info ov7251_mode_info_data[] = {
+static const struct ov7251_frame_ival_info ov7251_frame_ival_info_data[] = {
 	{
-		.width = 640,
-		.height = 480,
-		.data = ov7251_setting_vga,
-		.data_size = ARRAY_SIZE(ov7251_setting_vga),
-		.exposure_def = 504,
 		.vts = 0x6bc,
 		.timeperframe = {
 			.numerator = 100,
@@ -357,11 +356,6 @@ static const struct ov7251_mode_info ov7
 		}
 	},
 	{
-		.width = 640,
-		.height = 480,
-		.data = ov7251_setting_vga,
-		.data_size = ARRAY_SIZE(ov7251_setting_vga),
-		.exposure_def = 504,
 		.vts = 0x35c,
 		.timeperframe = {
 			.numerator = 100,
@@ -369,11 +363,6 @@ static const struct ov7251_mode_info ov7
 		}
 	},
 	{
-		.width = 640,
-		.height = 480,
-		.data = ov7251_setting_vga,
-		.data_size = ARRAY_SIZE(ov7251_setting_vga),
-		.exposure_def = 504,
 		.vts = 0x23c,
 		.timeperframe = {
 			.numerator = 100,
@@ -382,6 +371,16 @@ static const struct ov7251_mode_info ov7
 	},
 };
 
+static const struct ov7251_mode_info ov7251_mode_info_data[] = {
+	{
+		.width = 640,
+		.height = 480,
+		.data = ov7251_setting_vga,
+		.data_size = ARRAY_SIZE(ov7251_setting_vga),
+		.exposure_def = 504,
+	},
+};
+
 static int ov7251_regulators_enable(struct ov7251 *ov7251)
 {
 	int ret;
@@ -789,13 +788,13 @@ static int ov7251_enum_frame_ival(struct
 	unsigned int index = fie->index;
 	unsigned int i;
 
-	for (i = 0; i < ARRAY_SIZE(ov7251_mode_info_data); i++) {
-		if (fie->width != ov7251_mode_info_data[i].width ||
-		    fie->height != ov7251_mode_info_data[i].height)
+	for (i = 0; i < ARRAY_SIZE(ov7251_frame_ival_info_data); i++) {
+		if (fie->width != ov7251_mode_info_data[0].width ||
+		    fie->height != ov7251_mode_info_data[0].height)
 			continue;
 
 		if (index-- == 0) {
-			fie->interval = ov7251_mode_info_data[i].timeperframe;
+			fie->interval = ov7251_frame_ival_info_data[i].timeperframe;
 			return 0;
 		}
 	}
@@ -854,23 +853,18 @@ static inline u32 avg_fps(const struct v
 	return (t->denominator + (t->numerator >> 1)) / t->numerator;
 }
 
-static const struct ov7251_mode_info *
-ov7251_find_mode_by_ival(struct ov7251 *ov7251, struct v4l2_fract *timeperframe)
+static const struct ov7251_frame_ival_info *
+ov7251_find_frame_ival_by_ival(struct ov7251 *ov7251, struct v4l2_fract *timeperframe)
 {
-	const struct ov7251_mode_info *mode = ov7251->current_mode;
 	unsigned int fps_req = avg_fps(timeperframe);
 	unsigned int max_dist_match = (unsigned int) -1;
 	unsigned int i, n = 0;
 
-	for (i = 0; i < ARRAY_SIZE(ov7251_mode_info_data); i++) {
+	for (i = 0; i < ARRAY_SIZE(ov7251_frame_ival_info_data); i++) {
 		unsigned int dist;
 		unsigned int fps_tmp;
 
-		if (mode->width != ov7251_mode_info_data[i].width ||
-		    mode->height != ov7251_mode_info_data[i].height)
-			continue;
-
-		fps_tmp = avg_fps(&ov7251_mode_info_data[i].timeperframe);
+		fps_tmp = avg_fps(&ov7251_frame_ival_info_data[i].timeperframe);
 
 		dist = abs(fps_req - fps_tmp);
 
@@ -880,7 +874,7 @@ ov7251_find_mode_by_ival(struct ov7251 *
 		}
 	}
 
-	return &ov7251_mode_info_data[n];
+	return &ov7251_frame_ival_info_data[n];
 }
 
 static int ov7251_set_format(struct v4l2_subdev *sd,
@@ -914,7 +908,8 @@ static int ov7251_set_format(struct v4l2
 		__v4l2_ctrl_s_ctrl(ov7251->hblank, h_blank);
 
 		ret = __v4l2_ctrl_modify_range(ov7251->exposure, 1,
-					       new_mode->vts - OV7251_EXPOSURE_OFFSET,
+					       ov7251->current_ival->vts -
+							OV7251_EXPOSURE_OFFSET,
 					       1, new_mode->exposure_def);
 		if (ret < 0)
 			goto exit;
@@ -1036,11 +1031,11 @@ static int ov7251_s_stream(struct v4l2_s
 			goto err_power_down;
 		}
 		ret = ov7251_write_reg(ov7251, OV7251_VTS_HIGH,
-				       ov7251->current_mode->vts >> 8);
+				       ov7251->current_ival->vts >> 8);
 		if (ret)
 			goto err_power_down;
 		ret = ov7251_write_reg(ov7251, OV7251_VTS_LOW,
-				       ov7251->current_mode->vts & 0xff);
+				       ov7251->current_ival->vts & 0xff);
 		if (ret)
 			goto err_power_down;
 		ret = __v4l2_ctrl_handler_setup(&ov7251->ctrls);
@@ -1073,7 +1068,7 @@ static int ov7251_get_frame_interval(str
 	struct ov7251 *ov7251 = to_ov7251(subdev);
 
 	mutex_lock(&ov7251->lock);
-	fi->interval = ov7251->current_mode->timeperframe;
+	fi->interval = ov7251->current_ival->timeperframe;
 	mutex_unlock(&ov7251->lock);
 
 	return 0;
@@ -1083,28 +1078,29 @@ static int ov7251_set_frame_interval(str
 				     struct v4l2_subdev_frame_interval *fi)
 {
 	struct ov7251 *ov7251 = to_ov7251(subdev);
-	const struct ov7251_mode_info *new_mode;
+	const struct ov7251_frame_ival_info *new_ival;
 	int ret = 0;
 
 	mutex_lock(&ov7251->lock);
-	new_mode = ov7251_find_mode_by_ival(ov7251, &fi->interval);
+	new_ival = ov7251_find_frame_ival_by_ival(ov7251, &fi->interval);
 
-	if (new_mode != ov7251->current_mode) {
+	if (new_ival != ov7251->current_ival) {
 		ret = __v4l2_ctrl_modify_range(ov7251->exposure, 1,
-					       new_mode->vts - OV7251_EXPOSURE_OFFSET,
-					       1, new_mode->exposure_def);
+					       new_ival->vts -
+							OV7251_EXPOSURE_OFFSET,
+					       1, ov7251->current_mode->exposure_def);
 		if (ret < 0)
 			goto exit;
 
 		ret = __v4l2_ctrl_s_ctrl(ov7251->exposure,
-					 new_mode->exposure_def);
+					 ov7251->current_mode->exposure_def);
 		if (ret < 0)
 			goto exit;
 
-		ov7251->current_mode = new_mode;
+		ov7251->current_ival = new_ival;
 	}
 
-	fi->interval = ov7251->current_mode->timeperframe;
+	fi->interval = ov7251->current_ival->timeperframe;
 
 exit:
 	mutex_unlock(&ov7251->lock);
@@ -1316,6 +1312,7 @@ static int ov7251_probe(struct i2c_clien
 	mutex_init(&ov7251->lock);
 
 	ov7251->current_mode = &ov7251_mode_info_data[0];
+	ov7251->current_ival = &ov7251_frame_ival_info_data[0];
 
 	v4l2_ctrl_handler_init(&ov7251->ctrls, 10);
 	ov7251->ctrls.lock = &ov7251->lock;
