diff options
author | Ben Skeggs <bskeggs@redhat.com> | 2010-09-19 20:06:50 -0400 |
---|---|---|
committer | Ben Skeggs <bskeggs@redhat.com> | 2010-09-24 02:27:54 -0400 |
commit | e49f70f775335ab1ee0ecd54904d2b25982a2600 (patch) | |
tree | 1cd1a9f021caccf7eaba7a736c300c2ffad2452e /drivers/gpu/drm/nouveau/nouveau_bios.c | |
parent | 07b1266962085412e85af2e7df471ec9ed0c35f5 (diff) |
drm/nouveau: implement parsing of DCB 2.2 GPIO table
Found on NV3x boards, this should allow voltage modifications to work
on these chipsets.
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bios.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 156 |
1 files changed, 63 insertions, 93 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 07171dd3c16..8d60bfdf6c7 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -5762,8 +5762,14 @@ static uint16_t findstr(uint8_t *data, int n, const uint8_t *str, int len) | |||
5762 | static struct dcb_gpio_entry * | 5762 | static struct dcb_gpio_entry * |
5763 | new_gpio_entry(struct nvbios *bios) | 5763 | new_gpio_entry(struct nvbios *bios) |
5764 | { | 5764 | { |
5765 | struct drm_device *dev = bios->dev; | ||
5765 | struct dcb_gpio_table *gpio = &bios->dcb.gpio; | 5766 | struct dcb_gpio_table *gpio = &bios->dcb.gpio; |
5766 | 5767 | ||
5768 | if (gpio->entries >= DCB_MAX_NUM_GPIO_ENTRIES) { | ||
5769 | NV_ERROR(dev, "exceeded maximum number of gpio entries!!\n"); | ||
5770 | return NULL; | ||
5771 | } | ||
5772 | |||
5767 | return &gpio->entry[gpio->entries++]; | 5773 | return &gpio->entry[gpio->entries++]; |
5768 | } | 5774 | } |
5769 | 5775 | ||
@@ -5785,113 +5791,77 @@ nouveau_bios_gpio_entry(struct drm_device *dev, enum dcb_gpio_tag tag) | |||
5785 | } | 5791 | } |
5786 | 5792 | ||
5787 | static void | 5793 | static void |
5788 | parse_dcb30_gpio_entry(struct nvbios *bios, uint16_t offset) | ||
5789 | { | ||
5790 | struct dcb_gpio_entry *gpio; | ||
5791 | uint16_t ent = ROM16(bios->data[offset]); | ||
5792 | uint8_t line = ent & 0x1f, | ||
5793 | tag = ent >> 5 & 0x3f, | ||
5794 | flags = ent >> 11 & 0x1f; | ||
5795 | |||
5796 | if (tag == 0x3f) | ||
5797 | return; | ||
5798 | |||
5799 | gpio = new_gpio_entry(bios); | ||
5800 | |||
5801 | gpio->tag = tag; | ||
5802 | gpio->line = line; | ||
5803 | gpio->invert = flags != 4; | ||
5804 | gpio->entry = ent; | ||
5805 | } | ||
5806 | |||
5807 | static void | ||
5808 | parse_dcb40_gpio_entry(struct nvbios *bios, uint16_t offset) | ||
5809 | { | ||
5810 | uint32_t entry = ROM32(bios->data[offset]); | ||
5811 | struct dcb_gpio_entry *gpio; | ||
5812 | |||
5813 | if ((entry & 0x0000ff00) == 0x0000ff00) | ||
5814 | return; | ||
5815 | |||
5816 | gpio = new_gpio_entry(bios); | ||
5817 | gpio->tag = (entry & 0x0000ff00) >> 8; | ||
5818 | gpio->line = (entry & 0x0000001f) >> 0; | ||
5819 | gpio->state_default = (entry & 0x01000000) >> 24; | ||
5820 | gpio->state[0] = (entry & 0x18000000) >> 27; | ||
5821 | gpio->state[1] = (entry & 0x60000000) >> 29; | ||
5822 | gpio->entry = entry; | ||
5823 | } | ||
5824 | |||
5825 | static void | ||
5826 | parse_dcb_gpio_table(struct nvbios *bios) | 5794 | parse_dcb_gpio_table(struct nvbios *bios) |
5827 | { | 5795 | { |
5828 | struct drm_device *dev = bios->dev; | 5796 | struct drm_device *dev = bios->dev; |
5829 | uint16_t gpio_table_ptr = bios->dcb.gpio_table_ptr; | 5797 | struct dcb_gpio_entry *e; |
5830 | uint8_t *gpio_table = &bios->data[gpio_table_ptr]; | 5798 | u8 headerlen, entries, recordlen; |
5831 | int header_len = gpio_table[1], | 5799 | u8 *dcb, *gpio = NULL, *entry; |
5832 | entries = gpio_table[2], | ||
5833 | entry_len = gpio_table[3]; | ||
5834 | void (*parse_entry)(struct nvbios *, uint16_t) = NULL; | ||
5835 | int i; | 5800 | int i; |
5836 | 5801 | ||
5837 | if (bios->dcb.version >= 0x40) { | 5802 | dcb = ROMPTR(bios, bios->data[0x36]); |
5838 | if (gpio_table_ptr && entry_len != 4) { | 5803 | if (dcb[0] >= 0x30) { |
5839 | NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); | 5804 | gpio = ROMPTR(bios, dcb[10]); |
5840 | return; | 5805 | if (!gpio) |
5841 | } | 5806 | goto no_table; |
5842 | |||
5843 | parse_entry = parse_dcb40_gpio_entry; | ||
5844 | |||
5845 | } else if (bios->dcb.version >= 0x30) { | ||
5846 | if (gpio_table_ptr && entry_len != 2) { | ||
5847 | NV_WARN(dev, "Invalid DCB GPIO table entry length.\n"); | ||
5848 | return; | ||
5849 | } | ||
5850 | |||
5851 | parse_entry = parse_dcb30_gpio_entry; | ||
5852 | 5807 | ||
5853 | } else if (bios->dcb.version >= 0x22) { | 5808 | headerlen = gpio[1]; |
5854 | /* | 5809 | entries = gpio[2]; |
5855 | * DCBs older than v3.0 don't really have a GPIO | 5810 | recordlen = gpio[3]; |
5856 | * table, instead they keep some GPIO info at fixed | 5811 | } else |
5857 | * locations. | 5812 | if (dcb[0] >= 0x22) { |
5858 | */ | 5813 | gpio = ROMPTR(bios, dcb[-15]); |
5859 | uint16_t dcbptr = ROM16(bios->data[0x36]); | 5814 | if (!gpio) |
5860 | uint8_t *tvdac_gpio = &bios->data[dcbptr - 5]; | 5815 | goto no_table; |
5816 | |||
5817 | headerlen = 3; | ||
5818 | entries = gpio[2]; | ||
5819 | recordlen = gpio[1]; | ||
5820 | } else { | ||
5821 | NV_DEBUG(dev, "no/unknown gpio table on DCB 0x%02x\n", dcb[0]); | ||
5822 | goto no_table; | ||
5823 | } | ||
5861 | 5824 | ||
5862 | if (tvdac_gpio[0] & 1) { | 5825 | entry = gpio + headerlen; |
5863 | struct dcb_gpio_entry *gpio = new_gpio_entry(bios); | 5826 | for (i = 0; i < entries; i++, entry += recordlen) { |
5827 | e = new_gpio_entry(bios); | ||
5828 | if (!e) | ||
5829 | break; | ||
5864 | 5830 | ||
5865 | gpio->tag = DCB_GPIO_TVDAC0; | 5831 | if (gpio[0] < 0x40) { |
5866 | gpio->line = tvdac_gpio[1] >> 4; | 5832 | e->entry = ROM16(entry[0]); |
5867 | gpio->invert = tvdac_gpio[0] & 2; | 5833 | e->tag = (e->entry & 0x07e0) >> 5; |
5868 | } | 5834 | if (e->tag == 0x3f) { |
5869 | } else { | 5835 | bios->dcb.gpio.entries--; |
5870 | /* | 5836 | continue; |
5871 | * No systematic way to store GPIO info on pre-v2.2 | 5837 | } |
5872 | * DCBs, try to match the PCI device IDs. | ||
5873 | */ | ||
5874 | 5838 | ||
5875 | /* Apple iMac G4 NV18 */ | 5839 | e->line = (e->entry & 0x001f); |
5876 | if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { | 5840 | e->invert = ((e->entry & 0xf800) >> 11) != 4; |
5877 | struct dcb_gpio_entry *gpio = new_gpio_entry(bios); | 5841 | } else { |
5842 | e->entry = ROM32(entry[0]); | ||
5843 | e->tag = (e->entry & 0x0000ff00) >> 8; | ||
5844 | if (e->tag == 0xff) { | ||
5845 | bios->dcb.gpio.entries--; | ||
5846 | continue; | ||
5847 | } | ||
5878 | 5848 | ||
5879 | gpio->tag = DCB_GPIO_TVDAC0; | 5849 | e->line = (e->entry & 0x0000001f) >> 0; |
5880 | gpio->line = 4; | 5850 | e->state_default = (e->entry & 0x01000000) >> 24; |
5851 | e->state[0] = (e->entry & 0x18000000) >> 27; | ||
5852 | e->state[1] = (e->entry & 0x60000000) >> 29; | ||
5881 | } | 5853 | } |
5882 | |||
5883 | } | 5854 | } |
5884 | 5855 | ||
5885 | if (!gpio_table_ptr) | 5856 | no_table: |
5886 | return; | 5857 | /* Apple iMac G4 NV18 */ |
5887 | 5858 | if (nv_match_device(dev, 0x0189, 0x10de, 0x0010)) { | |
5888 | if (entries > DCB_MAX_NUM_GPIO_ENTRIES) { | 5859 | e = new_gpio_entry(bios); |
5889 | NV_WARN(dev, "Too many entries in the DCB GPIO table.\n"); | 5860 | if (e) { |
5890 | entries = DCB_MAX_NUM_GPIO_ENTRIES; | 5861 | e->tag = DCB_GPIO_TVDAC0; |
5862 | e->line = 4; | ||
5863 | } | ||
5891 | } | 5864 | } |
5892 | |||
5893 | for (i = 0; i < entries; i++) | ||
5894 | parse_entry(bios, gpio_table_ptr + header_len + entry_len * i); | ||
5895 | } | 5865 | } |
5896 | 5866 | ||
5897 | struct dcb_connector_table_entry * | 5867 | struct dcb_connector_table_entry * |