diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nouveau_bios.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 96 |
1 files changed, 81 insertions, 15 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index e7e69ccce5c9..fc924b649195 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -178,6 +178,25 @@ out: | |||
178 | pci_disable_rom(dev->pdev); | 178 | pci_disable_rom(dev->pdev); |
179 | } | 179 | } |
180 | 180 | ||
181 | static void load_vbios_acpi(struct drm_device *dev, uint8_t *data) | ||
182 | { | ||
183 | int i; | ||
184 | int ret; | ||
185 | int size = 64 * 1024; | ||
186 | |||
187 | if (!nouveau_acpi_rom_supported(dev->pdev)) | ||
188 | return; | ||
189 | |||
190 | for (i = 0; i < (size / ROM_BIOS_PAGE); i++) { | ||
191 | ret = nouveau_acpi_get_bios_chunk(data, | ||
192 | (i * ROM_BIOS_PAGE), | ||
193 | ROM_BIOS_PAGE); | ||
194 | if (ret <= 0) | ||
195 | break; | ||
196 | } | ||
197 | return; | ||
198 | } | ||
199 | |||
181 | struct methods { | 200 | struct methods { |
182 | const char desc[8]; | 201 | const char desc[8]; |
183 | void (*loadbios)(struct drm_device *, uint8_t *); | 202 | void (*loadbios)(struct drm_device *, uint8_t *); |
@@ -191,6 +210,7 @@ static struct methods nv04_methods[] = { | |||
191 | }; | 210 | }; |
192 | 211 | ||
193 | static struct methods nv50_methods[] = { | 212 | static struct methods nv50_methods[] = { |
213 | { "ACPI", load_vbios_acpi, true }, | ||
194 | { "PRAMIN", load_vbios_pramin, true }, | 214 | { "PRAMIN", load_vbios_pramin, true }, |
195 | { "PROM", load_vbios_prom, false }, | 215 | { "PROM", load_vbios_prom, false }, |
196 | { "PCIROM", load_vbios_pci, true }, | 216 | { "PCIROM", load_vbios_pci, true }, |
@@ -814,7 +834,7 @@ init_i2c_device_find(struct drm_device *dev, int i2c_index) | |||
814 | if (i2c_index == 0x81) | 834 | if (i2c_index == 0x81) |
815 | i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; | 835 | i2c_index = (dcb->i2c_default_indices & 0xf0) >> 4; |
816 | 836 | ||
817 | if (i2c_index > DCB_MAX_NUM_I2C_ENTRIES) { | 837 | if (i2c_index >= DCB_MAX_NUM_I2C_ENTRIES) { |
818 | NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); | 838 | NV_ERROR(dev, "invalid i2c_index 0x%x\n", i2c_index); |
819 | return NULL; | 839 | return NULL; |
820 | } | 840 | } |
@@ -2807,7 +2827,10 @@ init_gpio(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) | |||
2807 | 2827 | ||
2808 | BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); | 2828 | BIOSLOG(bios, "0x%04X: Entry: 0x%08X\n", offset, gpio->entry); |
2809 | 2829 | ||
2810 | nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default); | 2830 | BIOSLOG(bios, "0x%04X: set gpio 0x%02x, state %d\n", |
2831 | offset, gpio->tag, gpio->state_default); | ||
2832 | if (bios->execute) | ||
2833 | nv50_gpio_set(bios->dev, gpio->tag, gpio->state_default); | ||
2811 | 2834 | ||
2812 | /* The NVIDIA binary driver doesn't appear to actually do | 2835 | /* The NVIDIA binary driver doesn't appear to actually do |
2813 | * any of this, my VBIOS does however. | 2836 | * any of this, my VBIOS does however. |
@@ -3897,7 +3920,8 @@ int nouveau_bios_parse_lvds_table(struct drm_device *dev, int pxclk, bool *dl, b | |||
3897 | 3920 | ||
3898 | static uint8_t * | 3921 | static uint8_t * |
3899 | bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, | 3922 | bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, |
3900 | uint16_t record, int record_len, int record_nr) | 3923 | uint16_t record, int record_len, int record_nr, |
3924 | bool match_link) | ||
3901 | { | 3925 | { |
3902 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 3926 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
3903 | struct nvbios *bios = &dev_priv->vbios; | 3927 | struct nvbios *bios = &dev_priv->vbios; |
@@ -3905,12 +3929,28 @@ bios_output_config_match(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3905 | uint16_t table; | 3929 | uint16_t table; |
3906 | int i, v; | 3930 | int i, v; |
3907 | 3931 | ||
3932 | switch (dcbent->type) { | ||
3933 | case OUTPUT_TMDS: | ||
3934 | case OUTPUT_LVDS: | ||
3935 | case OUTPUT_DP: | ||
3936 | break; | ||
3937 | default: | ||
3938 | match_link = false; | ||
3939 | break; | ||
3940 | } | ||
3941 | |||
3908 | for (i = 0; i < record_nr; i++, record += record_len) { | 3942 | for (i = 0; i < record_nr; i++, record += record_len) { |
3909 | table = ROM16(bios->data[record]); | 3943 | table = ROM16(bios->data[record]); |
3910 | if (!table) | 3944 | if (!table) |
3911 | continue; | 3945 | continue; |
3912 | entry = ROM32(bios->data[table]); | 3946 | entry = ROM32(bios->data[table]); |
3913 | 3947 | ||
3948 | if (match_link) { | ||
3949 | v = (entry & 0x00c00000) >> 22; | ||
3950 | if (!(v & dcbent->sorconf.link)) | ||
3951 | continue; | ||
3952 | } | ||
3953 | |||
3914 | v = (entry & 0x000f0000) >> 16; | 3954 | v = (entry & 0x000f0000) >> 16; |
3915 | if (!(v & dcbent->or)) | 3955 | if (!(v & dcbent->or)) |
3916 | continue; | 3956 | continue; |
@@ -3952,7 +3992,7 @@ nouveau_bios_dp_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
3952 | *length = table[4]; | 3992 | *length = table[4]; |
3953 | return bios_output_config_match(dev, dcbent, | 3993 | return bios_output_config_match(dev, dcbent, |
3954 | bios->display.dp_table_ptr + table[1], | 3994 | bios->display.dp_table_ptr + table[1], |
3955 | table[2], table[3]); | 3995 | table[2], table[3], table[0] >= 0x21); |
3956 | } | 3996 | } |
3957 | 3997 | ||
3958 | int | 3998 | int |
@@ -4041,7 +4081,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, | |||
4041 | dcbent->type, dcbent->location, dcbent->or); | 4081 | dcbent->type, dcbent->location, dcbent->or); |
4042 | otable = bios_output_config_match(dev, dcbent, table[1] + | 4082 | otable = bios_output_config_match(dev, dcbent, table[1] + |
4043 | bios->display.script_table_ptr, | 4083 | bios->display.script_table_ptr, |
4044 | table[2], table[3]); | 4084 | table[2], table[3], table[0] >= 0x21); |
4045 | if (!otable) { | 4085 | if (!otable) { |
4046 | NV_ERROR(dev, "Couldn't find matching output script table\n"); | 4086 | NV_ERROR(dev, "Couldn't find matching output script table\n"); |
4047 | return 1; | 4087 | return 1; |
@@ -5533,12 +5573,6 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
5533 | entry->bus = (conn >> 16) & 0xf; | 5573 | entry->bus = (conn >> 16) & 0xf; |
5534 | entry->location = (conn >> 20) & 0x3; | 5574 | entry->location = (conn >> 20) & 0x3; |
5535 | entry->or = (conn >> 24) & 0xf; | 5575 | entry->or = (conn >> 24) & 0xf; |
5536 | /* | ||
5537 | * Normal entries consist of a single bit, but dual link has the | ||
5538 | * next most significant bit set too | ||
5539 | */ | ||
5540 | entry->duallink_possible = | ||
5541 | ((1 << (ffs(entry->or) - 1)) * 3 == entry->or); | ||
5542 | 5576 | ||
5543 | switch (entry->type) { | 5577 | switch (entry->type) { |
5544 | case OUTPUT_ANALOG: | 5578 | case OUTPUT_ANALOG: |
@@ -5622,6 +5656,16 @@ parse_dcb20_entry(struct drm_device *dev, struct dcb_table *dcb, | |||
5622 | break; | 5656 | break; |
5623 | } | 5657 | } |
5624 | 5658 | ||
5659 | if (dcb->version < 0x40) { | ||
5660 | /* Normal entries consist of a single bit, but dual link has | ||
5661 | * the next most significant bit set too | ||
5662 | */ | ||
5663 | entry->duallink_possible = | ||
5664 | ((1 << (ffs(entry->or) - 1)) * 3 == entry->or); | ||
5665 | } else { | ||
5666 | entry->duallink_possible = (entry->sorconf.link == 3); | ||
5667 | } | ||
5668 | |||
5625 | /* unsure what DCB version introduces this, 3.0? */ | 5669 | /* unsure what DCB version introduces this, 3.0? */ |
5626 | if (conf & 0x100000) | 5670 | if (conf & 0x100000) |
5627 | entry->i2c_upper_default = true; | 5671 | entry->i2c_upper_default = true; |
@@ -6205,6 +6249,30 @@ nouveau_bios_i2c_devices_takedown(struct drm_device *dev) | |||
6205 | nouveau_i2c_fini(dev, entry); | 6249 | nouveau_i2c_fini(dev, entry); |
6206 | } | 6250 | } |
6207 | 6251 | ||
6252 | static bool | ||
6253 | nouveau_bios_posted(struct drm_device *dev) | ||
6254 | { | ||
6255 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
6256 | bool was_locked; | ||
6257 | unsigned htotal; | ||
6258 | |||
6259 | if (dev_priv->chipset >= NV_50) { | ||
6260 | if (NVReadVgaCrtc(dev, 0, 0x00) == 0 && | ||
6261 | NVReadVgaCrtc(dev, 0, 0x1a) == 0) | ||
6262 | return false; | ||
6263 | return true; | ||
6264 | } | ||
6265 | |||
6266 | was_locked = NVLockVgaCrtcs(dev, false); | ||
6267 | htotal = NVReadVgaCrtc(dev, 0, 0x06); | ||
6268 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x01) << 8; | ||
6269 | htotal |= (NVReadVgaCrtc(dev, 0, 0x07) & 0x20) << 4; | ||
6270 | htotal |= (NVReadVgaCrtc(dev, 0, 0x25) & 0x01) << 10; | ||
6271 | htotal |= (NVReadVgaCrtc(dev, 0, 0x41) & 0x01) << 11; | ||
6272 | NVLockVgaCrtcs(dev, was_locked); | ||
6273 | return (htotal != 0); | ||
6274 | } | ||
6275 | |||
6208 | int | 6276 | int |
6209 | nouveau_bios_init(struct drm_device *dev) | 6277 | nouveau_bios_init(struct drm_device *dev) |
6210 | { | 6278 | { |
@@ -6239,11 +6307,9 @@ nouveau_bios_init(struct drm_device *dev) | |||
6239 | bios->execute = false; | 6307 | bios->execute = false; |
6240 | 6308 | ||
6241 | /* ... unless card isn't POSTed already */ | 6309 | /* ... unless card isn't POSTed already */ |
6242 | if (dev_priv->card_type >= NV_10 && | 6310 | if (!nouveau_bios_posted(dev)) { |
6243 | NVReadVgaCrtc(dev, 0, 0x00) == 0 && | ||
6244 | NVReadVgaCrtc(dev, 0, 0x1a) == 0) { | ||
6245 | NV_INFO(dev, "Adaptor not initialised\n"); | 6311 | NV_INFO(dev, "Adaptor not initialised\n"); |
6246 | if (dev_priv->card_type < NV_50) { | 6312 | if (dev_priv->card_type < NV_40) { |
6247 | NV_ERROR(dev, "Unable to POST this chipset\n"); | 6313 | NV_ERROR(dev, "Unable to POST this chipset\n"); |
6248 | return -ENODEV; | 6314 | return -ENODEV; |
6249 | } | 6315 | } |