1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* |
3 | * Driver for Analog Devices ADV748X HDMI receiver with AFE |
4 | * |
5 | * Copyright (C) 2017 Renesas Electronics Corp. |
6 | * |
7 | * Authors: |
8 | * Koji Matsuoka <koji.matsuoka.xm@renesas.com> |
9 | * Niklas Söderlund <niklas.soderlund@ragnatech.se> |
10 | * Kieran Bingham <kieran.bingham@ideasonboard.com> |
11 | */ |
12 | |
13 | #include <linux/delay.h> |
14 | #include <linux/errno.h> |
15 | #include <linux/i2c.h> |
16 | #include <linux/module.h> |
17 | #include <linux/mutex.h> |
18 | #include <linux/of_graph.h> |
19 | #include <linux/regmap.h> |
20 | #include <linux/slab.h> |
21 | #include <linux/v4l2-dv-timings.h> |
22 | |
23 | #include <media/v4l2-ctrls.h> |
24 | #include <media/v4l2-device.h> |
25 | #include <media/v4l2-dv-timings.h> |
26 | #include <media/v4l2-fwnode.h> |
27 | #include <media/v4l2-ioctl.h> |
28 | |
29 | #include "adv748x.h" |
30 | |
31 | /* ----------------------------------------------------------------------------- |
32 | * Register manipulation |
33 | */ |
34 | |
35 | #define ADV748X_REGMAP_CONF(n) \ |
36 | { \ |
37 | .name = n, \ |
38 | .reg_bits = 8, \ |
39 | .val_bits = 8, \ |
40 | .max_register = 0xff, \ |
41 | .cache_type = REGCACHE_NONE, \ |
42 | } |
43 | |
44 | static const struct regmap_config adv748x_regmap_cnf[] = { |
45 | ADV748X_REGMAP_CONF("io" ), |
46 | ADV748X_REGMAP_CONF("dpll" ), |
47 | ADV748X_REGMAP_CONF("cp" ), |
48 | ADV748X_REGMAP_CONF("hdmi" ), |
49 | ADV748X_REGMAP_CONF("edid" ), |
50 | ADV748X_REGMAP_CONF("repeater" ), |
51 | ADV748X_REGMAP_CONF("infoframe" ), |
52 | ADV748X_REGMAP_CONF("cbus" ), |
53 | ADV748X_REGMAP_CONF("cec" ), |
54 | ADV748X_REGMAP_CONF("sdp" ), |
55 | ADV748X_REGMAP_CONF("txa" ), |
56 | ADV748X_REGMAP_CONF("txb" ), |
57 | }; |
58 | |
59 | static int adv748x_configure_regmap(struct adv748x_state *state, int region) |
60 | { |
61 | int err; |
62 | |
63 | if (!state->i2c_clients[region]) |
64 | return -ENODEV; |
65 | |
66 | state->regmap[region] = |
67 | devm_regmap_init_i2c(state->i2c_clients[region], |
68 | &adv748x_regmap_cnf[region]); |
69 | |
70 | if (IS_ERR(ptr: state->regmap[region])) { |
71 | err = PTR_ERR(ptr: state->regmap[region]); |
72 | adv_err(state, |
73 | "Error initializing regmap %d with error %d\n" , |
74 | region, err); |
75 | return -EINVAL; |
76 | } |
77 | |
78 | return 0; |
79 | } |
80 | struct adv748x_register_map { |
81 | const char *name; |
82 | u8 default_addr; |
83 | }; |
84 | |
85 | static const struct adv748x_register_map adv748x_default_addresses[] = { |
86 | [ADV748X_PAGE_IO] = { "main" , 0x70 }, |
87 | [ADV748X_PAGE_DPLL] = { .name: "dpll" , .default_addr: 0x26 }, |
88 | [ADV748X_PAGE_CP] = { .name: "cp" , .default_addr: 0x22 }, |
89 | [ADV748X_PAGE_HDMI] = { .name: "hdmi" , .default_addr: 0x34 }, |
90 | [ADV748X_PAGE_EDID] = { .name: "edid" , .default_addr: 0x36 }, |
91 | [ADV748X_PAGE_REPEATER] = { .name: "repeater" , .default_addr: 0x32 }, |
92 | [ADV748X_PAGE_INFOFRAME] = { .name: "infoframe" , .default_addr: 0x31 }, |
93 | [ADV748X_PAGE_CBUS] = { .name: "cbus" , .default_addr: 0x30 }, |
94 | [ADV748X_PAGE_CEC] = { .name: "cec" , .default_addr: 0x41 }, |
95 | [ADV748X_PAGE_SDP] = { .name: "sdp" , .default_addr: 0x79 }, |
96 | [ADV748X_PAGE_TXB] = { .name: "txb" , .default_addr: 0x48 }, |
97 | [ADV748X_PAGE_TXA] = { .name: "txa" , .default_addr: 0x4a }, |
98 | }; |
99 | |
100 | static int adv748x_read_check(struct adv748x_state *state, |
101 | int client_page, u8 reg) |
102 | { |
103 | struct i2c_client *client = state->i2c_clients[client_page]; |
104 | int err; |
105 | unsigned int val; |
106 | |
107 | err = regmap_read(map: state->regmap[client_page], reg, val: &val); |
108 | |
109 | if (err) { |
110 | adv_err(state, "error reading %02x, %02x\n" , |
111 | client->addr, reg); |
112 | return err; |
113 | } |
114 | |
115 | return val; |
116 | } |
117 | |
118 | int adv748x_read(struct adv748x_state *state, u8 page, u8 reg) |
119 | { |
120 | return adv748x_read_check(state, client_page: page, reg); |
121 | } |
122 | |
123 | int adv748x_write(struct adv748x_state *state, u8 page, u8 reg, u8 value) |
124 | { |
125 | return regmap_write(map: state->regmap[page], reg, val: value); |
126 | } |
127 | |
128 | static int adv748x_write_check(struct adv748x_state *state, u8 page, u8 reg, |
129 | u8 value, int *error) |
130 | { |
131 | if (*error) |
132 | return *error; |
133 | |
134 | *error = adv748x_write(state, page, reg, value); |
135 | return *error; |
136 | } |
137 | |
138 | /* adv748x_write_block(): Write raw data with a maximum of I2C_SMBUS_BLOCK_MAX |
139 | * size to one or more registers. |
140 | * |
141 | * A value of zero will be returned on success, a negative errno will |
142 | * be returned in error cases. |
143 | */ |
144 | int adv748x_write_block(struct adv748x_state *state, int client_page, |
145 | unsigned int init_reg, const void *val, |
146 | size_t val_len) |
147 | { |
148 | struct regmap *regmap = state->regmap[client_page]; |
149 | |
150 | if (val_len > I2C_SMBUS_BLOCK_MAX) |
151 | val_len = I2C_SMBUS_BLOCK_MAX; |
152 | |
153 | return regmap_raw_write(map: regmap, reg: init_reg, val, val_len); |
154 | } |
155 | |
156 | static int adv748x_set_slave_addresses(struct adv748x_state *state) |
157 | { |
158 | struct i2c_client *client; |
159 | unsigned int i; |
160 | u8 io_reg; |
161 | |
162 | for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { |
163 | io_reg = ADV748X_IO_SLAVE_ADDR_BASE + i; |
164 | client = state->i2c_clients[i]; |
165 | |
166 | io_write(state, io_reg, client->addr << 1); |
167 | } |
168 | |
169 | return 0; |
170 | } |
171 | |
172 | static void adv748x_unregister_clients(struct adv748x_state *state) |
173 | { |
174 | unsigned int i; |
175 | |
176 | for (i = 1; i < ARRAY_SIZE(state->i2c_clients); ++i) |
177 | i2c_unregister_device(client: state->i2c_clients[i]); |
178 | } |
179 | |
180 | static int adv748x_initialise_clients(struct adv748x_state *state) |
181 | { |
182 | unsigned int i; |
183 | int ret; |
184 | |
185 | for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) { |
186 | state->i2c_clients[i] = i2c_new_ancillary_device( |
187 | client: state->client, |
188 | name: adv748x_default_addresses[i].name, |
189 | default_addr: adv748x_default_addresses[i].default_addr); |
190 | |
191 | if (IS_ERR(ptr: state->i2c_clients[i])) { |
192 | adv_err(state, "failed to create i2c client %u\n" , i); |
193 | return PTR_ERR(ptr: state->i2c_clients[i]); |
194 | } |
195 | |
196 | ret = adv748x_configure_regmap(state, region: i); |
197 | if (ret) |
198 | return ret; |
199 | } |
200 | |
201 | return 0; |
202 | } |
203 | |
204 | /** |
205 | * struct adv748x_reg_value - Register write instruction |
206 | * @page: Regmap page identifier |
207 | * @reg: I2C register |
208 | * @value: value to write to @page at @reg |
209 | */ |
210 | struct adv748x_reg_value { |
211 | u8 page; |
212 | u8 reg; |
213 | u8 value; |
214 | }; |
215 | |
216 | static int adv748x_write_regs(struct adv748x_state *state, |
217 | const struct adv748x_reg_value *regs) |
218 | { |
219 | int ret; |
220 | |
221 | for (; regs->page != ADV748X_PAGE_EOR; regs++) { |
222 | ret = adv748x_write(state, page: regs->page, reg: regs->reg, value: regs->value); |
223 | if (ret < 0) { |
224 | adv_err(state, "Error regs page: 0x%02x reg: 0x%02x\n" , |
225 | regs->page, regs->reg); |
226 | return ret; |
227 | } |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | /* ----------------------------------------------------------------------------- |
234 | * TXA and TXB |
235 | */ |
236 | |
237 | static int adv748x_power_up_tx(struct adv748x_csi2 *tx) |
238 | { |
239 | struct adv748x_state *state = tx->state; |
240 | u8 page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB; |
241 | int ret = 0; |
242 | |
243 | /* Enable n-lane MIPI */ |
244 | adv748x_write_check(state, page, reg: 0x00, value: 0x80 | tx->active_lanes, error: &ret); |
245 | |
246 | /* Set Auto DPHY Timing */ |
247 | adv748x_write_check(state, page, reg: 0x00, value: 0xa0 | tx->active_lanes, error: &ret); |
248 | |
249 | /* ADI Required Write */ |
250 | if (tx->src == &state->hdmi.sd) { |
251 | adv748x_write_check(state, page, reg: 0xdb, value: 0x10, error: &ret); |
252 | adv748x_write_check(state, page, reg: 0xd6, value: 0x07, error: &ret); |
253 | } else { |
254 | adv748x_write_check(state, page, reg: 0xd2, value: 0x40, error: &ret); |
255 | } |
256 | |
257 | adv748x_write_check(state, page, reg: 0xc4, value: 0x0a, error: &ret); |
258 | adv748x_write_check(state, page, reg: 0x71, value: 0x33, error: &ret); |
259 | adv748x_write_check(state, page, reg: 0x72, value: 0x11, error: &ret); |
260 | |
261 | /* i2c_dphy_pwdn - 1'b0 */ |
262 | adv748x_write_check(state, page, reg: 0xf0, value: 0x00, error: &ret); |
263 | |
264 | /* ADI Required Writes*/ |
265 | adv748x_write_check(state, page, reg: 0x31, value: 0x82, error: &ret); |
266 | adv748x_write_check(state, page, reg: 0x1e, value: 0x40, error: &ret); |
267 | |
268 | /* i2c_mipi_pll_en - 1'b1 */ |
269 | adv748x_write_check(state, page, reg: 0xda, value: 0x01, error: &ret); |
270 | usleep_range(min: 2000, max: 2500); |
271 | |
272 | /* Power-up CSI-TX */ |
273 | adv748x_write_check(state, page, reg: 0x00, value: 0x20 | tx->active_lanes, error: &ret); |
274 | usleep_range(min: 1000, max: 1500); |
275 | |
276 | /* ADI Required Writes */ |
277 | adv748x_write_check(state, page, reg: 0xc1, value: 0x2b, error: &ret); |
278 | usleep_range(min: 1000, max: 1500); |
279 | adv748x_write_check(state, page, reg: 0x31, value: 0x80, error: &ret); |
280 | |
281 | return ret; |
282 | } |
283 | |
284 | static int adv748x_power_down_tx(struct adv748x_csi2 *tx) |
285 | { |
286 | struct adv748x_state *state = tx->state; |
287 | u8 page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB; |
288 | int ret = 0; |
289 | |
290 | /* ADI Required Writes */ |
291 | adv748x_write_check(state, page, reg: 0x31, value: 0x82, error: &ret); |
292 | adv748x_write_check(state, page, reg: 0x1e, value: 0x00, error: &ret); |
293 | |
294 | /* Enable n-lane MIPI */ |
295 | adv748x_write_check(state, page, reg: 0x00, value: 0x80 | tx->active_lanes, error: &ret); |
296 | |
297 | /* i2c_mipi_pll_en - 1'b1 */ |
298 | adv748x_write_check(state, page, reg: 0xda, value: 0x01, error: &ret); |
299 | |
300 | /* ADI Required Write */ |
301 | adv748x_write_check(state, page, reg: 0xc1, value: 0x3b, error: &ret); |
302 | |
303 | return ret; |
304 | } |
305 | |
306 | int adv748x_tx_power(struct adv748x_csi2 *tx, bool on) |
307 | { |
308 | int val; |
309 | |
310 | if (!is_tx_enabled(tx)) |
311 | return 0; |
312 | |
313 | val = tx_read(tx, ADV748X_CSI_FS_AS_LS); |
314 | if (val < 0) |
315 | return val; |
316 | |
317 | /* |
318 | * This test against BIT(6) is not documented by the datasheet, but was |
319 | * specified in the downstream driver. |
320 | * Track with a WARN_ONCE to determine if it is ever set by HW. |
321 | */ |
322 | WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN), |
323 | "Enabling with unknown bit set" ); |
324 | |
325 | return on ? adv748x_power_up_tx(tx) : adv748x_power_down_tx(tx); |
326 | } |
327 | |
328 | /* ----------------------------------------------------------------------------- |
329 | * Media Operations |
330 | */ |
331 | static int adv748x_link_setup(struct media_entity *entity, |
332 | const struct media_pad *local, |
333 | const struct media_pad *remote, u32 flags) |
334 | { |
335 | struct v4l2_subdev *rsd = media_entity_to_v4l2_subdev(remote->entity); |
336 | struct v4l2_subdev *sd = media_entity_to_v4l2_subdev(entity); |
337 | struct adv748x_state *state = v4l2_get_subdevdata(sd); |
338 | struct adv748x_csi2 *tx = adv748x_sd_to_csi2(sd); |
339 | bool enable = flags & MEDIA_LNK_FL_ENABLED; |
340 | u8 io10_mask = ADV748X_IO_10_CSI1_EN | |
341 | ADV748X_IO_10_CSI4_EN | |
342 | ADV748X_IO_10_CSI4_IN_SEL_AFE; |
343 | u8 io10 = 0; |
344 | |
345 | /* Refuse to enable multiple links to the same TX at the same time. */ |
346 | if (enable && tx->src) |
347 | return -EINVAL; |
348 | |
349 | /* Set or clear the source (HDMI or AFE) and the current TX. */ |
350 | if (rsd == &state->afe.sd) |
351 | state->afe.tx = enable ? tx : NULL; |
352 | else |
353 | state->hdmi.tx = enable ? tx : NULL; |
354 | |
355 | tx->src = enable ? rsd : NULL; |
356 | |
357 | if (state->afe.tx) { |
358 | /* AFE Requires TXA enabled, even when output to TXB */ |
359 | io10 |= ADV748X_IO_10_CSI4_EN; |
360 | if (is_txa(tx)) { |
361 | /* |
362 | * Output from the SD-core (480i and 576i) from the TXA |
363 | * interface requires reducing the number of enabled |
364 | * data lanes in order to guarantee a valid link |
365 | * frequency. |
366 | */ |
367 | tx->active_lanes = min(tx->num_lanes, 2U); |
368 | io10 |= ADV748X_IO_10_CSI4_IN_SEL_AFE; |
369 | } else { |
370 | /* TXB has a single data lane, no need to adjust. */ |
371 | io10 |= ADV748X_IO_10_CSI1_EN; |
372 | } |
373 | } |
374 | |
375 | if (state->hdmi.tx) { |
376 | /* |
377 | * Restore the number of active lanes, in case we have gone |
378 | * through an AFE->TXA streaming sessions. |
379 | */ |
380 | tx->active_lanes = tx->num_lanes; |
381 | io10 |= ADV748X_IO_10_CSI4_EN; |
382 | } |
383 | |
384 | return io_clrset(state, ADV748X_IO_10, io10_mask, io10); |
385 | } |
386 | |
387 | static const struct media_entity_operations adv748x_tx_media_ops = { |
388 | .link_setup = adv748x_link_setup, |
389 | .link_validate = v4l2_subdev_link_validate, |
390 | }; |
391 | |
392 | static const struct media_entity_operations adv748x_media_ops = { |
393 | .link_validate = v4l2_subdev_link_validate, |
394 | }; |
395 | |
396 | /* ----------------------------------------------------------------------------- |
397 | * HW setup |
398 | */ |
399 | |
400 | /* Initialize CP Core with RGB888 format. */ |
401 | static const struct adv748x_reg_value adv748x_init_hdmi[] = { |
402 | /* Disable chip powerdown & Enable HDMI Rx block */ |
403 | {ADV748X_PAGE_IO, 0x00, 0x40}, |
404 | |
405 | {ADV748X_PAGE_REPEATER, 0x40, 0x83}, /* Enable HDCP 1.1 */ |
406 | |
407 | {ADV748X_PAGE_HDMI, 0x00, 0x08},/* Foreground Channel = A */ |
408 | {ADV748X_PAGE_HDMI, 0x98, 0xff},/* ADI Required Write */ |
409 | {ADV748X_PAGE_HDMI, 0x99, 0xa3},/* ADI Required Write */ |
410 | {ADV748X_PAGE_HDMI, 0x9a, 0x00},/* ADI Required Write */ |
411 | {ADV748X_PAGE_HDMI, 0x9b, 0x0a},/* ADI Required Write */ |
412 | {ADV748X_PAGE_HDMI, 0x9d, 0x40},/* ADI Required Write */ |
413 | {ADV748X_PAGE_HDMI, 0xcb, 0x09},/* ADI Required Write */ |
414 | {ADV748X_PAGE_HDMI, 0x3d, 0x10},/* ADI Required Write */ |
415 | {ADV748X_PAGE_HDMI, 0x3e, 0x7b},/* ADI Required Write */ |
416 | {ADV748X_PAGE_HDMI, 0x3f, 0x5e},/* ADI Required Write */ |
417 | {ADV748X_PAGE_HDMI, 0x4e, 0xfe},/* ADI Required Write */ |
418 | {ADV748X_PAGE_HDMI, 0x4f, 0x18},/* ADI Required Write */ |
419 | {ADV748X_PAGE_HDMI, 0x57, 0xa3},/* ADI Required Write */ |
420 | {ADV748X_PAGE_HDMI, 0x58, 0x04},/* ADI Required Write */ |
421 | {ADV748X_PAGE_HDMI, 0x85, 0x10},/* ADI Required Write */ |
422 | |
423 | {ADV748X_PAGE_HDMI, 0x83, 0x00},/* Enable All Terminations */ |
424 | {ADV748X_PAGE_HDMI, 0xa3, 0x01},/* ADI Required Write */ |
425 | {ADV748X_PAGE_HDMI, 0xbe, 0x00},/* ADI Required Write */ |
426 | |
427 | {ADV748X_PAGE_HDMI, 0x6c, 0x01},/* HPA Manual Enable */ |
428 | {ADV748X_PAGE_HDMI, 0xf8, 0x01},/* HPA Asserted */ |
429 | {ADV748X_PAGE_HDMI, 0x0f, 0x00},/* Audio Mute Speed Set to Fastest */ |
430 | /* (Smallest Step Size) */ |
431 | |
432 | {ADV748X_PAGE_IO, 0x04, 0x02}, /* RGB Out of CP */ |
433 | {ADV748X_PAGE_IO, 0x12, 0xf0}, /* CSC Depends on ip Packets, SDR 444 */ |
434 | {ADV748X_PAGE_IO, 0x17, 0x80}, /* Luma & Chroma can reach 254d */ |
435 | {ADV748X_PAGE_IO, 0x03, 0x86}, /* CP-Insert_AV_Code */ |
436 | |
437 | {ADV748X_PAGE_CP, 0x7c, 0x00}, /* ADI Required Write */ |
438 | |
439 | {ADV748X_PAGE_IO, 0x0c, 0xe0}, /* Enable LLC_DLL & Double LLC Timing */ |
440 | {ADV748X_PAGE_IO, 0x0e, 0xdd}, /* LLC/PIX/SPI PINS TRISTATED AUD */ |
441 | |
442 | {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ |
443 | }; |
444 | |
445 | /* Initialize AFE core with YUV8 format. */ |
446 | static const struct adv748x_reg_value adv748x_init_afe[] = { |
447 | {ADV748X_PAGE_IO, 0x00, 0x30}, /* Disable chip powerdown Rx */ |
448 | {ADV748X_PAGE_IO, 0xf2, 0x01}, /* Enable I2C Read Auto-Increment */ |
449 | |
450 | {ADV748X_PAGE_IO, 0x0e, 0xff}, /* LLC/PIX/AUD/SPI PINS TRISTATED */ |
451 | |
452 | {ADV748X_PAGE_SDP, 0x0f, 0x00}, /* Exit Power Down Mode */ |
453 | {ADV748X_PAGE_SDP, 0x52, 0xcd}, /* ADI Required Write */ |
454 | |
455 | {ADV748X_PAGE_SDP, 0x0e, 0x80}, /* ADI Required Write */ |
456 | {ADV748X_PAGE_SDP, 0x9c, 0x00}, /* ADI Required Write */ |
457 | {ADV748X_PAGE_SDP, 0x9c, 0xff}, /* ADI Required Write */ |
458 | {ADV748X_PAGE_SDP, 0x0e, 0x00}, /* ADI Required Write */ |
459 | |
460 | /* ADI recommended writes for improved video quality */ |
461 | {ADV748X_PAGE_SDP, 0x80, 0x51}, /* ADI Required Write */ |
462 | {ADV748X_PAGE_SDP, 0x81, 0x51}, /* ADI Required Write */ |
463 | {ADV748X_PAGE_SDP, 0x82, 0x68}, /* ADI Required Write */ |
464 | |
465 | {ADV748X_PAGE_SDP, 0x03, 0x42}, /* Tri-S Output , PwrDwn 656 pads */ |
466 | {ADV748X_PAGE_SDP, 0x04, 0xb5}, /* ITU-R BT.656-4 compatible */ |
467 | {ADV748X_PAGE_SDP, 0x13, 0x00}, /* ADI Required Write */ |
468 | |
469 | {ADV748X_PAGE_SDP, 0x17, 0x41}, /* Select SH1 */ |
470 | {ADV748X_PAGE_SDP, 0x31, 0x12}, /* ADI Required Write */ |
471 | {ADV748X_PAGE_SDP, 0xe6, 0x4f}, /* V bit end pos manually in NTSC */ |
472 | |
473 | {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */ |
474 | }; |
475 | |
476 | static int adv748x_sw_reset(struct adv748x_state *state) |
477 | { |
478 | int ret; |
479 | |
480 | ret = io_write(state, ADV748X_IO_REG_FF, ADV748X_IO_REG_FF_MAIN_RESET); |
481 | if (ret) |
482 | return ret; |
483 | |
484 | usleep_range(min: 5000, max: 6000); |
485 | |
486 | /* Disable CEC Wakeup from power-down mode */ |
487 | ret = io_clrset(state, ADV748X_IO_REG_01, ADV748X_IO_REG_01_PWRDN_MASK, |
488 | ADV748X_IO_REG_01_PWRDNB); |
489 | if (ret) |
490 | return ret; |
491 | |
492 | /* Enable I2C Read Auto-Increment for consecutive reads */ |
493 | return io_write(state, ADV748X_IO_REG_F2, |
494 | ADV748X_IO_REG_F2_READ_AUTO_INC); |
495 | } |
496 | |
497 | static int adv748x_reset(struct adv748x_state *state) |
498 | { |
499 | int ret; |
500 | u8 regval = 0; |
501 | |
502 | ret = adv748x_sw_reset(state); |
503 | if (ret < 0) |
504 | return ret; |
505 | |
506 | ret = adv748x_set_slave_addresses(state); |
507 | if (ret < 0) |
508 | return ret; |
509 | |
510 | /* Initialize CP and AFE cores. */ |
511 | ret = adv748x_write_regs(state, regs: adv748x_init_hdmi); |
512 | if (ret) |
513 | return ret; |
514 | |
515 | ret = adv748x_write_regs(state, regs: adv748x_init_afe); |
516 | if (ret) |
517 | return ret; |
518 | |
519 | adv748x_afe_s_input(afe: &state->afe, input: state->afe.input); |
520 | |
521 | adv_dbg(state, "AFE Default input set to %d\n" , state->afe.input); |
522 | |
523 | /* Reset TXA and TXB */ |
524 | adv748x_tx_power(tx: &state->txa, on: 1); |
525 | adv748x_tx_power(tx: &state->txa, on: 0); |
526 | adv748x_tx_power(tx: &state->txb, on: 1); |
527 | adv748x_tx_power(tx: &state->txb, on: 0); |
528 | |
529 | /* Disable chip powerdown & Enable HDMI Rx block */ |
530 | io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN); |
531 | |
532 | /* Conditionally enable TXa and TXb. */ |
533 | if (is_tx_enabled(&state->txa)) { |
534 | regval |= ADV748X_IO_10_CSI4_EN; |
535 | adv748x_csi2_set_virtual_channel(tx: &state->txa, vc: 0); |
536 | } |
537 | if (is_tx_enabled(&state->txb)) { |
538 | regval |= ADV748X_IO_10_CSI1_EN; |
539 | adv748x_csi2_set_virtual_channel(tx: &state->txb, vc: 0); |
540 | } |
541 | io_write(state, ADV748X_IO_10, regval); |
542 | |
543 | /* Use vid_std and v_freq as freerun resolution for CP */ |
544 | cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO, |
545 | ADV748X_CP_CLMP_POS_DIS_AUTO); |
546 | |
547 | return 0; |
548 | } |
549 | |
550 | static int adv748x_identify_chip(struct adv748x_state *state) |
551 | { |
552 | int msb, lsb; |
553 | |
554 | lsb = io_read(state, ADV748X_IO_CHIP_REV_ID_1); |
555 | msb = io_read(state, ADV748X_IO_CHIP_REV_ID_2); |
556 | |
557 | if (lsb < 0 || msb < 0) { |
558 | adv_err(state, "Failed to read chip revision\n" ); |
559 | return -EIO; |
560 | } |
561 | |
562 | adv_info(state, "chip found @ 0x%02x revision %02x%02x\n" , |
563 | state->client->addr << 1, lsb, msb); |
564 | |
565 | return 0; |
566 | } |
567 | |
568 | /* ----------------------------------------------------------------------------- |
569 | * Suspend / Resume |
570 | */ |
571 | |
572 | static int __maybe_unused adv748x_resume_early(struct device *dev) |
573 | { |
574 | struct i2c_client *client = to_i2c_client(dev); |
575 | struct adv748x_state *state = i2c_get_clientdata(client); |
576 | |
577 | return adv748x_reset(state); |
578 | } |
579 | |
580 | /* ----------------------------------------------------------------------------- |
581 | * i2c driver |
582 | */ |
583 | |
584 | void adv748x_subdev_init(struct v4l2_subdev *sd, struct adv748x_state *state, |
585 | const struct v4l2_subdev_ops *ops, u32 function, |
586 | const char *ident) |
587 | { |
588 | v4l2_subdev_init(sd, ops); |
589 | sd->flags |= V4L2_SUBDEV_FL_HAS_DEVNODE; |
590 | |
591 | /* the owner is the same as the i2c_client's driver owner */ |
592 | sd->owner = state->dev->driver->owner; |
593 | sd->dev = state->dev; |
594 | |
595 | v4l2_set_subdevdata(sd, p: state); |
596 | |
597 | /* initialize name */ |
598 | snprintf(buf: sd->name, size: sizeof(sd->name), fmt: "%s %d-%04x %s" , |
599 | state->dev->driver->name, |
600 | i2c_adapter_id(adap: state->client->adapter), |
601 | state->client->addr, ident); |
602 | |
603 | sd->entity.function = function; |
604 | sd->entity.ops = is_tx(adv748x_sd_to_csi2(sd)) ? |
605 | &adv748x_tx_media_ops : &adv748x_media_ops; |
606 | } |
607 | |
608 | static int adv748x_parse_csi2_lanes(struct adv748x_state *state, |
609 | unsigned int port, |
610 | struct device_node *ep) |
611 | { |
612 | struct v4l2_fwnode_endpoint vep = { .bus_type = V4L2_MBUS_CSI2_DPHY }; |
613 | unsigned int num_lanes; |
614 | int ret; |
615 | |
616 | if (port != ADV748X_PORT_TXA && port != ADV748X_PORT_TXB) |
617 | return 0; |
618 | |
619 | ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), vep: &vep); |
620 | if (ret) |
621 | return ret; |
622 | |
623 | num_lanes = vep.bus.mipi_csi2.num_data_lanes; |
624 | |
625 | if (vep.base.port == ADV748X_PORT_TXA) { |
626 | if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4) { |
627 | adv_err(state, "TXA: Invalid number (%u) of lanes\n" , |
628 | num_lanes); |
629 | return -EINVAL; |
630 | } |
631 | |
632 | state->txa.num_lanes = num_lanes; |
633 | state->txa.active_lanes = num_lanes; |
634 | adv_dbg(state, "TXA: using %u lanes\n" , state->txa.num_lanes); |
635 | } |
636 | |
637 | if (vep.base.port == ADV748X_PORT_TXB) { |
638 | if (num_lanes != 1) { |
639 | adv_err(state, "TXB: Invalid number (%u) of lanes\n" , |
640 | num_lanes); |
641 | return -EINVAL; |
642 | } |
643 | |
644 | state->txb.num_lanes = num_lanes; |
645 | state->txb.active_lanes = num_lanes; |
646 | adv_dbg(state, "TXB: using %u lanes\n" , state->txb.num_lanes); |
647 | } |
648 | |
649 | return 0; |
650 | } |
651 | |
652 | static int adv748x_parse_dt(struct adv748x_state *state) |
653 | { |
654 | struct device_node *ep_np = NULL; |
655 | struct of_endpoint ep; |
656 | bool out_found = false; |
657 | bool in_found = false; |
658 | int ret; |
659 | |
660 | for_each_endpoint_of_node(state->dev->of_node, ep_np) { |
661 | of_graph_parse_endpoint(node: ep_np, endpoint: &ep); |
662 | adv_info(state, "Endpoint %pOF on port %d" , ep.local_node, |
663 | ep.port); |
664 | |
665 | if (ep.port >= ADV748X_PORT_MAX) { |
666 | adv_err(state, "Invalid endpoint %pOF on port %d" , |
667 | ep.local_node, ep.port); |
668 | |
669 | continue; |
670 | } |
671 | |
672 | if (state->endpoints[ep.port]) { |
673 | adv_err(state, |
674 | "Multiple port endpoints are not supported" ); |
675 | continue; |
676 | } |
677 | |
678 | of_node_get(node: ep_np); |
679 | state->endpoints[ep.port] = ep_np; |
680 | |
681 | /* |
682 | * At least one input endpoint and one output endpoint shall |
683 | * be defined. |
684 | */ |
685 | if (ep.port < ADV748X_PORT_TXA) |
686 | in_found = true; |
687 | else |
688 | out_found = true; |
689 | |
690 | /* Store number of CSI-2 lanes used for TXA and TXB. */ |
691 | ret = adv748x_parse_csi2_lanes(state, port: ep.port, ep: ep_np); |
692 | if (ret) |
693 | return ret; |
694 | } |
695 | |
696 | return in_found && out_found ? 0 : -ENODEV; |
697 | } |
698 | |
699 | static void adv748x_dt_cleanup(struct adv748x_state *state) |
700 | { |
701 | unsigned int i; |
702 | |
703 | for (i = 0; i < ADV748X_PORT_MAX; i++) |
704 | of_node_put(node: state->endpoints[i]); |
705 | } |
706 | |
707 | static int adv748x_probe(struct i2c_client *client) |
708 | { |
709 | struct adv748x_state *state; |
710 | int ret; |
711 | |
712 | /* Check if the adapter supports the needed features */ |
713 | if (!i2c_check_functionality(adap: client->adapter, I2C_FUNC_SMBUS_BYTE_DATA)) |
714 | return -EIO; |
715 | |
716 | state = devm_kzalloc(dev: &client->dev, size: sizeof(*state), GFP_KERNEL); |
717 | if (!state) |
718 | return -ENOMEM; |
719 | |
720 | mutex_init(&state->mutex); |
721 | |
722 | state->dev = &client->dev; |
723 | state->client = client; |
724 | state->i2c_clients[ADV748X_PAGE_IO] = client; |
725 | i2c_set_clientdata(client, data: state); |
726 | |
727 | /* |
728 | * We can not use container_of to get back to the state with two TXs; |
729 | * Initialize the TXs's fields unconditionally on the endpoint |
730 | * presence to access them later. |
731 | */ |
732 | state->txa.state = state->txb.state = state; |
733 | state->txa.page = ADV748X_PAGE_TXA; |
734 | state->txb.page = ADV748X_PAGE_TXB; |
735 | state->txa.port = ADV748X_PORT_TXA; |
736 | state->txb.port = ADV748X_PORT_TXB; |
737 | |
738 | /* Discover and process ports declared by the Device tree endpoints */ |
739 | ret = adv748x_parse_dt(state); |
740 | if (ret) { |
741 | adv_err(state, "Failed to parse device tree" ); |
742 | goto err_free_mutex; |
743 | } |
744 | |
745 | /* Configure IO Regmap region */ |
746 | ret = adv748x_configure_regmap(state, region: ADV748X_PAGE_IO); |
747 | if (ret) { |
748 | adv_err(state, "Error configuring IO regmap region" ); |
749 | goto err_cleanup_dt; |
750 | } |
751 | |
752 | ret = adv748x_identify_chip(state); |
753 | if (ret) { |
754 | adv_err(state, "Failed to identify chip" ); |
755 | goto err_cleanup_dt; |
756 | } |
757 | |
758 | /* Configure remaining pages as I2C clients with regmap access */ |
759 | ret = adv748x_initialise_clients(state); |
760 | if (ret) { |
761 | adv_err(state, "Failed to setup client regmap pages" ); |
762 | goto err_cleanup_clients; |
763 | } |
764 | |
765 | /* SW reset ADV748X to its default values */ |
766 | ret = adv748x_reset(state); |
767 | if (ret) { |
768 | adv_err(state, "Failed to reset hardware" ); |
769 | goto err_cleanup_clients; |
770 | } |
771 | |
772 | /* Initialise HDMI */ |
773 | ret = adv748x_hdmi_init(hdmi: &state->hdmi); |
774 | if (ret) { |
775 | adv_err(state, "Failed to probe HDMI" ); |
776 | goto err_cleanup_clients; |
777 | } |
778 | |
779 | /* Initialise AFE */ |
780 | ret = adv748x_afe_init(afe: &state->afe); |
781 | if (ret) { |
782 | adv_err(state, "Failed to probe AFE" ); |
783 | goto err_cleanup_hdmi; |
784 | } |
785 | |
786 | /* Initialise TXA */ |
787 | ret = adv748x_csi2_init(state, tx: &state->txa); |
788 | if (ret) { |
789 | adv_err(state, "Failed to probe TXA" ); |
790 | goto err_cleanup_afe; |
791 | } |
792 | |
793 | /* Initialise TXB */ |
794 | ret = adv748x_csi2_init(state, tx: &state->txb); |
795 | if (ret) { |
796 | adv_err(state, "Failed to probe TXB" ); |
797 | goto err_cleanup_txa; |
798 | } |
799 | |
800 | return 0; |
801 | |
802 | err_cleanup_txa: |
803 | adv748x_csi2_cleanup(tx: &state->txa); |
804 | err_cleanup_afe: |
805 | adv748x_afe_cleanup(afe: &state->afe); |
806 | err_cleanup_hdmi: |
807 | adv748x_hdmi_cleanup(hdmi: &state->hdmi); |
808 | err_cleanup_clients: |
809 | adv748x_unregister_clients(state); |
810 | err_cleanup_dt: |
811 | adv748x_dt_cleanup(state); |
812 | err_free_mutex: |
813 | mutex_destroy(lock: &state->mutex); |
814 | |
815 | return ret; |
816 | } |
817 | |
818 | static void adv748x_remove(struct i2c_client *client) |
819 | { |
820 | struct adv748x_state *state = i2c_get_clientdata(client); |
821 | |
822 | adv748x_afe_cleanup(afe: &state->afe); |
823 | adv748x_hdmi_cleanup(hdmi: &state->hdmi); |
824 | |
825 | adv748x_csi2_cleanup(tx: &state->txa); |
826 | adv748x_csi2_cleanup(tx: &state->txb); |
827 | |
828 | adv748x_unregister_clients(state); |
829 | adv748x_dt_cleanup(state); |
830 | mutex_destroy(lock: &state->mutex); |
831 | } |
832 | |
833 | static const struct of_device_id adv748x_of_table[] = { |
834 | { .compatible = "adi,adv7481" , }, |
835 | { .compatible = "adi,adv7482" , }, |
836 | { } |
837 | }; |
838 | MODULE_DEVICE_TABLE(of, adv748x_of_table); |
839 | |
840 | static const struct dev_pm_ops adv748x_pm_ops = { |
841 | SET_LATE_SYSTEM_SLEEP_PM_OPS(NULL, adv748x_resume_early) |
842 | }; |
843 | |
844 | static struct i2c_driver adv748x_driver = { |
845 | .driver = { |
846 | .name = "adv748x" , |
847 | .of_match_table = adv748x_of_table, |
848 | .pm = &adv748x_pm_ops, |
849 | }, |
850 | .probe = adv748x_probe, |
851 | .remove = adv748x_remove, |
852 | }; |
853 | |
854 | module_i2c_driver(adv748x_driver); |
855 | |
856 | MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>" ); |
857 | MODULE_DESCRIPTION("ADV748X video decoder" ); |
858 | MODULE_LICENSE("GPL" ); |
859 | |