aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.4/950-0680-media-i2c-ov5647-Set-V4L2_SUBDEV_FL_HAS_EVENTS-flag.patch
blob: b7a3f19753f037b2b4ad1ffe582080b099112ada (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
From 0e864ac98ffc97d0bb5fc343ca62d860fbe8da09 Mon Sep 17 00:00:00 2001
From: Dave Stevenson <dave.stevenson@raspberrypi.com>
Date: Wed, 29 Apr 2020 17:25:56 +0100
Subject: [PATCH] media: i2c: ov5647: Set V4L2_SUBDEV_FL_HAS_EVENTS
 flag

The ov5647 subdev can generate control events, therefore set
the V4L2_SUBDEV_FL_HAS_EVENTS flag.

Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
---
 drivers/media/i2c/ov5647.c | 29 +++++++++++++++++++++++++++--
 1 file changed, 27 insertions(+), 2 deletions(-)

--- a/drivers/media/i2c/ov5647.c
+++ b/drivers/media/i2c/ov5647.c
@@ -90,6 +90,8 @@ struct ov5647_mode {
 	struct v4l2_rect crop;
 
 	u64 pixel_rate;
+	/* HTS as defined in the register set (0x380C/0x380D) */
+	int hts;
 
 	struct regval_list		*reg_list;
 	unsigned int			num_regs;
@@ -106,6 +108,7 @@ struct ov5647 {
 	unsigned int			flags;
 	struct v4l2_ctrl_handler	ctrls;
 	struct v4l2_ctrl		*pixel_rate;
+	struct v4l2_ctrl		*hblank;
 	bool				write_mode_regs;
 };
 
@@ -605,6 +608,7 @@ static struct ov5647_mode supported_mode
 			.height = 960,
 		},
 		.pixel_rate = 77291670,
+		.hts = 1896,
 		ov5647_640x480_8bit,
 		ARRAY_SIZE(ov5647_640x480_8bit)
 	},
@@ -629,6 +633,7 @@ static struct ov5647_mode supported_mode
 			.height = 1944
 		},
 		.pixel_rate = 87500000,
+		.hts = 2844,
 		ov5647_2592x1944_10bit,
 		ARRAY_SIZE(ov5647_2592x1944_10bit)
 	},
@@ -651,6 +656,7 @@ static struct ov5647_mode supported_mode
 			.height = 1080,
 		},
 		.pixel_rate = 81666700,
+		.hts = 2416,
 		ov5647_1080p30_10bit,
 		ARRAY_SIZE(ov5647_1080p30_10bit)
 	},
@@ -672,6 +678,7 @@ static struct ov5647_mode supported_mode
 			.height = 1944,
 		},
 		.pixel_rate = 81666700,
+		.hts = 1896,
 		ov5647_2x2binned_10bit,
 		ARRAY_SIZE(ov5647_2x2binned_10bit)
 	},
@@ -694,6 +701,7 @@ static struct ov5647_mode supported_mode
 			.height = 1920,
 		},
 		.pixel_rate = 55000000,
+		.hts = 1852,
 		ov5647_640x480_10bit,
 		ARRAY_SIZE(ov5647_640x480_10bit)
 	},
@@ -1168,6 +1176,8 @@ static int ov5647_set_fmt(struct v4l2_su
 		 * If we have changed modes, write the I2C register list on
 		 * a stream_on().
 		 */
+		int hblank;
+
 		if (state->mode != mode)
 			state->write_mode_regs = true;
 		state->mode = mode;
@@ -1176,6 +1186,9 @@ static int ov5647_set_fmt(struct v4l2_su
 					 mode->pixel_rate,
 					 mode->pixel_rate, 1,
 					 mode->pixel_rate);
+		hblank = mode->hts - mode->format.width;
+		__v4l2_ctrl_modify_range(state->hblank, hblank, hblank, 1,
+					 hblank);
 	}
 
 	mutex_unlock(&state->lock);
@@ -1395,6 +1408,9 @@ static int ov5647_s_ctrl(struct v4l2_ctr
 	case V4L2_CID_PIXEL_RATE:
 		/* Read-only, but we adjust it based on mode. */
 		break;
+	case V4L2_CID_HBLANK:
+		/* Read-only, but we adjust it based on mode. */
+		break;
 	default:
 		dev_info(&client->dev,
 			 "ctrl(id:0x%x,val:0x%x) is not handled\n",
@@ -1419,6 +1435,7 @@ static int ov5647_probe(struct i2c_clien
 	struct device_node *np = client->dev.of_node;
 	u32 xclk_freq;
 	struct v4l2_ctrl *ctrl;
+	int hblank;
 
 	sensor = devm_kzalloc(dev, sizeof(*sensor), GFP_KERNEL);
 	if (!sensor)
@@ -1452,7 +1469,7 @@ static int ov5647_probe(struct i2c_clien
 	mutex_init(&sensor->lock);
 
 	/* Initialise controls. */
-	v4l2_ctrl_handler_init(&sensor->ctrls, 6);
+	v4l2_ctrl_handler_init(&sensor->ctrls, 7);
 	v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
 			  V4L2_CID_AUTOGAIN,
 			  0,  /* min */
@@ -1495,6 +1512,13 @@ static int ov5647_probe(struct i2c_clien
 					       sensor->mode->pixel_rate, 1,
 					       sensor->mode->pixel_rate);
 
+	/* By default, HBLANK is read only, but it does change per mode */
+	hblank = sensor->mode->hts - sensor->mode->format.width;
+	sensor->hblank = v4l2_ctrl_new_std(&sensor->ctrls, &ov5647_ctrl_ops,
+					   V4L2_CID_HBLANK, hblank, hblank, 1,
+					   hblank);
+	sensor->hblank->flags |= V4L2_CTRL_FLAG_READ_ONLY;
+
 	if (sensor->ctrls.error) {
 		ret = sensor->ctrls.error;
 		dev_err(&client->dev, "%s control init failed (%d)\n",
@@ -1509,7 +1533,8 @@ static int ov5647_probe(struct i2c_clien
 	sd = &sensor->sd;
 	v4l2_i2c_subdev_init(sd, client, &ov5647_subdev_ops);
 	sensor->sd.internal_ops = &ov5647_subdev_internal_ops;
-	sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE;
+	sensor->sd.flags |= V4L2_SUBDEV_FL_HAS_DEVNODE |
+			    V4L2_SUBDEV_FL_HAS_EVENTS;
 
 	sensor->pad.flags = MEDIA_PAD_FL_SOURCE;
 	sd->entity.function = MEDIA_ENT_F_CAM_SENSOR;