aboutsummaryrefslogtreecommitdiffstats
path: root/target/linux/bcm27xx/patches-5.10/950-0261-media-irs1125-Keep-HW-in-sync-after-imager-reset.patch
blob: 1bacd924e235cb1942a25797f5e80927d9a7f6d2 (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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
From 60794484c063805631e50b5a4fbc81538d51944e Mon Sep 17 00:00:00 2001
From: Markus Proeller <markus.proeller@pieye.org>
Date: Tue, 16 Jun 2020 13:33:56 +0200
Subject: [PATCH] media: irs1125: Keep HW in sync after imager reset

When closing the video device, the irs1125 is put in power down state.
To keep V4L2 ctrls and the HW in sync, v4l2_ctrl_handler_setup is
called after power up.

The compound ctrl IRS1125_CID_MOD_PLL however has a default value
of all zeros, which puts the imager into a non responding state.
Thus, this ctrl is not written by the driver into HW after power up.
The userspace has to take care to write senseful data.

Signed-off-by: Markus Proeller <markus.proeller@pieye.org>
---
 drivers/media/i2c/irs1125.c | 121 +++++++++++++++++-------------------
 1 file changed, 58 insertions(+), 63 deletions(-)

--- a/drivers/media/i2c/irs1125.c
+++ b/drivers/media/i2c/irs1125.c
@@ -82,6 +82,7 @@ struct irs1125 {
 	struct v4l2_ctrl *ctrl_numseq;
 
 	int power_count;
+	bool mod_pll_init;
 };
 
 static inline struct irs1125 *to_state(struct v4l2_subdev *sd)
@@ -276,8 +277,7 @@ static struct regval_list irs1125_seq_cf
 	{0xC039, 0x0000},
 	{0xC401, 0x0002},
 
-	{0xFFFF, 1},
-	{0xA87C, 0x0001}
+	{0xFFFF, 1}
 };
 
 static int irs1125_write(struct v4l2_subdev *sd, u16 reg, u16 val)
@@ -471,7 +471,11 @@ static int __sensor_init(struct v4l2_sub
 		return ret;
 	}
 
-	return 0;
+	irs1125->mod_pll_init = true;
+	v4l2_ctrl_handler_setup(&irs1125->ctrl_handler);
+	irs1125->mod_pll_init = false;
+
+	return irs1125_write(sd, 0xA87C, 0x0001);
 }
 
 static int irs1125_sensor_power(struct v4l2_subdev *sd, int on)
@@ -607,8 +611,6 @@ static int irs1125_s_ctrl(struct v4l2_ct
 	struct irs1125 *dev = container_of(ctrl->handler,
 					struct irs1125, ctrl_handler);
 	struct i2c_client *client = v4l2_get_subdevdata(&dev->sd);
-	struct irs1125_mod_pll *mod_cur, *mod_new;
-	u16 addr, val;
 	int err = 0, i;
 
 	switch (ctrl->id) {
@@ -660,68 +662,61 @@ static int irs1125_s_ctrl(struct v4l2_ct
 				    ctrl->val);
 		break;
 	}
-	case IRS1125_CID_MOD_PLL:
+	case IRS1125_CID_MOD_PLL: {
+		struct irs1125_mod_pll *mod_new;
+
+		if (dev->mod_pll_init)
+			break;
+
 		mod_new = (struct irs1125_mod_pll *)ctrl->p_new.p;
-		mod_cur = (struct irs1125_mod_pll *)ctrl->p_cur.p;
 		for (i = 0; i < IRS1125_NUM_MOD_PLLS; i++) {
-			if (mod_cur[i].pllcfg1 != mod_new[i].pllcfg1) {
-				addr = 0xC3A0 + i * 3;
-				val = mod_new[i].pllcfg1;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg2 != mod_new[i].pllcfg2) {
-				addr = 0xC3A1 + i * 3;
-				val = mod_new[i].pllcfg2;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg3 != mod_new[i].pllcfg3) {
-				addr = 0xC3A2 + i * 3;
-				val = mod_new[i].pllcfg3;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg4 != mod_new[i].pllcfg4) {
-				addr = 0xC24C + i * 5;
-				val = mod_new[i].pllcfg4;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg5 != mod_new[i].pllcfg5) {
-				addr = 0xC24D + i * 5;
-				val = mod_new[i].pllcfg5;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg6 != mod_new[i].pllcfg6) {
-				addr = 0xC24E + i * 5;
-				val = mod_new[i].pllcfg6;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg7 != mod_new[i].pllcfg7) {
-				addr = 0xC24F + i * 5;
-				val = mod_new[i].pllcfg7;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
-			if (mod_cur[i].pllcfg8 != mod_new[i].pllcfg8) {
-				addr = 0xC250 + i * 5;
-				val = mod_new[i].pllcfg8;
-				err = irs1125_write(&dev->sd, addr, val);
-				if (err < 0)
-					break;
-			}
+			unsigned int pll_offset, ssc_offset;
+
+			pll_offset = i * 3;
+			ssc_offset = i * 5;
+
+			err = irs1125_write(&dev->sd, 0xC3A0 + pll_offset,
+					    mod_new[i].pllcfg1);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC3A1 + pll_offset,
+					    mod_new[i].pllcfg2);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC3A2 + pll_offset,
+					    mod_new[i].pllcfg3);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC24C + ssc_offset,
+					    mod_new[i].pllcfg4);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC24D + ssc_offset,
+					    mod_new[i].pllcfg5);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC24E + ssc_offset,
+					    mod_new[i].pllcfg6);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC24F + ssc_offset,
+					    mod_new[i].pllcfg7);
+			if (err < 0)
+				break;
+
+			err = irs1125_write(&dev->sd, 0xC250 + ssc_offset,
+					    mod_new[i].pllcfg8);
+			if (err < 0)
+				break;
 		}
 		break;
+	}
 	case IRS1125_CID_SEQ_CONFIG: {
 		struct irs1125_seq_cfg *cfg_new;