aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/gpu/drm
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-05-12 00:38:25 -0400
committerBen Skeggs <bskeggs@redhat.com>2010-05-19 02:22:05 -0400
commitf8b0be1a75dc62d2b5f5b9a8406c97d6c5f82b7d (patch)
treeebfae41b6b36206b26b47af26e5461a2a2725c75 /drivers/gpu/drm
parent92b9618761465d190b68519bcc6a6fbd8847cf2c (diff)
drm/nouveau: ensure we've parsed i2c table entry for INIT_*I2C* handlers
We may not have parsed the entry yet if the i2c_index is for an i2c bus that's not referenced by a DCB encoder. This could be done oh so much more nicely, except we have to care about prehistoric DCB tables too, and they make life painful. Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm')
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_bios.c165
1 files changed, 88 insertions, 77 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c
index d8dcb362e8b5..b0b98d7f4ea9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_bios.c
+++ b/drivers/gpu/drm/nouveau/nouveau_bios.c
@@ -715,6 +715,83 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev)
715 return dcb_entry; 715 return dcb_entry;
716} 716}
717 717
718static int
719read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
720{
721 uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
722 int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
723 int recordoffset = 0, rdofs = 1, wrofs = 0;
724 uint8_t port_type = 0;
725
726 if (!i2ctable)
727 return -EINVAL;
728
729 if (dcb_version >= 0x30) {
730 if (i2ctable[0] != dcb_version) /* necessary? */
731 NV_WARN(dev,
732 "DCB I2C table version mismatch (%02X vs %02X)\n",
733 i2ctable[0], dcb_version);
734 dcb_i2c_ver = i2ctable[0];
735 headerlen = i2ctable[1];
736 if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
737 i2c_entries = i2ctable[2];
738 else
739 NV_WARN(dev,
740 "DCB I2C table has more entries than indexable "
741 "(%d entries, max %d)\n", i2ctable[2],
742 DCB_MAX_NUM_I2C_ENTRIES);
743 entry_len = i2ctable[3];
744 /* [4] is i2c_default_indices, read in parse_dcb_table() */
745 }
746 /*
747 * It's your own fault if you call this function on a DCB 1.1 BIOS --
748 * the test below is for DCB 1.2
749 */
750 if (dcb_version < 0x14) {
751 recordoffset = 2;
752 rdofs = 0;
753 wrofs = 1;
754 }
755
756 if (index == 0xf)
757 return 0;
758 if (index >= i2c_entries) {
759 NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
760 index, i2ctable[2]);
761 return -ENOENT;
762 }
763 if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
764 NV_ERROR(dev, "DCB I2C entry invalid\n");
765 return -EINVAL;
766 }
767
768 if (dcb_i2c_ver >= 0x30) {
769 port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];
770
771 /*
772 * Fixup for chips using same address offset for read and
773 * write.
774 */
775 if (port_type == 4) /* seen on C51 */
776 rdofs = wrofs = 1;
777 if (port_type >= 5) /* G80+ */
778 rdofs = wrofs = 0;
779 }
780
781 if (dcb_i2c_ver >= 0x40) {
782 if (port_type != 5 && port_type != 6)
783 NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);
784
785 i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]);
786 }
787
788 i2c->port_type = port_type;
789 i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
790 i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];
791
792 return 0;
793}
794
718static struct nouveau_i2c_chan * 795static struct nouveau_i2c_chan *
719init_i2c_device_find(struct drm_device *dev, int i2c_index) 796init_i2c_device_find(struct drm_device *dev, int i2c_index)
720{ 797{
@@ -734,6 +811,17 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index)
734 if (i2c_index == 0x80) /* g80+ */ 811 if (i2c_index == 0x80) /* g80+ */
735 i2c_index = dcb->i2c_default_indices & 0xf; 812 i2c_index = dcb->i2c_default_indices & 0xf;
736 813
814 if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) {
815 NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index);
816 return NULL;
817 }
818
819 /* Make sure i2c table entry has been parsed, it may not
820 * have been if this is a bus not referenced by a DCB encoder
821 */
822 read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table,
823 i2c_index, &dcb->i2c[i2c_index]);
824
737 return nouveau_i2c_find(dev, i2c_index); 825 return nouveau_i2c_find(dev, i2c_index);
738} 826}
739 827
@@ -5090,83 +5178,6 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len)
5090 return 0; 5178 return 0;
5091} 5179}
5092 5180
5093static int
5094read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c)
5095{
5096 uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4;
5097 int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES;
5098 int recordoffset = 0, rdofs = 1, wrofs = 0;
5099 uint8_t port_type = 0;
5100
5101 if (!i2ctable)
5102 return -EINVAL;
5103
5104 if (dcb_version >= 0x30) {
5105 if (i2ctable[0] != dcb_version) /* necessary? */
5106 NV_WARN(dev,
5107 "DCB I2C table version mismatch (%02X vs %02X)\n",
5108 i2ctable[0], dcb_version);
5109 dcb_i2c_ver = i2ctable[0];
5110 headerlen = i2ctable[1];
5111 if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES)
5112 i2c_entries = i2ctable[2];
5113 else
5114 NV_WARN(dev,
5115 "DCB I2C table has more entries than indexable "
5116 "(%d entries, max %d)\n", i2ctable[2],
5117 DCB_MAX_NUM_I2C_ENTRIES);
5118 entry_len = i2ctable[3];
5119 /* [4] is i2c_default_indices, read in parse_dcb_table() */
5120 }
5121 /*
5122 * It's your own fault if you call this function on a DCB 1.1 BIOS --
5123 * the test below is for DCB 1.2
5124 */
5125 if (dcb_version < 0x14) {
5126 recordoffset = 2;
5127 rdofs = 0;
5128 wrofs = 1;
5129 }
5130
5131 if (index == 0xf)
5132 return 0;
5133 if (index >= i2c_entries) {
5134 NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n",
5135 index, i2ctable[2]);
5136 return -ENOENT;
5137 }
5138 if (i2ctable[headerlen + entry_len * index + 3] == 0xff) {
5139 NV_ERROR(dev, "DCB I2C entry invalid\n");
5140 return -EINVAL;
5141 }
5142
5143 if (dcb_i2c_ver >= 0x30) {
5144 port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index];
5145
5146 /*
5147 * Fixup for chips using same address offset for read and
5148 * write.
5149 */
5150 if (port_type == 4) /* seen on C51 */
5151 rdofs = wrofs = 1;
5152 if (port_type >= 5) /* G80+ */
5153 rdofs = wrofs = 0;
5154 }
5155
5156 if (dcb_i2c_ver >= 0x40) {
5157 if (port_type != 5 && port_type != 6)
5158 NV_WARN(dev, "DCB I2C table has port type %d\n", port_type);
5159
5160 i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]);
5161 }
5162
5163 i2c->port_type = port_type;
5164 i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index];
5165 i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index];
5166
5167 return 0;
5168}
5169
5170static struct dcb_gpio_entry * 5181static struct dcb_gpio_entry *
5171new_gpio_entry(struct nvbios *bios) 5182new_gpio_entry(struct nvbios *bios)
5172{ 5183{