hc
2023-12-11 d2ccde1c8e90d38cee87a1b0309ad2827f3fd30d
kernel/drivers/media/i2c/adv748x/adv748x-core.c
....@@ -1,12 +1,8 @@
1
+// SPDX-License-Identifier: GPL-2.0+
12 /*
23 * Driver for Analog Devices ADV748X HDMI receiver with AFE
34 *
45 * Copyright (C) 2017 Renesas Electronics Corp.
5
- *
6
- * This program is free software; you can redistribute it and/or modify it
7
- * under the terms of the GNU General Public License as published by the
8
- * Free Software Foundation; either version 2 of the License, or (at your
9
- * option) any later version.
106 *
117 * Authors:
128 * Koji Matsuoka <koji.matsuoka.xm@renesas.com>
....@@ -27,6 +23,7 @@
2723 #include <media/v4l2-ctrls.h>
2824 #include <media/v4l2-device.h>
2925 #include <media/v4l2-dv-timings.h>
26
+#include <media/v4l2-fwnode.h>
3027 #include <media/v4l2-ioctl.h>
3128
3229 #include "adv748x.h"
....@@ -128,6 +125,16 @@
128125 return regmap_write(state->regmap[page], reg, value);
129126 }
130127
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
+
131138 /* adv748x_write_block(): Write raw data with a maximum of I2C_SMBUS_BLOCK_MAX
132139 * size to one or more registers.
133140 *
....@@ -176,14 +183,14 @@
176183 int ret;
177184
178185 for (i = ADV748X_PAGE_DPLL; i < ADV748X_PAGE_MAX; ++i) {
179
- state->i2c_clients[i] = i2c_new_secondary_device(
186
+ state->i2c_clients[i] = i2c_new_ancillary_device(
180187 state->client,
181188 adv748x_default_addresses[i].name,
182189 adv748x_default_addresses[i].default_addr);
183190
184
- if (state->i2c_clients[i] == NULL) {
191
+ if (IS_ERR(state->i2c_clients[i])) {
185192 adv_err(state, "failed to create i2c client %u\n", i);
186
- return -ENOMEM;
193
+ return PTR_ERR(state->i2c_clients[i]);
187194 }
188195
189196 ret = adv748x_configure_regmap(state, i);
....@@ -211,20 +218,13 @@
211218 {
212219 int ret;
213220
214
- while (regs->page != ADV748X_PAGE_EOR) {
215
- if (regs->page == ADV748X_PAGE_WAIT) {
216
- msleep(regs->value);
217
- } else {
218
- ret = adv748x_write(state, regs->page, regs->reg,
219
- regs->value);
220
- if (ret < 0) {
221
- adv_err(state,
222
- "Error regs page: 0x%02x reg: 0x%02x\n",
223
- regs->page, regs->reg);
224
- return ret;
225
- }
221
+ for (; regs->page != ADV748X_PAGE_EOR; regs++) {
222
+ ret = adv748x_write(state, regs->page, regs->reg, 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;
226227 }
227
- regs++;
228228 }
229229
230230 return 0;
....@@ -234,91 +234,83 @@
234234 * TXA and TXB
235235 */
236236
237
-static const struct adv748x_reg_value adv748x_power_up_txa_4lane[] = {
238
-
239
- {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
240
- {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */
241
-
242
- {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */
243
- {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */
244
- {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
245
- {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
246
- {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */
247
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
248
- {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */
249
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
250
- {ADV748X_PAGE_TXA, 0x31, 0x80}, /* ADI Required Write */
251
-
252
- {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
253
-};
254
-
255
-static const struct adv748x_reg_value adv748x_power_down_txa_4lane[] = {
256
-
257
- {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */
258
- {ADV748X_PAGE_TXA, 0x1e, 0x00}, /* ADI Required Write */
259
- {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
260
- {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
261
- {ADV748X_PAGE_TXA, 0xc1, 0x3b}, /* ADI Required Write */
262
-
263
- {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
264
-};
265
-
266
-static const struct adv748x_reg_value adv748x_power_up_txb_1lane[] = {
267
-
268
- {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */
269
- {ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */
270
-
271
- {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */
272
- {ADV748X_PAGE_TXB, 0x1e, 0x40}, /* ADI Required Write */
273
- {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
274
- {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
275
- {ADV748X_PAGE_TXB, 0x00, 0x21 },/* Power-up CSI-TX */
276
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
277
- {ADV748X_PAGE_TXB, 0xc1, 0x2b}, /* ADI Required Write */
278
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
279
- {ADV748X_PAGE_TXB, 0x31, 0x80}, /* ADI Required Write */
280
-
281
- {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
282
-};
283
-
284
-static const struct adv748x_reg_value adv748x_power_down_txb_1lane[] = {
285
-
286
- {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */
287
- {ADV748X_PAGE_TXB, 0x1e, 0x00}, /* ADI Required Write */
288
- {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 4-lane MIPI */
289
- {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
290
- {ADV748X_PAGE_TXB, 0xc1, 0x3b}, /* ADI Required Write */
291
-
292
- {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
293
-};
294
-
295
-int adv748x_txa_power(struct adv748x_state *state, bool on)
237
+static int adv748x_power_up_tx(struct adv748x_csi2 *tx)
296238 {
297
- int val;
239
+ struct adv748x_state *state = tx->state;
240
+ u8 page = is_txa(tx) ? ADV748X_PAGE_TXA : ADV748X_PAGE_TXB;
241
+ int ret = 0;
298242
299
- val = txa_read(state, ADV748X_CSI_FS_AS_LS);
300
- if (val < 0)
301
- return val;
243
+ /* Enable n-lane MIPI */
244
+ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
302245
303
- /*
304
- * This test against BIT(6) is not documented by the datasheet, but was
305
- * specified in the downstream driver.
306
- * Track with a WARN_ONCE to determine if it is ever set by HW.
307
- */
308
- WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN),
309
- "Enabling with unknown bit set");
246
+ /* Set Auto DPHY Timing */
247
+ adv748x_write_check(state, page, 0x00, 0xa0 | tx->active_lanes, &ret);
310248
311
- if (on)
312
- return adv748x_write_regs(state, adv748x_power_up_txa_4lane);
249
+ /* ADI Required Write */
250
+ if (tx->src == &state->hdmi.sd) {
251
+ adv748x_write_check(state, page, 0xdb, 0x10, &ret);
252
+ adv748x_write_check(state, page, 0xd6, 0x07, &ret);
253
+ } else {
254
+ adv748x_write_check(state, page, 0xd2, 0x40, &ret);
255
+ }
313256
314
- return adv748x_write_regs(state, adv748x_power_down_txa_4lane);
257
+ adv748x_write_check(state, page, 0xc4, 0x0a, &ret);
258
+ adv748x_write_check(state, page, 0x71, 0x33, &ret);
259
+ adv748x_write_check(state, page, 0x72, 0x11, &ret);
260
+
261
+ /* i2c_dphy_pwdn - 1'b0 */
262
+ adv748x_write_check(state, page, 0xf0, 0x00, &ret);
263
+
264
+ /* ADI Required Writes*/
265
+ adv748x_write_check(state, page, 0x31, 0x82, &ret);
266
+ adv748x_write_check(state, page, 0x1e, 0x40, &ret);
267
+
268
+ /* i2c_mipi_pll_en - 1'b1 */
269
+ adv748x_write_check(state, page, 0xda, 0x01, &ret);
270
+ usleep_range(2000, 2500);
271
+
272
+ /* Power-up CSI-TX */
273
+ adv748x_write_check(state, page, 0x00, 0x20 | tx->active_lanes, &ret);
274
+ usleep_range(1000, 1500);
275
+
276
+ /* ADI Required Writes */
277
+ adv748x_write_check(state, page, 0xc1, 0x2b, &ret);
278
+ usleep_range(1000, 1500);
279
+ adv748x_write_check(state, page, 0x31, 0x80, &ret);
280
+
281
+ return ret;
315282 }
316283
317
-int adv748x_txb_power(struct adv748x_state *state, bool on)
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, 0x31, 0x82, &ret);
292
+ adv748x_write_check(state, page, 0x1e, 0x00, &ret);
293
+
294
+ /* Enable n-lane MIPI */
295
+ adv748x_write_check(state, page, 0x00, 0x80 | tx->active_lanes, &ret);
296
+
297
+ /* i2c_mipi_pll_en - 1'b1 */
298
+ adv748x_write_check(state, page, 0xda, 0x01, &ret);
299
+
300
+ /* ADI Required Write */
301
+ adv748x_write_check(state, page, 0xc1, 0x3b, &ret);
302
+
303
+ return ret;
304
+}
305
+
306
+int adv748x_tx_power(struct adv748x_csi2 *tx, bool on)
318307 {
319308 int val;
320309
321
- val = txb_read(state, ADV748X_CSI_FS_AS_LS);
310
+ if (!is_tx_enabled(tx))
311
+ return 0;
312
+
313
+ val = tx_read(tx, ADV748X_CSI_FS_AS_LS);
322314 if (val < 0)
323315 return val;
324316
....@@ -330,15 +322,72 @@
330322 WARN_ONCE((on && val & ADV748X_CSI_FS_AS_LS_UNKNOWN),
331323 "Enabling with unknown bit set");
332324
333
- if (on)
334
- return adv748x_write_regs(state, adv748x_power_up_txb_1lane);
335
-
336
- return adv748x_write_regs(state, adv748x_power_down_txb_1lane);
325
+ return on ? adv748x_power_up_tx(tx) : adv748x_power_down_tx(tx);
337326 }
338327
339328 /* -----------------------------------------------------------------------------
340329 * Media Operations
341330 */
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
+};
342391
343392 static const struct media_entity_operations adv748x_media_ops = {
344393 .link_validate = v4l2_subdev_link_validate,
....@@ -348,18 +397,8 @@
348397 * HW setup
349398 */
350399
351
-static const struct adv748x_reg_value adv748x_sw_reset[] = {
352
-
353
- {ADV748X_PAGE_IO, 0xff, 0xff}, /* SW reset */
354
- {ADV748X_PAGE_WAIT, 0x00, 0x05},/* delay 5 */
355
- {ADV748X_PAGE_IO, 0x01, 0x76}, /* ADI Required Write */
356
- {ADV748X_PAGE_IO, 0xf2, 0x01}, /* Enable I2C Read Auto-Increment */
357
- {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
358
-};
359
-
360
-/* Supported Formats For Script Below */
361
-/* - 01-29 HDMI to MIPI TxA CSI 4-Lane - RGB888: */
362
-static const struct adv748x_reg_value adv748x_init_txa_4lane[] = {
400
+/* Initialize CP Core with RGB888 format. */
401
+static const struct adv748x_reg_value adv748x_init_hdmi[] = {
363402 /* Disable chip powerdown & Enable HDMI Rx block */
364403 {ADV748X_PAGE_IO, 0x00, 0x40},
365404
....@@ -399,35 +438,12 @@
399438
400439 {ADV748X_PAGE_IO, 0x0c, 0xe0}, /* Enable LLC_DLL & Double LLC Timing */
401440 {ADV748X_PAGE_IO, 0x0e, 0xdd}, /* LLC/PIX/SPI PINS TRISTATED AUD */
402
- /* Outputs Enabled */
403
- {ADV748X_PAGE_IO, 0x10, 0xa0}, /* Enable 4-lane CSI Tx & Pixel Port */
404
-
405
- {ADV748X_PAGE_TXA, 0x00, 0x84}, /* Enable 4-lane MIPI */
406
- {ADV748X_PAGE_TXA, 0x00, 0xa4}, /* Set Auto DPHY Timing */
407
- {ADV748X_PAGE_TXA, 0xdb, 0x10}, /* ADI Required Write */
408
- {ADV748X_PAGE_TXA, 0xd6, 0x07}, /* ADI Required Write */
409
- {ADV748X_PAGE_TXA, 0xc4, 0x0a}, /* ADI Required Write */
410
- {ADV748X_PAGE_TXA, 0x71, 0x33}, /* ADI Required Write */
411
- {ADV748X_PAGE_TXA, 0x72, 0x11}, /* ADI Required Write */
412
- {ADV748X_PAGE_TXA, 0xf0, 0x00}, /* i2c_dphy_pwdn - 1'b0 */
413
-
414
- {ADV748X_PAGE_TXA, 0x31, 0x82}, /* ADI Required Write */
415
- {ADV748X_PAGE_TXA, 0x1e, 0x40}, /* ADI Required Write */
416
- {ADV748X_PAGE_TXA, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
417
- {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
418
- {ADV748X_PAGE_TXA, 0x00, 0x24 },/* Power-up CSI-TX */
419
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
420
- {ADV748X_PAGE_TXA, 0xc1, 0x2b}, /* ADI Required Write */
421
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
422
- {ADV748X_PAGE_TXA, 0x31, 0x80}, /* ADI Required Write */
423441
424442 {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
425443 };
426444
427
-/* 02-01 Analog CVBS to MIPI TX-B CSI 1-Lane - */
428
-/* Autodetect CVBS Single Ended In Ain 1 - MIPI Out */
429
-static const struct adv748x_reg_value adv748x_init_txb_1lane[] = {
430
-
445
+/* Initialize AFE core with YUV8 format. */
446
+static const struct adv748x_reg_value adv748x_init_afe[] = {
431447 {ADV748X_PAGE_IO, 0x00, 0x30}, /* Disable chip powerdown Rx */
432448 {ADV748X_PAGE_IO, 0xf2, 0x01}, /* Enable I2C Read Auto-Increment */
433449
....@@ -454,36 +470,36 @@
454470 {ADV748X_PAGE_SDP, 0x31, 0x12}, /* ADI Required Write */
455471 {ADV748X_PAGE_SDP, 0xe6, 0x4f}, /* V bit end pos manually in NTSC */
456472
457
- /* Enable 1-Lane MIPI Tx, */
458
- /* enable pixel output and route SD through Pixel port */
459
- {ADV748X_PAGE_IO, 0x10, 0x70},
460
-
461
- {ADV748X_PAGE_TXB, 0x00, 0x81}, /* Enable 1-lane MIPI */
462
- {ADV748X_PAGE_TXB, 0x00, 0xa1}, /* Set Auto DPHY Timing */
463
- {ADV748X_PAGE_TXB, 0xd2, 0x40}, /* ADI Required Write */
464
- {ADV748X_PAGE_TXB, 0xc4, 0x0a}, /* ADI Required Write */
465
- {ADV748X_PAGE_TXB, 0x71, 0x33}, /* ADI Required Write */
466
- {ADV748X_PAGE_TXB, 0x72, 0x11}, /* ADI Required Write */
467
- {ADV748X_PAGE_TXB, 0xf0, 0x00}, /* i2c_dphy_pwdn - 1'b0 */
468
- {ADV748X_PAGE_TXB, 0x31, 0x82}, /* ADI Required Write */
469
- {ADV748X_PAGE_TXB, 0x1e, 0x40}, /* ADI Required Write */
470
- {ADV748X_PAGE_TXB, 0xda, 0x01}, /* i2c_mipi_pll_en - 1'b1 */
471
-
472
- {ADV748X_PAGE_WAIT, 0x00, 0x02},/* delay 2 */
473
- {ADV748X_PAGE_TXB, 0x00, 0x21 },/* Power-up CSI-TX */
474
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
475
- {ADV748X_PAGE_TXB, 0xc1, 0x2b}, /* ADI Required Write */
476
- {ADV748X_PAGE_WAIT, 0x00, 0x01},/* delay 1 */
477
- {ADV748X_PAGE_TXB, 0x31, 0x80}, /* ADI Required Write */
478
-
479473 {ADV748X_PAGE_EOR, 0xff, 0xff} /* End of register table */
480474 };
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(5000, 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
+}
481496
482497 static int adv748x_reset(struct adv748x_state *state)
483498 {
484499 int ret;
500
+ u8 regval = 0;
485501
486
- ret = adv748x_write_regs(state, adv748x_sw_reset);
502
+ ret = adv748x_sw_reset(state);
487503 if (ret < 0)
488504 return ret;
489505
....@@ -491,27 +507,30 @@
491507 if (ret < 0)
492508 return ret;
493509
494
- /* Init and power down TXA */
495
- ret = adv748x_write_regs(state, adv748x_init_txa_4lane);
510
+ /* Initialize CP and AFE cores. */
511
+ ret = adv748x_write_regs(state, adv748x_init_hdmi);
496512 if (ret)
497513 return ret;
498514
499
- adv748x_txa_power(state, 0);
500
-
501
- /* Init and power down TXB */
502
- ret = adv748x_write_regs(state, adv748x_init_txb_1lane);
515
+ ret = adv748x_write_regs(state, adv748x_init_afe);
503516 if (ret)
504517 return ret;
505518
506
- adv748x_txb_power(state, 0);
519
+ /* Reset TXA and TXB */
520
+ adv748x_tx_power(&state->txa, 1);
521
+ adv748x_tx_power(&state->txa, 0);
522
+ adv748x_tx_power(&state->txb, 1);
523
+ adv748x_tx_power(&state->txb, 0);
507524
508525 /* Disable chip powerdown & Enable HDMI Rx block */
509526 io_write(state, ADV748X_IO_PD, ADV748X_IO_PD_RX_EN);
510527
511
- /* Enable 4-lane CSI Tx & Pixel Port */
512
- io_write(state, ADV748X_IO_10, ADV748X_IO_10_CSI4_EN |
513
- ADV748X_IO_10_CSI1_EN |
514
- ADV748X_IO_10_PIX_OUT_EN);
528
+ /* Conditionally enable TXa and TXb. */
529
+ if (is_tx_enabled(&state->txa))
530
+ regval |= ADV748X_IO_10_CSI4_EN;
531
+ if (is_tx_enabled(&state->txb))
532
+ regval |= ADV748X_IO_10_CSI1_EN;
533
+ io_write(state, ADV748X_IO_10, regval);
515534
516535 /* Use vid_std and v_freq as freerun resolution for CP */
517536 cp_clrset(state, ADV748X_CP_CLMP_POS, ADV748X_CP_CLMP_POS_DIS_AUTO,
....@@ -562,7 +581,53 @@
562581 state->client->addr, ident);
563582
564583 sd->entity.function = function;
565
- sd->entity.ops = &adv748x_media_ops;
584
+ sd->entity.ops = is_tx(adv748x_sd_to_csi2(sd)) ?
585
+ &adv748x_tx_media_ops : &adv748x_media_ops;
586
+}
587
+
588
+static int adv748x_parse_csi2_lanes(struct adv748x_state *state,
589
+ unsigned int port,
590
+ struct device_node *ep)
591
+{
592
+ struct v4l2_fwnode_endpoint vep;
593
+ unsigned int num_lanes;
594
+ int ret;
595
+
596
+ if (port != ADV748X_PORT_TXA && port != ADV748X_PORT_TXB)
597
+ return 0;
598
+
599
+ vep.bus_type = V4L2_MBUS_CSI2_DPHY;
600
+ ret = v4l2_fwnode_endpoint_parse(of_fwnode_handle(ep), &vep);
601
+ if (ret)
602
+ return ret;
603
+
604
+ num_lanes = vep.bus.mipi_csi2.num_data_lanes;
605
+
606
+ if (vep.base.port == ADV748X_PORT_TXA) {
607
+ if (num_lanes != 1 && num_lanes != 2 && num_lanes != 4) {
608
+ adv_err(state, "TXA: Invalid number (%u) of lanes\n",
609
+ num_lanes);
610
+ return -EINVAL;
611
+ }
612
+
613
+ state->txa.num_lanes = num_lanes;
614
+ state->txa.active_lanes = num_lanes;
615
+ adv_dbg(state, "TXA: using %u lanes\n", state->txa.num_lanes);
616
+ }
617
+
618
+ if (vep.base.port == ADV748X_PORT_TXB) {
619
+ if (num_lanes != 1) {
620
+ adv_err(state, "TXB: Invalid number (%u) of lanes\n",
621
+ num_lanes);
622
+ return -EINVAL;
623
+ }
624
+
625
+ state->txb.num_lanes = num_lanes;
626
+ state->txb.active_lanes = num_lanes;
627
+ adv_dbg(state, "TXB: using %u lanes\n", state->txb.num_lanes);
628
+ }
629
+
630
+ return 0;
566631 }
567632
568633 static int adv748x_parse_dt(struct adv748x_state *state)
....@@ -571,6 +636,7 @@
571636 struct of_endpoint ep;
572637 bool out_found = false;
573638 bool in_found = false;
639
+ int ret;
574640
575641 for_each_endpoint_of_node(state->dev->of_node, ep_np) {
576642 of_graph_parse_endpoint(ep_np, &ep);
....@@ -601,6 +667,11 @@
601667 in_found = true;
602668 else
603669 out_found = true;
670
+
671
+ /* Store number of CSI-2 lanes used for TXA and TXB. */
672
+ ret = adv748x_parse_csi2_lanes(state, ep.port, ep_np);
673
+ if (ret)
674
+ return ret;
604675 }
605676
606677 return in_found && out_found ? 0 : -ENODEV;
....@@ -614,8 +685,7 @@
614685 of_node_put(state->endpoints[i]);
615686 }
616687
617
-static int adv748x_probe(struct i2c_client *client,
618
- const struct i2c_device_id *id)
688
+static int adv748x_probe(struct i2c_client *client)
619689 {
620690 struct adv748x_state *state;
621691 int ret;
....@@ -624,7 +694,7 @@
624694 if (!i2c_check_functionality(client->adapter, I2C_FUNC_SMBUS_BYTE_DATA))
625695 return -EIO;
626696
627
- state = kzalloc(sizeof(struct adv748x_state), GFP_KERNEL);
697
+ state = devm_kzalloc(&client->dev, sizeof(*state), GFP_KERNEL);
628698 if (!state)
629699 return -ENOMEM;
630700
....@@ -722,7 +792,6 @@
722792 adv748x_dt_cleanup(state);
723793 err_free_mutex:
724794 mutex_destroy(&state->mutex);
725
- kfree(state);
726795
727796 return ret;
728797 }
....@@ -741,17 +810,8 @@
741810 adv748x_dt_cleanup(state);
742811 mutex_destroy(&state->mutex);
743812
744
- kfree(state);
745
-
746813 return 0;
747814 }
748
-
749
-static const struct i2c_device_id adv748x_id[] = {
750
- { "adv7481", 0 },
751
- { "adv7482", 0 },
752
- { },
753
-};
754
-MODULE_DEVICE_TABLE(i2c, adv748x_id);
755815
756816 static const struct of_device_id adv748x_of_table[] = {
757817 { .compatible = "adi,adv7481", },
....@@ -765,13 +825,12 @@
765825 .name = "adv748x",
766826 .of_match_table = adv748x_of_table,
767827 },
768
- .probe = adv748x_probe,
828
+ .probe_new = adv748x_probe,
769829 .remove = adv748x_remove,
770
- .id_table = adv748x_id,
771830 };
772831
773832 module_i2c_driver(adv748x_driver);
774833
775834 MODULE_AUTHOR("Kieran Bingham <kieran.bingham@ideasonboard.com>");
776835 MODULE_DESCRIPTION("ADV748X video decoder");
777
-MODULE_LICENSE("GPL v2");
836
+MODULE_LICENSE("GPL");