diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2011-11-10 19:22:19 -0500 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2011-12-21 04:01:40 -0500 |
commit | 486a45c2a6c19b159602d044ab601a92cd81f524 (patch) | |
tree | 350a368208768873667cd1a659a6d264a76f7c91 | |
parent | 6b5a81a2e783f26a69fc262b3c393f0b391c8613 (diff) |
drm/nouveau/i2c: do parsing of i2c-related vbios info in nouveau_i2c.c
Not much point parsing the vbios data into a struct which is only used once
to parse the data into another struct, go directly from vbios to
nouveau_i2c_chan.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 166 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.h | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 1 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.c | 302 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_i2c.h | 14 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_temp.c | 6 |
6 files changed, 222 insertions, 278 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index c7723fb54077..7922bb969d25 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -720,116 +720,20 @@ static int dcb_entry_idx_from_crtchead(struct drm_device *dev) | |||
720 | return dcb_entry; | 720 | return dcb_entry; |
721 | } | 721 | } |
722 | 722 | ||
723 | static int | ||
724 | read_dcb_i2c_entry(struct drm_device *dev, int dcb_version, uint8_t *i2ctable, int index, struct dcb_i2c_entry *i2c) | ||
725 | { | ||
726 | uint8_t dcb_i2c_ver = dcb_version, headerlen = 0, entry_len = 4; | ||
727 | int i2c_entries = DCB_MAX_NUM_I2C_ENTRIES; | ||
728 | int recordoffset = 0, rdofs = 1, wrofs = 0; | ||
729 | uint8_t port_type = 0; | ||
730 | |||
731 | if (!i2ctable) | ||
732 | return -EINVAL; | ||
733 | |||
734 | if (dcb_version >= 0x30) { | ||
735 | if (i2ctable[0] != dcb_version) /* necessary? */ | ||
736 | NV_WARN(dev, | ||
737 | "DCB I2C table version mismatch (%02X vs %02X)\n", | ||
738 | i2ctable[0], dcb_version); | ||
739 | dcb_i2c_ver = i2ctable[0]; | ||
740 | headerlen = i2ctable[1]; | ||
741 | if (i2ctable[2] <= DCB_MAX_NUM_I2C_ENTRIES) | ||
742 | i2c_entries = i2ctable[2]; | ||
743 | else | ||
744 | NV_WARN(dev, | ||
745 | "DCB I2C table has more entries than indexable " | ||
746 | "(%d entries, max %d)\n", i2ctable[2], | ||
747 | DCB_MAX_NUM_I2C_ENTRIES); | ||
748 | entry_len = i2ctable[3]; | ||
749 | /* [4] is i2c_default_indices, read in parse_dcb_table() */ | ||
750 | } | ||
751 | /* | ||
752 | * It's your own fault if you call this function on a DCB 1.1 BIOS -- | ||
753 | * the test below is for DCB 1.2 | ||
754 | */ | ||
755 | if (dcb_version < 0x14) { | ||
756 | recordoffset = 2; | ||
757 | rdofs = 0; | ||
758 | wrofs = 1; | ||
759 | } | ||
760 | |||
761 | if (index == 0xf) | ||
762 | return 0; | ||
763 | if (index >= i2c_entries) { | ||
764 | NV_ERROR(dev, "DCB I2C index too big (%d >= %d)\n", | ||
765 | index, i2ctable[2]); | ||
766 | return -ENOENT; | ||
767 | } | ||
768 | if (i2ctable[headerlen + entry_len * index + 3] == 0xff) { | ||
769 | NV_ERROR(dev, "DCB I2C entry invalid\n"); | ||
770 | return -EINVAL; | ||
771 | } | ||
772 | |||
773 | if (dcb_i2c_ver >= 0x30) { | ||
774 | port_type = i2ctable[headerlen + recordoffset + 3 + entry_len * index]; | ||
775 | |||
776 | /* | ||
777 | * Fixup for chips using same address offset for read and | ||
778 | * write. | ||
779 | */ | ||
780 | if (port_type == 4) /* seen on C51 */ | ||
781 | rdofs = wrofs = 1; | ||
782 | if (port_type >= 5) /* G80+ */ | ||
783 | rdofs = wrofs = 0; | ||
784 | } | ||
785 | |||
786 | if (dcb_i2c_ver >= 0x40) { | ||
787 | if (port_type != 5 && port_type != 6) | ||
788 | NV_WARN(dev, "DCB I2C table has port type %d\n", port_type); | ||
789 | |||
790 | i2c->entry = ROM32(i2ctable[headerlen + recordoffset + entry_len * index]); | ||
791 | } | ||
792 | |||
793 | i2c->port_type = port_type; | ||
794 | i2c->read = i2ctable[headerlen + recordoffset + rdofs + entry_len * index]; | ||
795 | i2c->write = i2ctable[headerlen + recordoffset + wrofs + entry_len * index]; | ||
796 | |||
797 | return 0; | ||
798 | } | ||
799 | |||
800 | static struct nouveau_i2c_chan * | 723 | static struct nouveau_i2c_chan * |
801 | init_i2c_device_find(struct drm_device *dev, int i2c_index) | 724 | init_i2c_device_find(struct drm_device *dev, int i2c_index) |
802 | { | 725 | { |
803 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
804 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | ||
805 | |||
806 | if (i2c_index == 0xff) { | 726 | if (i2c_index == 0xff) { |
727 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
728 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | ||
807 | /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ | 729 | /* note: dcb_entry_idx_from_crtchead needs pre-script set-up */ |
808 | int idx = dcb_entry_idx_from_crtchead(dev), shift = 0; | 730 | int idx = dcb_entry_idx_from_crtchead(dev); |
809 | int default_indices = dcb->i2c_default_indices; | ||
810 | 731 | ||
732 | i2c_index = NV_I2C_DEFAULT(0); | ||
811 | if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) | 733 | if (idx != 0x7f && dcb->entry[idx].i2c_upper_default) |
812 | shift = 4; | 734 | i2c_index = NV_I2C_DEFAULT(1); |
813 | |||
814 | i2c_index = (default_indices >> shift) & 0xf; | ||
815 | } | ||
816 | if (i2c_index == 0x80) /* g80+ */ | ||
817 | i2c_index = dcb->i2c_default_indices & 0xf; | ||
818 | else | ||
819 | if (i2c_index == 0x81) | ||
820 | i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; | ||
821 | |||
822 | if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) { | ||
823 | NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); | ||
824 | return NULL; | ||
825 | } | 735 | } |
826 | 736 | ||
827 | /* Make sure i2c table entry has been parsed, it may not | ||
828 | * have been if this is a bus not referenced by a DCB encoder | ||
829 | */ | ||
830 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
831 | i2c_index, &dcb->i2c[i2c_index]); | ||
832 | |||
833 | return nouveau_i2c_find(dev, i2c_index); | 737 | return nouveau_i2c_find(dev, i2c_index); |
834 | } | 738 | } |
835 | 739 | ||
@@ -5595,10 +5499,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | |||
5595 | uint16_t legacy_scripts_offset, legacy_i2c_offset; | 5499 | uint16_t legacy_scripts_offset, legacy_i2c_offset; |
5596 | 5500 | ||
5597 | /* load needed defaults in case we can't parse this info */ | 5501 | /* load needed defaults in case we can't parse this info */ |
5598 | bios->dcb.i2c[0].write = NV_CIO_CRE_DDC_WR__INDEX; | ||
5599 | bios->dcb.i2c[0].read = NV_CIO_CRE_DDC_STATUS__INDEX; | ||
5600 | bios->dcb.i2c[1].write = NV_CIO_CRE_DDC0_WR__INDEX; | ||
5601 | bios->dcb.i2c[1].read = NV_CIO_CRE_DDC0_STATUS__INDEX; | ||
5602 | bios->digital_min_front_porch = 0x4b; | 5502 | bios->digital_min_front_porch = 0x4b; |
5603 | bios->fmaxvco = 256000; | 5503 | bios->fmaxvco = 256000; |
5604 | bios->fminvco = 128000; | 5504 | bios->fminvco = 128000; |
@@ -5706,14 +5606,6 @@ static int parse_bmp_structure(struct drm_device *dev, struct nvbios *bios, unsi | |||
5706 | bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; | 5606 | bios->legacy.i2c_indices.crt = bios->data[legacy_i2c_offset]; |
5707 | bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; | 5607 | bios->legacy.i2c_indices.tv = bios->data[legacy_i2c_offset + 1]; |
5708 | bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; | 5608 | bios->legacy.i2c_indices.panel = bios->data[legacy_i2c_offset + 2]; |
5709 | if (bios->data[legacy_i2c_offset + 4]) | ||
5710 | bios->dcb.i2c[0].write = bios->data[legacy_i2c_offset + 4]; | ||
5711 | if (bios->data[legacy_i2c_offset + 5]) | ||
5712 | bios->dcb.i2c[0].read = bios->data[legacy_i2c_offset + 5]; | ||
5713 | if (bios->data[legacy_i2c_offset + 6]) | ||
5714 | bios->dcb.i2c[1].write = bios->data[legacy_i2c_offset + 6]; | ||
5715 | if (bios->data[legacy_i2c_offset + 7]) | ||
5716 | bios->dcb.i2c[1].read = bios->data[legacy_i2c_offset + 7]; | ||
5717 | 5609 | ||
5718 | if (bmplength > 74) { | 5610 | if (bmplength > 74) { |
5719 | bios->fmaxvco = ROM32(bmp[67]); | 5611 | bios->fmaxvco = ROM32(bmp[67]); |
@@ -6549,10 +6441,6 @@ parse_dcb_entry(struct drm_device *dev, void *data, int idx, u8 *outp) | |||
6549 | ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); | 6441 | ret = parse_dcb15_entry(dev, dcb, conn, conf, entry); |
6550 | if (!ret) | 6442 | if (!ret) |
6551 | return 1; /* stop parsing */ | 6443 | return 1; /* stop parsing */ |
6552 | |||
6553 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
6554 | entry->i2c_index, | ||
6555 | &dcb->i2c[entry->i2c_index]); | ||
6556 | } | 6444 | } |
6557 | 6445 | ||
6558 | return 0; | 6446 | return 0; |
@@ -6562,7 +6450,6 @@ static int | |||
6562 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | 6450 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios) |
6563 | { | 6451 | { |
6564 | struct dcb_table *dcb = &bios->dcb; | 6452 | struct dcb_table *dcb = &bios->dcb; |
6565 | u16 i2ctabptr = 0x0000; | ||
6566 | u8 *dcbt; | 6453 | u8 *dcbt; |
6567 | 6454 | ||
6568 | dcbt = dcb_table(dev); | 6455 | dcbt = dcb_table(dev); |
@@ -6580,32 +6467,8 @@ parse_dcb_table(struct drm_device *dev, struct nvbios *bios) | |||
6580 | 6467 | ||
6581 | dcb->version = dcbt[0]; | 6468 | dcb->version = dcbt[0]; |
6582 | if (dcb->version >= 0x30) { | 6469 | if (dcb->version >= 0x30) { |
6583 | i2ctabptr = ROM16(dcbt[4]); | ||
6584 | dcb->gpio_table_ptr = ROM16(dcbt[10]); | 6470 | dcb->gpio_table_ptr = ROM16(dcbt[10]); |
6585 | dcb->connector_table_ptr = ROM16(dcbt[20]); | 6471 | dcb->connector_table_ptr = ROM16(dcbt[20]); |
6586 | } else | ||
6587 | if (dcb->version >= 0x15) { | ||
6588 | i2ctabptr = ROM16(dcbt[2]); | ||
6589 | } | ||
6590 | |||
6591 | if (!i2ctabptr) | ||
6592 | NV_WARN(dev, "No pointer to DCB I2C port table\n"); | ||
6593 | else { | ||
6594 | dcb->i2c_table = &bios->data[i2ctabptr]; | ||
6595 | if (dcb->version >= 0x30) | ||
6596 | dcb->i2c_default_indices = dcb->i2c_table[4]; | ||
6597 | |||
6598 | /* | ||
6599 | * Parse the "management" I2C bus, used for hardware | ||
6600 | * monitoring and some external TMDS transmitters. | ||
6601 | */ | ||
6602 | if (dcb->version >= 0x22) { | ||
6603 | int idx = (dcb->version >= 0x40 ? | ||
6604 | dcb->i2c_default_indices & 0xf : 2); | ||
6605 | |||
6606 | read_dcb_i2c_entry(dev, dcb->version, dcb->i2c_table, | ||
6607 | idx, &dcb->i2c[idx]); | ||
6608 | } | ||
6609 | } | 6472 | } |
6610 | 6473 | ||
6611 | dcb_outp_foreach(dev, NULL, parse_dcb_entry); | 6474 | dcb_outp_foreach(dev, NULL, parse_dcb_entry); |
@@ -6893,19 +6756,6 @@ nouveau_run_vbios_init(struct drm_device *dev) | |||
6893 | return ret; | 6756 | return ret; |
6894 | } | 6757 | } |
6895 | 6758 | ||
6896 | static void | ||
6897 | nouveau_bios_i2c_devices_takedown(struct drm_device *dev) | ||
6898 | { | ||
6899 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
6900 | struct nvbios *bios = &dev_priv->vbios; | ||
6901 | struct dcb_i2c_entry *entry; | ||
6902 | int i; | ||
6903 | |||
6904 | entry = &bios->dcb.i2c[0]; | ||
6905 | for (i = 0; i < DCB_MAX_NUM_I2C_ENTRIES; i++, entry++) | ||
6906 | nouveau_i2c_fini(dev, entry); | ||
6907 | } | ||
6908 | |||
6909 | static bool | 6759 | static bool |
6910 | nouveau_bios_posted(struct drm_device *dev) | 6760 | nouveau_bios_posted(struct drm_device *dev) |
6911 | { | 6761 | { |
@@ -6942,6 +6792,10 @@ nouveau_bios_init(struct drm_device *dev) | |||
6942 | if (ret) | 6792 | if (ret) |
6943 | return ret; | 6793 | return ret; |
6944 | 6794 | ||
6795 | ret = nouveau_i2c_init(dev); | ||
6796 | if (ret) | ||
6797 | return ret; | ||
6798 | |||
6945 | ret = parse_dcb_table(dev, bios); | 6799 | ret = parse_dcb_table(dev, bios); |
6946 | if (ret) | 6800 | if (ret) |
6947 | return ret; | 6801 | return ret; |
@@ -6984,5 +6838,5 @@ nouveau_bios_init(struct drm_device *dev) | |||
6984 | void | 6838 | void |
6985 | nouveau_bios_takedown(struct drm_device *dev) | 6839 | nouveau_bios_takedown(struct drm_device *dev) |
6986 | { | 6840 | { |
6987 | nouveau_bios_i2c_devices_takedown(dev); | 6841 | nouveau_i2c_fini(dev); |
6988 | } | 6842 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.h b/drivers/gpu/drm/nouveau/nouveau_bios.h index b9f2da394f89..a0e9c2c7ae8c 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.h +++ b/drivers/gpu/drm/nouveau/nouveau_bios.h | |||
@@ -53,13 +53,6 @@ struct bit_entry { | |||
53 | 53 | ||
54 | int bit_table(struct drm_device *, u8 id, struct bit_entry *); | 54 | int bit_table(struct drm_device *, u8 id, struct bit_entry *); |
55 | 55 | ||
56 | struct dcb_i2c_entry { | ||
57 | uint32_t entry; | ||
58 | uint8_t port_type; | ||
59 | uint8_t read, write; | ||
60 | struct nouveau_i2c_chan *chan; | ||
61 | }; | ||
62 | |||
63 | enum dcb_gpio_tag { | 56 | enum dcb_gpio_tag { |
64 | DCB_GPIO_TVDAC0 = 0xc, | 57 | DCB_GPIO_TVDAC0 = 0xc, |
65 | DCB_GPIO_TVDAC1 = 0x2d, | 58 | DCB_GPIO_TVDAC1 = 0x2d, |
@@ -166,10 +159,6 @@ struct dcb_table { | |||
166 | int entries; | 159 | int entries; |
167 | struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; | 160 | struct dcb_entry entry[DCB_MAX_NUM_ENTRIES]; |
168 | 161 | ||
169 | uint8_t *i2c_table; | ||
170 | uint8_t i2c_default_indices; | ||
171 | struct dcb_i2c_entry i2c[DCB_MAX_NUM_I2C_ENTRIES]; | ||
172 | |||
173 | uint16_t gpio_table_ptr; | 162 | uint16_t gpio_table_ptr; |
174 | struct dcb_gpio_table gpio; | 163 | struct dcb_gpio_table gpio; |
175 | uint16_t connector_table_ptr; | 164 | uint16_t connector_table_ptr; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 446caedbcff9..fb126c1508b5 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -793,6 +793,7 @@ struct drm_nouveau_private { | |||
793 | struct nouveau_vm *chan_vm; | 793 | struct nouveau_vm *chan_vm; |
794 | 794 | ||
795 | struct nvbios vbios; | 795 | struct nvbios vbios; |
796 | struct list_head i2c_ports; | ||
796 | 797 | ||
797 | struct nv04_mode_state mode_reg; | 798 | struct nv04_mode_state mode_reg; |
798 | struct nv04_mode_state saved_reg; | 799 | struct nv04_mode_state saved_reg; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.c b/drivers/gpu/drm/nouveau/nouveau_i2c.c index d39b2202b197..36ffcb84f55a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.c +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.c | |||
@@ -109,13 +109,6 @@ nv4e_i2c_getsda(void *data) | |||
109 | return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); | 109 | return !!((nv_rd32(dev, i2c->rd) >> 16) & 8); |
110 | } | 110 | } |
111 | 111 | ||
112 | static const uint32_t nv50_i2c_port[] = { | ||
113 | 0x00e138, 0x00e150, 0x00e168, 0x00e180, | ||
114 | 0x00e254, 0x00e274, 0x00e764, 0x00e780, | ||
115 | 0x00e79c, 0x00e7b8 | ||
116 | }; | ||
117 | #define NV50_I2C_PORTS ARRAY_SIZE(nv50_i2c_port) | ||
118 | |||
119 | static int | 112 | static int |
120 | nv50_i2c_getscl(void *data) | 113 | nv50_i2c_getscl(void *data) |
121 | { | 114 | { |
@@ -125,7 +118,6 @@ nv50_i2c_getscl(void *data) | |||
125 | return !!(nv_rd32(dev, i2c->rd) & 1); | 118 | return !!(nv_rd32(dev, i2c->rd) & 1); |
126 | } | 119 | } |
127 | 120 | ||
128 | |||
129 | static int | 121 | static int |
130 | nv50_i2c_getsda(void *data) | 122 | nv50_i2c_getsda(void *data) |
131 | { | 123 | { |
@@ -166,125 +158,233 @@ nvd0_i2c_getsda(void *data) | |||
166 | return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); | 158 | return !!(nv_rd32(i2c->dev, i2c->rd) & 0x20); |
167 | } | 159 | } |
168 | 160 | ||
161 | static const uint32_t nv50_i2c_port[] = { | ||
162 | 0x00e138, 0x00e150, 0x00e168, 0x00e180, | ||
163 | 0x00e254, 0x00e274, 0x00e764, 0x00e780, | ||
164 | 0x00e79c, 0x00e7b8 | ||
165 | }; | ||
166 | |||
167 | static u8 * | ||
168 | i2c_table(struct drm_device *dev, u8 *version) | ||
169 | { | ||
170 | u8 *dcb = dcb_table(dev), *i2c = NULL; | ||
171 | if (dcb) { | ||
172 | if (dcb[0] >= 0x15) | ||
173 | i2c = ROMPTR(dev, dcb[2]); | ||
174 | if (dcb[0] >= 0x30) | ||
175 | i2c = ROMPTR(dev, dcb[4]); | ||
176 | } | ||
177 | |||
178 | /* early revisions had no version number, use dcb version */ | ||
179 | if (i2c) { | ||
180 | *version = dcb[0]; | ||
181 | if (*version >= 0x30) | ||
182 | *version = i2c[0]; | ||
183 | } | ||
184 | |||
185 | return i2c; | ||
186 | } | ||
187 | |||
169 | int | 188 | int |
170 | nouveau_i2c_init(struct drm_device *dev, struct dcb_i2c_entry *entry, int index) | 189 | nouveau_i2c_init(struct drm_device *dev) |
171 | { | 190 | { |
172 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 191 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
173 | struct nouveau_i2c_chan *i2c; | 192 | struct nvbios *bios = &dev_priv->vbios; |
174 | int ret; | 193 | struct nouveau_i2c_chan *port; |
175 | 194 | u8 *i2c, *entry, legacy[2][4] = {}; | |
176 | if (entry->chan) | 195 | u8 version, entries, recordlen; |
177 | return -EEXIST; | 196 | int ret, i; |
197 | |||
198 | INIT_LIST_HEAD(&dev_priv->i2c_ports); | ||
199 | |||
200 | i2c = i2c_table(dev, &version); | ||
201 | if (!i2c) { | ||
202 | u8 *bmp = &bios->data[bios->offset]; | ||
203 | if (bios->type != NVBIOS_BMP) | ||
204 | return -ENODEV; | ||
205 | |||
206 | legacy[0][0] = NV_CIO_CRE_DDC_WR__INDEX; | ||
207 | legacy[0][1] = NV_CIO_CRE_DDC_STATUS__INDEX; | ||
208 | legacy[1][0] = NV_CIO_CRE_DDC0_WR__INDEX; | ||
209 | legacy[1][1] = NV_CIO_CRE_DDC0_STATUS__INDEX; | ||
210 | |||
211 | /* BMP (from v4.0) has i2c info in the structure, it's in a | ||
212 | * fixed location on earlier VBIOS | ||
213 | */ | ||
214 | if (bmp[5] < 4) | ||
215 | i2c = &bios->data[0x48]; | ||
216 | else | ||
217 | i2c = &bmp[0x36]; | ||
218 | |||
219 | if (i2c[4]) legacy[0][0] = i2c[4]; | ||
220 | if (i2c[5]) legacy[0][1] = i2c[5]; | ||
221 | if (i2c[6]) legacy[1][0] = i2c[6]; | ||
222 | if (i2c[7]) legacy[1][1] = i2c[7]; | ||
223 | } | ||
178 | 224 | ||
179 | if (dev_priv->card_type >= NV_50 && | 225 | if (i2c && version >= 0x30) { |
180 | dev_priv->card_type <= NV_C0 && entry->read >= NV50_I2C_PORTS) { | 226 | entry = i2c[1] + i2c; |
181 | NV_ERROR(dev, "unknown i2c port %d\n", entry->read); | 227 | entries = i2c[2]; |
182 | return -EINVAL; | 228 | recordlen = i2c[3]; |
229 | } else | ||
230 | if (i2c) { | ||
231 | entry = i2c; | ||
232 | entries = 16; | ||
233 | recordlen = 4; | ||
234 | } else { | ||
235 | entry = legacy[0]; | ||
236 | entries = 2; | ||
237 | recordlen = 4; | ||
183 | } | 238 | } |
184 | 239 | ||
185 | i2c = kzalloc(sizeof(*i2c), GFP_KERNEL); | 240 | for (i = 0; i < entries; i++, entry += recordlen) { |
186 | if (i2c == NULL) | 241 | port = kzalloc(sizeof(*port), GFP_KERNEL); |
187 | return -ENOMEM; | 242 | if (port == NULL) { |
188 | 243 | nouveau_i2c_fini(dev); | |
189 | switch (entry->port_type) { | 244 | return -ENOMEM; |
190 | case 0: | 245 | } |
191 | i2c->bit.setsda = nv04_i2c_setsda; | 246 | |
192 | i2c->bit.setscl = nv04_i2c_setscl; | 247 | port->type = entry[3]; |
193 | i2c->bit.getsda = nv04_i2c_getsda; | 248 | if (version < 0x30) { |
194 | i2c->bit.getscl = nv04_i2c_getscl; | 249 | port->type &= 0x07; |
195 | i2c->rd = entry->read; | 250 | if (port->type == 0x07) |
196 | i2c->wr = entry->write; | 251 | port->type = 0xff; |
197 | break; | 252 | } |
198 | case 4: | 253 | |
199 | i2c->bit.setsda = nv4e_i2c_setsda; | 254 | if (port->type == 0xff) { |
200 | i2c->bit.setscl = nv4e_i2c_setscl; | 255 | kfree(port); |
201 | i2c->bit.getsda = nv4e_i2c_getsda; | 256 | continue; |
202 | i2c->bit.getscl = nv4e_i2c_getscl; | 257 | } |
203 | i2c->rd = 0x600800 + entry->read; | 258 | |
204 | i2c->wr = 0x600800 + entry->write; | 259 | switch (port->type) { |
205 | break; | 260 | case 0: /* NV04:NV50 */ |
206 | case 5: | 261 | port->wr = entry[0]; |
207 | i2c->bit.setsda = nv50_i2c_setsda; | 262 | port->rd = entry[1]; |
208 | i2c->bit.setscl = nv50_i2c_setscl; | 263 | port->bit.setsda = nv04_i2c_setsda; |
209 | if (dev_priv->card_type < NV_D0) { | 264 | port->bit.setscl = nv04_i2c_setscl; |
210 | i2c->bit.getsda = nv50_i2c_getsda; | 265 | port->bit.getsda = nv04_i2c_getsda; |
211 | i2c->bit.getscl = nv50_i2c_getscl; | 266 | port->bit.getscl = nv04_i2c_getscl; |
212 | i2c->rd = nv50_i2c_port[entry->read]; | 267 | break; |
213 | i2c->wr = i2c->rd; | 268 | case 4: /* NV4E */ |
269 | port->wr = 0x600800 + entry[1]; | ||
270 | port->rd = port->wr; | ||
271 | port->bit.setsda = nv4e_i2c_setsda; | ||
272 | port->bit.setscl = nv4e_i2c_setscl; | ||
273 | port->bit.getsda = nv4e_i2c_getsda; | ||
274 | port->bit.getscl = nv4e_i2c_getscl; | ||
275 | break; | ||
276 | case 5: /* NV50- */ | ||
277 | port->wr = entry[0] & 0x0f; | ||
278 | if (dev_priv->card_type < NV_D0) { | ||
279 | if (port->wr >= ARRAY_SIZE(nv50_i2c_port)) | ||
280 | break; | ||
281 | port->wr = nv50_i2c_port[port->wr]; | ||
282 | port->rd = port->wr; | ||
283 | port->bit.getsda = nv50_i2c_getsda; | ||
284 | port->bit.getscl = nv50_i2c_getscl; | ||
285 | } else { | ||
286 | port->wr = 0x00d014 + (port->wr * 0x20); | ||
287 | port->rd = port->wr; | ||
288 | port->bit.getsda = nvd0_i2c_getsda; | ||
289 | port->bit.getscl = nvd0_i2c_getscl; | ||
290 | } | ||
291 | port->bit.setsda = nv50_i2c_setsda; | ||
292 | port->bit.setscl = nv50_i2c_setscl; | ||
293 | break; | ||
294 | case 6: /* NV50- DP AUX */ | ||
295 | port->wr = entry[0]; | ||
296 | port->rd = port->wr; | ||
297 | port->adapter.algo = &nouveau_dp_i2c_algo; | ||
298 | break; | ||
299 | default: | ||
300 | break; | ||
301 | } | ||
302 | |||
303 | if (!port->adapter.algo && !port->wr) { | ||
304 | NV_ERROR(dev, "I2C%d: type %d index %x/%x unknown\n", | ||
305 | i, port->type, port->wr, port->rd); | ||
306 | kfree(port); | ||
307 | continue; | ||
308 | } | ||
309 | |||
310 | snprintf(port->adapter.name, sizeof(port->adapter.name), | ||
311 | "nouveau-%s-%d", pci_name(dev->pdev), i); | ||
312 | port->adapter.owner = THIS_MODULE; | ||
313 | port->adapter.dev.parent = &dev->pdev->dev; | ||
314 | port->dev = dev; | ||
315 | port->index = i; | ||
316 | port->dcb = ROM32(entry[0]); | ||
317 | i2c_set_adapdata(&port->adapter, i2c); | ||
318 | |||
319 | if (port->adapter.algo != &nouveau_dp_i2c_algo) { | ||
320 | port->adapter.algo_data = &port->bit; | ||
321 | port->bit.udelay = 40; | ||
322 | port->bit.timeout = usecs_to_jiffies(5000); | ||
323 | port->bit.data = port; | ||
324 | ret = i2c_bit_add_bus(&port->adapter); | ||
214 | } else { | 325 | } else { |
215 | i2c->bit.getsda = nvd0_i2c_getsda; | 326 | port->adapter.algo = &nouveau_dp_i2c_algo; |
216 | i2c->bit.getscl = nvd0_i2c_getscl; | 327 | ret = i2c_add_adapter(&port->adapter); |
217 | i2c->rd = 0x00d014 + (entry->read * 0x20); | ||
218 | i2c->wr = i2c->rd; | ||
219 | } | 328 | } |
220 | break; | ||
221 | case 6: | ||
222 | i2c->rd = entry->read; | ||
223 | i2c->wr = entry->write; | ||
224 | break; | ||
225 | default: | ||
226 | NV_ERROR(dev, "DCB I2C port type %d unknown\n", | ||
227 | entry->port_type); | ||
228 | kfree(i2c); | ||
229 | return -EINVAL; | ||
230 | } | ||
231 | 329 | ||
232 | snprintf(i2c->adapter.name, sizeof(i2c->adapter.name), | 330 | if (ret) { |
233 | "nouveau-%s-%d", pci_name(dev->pdev), index); | 331 | NV_ERROR(dev, "I2C%d: failed register: %d\n", i, ret); |
234 | i2c->adapter.owner = THIS_MODULE; | 332 | kfree(port); |
235 | i2c->adapter.dev.parent = &dev->pdev->dev; | 333 | continue; |
236 | i2c->dev = dev; | 334 | } |
237 | i2c_set_adapdata(&i2c->adapter, i2c); | ||
238 | |||
239 | if (entry->port_type < 6) { | ||
240 | i2c->adapter.algo_data = &i2c->bit; | ||
241 | i2c->bit.udelay = 40; | ||
242 | i2c->bit.timeout = usecs_to_jiffies(5000); | ||
243 | i2c->bit.data = i2c; | ||
244 | ret = i2c_bit_add_bus(&i2c->adapter); | ||
245 | } else { | ||
246 | i2c->adapter.algo = &nouveau_dp_i2c_algo; | ||
247 | ret = i2c_add_adapter(&i2c->adapter); | ||
248 | } | ||
249 | 335 | ||
250 | if (ret) { | 336 | list_add_tail(&port->head, &dev_priv->i2c_ports); |
251 | NV_ERROR(dev, "Failed to register i2c %d\n", index); | ||
252 | kfree(i2c); | ||
253 | return ret; | ||
254 | } | 337 | } |
255 | 338 | ||
256 | entry->chan = i2c; | ||
257 | return 0; | 339 | return 0; |
258 | } | 340 | } |
259 | 341 | ||
260 | void | 342 | void |
261 | nouveau_i2c_fini(struct drm_device *dev, struct dcb_i2c_entry *entry) | 343 | nouveau_i2c_fini(struct drm_device *dev) |
262 | { | 344 | { |
263 | if (!entry->chan) | 345 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
264 | return; | 346 | struct nouveau_i2c_chan *port, *tmp; |
265 | 347 | ||
266 | i2c_del_adapter(&entry->chan->adapter); | 348 | list_for_each_entry_safe(port, tmp, &dev_priv->i2c_ports, head) { |
267 | kfree(entry->chan); | 349 | i2c_del_adapter(&port->adapter); |
268 | entry->chan = NULL; | 350 | kfree(port); |
351 | } | ||
269 | } | 352 | } |
270 | 353 | ||
271 | struct nouveau_i2c_chan * | 354 | struct nouveau_i2c_chan * |
272 | nouveau_i2c_find(struct drm_device *dev, int index) | 355 | nouveau_i2c_find(struct drm_device *dev, u8 index) |
273 | { | 356 | { |
274 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 357 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
275 | struct dcb_i2c_entry *i2c = &dev_priv->vbios.dcb.i2c[index]; | 358 | struct nouveau_i2c_chan *port; |
359 | |||
360 | if (index == NV_I2C_DEFAULT(0) || | ||
361 | index == NV_I2C_DEFAULT(1)) { | ||
362 | u8 version, *i2c = i2c_table(dev, &version); | ||
363 | if (i2c && version >= 0x30) { | ||
364 | if (index == NV_I2C_DEFAULT(0)) | ||
365 | index = (i2c[4] & 0x0f); | ||
366 | else | ||
367 | index = (i2c[4] & 0xf0) >> 4; | ||
368 | } else { | ||
369 | index = 2; | ||
370 | } | ||
371 | } | ||
276 | 372 | ||
277 | if (index >= DCB_MAX_NUM_I2C_ENTRIES) | 373 | list_for_each_entry(port, &dev_priv->i2c_ports, head) { |
278 | return NULL; | 374 | if (port->index == index) |
375 | break; | ||
376 | } | ||
279 | 377 | ||
280 | if (dev_priv->card_type >= NV_50 && (i2c->entry & 0x00000100)) { | 378 | if (&port->head == &dev_priv->i2c_ports) |
281 | uint32_t reg = 0xe500, val; | 379 | return NULL; |
282 | 380 | ||
283 | if (i2c->port_type == 6) { | 381 | if (dev_priv->card_type >= NV_50 && (port->dcb & 0x00000100)) { |
284 | reg += i2c->read * 0x50; | 382 | u32 reg = 0x00e500, val; |
383 | if (port->type == 6) { | ||
384 | reg += port->rd * 0x50; | ||
285 | val = 0x2002; | 385 | val = 0x2002; |
286 | } else { | 386 | } else { |
287 | reg += ((i2c->entry & 0x1e00) >> 9) * 0x50; | 387 | reg += ((port->dcb & 0x1e00) >> 9) * 0x50; |
288 | val = 0xe001; | 388 | val = 0xe001; |
289 | } | 389 | } |
290 | 390 | ||
@@ -294,9 +394,7 @@ nouveau_i2c_find(struct drm_device *dev, int index) | |||
294 | nv_mask(dev, reg + 0x00, 0x0000f003, val); | 394 | nv_mask(dev, reg + 0x00, 0x0000f003, val); |
295 | } | 395 | } |
296 | 396 | ||
297 | if (!i2c->chan && nouveau_i2c_init(dev, i2c, index)) | 397 | return port; |
298 | return NULL; | ||
299 | return i2c->chan; | ||
300 | } | 398 | } |
301 | 399 | ||
302 | bool | 400 | bool |
diff --git a/drivers/gpu/drm/nouveau/nouveau_i2c.h b/drivers/gpu/drm/nouveau/nouveau_i2c.h index 422b62fd8272..cf5f67d51fba 100644 --- a/drivers/gpu/drm/nouveau/nouveau_i2c.h +++ b/drivers/gpu/drm/nouveau/nouveau_i2c.h | |||
@@ -27,20 +27,26 @@ | |||
27 | #include <linux/i2c-algo-bit.h> | 27 | #include <linux/i2c-algo-bit.h> |
28 | #include "drm_dp_helper.h" | 28 | #include "drm_dp_helper.h" |
29 | 29 | ||
30 | struct dcb_i2c_entry; | 30 | #define NV_I2C_PORT(n) (0x00 + (n)) |
31 | #define NV_I2C_PORT_NUM 0x10 | ||
32 | #define NV_I2C_DEFAULT(n) (0x80 + (n)) | ||
31 | 33 | ||
32 | struct nouveau_i2c_chan { | 34 | struct nouveau_i2c_chan { |
33 | struct i2c_adapter adapter; | 35 | struct i2c_adapter adapter; |
34 | struct drm_device *dev; | 36 | struct drm_device *dev; |
35 | struct i2c_algo_bit_data bit; | 37 | struct i2c_algo_bit_data bit; |
38 | struct list_head head; | ||
39 | u8 index; | ||
40 | u8 type; | ||
41 | u32 dcb; | ||
36 | unsigned rd; | 42 | unsigned rd; |
37 | unsigned wr; | 43 | unsigned wr; |
38 | unsigned data; | 44 | unsigned data; |
39 | }; | 45 | }; |
40 | 46 | ||
41 | int nouveau_i2c_init(struct drm_device *, struct dcb_i2c_entry *, int index); | 47 | int nouveau_i2c_init(struct drm_device *); |
42 | void nouveau_i2c_fini(struct drm_device *, struct dcb_i2c_entry *); | 48 | void nouveau_i2c_fini(struct drm_device *); |
43 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, int index); | 49 | struct nouveau_i2c_chan *nouveau_i2c_find(struct drm_device *, u8 index); |
44 | bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); | 50 | bool nouveau_probe_i2c_addr(struct nouveau_i2c_chan *i2c, int addr); |
45 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, | 51 | int nouveau_i2c_identify(struct drm_device *dev, const char *what, |
46 | struct i2c_board_info *info, | 52 | struct i2c_board_info *info, |
diff --git a/drivers/gpu/drm/nouveau/nouveau_temp.c b/drivers/gpu/drm/nouveau/nouveau_temp.c index 4c46adeb0715..0f5a30160556 100644 --- a/drivers/gpu/drm/nouveau/nouveau_temp.c +++ b/drivers/gpu/drm/nouveau/nouveau_temp.c | |||
@@ -286,8 +286,6 @@ probe_monitoring_device(struct nouveau_i2c_chan *i2c, | |||
286 | static void | 286 | static void |
287 | nouveau_temp_probe_i2c(struct drm_device *dev) | 287 | nouveau_temp_probe_i2c(struct drm_device *dev) |
288 | { | 288 | { |
289 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
290 | struct dcb_table *dcb = &dev_priv->vbios.dcb; | ||
291 | struct i2c_board_info info[] = { | 289 | struct i2c_board_info info[] = { |
292 | { I2C_BOARD_INFO("w83l785ts", 0x2d) }, | 290 | { I2C_BOARD_INFO("w83l785ts", 0x2d) }, |
293 | { I2C_BOARD_INFO("w83781d", 0x2d) }, | 291 | { I2C_BOARD_INFO("w83781d", 0x2d) }, |
@@ -296,11 +294,9 @@ nouveau_temp_probe_i2c(struct drm_device *dev) | |||
296 | { I2C_BOARD_INFO("lm99", 0x4c) }, | 294 | { I2C_BOARD_INFO("lm99", 0x4c) }, |
297 | { } | 295 | { } |
298 | }; | 296 | }; |
299 | int idx = (dcb->version >= 0x40 ? | ||
300 | dcb->i2c_default_indices & 0xf : 2); | ||
301 | 297 | ||
302 | nouveau_i2c_identify(dev, "monitoring device", info, | 298 | nouveau_i2c_identify(dev, "monitoring device", info, |
303 | probe_monitoring_device, idx); | 299 | probe_monitoring_device, NV_I2C_DEFAULT(0)); |
304 | } | 300 | } |
305 | 301 | ||
306 | void | 302 | void |