aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHans Verkuil <hans.verkuil@cisco.com>2015-06-07 06:32:32 -0400
committerMauro Carvalho Chehab <mchehab@osg.samsung.com>2015-06-09 16:30:39 -0400
commitb4dbad8fe3b60466e0d364b34c075117757838f2 (patch)
tree3a1b444ec76005a61be83956f1381d53193f965b
parent28a769f1abfe8f6958c14b3b4163360e3c931133 (diff)
[media] adv7511: log the currently set infoframes
The adv7511 sets up InfoFrames that are used when transmitting video. Log the contents of those InfoFrames so it is possible to see exactly what the transmitter is sending. Signed-off-by: Hans Verkuil <hans.verkuil@cisco.com> Signed-off-by: Mauro Carvalho Chehab <mchehab@osg.samsung.com>
-rw-r--r--drivers/media/i2c/Kconfig1
-rw-r--r--drivers/media/i2c/adv7511.c123
-rw-r--r--drivers/media/pci/cobalt/cobalt-driver.c1
-rw-r--r--include/media/adv7511.h1
4 files changed, 124 insertions, 2 deletions
diff --git a/drivers/media/i2c/Kconfig b/drivers/media/i2c/Kconfig
index 36f5563ca9cd..c92180d4036e 100644
--- a/drivers/media/i2c/Kconfig
+++ b/drivers/media/i2c/Kconfig
@@ -424,6 +424,7 @@ config VIDEO_ADV7393
424config VIDEO_ADV7511 424config VIDEO_ADV7511
425 tristate "Analog Devices ADV7511 encoder" 425 tristate "Analog Devices ADV7511 encoder"
426 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API 426 depends on VIDEO_V4L2 && I2C && VIDEO_V4L2_SUBDEV_API
427 select HDMI
427 ---help--- 428 ---help---
428 Support for the Analog Devices ADV7511 video encoder. 429 Support for the Analog Devices ADV7511 video encoder.
429 430
diff --git a/drivers/media/i2c/adv7511.c b/drivers/media/i2c/adv7511.c
index d9bb90b383fb..95bcd4026451 100644
--- a/drivers/media/i2c/adv7511.c
+++ b/drivers/media/i2c/adv7511.c
@@ -91,6 +91,7 @@ struct adv7511_state {
91 int chip_revision; 91 int chip_revision;
92 u8 i2c_edid_addr; 92 u8 i2c_edid_addr;
93 u8 i2c_cec_addr; 93 u8 i2c_cec_addr;
94 u8 i2c_pktmem_addr;
94 /* Is the adv7511 powered on? */ 95 /* Is the adv7511 powered on? */
95 bool power_on; 96 bool power_on;
96 /* Did we receive hotplug and rx-sense signals? */ 97 /* Did we receive hotplug and rx-sense signals? */
@@ -109,6 +110,7 @@ struct adv7511_state {
109 struct v4l2_ctrl *have_edid0_ctrl; 110 struct v4l2_ctrl *have_edid0_ctrl;
110 struct v4l2_ctrl *rgb_quantization_range_ctrl; 111 struct v4l2_ctrl *rgb_quantization_range_ctrl;
111 struct i2c_client *i2c_edid; 112 struct i2c_client *i2c_edid;
113 struct i2c_client *i2c_pktmem;
112 struct adv7511_state_edid edid; 114 struct adv7511_state_edid edid;
113 /* Running counter of the number of detected EDIDs (for debugging) */ 115 /* Running counter of the number of detected EDIDs (for debugging) */
114 unsigned edid_detect_counter; 116 unsigned edid_detect_counter;
@@ -238,6 +240,35 @@ static inline void adv7511_edid_rd(struct v4l2_subdev *sd, u16 len, u8 *buf)
238 v4l2_err(sd, "%s: i2c read error\n", __func__); 240 v4l2_err(sd, "%s: i2c read error\n", __func__);
239} 241}
240 242
243static int adv7511_pktmem_rd(struct v4l2_subdev *sd, u8 reg)
244{
245 struct adv7511_state *state = get_adv7511_state(sd);
246
247 return adv_smbus_read_byte_data(state->i2c_pktmem, reg);
248}
249
250static int adv7511_pktmem_wr(struct v4l2_subdev *sd, u8 reg, u8 val)
251{
252 struct adv7511_state *state = get_adv7511_state(sd);
253 int ret;
254 int i;
255
256 for (i = 0; i < 3; i++) {
257 ret = i2c_smbus_write_byte_data(state->i2c_pktmem, reg, val);
258 if (ret == 0)
259 return 0;
260 }
261 v4l2_err(sd, "%s: i2c write error\n", __func__);
262 return ret;
263}
264
265/* To set specific bits in the register, a clear-mask is given (to be AND-ed),
266 and then the value-mask (to be OR-ed). */
267static inline void adv7511_pktmem_wr_and_or(struct v4l2_subdev *sd, u8 reg, u8 clr_mask, u8 val_mask)
268{
269 adv7511_pktmem_wr(sd, reg, (adv7511_pktmem_rd(sd, reg) & clr_mask) | val_mask);
270}
271
241static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd) 272static inline bool adv7511_have_hotplug(struct v4l2_subdev *sd)
242{ 273{
243 return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT; 274 return adv7511_rd(sd, 0x42) & MASK_ADV7511_HPD_DETECT;
@@ -415,6 +446,80 @@ static int adv7511_s_register(struct v4l2_subdev *sd, const struct v4l2_dbg_regi
415} 446}
416#endif 447#endif
417 448
449struct adv7511_cfg_read_infoframe {
450 const char *desc;
451 u8 present_reg;
452 u8 present_mask;
453 u8 header[3];
454 u16 payload_addr;
455};
456
457static u8 hdmi_infoframe_checksum(u8 *ptr, size_t size)
458{
459 u8 csum = 0;
460 size_t i;
461
462 /* compute checksum */
463 for (i = 0; i < size; i++)
464 csum += ptr[i];
465
466 return 256 - csum;
467}
468
469static void log_infoframe(struct v4l2_subdev *sd, const struct adv7511_cfg_read_infoframe *cri)
470{
471 struct i2c_client *client = v4l2_get_subdevdata(sd);
472 struct device *dev = &client->dev;
473 union hdmi_infoframe frame;
474 u8 buffer[32];
475 u8 len;
476 int i;
477
478 if (!(adv7511_rd(sd, cri->present_reg) & cri->present_mask)) {
479 v4l2_info(sd, "%s infoframe not transmitted\n", cri->desc);
480 return;
481 }
482
483 memcpy(buffer, cri->header, sizeof(cri->header));
484
485 len = buffer[2];
486
487 if (len + 4 > sizeof(buffer)) {
488 v4l2_err(sd, "%s: invalid %s infoframe length %d\n", __func__, cri->desc, len);
489 return;
490 }
491
492 if (cri->payload_addr >= 0x100) {
493 for (i = 0; i < len; i++)
494 buffer[i + 4] = adv7511_pktmem_rd(sd, cri->payload_addr + i - 0x100);
495 } else {
496 for (i = 0; i < len; i++)
497 buffer[i + 4] = adv7511_rd(sd, cri->payload_addr + i);
498 }
499 buffer[3] = 0;
500 buffer[3] = hdmi_infoframe_checksum(buffer, len + 4);
501
502 if (hdmi_infoframe_unpack(&frame, buffer) < 0) {
503 v4l2_err(sd, "%s: unpack of %s infoframe failed\n", __func__, cri->desc);
504 return;
505 }
506
507 hdmi_infoframe_log(KERN_INFO, dev, &frame);
508}
509
510static void adv7511_log_infoframes(struct v4l2_subdev *sd)
511{
512 static const struct adv7511_cfg_read_infoframe cri[] = {
513 { "AVI", 0x44, 0x10, { 0x82, 2, 13 }, 0x55 },
514 { "Audio", 0x44, 0x08, { 0x84, 1, 10 }, 0x73 },
515 { "SDP", 0x40, 0x40, { 0x83, 1, 25 }, 0x103 },
516 };
517 int i;
518
519 for (i = 0; i < ARRAY_SIZE(cri); i++)
520 log_infoframe(sd, &cri[i]);
521}
522
418static int adv7511_log_status(struct v4l2_subdev *sd) 523static int adv7511_log_status(struct v4l2_subdev *sd)
419{ 524{
420 struct adv7511_state *state = get_adv7511_state(sd); 525 struct adv7511_state *state = get_adv7511_state(sd);
@@ -480,6 +585,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd)
480 manual_cts ? "manual" : "automatic", N, CTS); 585 manual_cts ? "manual" : "automatic", N, CTS);
481 v4l2_info(sd, "VIC: detected %d, sent %d\n", 586 v4l2_info(sd, "VIC: detected %d, sent %d\n",
482 vic_detect, vic_sent); 587 vic_detect, vic_sent);
588 adv7511_log_infoframes(sd);
483 } 589 }
484 if (state->dv_timings.type == V4L2_DV_BT_656_1120) 590 if (state->dv_timings.type == V4L2_DV_BT_656_1120)
485 v4l2_print_dv_timings(sd->name, "timings: ", 591 v4l2_print_dv_timings(sd->name, "timings: ",
@@ -488,6 +594,7 @@ static int adv7511_log_status(struct v4l2_subdev *sd)
488 v4l2_info(sd, "no timings set\n"); 594 v4l2_info(sd, "no timings set\n");
489 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr); 595 v4l2_info(sd, "i2c edid addr: 0x%x\n", state->i2c_edid_addr);
490 v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr); 596 v4l2_info(sd, "i2c cec addr: 0x%x\n", state->i2c_cec_addr);
597 v4l2_info(sd, "i2c pktmem addr: 0x%x\n", state->i2c_pktmem_addr);
491 return 0; 598 return 0;
492} 599}
493 600
@@ -537,6 +644,7 @@ static int adv7511_s_power(struct v4l2_subdev *sd, int on)
537 adv7511_wr(sd, 0xf9, 0x00); 644 adv7511_wr(sd, 0xf9, 0x00);
538 645
539 adv7511_wr(sd, 0x43, state->i2c_edid_addr); 646 adv7511_wr(sd, 0x43, state->i2c_edid_addr);
647 adv7511_wr(sd, 0x45, state->i2c_pktmem_addr);
540 648
541 /* Set number of attempts to read the EDID */ 649 /* Set number of attempts to read the EDID */
542 adv7511_wr(sd, 0xc9, 0xf); 650 adv7511_wr(sd, 0xc9, 0xf);
@@ -1381,6 +1489,7 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
1381 /* EDID and CEC i2c addr */ 1489 /* EDID and CEC i2c addr */
1382 state->i2c_edid_addr = state->pdata.i2c_edid << 1; 1490 state->i2c_edid_addr = state->pdata.i2c_edid << 1;
1383 state->i2c_cec_addr = state->pdata.i2c_cec << 1; 1491 state->i2c_cec_addr = state->pdata.i2c_cec << 1;
1492 state->i2c_pktmem_addr = state->pdata.i2c_pktmem << 1;
1384 1493
1385 state->chip_revision = adv7511_rd(sd, 0x0); 1494 state->chip_revision = adv7511_rd(sd, 0x0);
1386 chip_id[0] = adv7511_rd(sd, 0xf5); 1495 chip_id[0] = adv7511_rd(sd, 0xf5);
@@ -1398,12 +1507,19 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
1398 goto err_entity; 1507 goto err_entity;
1399 } 1508 }
1400 1509
1510 state->i2c_pktmem = i2c_new_dummy(client->adapter, state->i2c_pktmem_addr >> 1);
1511 if (state->i2c_pktmem == NULL) {
1512 v4l2_err(sd, "failed to register pktmem i2c client\n");
1513 err = -ENOMEM;
1514 goto err_unreg_edid;
1515 }
1516
1401 adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */ 1517 adv7511_wr(sd, 0xe2, 0x01); /* power down cec section */
1402 state->work_queue = create_singlethread_workqueue(sd->name); 1518 state->work_queue = create_singlethread_workqueue(sd->name);
1403 if (state->work_queue == NULL) { 1519 if (state->work_queue == NULL) {
1404 v4l2_err(sd, "could not create workqueue\n"); 1520 v4l2_err(sd, "could not create workqueue\n");
1405 err = -ENOMEM; 1521 err = -ENOMEM;
1406 goto err_unreg_cec; 1522 goto err_unreg_pktmem;
1407 } 1523 }
1408 1524
1409 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler); 1525 INIT_DELAYED_WORK(&state->edid_handler, adv7511_edid_handler);
@@ -1416,7 +1532,9 @@ static int adv7511_probe(struct i2c_client *client, const struct i2c_device_id *
1416 client->addr << 1, client->adapter->name); 1532 client->addr << 1, client->adapter->name);
1417 return 0; 1533 return 0;
1418 1534
1419err_unreg_cec: 1535err_unreg_pktmem:
1536 i2c_unregister_device(state->i2c_pktmem);
1537err_unreg_edid:
1420 i2c_unregister_device(state->i2c_edid); 1538 i2c_unregister_device(state->i2c_edid);
1421err_entity: 1539err_entity:
1422 media_entity_cleanup(&sd->entity); 1540 media_entity_cleanup(&sd->entity);
@@ -1440,6 +1558,7 @@ static int adv7511_remove(struct i2c_client *client)
1440 adv7511_init_setup(sd); 1558 adv7511_init_setup(sd);
1441 cancel_delayed_work(&state->edid_handler); 1559 cancel_delayed_work(&state->edid_handler);
1442 i2c_unregister_device(state->i2c_edid); 1560 i2c_unregister_device(state->i2c_edid);
1561 i2c_unregister_device(state->i2c_pktmem);
1443 destroy_workqueue(state->work_queue); 1562 destroy_workqueue(state->work_queue);
1444 v4l2_device_unregister_subdev(sd); 1563 v4l2_device_unregister_subdev(sd);
1445 media_entity_cleanup(&sd->entity); 1564 media_entity_cleanup(&sd->entity);
diff --git a/drivers/media/pci/cobalt/cobalt-driver.c b/drivers/media/pci/cobalt/cobalt-driver.c
index c2974e699ecf..b994b8efdc99 100644
--- a/drivers/media/pci/cobalt/cobalt-driver.c
+++ b/drivers/media/pci/cobalt/cobalt-driver.c
@@ -602,6 +602,7 @@ static int cobalt_subdevs_hsma_init(struct cobalt *cobalt)
602 static struct adv7511_platform_data adv7511_pdata = { 602 static struct adv7511_platform_data adv7511_pdata = {
603 .i2c_edid = 0x7e >> 1, 603 .i2c_edid = 0x7e >> 1,
604 .i2c_cec = 0x7c >> 1, 604 .i2c_cec = 0x7c >> 1,
605 .i2c_pktmem = 0x70 >> 1,
605 .cec_clk = 12000000, 606 .cec_clk = 12000000,
606 }; 607 };
607 static struct i2c_board_info adv7511_info = { 608 static struct i2c_board_info adv7511_info = {
diff --git a/include/media/adv7511.h b/include/media/adv7511.h
index f351eff404d6..d83b91d80764 100644
--- a/include/media/adv7511.h
+++ b/include/media/adv7511.h
@@ -42,6 +42,7 @@ struct adv7511_cec_arg {
42struct adv7511_platform_data { 42struct adv7511_platform_data {
43 u8 i2c_edid; 43 u8 i2c_edid;
44 u8 i2c_cec; 44 u8 i2c_cec;
45 u8 i2c_pktmem;
45 u32 cec_clk; 46 u32 cec_clk;
46}; 47};
47 48