aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMa Ling <ling.ma@intel.com>2009-03-20 02:09:48 -0400
committerDave Airlie <airlied@redhat.com>2009-03-29 04:31:41 -0400
commit167f3a04d7366d65c7fa9a92f0d604cdcf4a11ae (patch)
tree10474106c3c5e86bd4dbf85322fadcfeb091e093 /drivers/gpu
parent955a23eb3cfc773e71b05bb7a0a0938a9e1b2568 (diff)
drm: read EDID extensions from monitor
Usually drm read basic EDID, that is enough for us, but since igital display were introduced i.e. HDMI monitor, sometime we need to interact with monitor by EDID extension information, EDID extensions include audio/video data block, speaker allocation and vendor specific data blocks. This patch intends to read EDID extensions from digital monitor for users. Signed-off-by: Ma Ling <ling.ma@intel.com> Signed-off-by: Dave Airlie <airlied@redhat.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/drm_edid.c121
1 files changed, 93 insertions, 28 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c
index a839a28d8ee6..fab2bdf9c423 100644
--- a/drivers/gpu/drm/drm_edid.c
+++ b/drivers/gpu/drm/drm_edid.c
@@ -550,11 +550,20 @@ static int add_detailed_info(struct drm_connector *connector,
550} 550}
551 551
552#define DDC_ADDR 0x50 552#define DDC_ADDR 0x50
553 553/**
554unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter) 554 * Get EDID information via I2C.
555 *
556 * \param adapter : i2c device adaptor
557 * \param buf : EDID data buffer to be filled
558 * \param len : EDID data buffer length
559 * \return 0 on success or -1 on failure.
560 *
561 * Try to fetch EDID information by calling i2c driver function.
562 */
563int drm_do_probe_ddc_edid(struct i2c_adapter *adapter,
564 unsigned char *buf, int len)
555{ 565{
556 unsigned char start = 0x0; 566 unsigned char start = 0x0;
557 unsigned char *buf = kmalloc(EDID_LENGTH, GFP_KERNEL);
558 struct i2c_msg msgs[] = { 567 struct i2c_msg msgs[] = {
559 { 568 {
560 .addr = DDC_ADDR, 569 .addr = DDC_ADDR,
@@ -564,31 +573,36 @@ unsigned char *drm_do_probe_ddc_edid(struct i2c_adapter *adapter)
564 }, { 573 }, {
565 .addr = DDC_ADDR, 574 .addr = DDC_ADDR,
566 .flags = I2C_M_RD, 575 .flags = I2C_M_RD,
567 .len = EDID_LENGTH, 576 .len = len,
568 .buf = buf, 577 .buf = buf,
569 } 578 }
570 }; 579 };
571 580
572 if (!buf) {
573 dev_warn(&adapter->dev, "unable to allocate memory for EDID "
574 "block.\n");
575 return NULL;
576 }
577
578 if (i2c_transfer(adapter, msgs, 2) == 2) 581 if (i2c_transfer(adapter, msgs, 2) == 2)
579 return buf; 582 return 0;
580 583
581 dev_info(&adapter->dev, "unable to read EDID block.\n"); 584 dev_info(&adapter->dev, "unable to read EDID block.\n");
582 kfree(buf); 585 return -1;
583 return NULL;
584} 586}
585EXPORT_SYMBOL(drm_do_probe_ddc_edid); 587EXPORT_SYMBOL(drm_do_probe_ddc_edid);
586 588
587static unsigned char *drm_ddc_read(struct i2c_adapter *adapter) 589/**
590 * Get EDID information.
591 *
592 * \param adapter : i2c device adaptor.
593 * \param buf : EDID data buffer to be filled
594 * \param len : EDID data buffer length
595 * \return 0 on success or -1 on failure.
596 *
597 * Initialize DDC, then fetch EDID information
598 * by calling drm_do_probe_ddc_edid function.
599 */
600static int drm_ddc_read(struct i2c_adapter *adapter,
601 unsigned char *buf, int len)
588{ 602{
589 struct i2c_algo_bit_data *algo_data = adapter->algo_data; 603 struct i2c_algo_bit_data *algo_data = adapter->algo_data;
590 unsigned char *edid = NULL;
591 int i, j; 604 int i, j;
605 int ret = -1;
592 606
593 algo_data->setscl(algo_data->data, 1); 607 algo_data->setscl(algo_data->data, 1);
594 608
@@ -616,7 +630,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
616 msleep(15); 630 msleep(15);
617 631
618 /* Do the real work */ 632 /* Do the real work */
619 edid = drm_do_probe_ddc_edid(adapter); 633 ret = drm_do_probe_ddc_edid(adapter, buf, len);
620 algo_data->setsda(algo_data->data, 0); 634 algo_data->setsda(algo_data->data, 0);
621 algo_data->setscl(algo_data->data, 0); 635 algo_data->setscl(algo_data->data, 0);
622 msleep(15); 636 msleep(15);
@@ -632,7 +646,7 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
632 msleep(15); 646 msleep(15);
633 algo_data->setscl(algo_data->data, 0); 647 algo_data->setscl(algo_data->data, 0);
634 algo_data->setsda(algo_data->data, 0); 648 algo_data->setsda(algo_data->data, 0);
635 if (edid) 649 if (ret == 0)
636 break; 650 break;
637 } 651 }
638 /* Release the DDC lines when done or the Apple Cinema HD display 652 /* Release the DDC lines when done or the Apple Cinema HD display
@@ -641,9 +655,31 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
641 algo_data->setsda(algo_data->data, 1); 655 algo_data->setsda(algo_data->data, 1);
642 algo_data->setscl(algo_data->data, 1); 656 algo_data->setscl(algo_data->data, 1);
643 657
644 return edid; 658 return ret;
659}
660
661static int drm_ddc_read_edid(struct drm_connector *connector,
662 struct i2c_adapter *adapter,
663 char *buf, int len)
664{
665 int ret;
666
667 ret = drm_ddc_read(adapter, buf, len);
668 if (ret != 0) {
669 dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n",
670 drm_get_connector_name(connector));
671 goto end;
672 }
673 if (!edid_is_valid((struct edid *)buf)) {
674 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n",
675 drm_get_connector_name(connector));
676 ret = -1;
677 }
678end:
679 return ret;
645} 680}
646 681
682#define MAX_EDID_EXT_NUM 4
647/** 683/**
648 * drm_get_edid - get EDID data, if available 684 * drm_get_edid - get EDID data, if available
649 * @connector: connector we're probing 685 * @connector: connector we're probing
@@ -656,24 +692,53 @@ static unsigned char *drm_ddc_read(struct i2c_adapter *adapter)
656struct edid *drm_get_edid(struct drm_connector *connector, 692struct edid *drm_get_edid(struct drm_connector *connector,
657 struct i2c_adapter *adapter) 693 struct i2c_adapter *adapter)
658{ 694{
695 int ret;
659 struct edid *edid; 696 struct edid *edid;
660 697
661 edid = (struct edid *)drm_ddc_read(adapter); 698 edid = kmalloc(EDID_LENGTH * (MAX_EDID_EXT_NUM + 1),
662 if (!edid) { 699 GFP_KERNEL);
663 dev_info(&connector->dev->pdev->dev, "%s: no EDID data\n", 700 if (edid == NULL) {
664 drm_get_connector_name(connector)); 701 dev_warn(&connector->dev->pdev->dev,
665 return NULL; 702 "Failed to allocate EDID\n");
703 goto end;
666 } 704 }
667 if (!edid_is_valid(edid)) { 705
668 dev_warn(&connector->dev->pdev->dev, "%s: EDID invalid.\n", 706 /* Read first EDID block */
669 drm_get_connector_name(connector)); 707 ret = drm_ddc_read_edid(connector, adapter,
670 kfree(edid); 708 (unsigned char *)edid, EDID_LENGTH);
671 return NULL; 709 if (ret != 0)
710 goto clean_up;
711
712 /* There are EDID extensions to be read */
713 if (edid->extensions != 0) {
714 int edid_ext_num = edid->extensions;
715
716 if (edid_ext_num > MAX_EDID_EXT_NUM) {
717 dev_warn(&connector->dev->pdev->dev,
718 "The number of extension(%d) is "
719 "over max (%d), actually read number (%d)\n",
720 edid_ext_num, MAX_EDID_EXT_NUM,
721 MAX_EDID_EXT_NUM);
722 /* Reset EDID extension number to be read */
723 edid_ext_num = MAX_EDID_EXT_NUM;
724 }
725 /* Read EDID including extensions too */
726 ret = drm_ddc_read_edid(connector, adapter, (char *)edid,
727 EDID_LENGTH * (edid_ext_num + 1));
728 if (ret != 0)
729 goto clean_up;
730
672 } 731 }
673 732
674 connector->display_info.raw_edid = (char *)edid; 733 connector->display_info.raw_edid = (char *)edid;
734 goto end;
675 735
736clean_up:
737 kfree(edid);
738 edid = NULL;
739end:
676 return edid; 740 return edid;
741
677} 742}
678EXPORT_SYMBOL(drm_get_edid); 743EXPORT_SYMBOL(drm_get_edid);
679 744