ee060519576c89c11ddb8816b62d496299b24953
[openwrt/staging/linusw.git] /
1 From 35e50ee3d66e014d869f0d7a3468bef964d26d32 Mon Sep 17 00:00:00 2001
2 From: Dave Stevenson <dave.stevenson@raspberrypi.com>
3 Date: Thu, 14 Nov 2024 13:14:02 +0000
4 Subject: [PATCH] media: i2c: imx477: Add options for slightly modifying the
5 link freq
6
7 The default link frequency of 450MHz has been noted to interfere
8 with GPS if they are in close proximty.
9 Add the option for 453 and 456MHz to move the signal slightly out
10 of the band. (447MHz can not be offered as corruption is then observed
11 on the 133x992 10bit mode).
12
13 Signed-off-by: Dave Stevenson <dave.stevenson@raspberrypi.com>
14
15 fixup imx477 gps
16 ---
17 drivers/media/i2c/imx477.c | 86 +++++++++++++++++++++++++++++---------
18 1 file changed, 67 insertions(+), 19 deletions(-)
19
20 --- a/drivers/media/i2c/imx477.c
21 +++ b/drivers/media/i2c/imx477.c
22 @@ -164,8 +164,48 @@ struct imx477_mode {
23 struct imx477_reg_list reg_list;
24 };
25
26 -static const s64 imx477_link_freq_menu[] = {
27 - IMX477_DEFAULT_LINK_FREQ,
28 +/* Link frequency setup */
29 +enum {
30 + IMX477_LINK_FREQ_450MHZ,
31 + IMX477_LINK_FREQ_453MHZ,
32 + IMX477_LINK_FREQ_456MHZ,
33 +};
34 +
35 +static const s64 link_freqs[] = {
36 + [IMX477_LINK_FREQ_450MHZ] = 450000000,
37 + [IMX477_LINK_FREQ_453MHZ] = 453000000,
38 + [IMX477_LINK_FREQ_456MHZ] = 456000000,
39 +};
40 +
41 +/* 450MHz is the nominal "default" link frequency */
42 +static const struct imx477_reg link_450Mhz_regs[] = {
43 + {0x030E, 0x00},
44 + {0x030F, 0x96},
45 +};
46 +
47 +static const struct imx477_reg link_453Mhz_regs[] = {
48 + {0x030E, 0x00},
49 + {0x030F, 0x97},
50 +};
51 +
52 +static const struct imx477_reg link_456Mhz_regs[] = {
53 + {0x030E, 0x00},
54 + {0x030F, 0x98},
55 +};
56 +
57 +static const struct imx477_reg_list link_freq_regs[] = {
58 + [IMX477_LINK_FREQ_450MHZ] = {
59 + .regs = link_450Mhz_regs,
60 + .num_of_regs = ARRAY_SIZE(link_450Mhz_regs)
61 + },
62 + [IMX477_LINK_FREQ_453MHZ] = {
63 + .regs = link_453Mhz_regs,
64 + .num_of_regs = ARRAY_SIZE(link_453Mhz_regs)
65 + },
66 + [IMX477_LINK_FREQ_456MHZ] = {
67 + .regs = link_456Mhz_regs,
68 + .num_of_regs = ARRAY_SIZE(link_456Mhz_regs)
69 + },
70 };
71
72 static const struct imx477_reg mode_common_regs[] = {
73 @@ -558,8 +598,6 @@ static const struct imx477_reg mode_4056
74 {0x0309, 0x0c},
75 {0x030b, 0x02},
76 {0x030d, 0x02},
77 - {0x030e, 0x00},
78 - {0x030f, 0x96},
79 {0x0310, 0x01},
80 {0x0820, 0x07},
81 {0x0821, 0x08},
82 @@ -659,8 +697,6 @@ static const struct imx477_reg mode_2028
83 {0x0309, 0x0c},
84 {0x030b, 0x02},
85 {0x030d, 0x02},
86 - {0x030e, 0x00},
87 - {0x030f, 0x96},
88 {0x0310, 0x01},
89 {0x0820, 0x07},
90 {0x0821, 0x08},
91 @@ -760,8 +796,6 @@ static const struct imx477_reg mode_2028
92 {0x0309, 0x0c},
93 {0x030b, 0x02},
94 {0x030d, 0x02},
95 - {0x030e, 0x00},
96 - {0x030f, 0x96},
97 {0x0310, 0x01},
98 {0x0820, 0x07},
99 {0x0821, 0x08},
100 @@ -890,8 +924,6 @@ static const struct imx477_reg mode_1332
101 {0x0309, 0x0a},
102 {0x030b, 0x02},
103 {0x030d, 0x02},
104 - {0x030e, 0x00},
105 - {0x030f, 0x96},
106 {0x0310, 0x01},
107 {0x0820, 0x07},
108 {0x0821, 0x08},
109 @@ -1121,6 +1153,8 @@ struct imx477 {
110 struct v4l2_ctrl *vblank;
111 struct v4l2_ctrl *hblank;
112
113 + unsigned int link_freq_idx;
114 +
115 /* Current mode */
116 const struct imx477_mode *mode;
117
118 @@ -1712,7 +1746,7 @@ static int imx477_get_selection(struct v
119 static int imx477_start_streaming(struct imx477 *imx477)
120 {
121 struct i2c_client *client = v4l2_get_subdevdata(&imx477->sd);
122 - const struct imx477_reg_list *reg_list;
123 + const struct imx477_reg_list *reg_list, *freq_regs;
124 const struct imx477_reg_list *extra_regs;
125 int ret, tm;
126
127 @@ -1725,6 +1759,13 @@ static int imx477_start_streaming(struct
128 extra_regs->num_of_regs);
129 }
130
131 + if (!ret) {
132 + /* Update the link frequency registers */
133 + freq_regs = &link_freq_regs[imx477->link_freq_idx];
134 + ret = imx477_write_regs(imx477, freq_regs->regs,
135 + freq_regs->num_of_regs);
136 + }
137 +
138 if (ret) {
139 dev_err(&client->dev, "%s failed to set common settings\n",
140 __func__);
141 @@ -2010,9 +2051,8 @@ static int imx477_init_controls(struct i
142 /* LINK_FREQ is also read only */
143 imx477->link_freq =
144 v4l2_ctrl_new_int_menu(ctrl_hdlr, &imx477_ctrl_ops,
145 - V4L2_CID_LINK_FREQ,
146 - ARRAY_SIZE(imx477_link_freq_menu) - 1, 0,
147 - imx477_link_freq_menu);
148 + V4L2_CID_LINK_FREQ, 1, 0,
149 + &link_freqs[imx477->link_freq_idx]);
150 if (imx477->link_freq)
151 imx477->link_freq->flags |= V4L2_CTRL_FLAG_READ_ONLY;
152
153 @@ -2110,13 +2150,14 @@ static void imx477_free_controls(struct
154 mutex_destroy(&imx477->mutex);
155 }
156
157 -static int imx477_check_hwcfg(struct device *dev)
158 +static int imx477_check_hwcfg(struct device *dev, struct imx477 *imx477)
159 {
160 struct fwnode_handle *endpoint;
161 struct v4l2_fwnode_endpoint ep_cfg = {
162 .bus_type = V4L2_MBUS_CSI2_DPHY
163 };
164 int ret = -EINVAL;
165 + int i;
166
167 endpoint = fwnode_graph_get_next_endpoint(dev_fwnode(dev), NULL);
168 if (!endpoint) {
169 @@ -2141,11 +2182,18 @@ static int imx477_check_hwcfg(struct dev
170 goto error_out;
171 }
172
173 - if (ep_cfg.nr_of_link_frequencies != 1 ||
174 - ep_cfg.link_frequencies[0] != IMX477_DEFAULT_LINK_FREQ) {
175 + for (i = 0; i < ARRAY_SIZE(link_freqs); i++) {
176 + if (link_freqs[i] == ep_cfg.link_frequencies[0]) {
177 + imx477->link_freq_idx = i;
178 + break;
179 + }
180 + }
181 +
182 + if (i == ARRAY_SIZE(link_freqs)) {
183 dev_err(dev, "Link frequency not supported: %lld\n",
184 ep_cfg.link_frequencies[0]);
185 - goto error_out;
186 + ret = -EINVAL;
187 + goto error_out;
188 }
189
190 ret = 0;
191 @@ -2206,7 +2254,7 @@ static int imx477_probe(struct i2c_clien
192 (const struct imx477_compatible_data *)match->data;
193
194 /* Check the hardware configuration in device tree */
195 - if (imx477_check_hwcfg(dev))
196 + if (imx477_check_hwcfg(dev, imx477))
197 return -EINVAL;
198
199 /* Default the trigger mode from OF to -1, which means invalid */