diff options
| author | Dave Airlie <airlied@redhat.com> | 2010-01-14 22:22:59 -0500 |
|---|---|---|
| committer | Dave Airlie <airlied@redhat.com> | 2010-01-14 22:25:38 -0500 |
| commit | 1c974dc21898f9abbcb5e47ae9ddb7e6b473de2e (patch) | |
| tree | 60f76a234060d19c4d63335d292fc1b93330746a | |
| parent | 354fb52cb6138de0e6cf84a0f6a7f3467586e390 (diff) | |
| parent | 12f735b79f0ad63964dedabed3eee8a581bb66a5 (diff) | |
Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-linus
* 'nouveau/for-airlied' of ../drm-nouveau-next: (44 commits)
drm/nouveau: check pushbuffer bounds in ioctl
drm/nouveau: reserve VGA area for the moment
drm/nouveau: Unset the EDID connector property when the EDID block goes away.
drm/nouveau: Fallback to analog load detection when the EDID block is invalid.
drm/nouveau: fix edid memleak in nouveau_connector
drm/nouveau: Break some long lines.
drm/nouveau: add NV18 device id to call_lvds_manufacturer_script
drm/nv50: Fix typo in PGRAPH initialisation.
drm/nouveau: less magic DCB 1.5 parsing
drm/nouveau: assume no nv04 board has a DCB table
drm/nouveau: remove PRIV0 check in nouveau_mem_close()
drm/nouveau: wait on fence after bo move if validating for another channel
drm/nouveau: trust init table registers are safe
drm/nv50: wait for pgraph to idle before unloading the context
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 187 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bo.c | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 24 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 2 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_gem.c | 19 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_mem.c | 16 | ||||
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 3 |
7 files changed, 134 insertions, 119 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index ba143972769f..d7f8d8b4a4b8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
| @@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg) | |||
| 310 | struct drm_device *dev = bios->dev; | 310 | struct drm_device *dev = bios->dev; |
| 311 | 311 | ||
| 312 | /* C51 has misaligned regs on purpose. Marvellous */ | 312 | /* C51 has misaligned regs on purpose. Marvellous */ |
| 313 | if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) { | 313 | if (reg & 0x2 || |
| 314 | NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n", | 314 | (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) |
| 315 | reg); | 315 | NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg); |
| 316 | return 0; | 316 | |
| 317 | } | 317 | /* warn on C51 regs that haven't been verified accessible in tracing */ |
| 318 | /* | ||
| 319 | * Warn on C51 regs that have not been verified accessible in | ||
| 320 | * mmiotracing | ||
| 321 | */ | ||
| 322 | if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 && | 318 | if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 && |
| 323 | reg != 0x130d && reg != 0x1311 && reg != 0x60081d) | 319 | reg != 0x130d && reg != 0x1311 && reg != 0x60081d) |
| 324 | NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n", | 320 | NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n", |
| 325 | reg); | 321 | reg); |
| 326 | 322 | ||
| 327 | /* Trust the init scripts on G80 */ | 323 | if (reg >= (8*1024*1024)) { |
| 328 | if (dev_priv->card_type >= NV_50) | 324 | NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg); |
| 329 | return 1; | 325 | return 0; |
| 330 | |||
| 331 | #define WITHIN(x, y, z) ((x >= y) && (x < y + z)) | ||
| 332 | if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE)) | ||
| 333 | return 1; | ||
| 334 | if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE)) | ||
| 335 | return 1; | ||
| 336 | if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE)) | ||
| 337 | return 1; | ||
| 338 | if (dev_priv->VBIOS.pub.chip_version >= 0x30 && | ||
| 339 | (WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600)) | ||
| 340 | return 1; | ||
| 341 | if (dev_priv->VBIOS.pub.chip_version >= 0x40 && | ||
| 342 | WITHIN(reg, 0xc000, 0x48)) | ||
| 343 | return 1; | ||
| 344 | if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204) | ||
| 345 | return 1; | ||
| 346 | if (dev_priv->VBIOS.pub.chip_version >= 0x40) { | ||
| 347 | if (reg == 0x00011014 || reg == 0x00020328) | ||
| 348 | return 1; | ||
| 349 | if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */ | ||
| 350 | return 1; | ||
| 351 | } | 326 | } |
| 352 | if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE)) | ||
| 353 | return 1; | ||
| 354 | if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE)) | ||
| 355 | return 1; | ||
| 356 | if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2)) | ||
| 357 | return 1; | ||
| 358 | if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2)) | ||
| 359 | return 1; | ||
| 360 | if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0) | ||
| 361 | return 1; | ||
| 362 | if (dev_priv->VBIOS.pub.chip_version == 0x51 && | ||
| 363 | WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE)) | ||
| 364 | return 1; | ||
| 365 | #undef WITHIN | ||
| 366 | 327 | ||
| 367 | NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg); | 328 | return 1; |
| 368 | |||
| 369 | return 0; | ||
| 370 | } | 329 | } |
| 371 | 330 | ||
| 372 | static bool | 331 | static bool |
| @@ -3196,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr | |||
| 3196 | } | 3155 | } |
| 3197 | #ifdef __powerpc__ | 3156 | #ifdef __powerpc__ |
| 3198 | /* Powerbook specific quirks */ | 3157 | /* Powerbook specific quirks */ |
| 3199 | if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329)) | 3158 | if ((dev->pci_device & 0xffff) == 0x0179 || |
| 3200 | nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); | 3159 | (dev->pci_device & 0xffff) == 0x0189 || |
| 3201 | if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) { | 3160 | (dev->pci_device & 0xffff) == 0x0329) { |
| 3202 | if (script == LVDS_PANEL_ON) { | 3161 | if (script == LVDS_RESET) { |
| 3203 | bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31)); | 3162 | nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72); |
| 3204 | bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); | 3163 | |
| 3205 | } | 3164 | } else if (script == LVDS_PANEL_ON) { |
| 3206 | if (script == LVDS_PANEL_OFF) { | 3165 | bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, |
| 3207 | bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31)); | 3166 | bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) |
| 3208 | bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); | 3167 | | (1 << 31)); |
| 3168 | bios_wr32(bios, NV_PCRTC_GPIO_EXT, | ||
| 3169 | bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1); | ||
| 3170 | |||
| 3171 | } else if (script == LVDS_PANEL_OFF) { | ||
| 3172 | bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, | ||
| 3173 | bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | ||
| 3174 | & ~(1 << 31)); | ||
| 3175 | bios_wr32(bios, NV_PCRTC_GPIO_EXT, | ||
| 3176 | bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3); | ||
| 3209 | } | 3177 | } |
| 3210 | } | 3178 | } |
| 3211 | #endif | 3179 | #endif |
| @@ -5434,52 +5402,49 @@ static bool | |||
| 5434 | parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, | 5402 | parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, |
| 5435 | uint32_t conn, uint32_t conf, struct dcb_entry *entry) | 5403 | uint32_t conn, uint32_t conf, struct dcb_entry *entry) |
| 5436 | { | 5404 | { |
| 5437 | if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 && | 5405 | switch (conn & 0x0000000f) { |
| 5438 | conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 && | 5406 | case 0: |
| 5439 | conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 && | 5407 | entry->type = OUTPUT_ANALOG; |
| 5440 | conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 && | 5408 | break; |
| 5441 | conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 && | 5409 | case 1: |
| 5442 | conn != 0xf2205004 && conn != 0xf2209004) { | 5410 | entry->type = OUTPUT_TV; |
| 5443 | NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n"); | 5411 | break; |
| 5444 | 5412 | case 2: | |
| 5445 | /* cause output setting to fail for !TV, so message is seen */ | 5413 | case 3: |
| 5446 | if ((conn & 0xf) != 0x1) | ||
| 5447 | dcb->entries = 0; | ||
| 5448 | |||
| 5449 | return false; | ||
| 5450 | } | ||
| 5451 | /* most of the below is a "best guess" atm */ | ||
| 5452 | entry->type = conn & 0xf; | ||
| 5453 | if (entry->type == 2) | ||
| 5454 | /* another way of specifying straps based lvds... */ | ||
| 5455 | entry->type = OUTPUT_LVDS; | 5414 | entry->type = OUTPUT_LVDS; |
| 5456 | if (entry->type == 4) { /* digital */ | 5415 | break; |
| 5457 | if (conn & 0x10) | 5416 | case 4: |
| 5458 | entry->type = OUTPUT_LVDS; | 5417 | switch ((conn & 0x000000f0) >> 4) { |
| 5459 | else | 5418 | case 0: |
| 5460 | entry->type = OUTPUT_TMDS; | 5419 | entry->type = OUTPUT_TMDS; |
| 5420 | break; | ||
| 5421 | case 1: | ||
| 5422 | entry->type = OUTPUT_LVDS; | ||
| 5423 | break; | ||
| 5424 | default: | ||
| 5425 | NV_ERROR(dev, "Unknown DCB subtype 4/%d\n", | ||
| 5426 | (conn & 0x000000f0) >> 4); | ||
| 5427 | return false; | ||
| 5428 | } | ||
| 5429 | break; | ||
| 5430 | default: | ||
| 5431 | NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f); | ||
| 5432 | return false; | ||
| 5461 | } | 5433 | } |
| 5462 | /* what's in bits 5-13? could be some encoder maker thing, in tv case */ | 5434 | |
| 5463 | entry->i2c_index = (conn >> 14) & 0xf; | 5435 | entry->i2c_index = (conn & 0x0003c000) >> 14; |
| 5464 | /* raw heads field is in range 0-1, so move to 1-2 */ | 5436 | entry->heads = ((conn & 0x001c0000) >> 18) + 1; |
| 5465 | entry->heads = ((conn >> 18) & 0x7) + 1; | 5437 | entry->or = entry->heads; /* same as heads, hopefully safe enough */ |
| 5466 | entry->location = (conn >> 21) & 0xf; | 5438 | entry->location = (conn & 0x01e00000) >> 21; |
| 5467 | /* unused: entry->bus = (conn >> 25) & 0x7; */ | 5439 | entry->bus = (conn & 0x0e000000) >> 25; |
| 5468 | /* set or to be same as heads -- hopefully safe enough */ | ||
| 5469 | entry->or = entry->heads; | ||
| 5470 | entry->duallink_possible = false; | 5440 | entry->duallink_possible = false; |
| 5471 | 5441 | ||
| 5472 | switch (entry->type) { | 5442 | switch (entry->type) { |
| 5473 | case OUTPUT_ANALOG: | 5443 | case OUTPUT_ANALOG: |
| 5474 | entry->crtconf.maxfreq = (conf & 0xffff) * 10; | 5444 | entry->crtconf.maxfreq = (conf & 0xffff) * 10; |
| 5475 | break; | 5445 | break; |
| 5476 | case OUTPUT_LVDS: | 5446 | case OUTPUT_TV: |
| 5477 | /* | 5447 | entry->tvconf.has_component_output = false; |
| 5478 | * This is probably buried in conn's unknown bits. | ||
| 5479 | * This will upset EDID-ful models, if they exist | ||
| 5480 | */ | ||
| 5481 | entry->lvdsconf.use_straps_for_mode = true; | ||
| 5482 | entry->lvdsconf.use_power_scripts = true; | ||
| 5483 | break; | 5448 | break; |
| 5484 | case OUTPUT_TMDS: | 5449 | case OUTPUT_TMDS: |
| 5485 | /* | 5450 | /* |
| @@ -5488,8 +5453,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb, | |||
| 5488 | */ | 5453 | */ |
| 5489 | fabricate_vga_output(dcb, entry->i2c_index, entry->heads); | 5454 | fabricate_vga_output(dcb, entry->i2c_index, entry->heads); |
| 5490 | break; | 5455 | break; |
| 5491 | case OUTPUT_TV: | 5456 | case OUTPUT_LVDS: |
| 5492 | entry->tvconf.has_component_output = false; | 5457 | if ((conn & 0x00003f00) != 0x10) |
| 5458 | entry->lvdsconf.use_straps_for_mode = true; | ||
| 5459 | entry->lvdsconf.use_power_scripts = true; | ||
| 5460 | break; | ||
| 5461 | default: | ||
| 5493 | break; | 5462 | break; |
| 5494 | } | 5463 | } |
| 5495 | 5464 | ||
| @@ -5564,11 +5533,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb) | |||
| 5564 | dcb->entries = newentries; | 5533 | dcb->entries = newentries; |
| 5565 | } | 5534 | } |
| 5566 | 5535 | ||
| 5567 | static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | 5536 | static int |
| 5537 | parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads) | ||
| 5568 | { | 5538 | { |
| 5539 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 5569 | struct bios_parsed_dcb *bdcb = &bios->bdcb; | 5540 | struct bios_parsed_dcb *bdcb = &bios->bdcb; |
| 5570 | struct parsed_dcb *dcb; | 5541 | struct parsed_dcb *dcb; |
| 5571 | uint16_t dcbptr, i2ctabptr = 0; | 5542 | uint16_t dcbptr = 0, i2ctabptr = 0; |
| 5572 | uint8_t *dcbtable; | 5543 | uint8_t *dcbtable; |
| 5573 | uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; | 5544 | uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES; |
| 5574 | bool configblock = true; | 5545 | bool configblock = true; |
| @@ -5579,16 +5550,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two | |||
| 5579 | dcb->entries = 0; | 5550 | dcb->entries = 0; |
| 5580 | 5551 | ||
| 5581 | /* get the offset from 0x36 */ | 5552 | /* get the offset from 0x36 */ |
| 5582 | dcbptr = ROM16(bios->data[0x36]); | 5553 | if (dev_priv->card_type > NV_04) { |
| 5554 | dcbptr = ROM16(bios->data[0x36]); | ||
| 5555 | if (dcbptr == 0x0000) | ||
| 5556 | NV_WARN(dev, "No output data (DCB) found in BIOS\n"); | ||
| 5557 | } | ||
| 5583 | 5558 | ||
| 5559 | /* this situation likely means a really old card, pre DCB */ | ||
| 5584 | if (dcbptr == 0x0) { | 5560 | if (dcbptr == 0x0) { |
| 5585 | NV_WARN(dev, "No output data (DCB) found in BIOS, " | 5561 | NV_INFO(dev, "Assuming a CRT output exists\n"); |
| 5586 | "assuming a CRT output exists\n"); | ||
| 5587 | /* this situation likely means a really old card, pre DCB */ | ||
| 5588 | fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); | 5562 | fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1); |
| 5589 | 5563 | ||
| 5590 | if (nv04_tv_identify(dev, | 5564 | if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0) |
| 5591 | bios->legacy.i2c_indices.tv) >= 0) | ||
| 5592 | fabricate_tv_output(dcb, twoHeads); | 5565 | fabricate_tv_output(dcb, twoHeads); |
| 5593 | 5566 | ||
| 5594 | return 0; | 5567 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_bo.c b/drivers/gpu/drm/nouveau/nouveau_bo.c index e342a418d434..db0ed4c13f98 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bo.c +++ b/drivers/gpu/drm/nouveau/nouveau_bo.c | |||
| @@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan, | |||
| 469 | 469 | ||
| 470 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, | 470 | ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL, |
| 471 | evict, no_wait, new_mem); | 471 | evict, no_wait, new_mem); |
| 472 | if (nvbo->channel && nvbo->channel != chan) | ||
| 473 | ret = nouveau_fence_wait(fence, NULL, false, false); | ||
| 472 | nouveau_fence_unref((void *)&fence); | 474 | nouveau_fence_unref((void *)&fence); |
| 473 | return ret; | 475 | return ret; |
| 474 | } | 476 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 5a10deb8bdbd..8da35281a0c3 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
| @@ -83,14 +83,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) | |||
| 83 | static void | 83 | static void |
| 84 | nouveau_connector_destroy(struct drm_connector *drm_connector) | 84 | nouveau_connector_destroy(struct drm_connector *drm_connector) |
| 85 | { | 85 | { |
| 86 | struct nouveau_connector *connector = nouveau_connector(drm_connector); | 86 | struct nouveau_connector *nv_connector = |
| 87 | struct drm_device *dev = connector->base.dev; | 87 | nouveau_connector(drm_connector); |
| 88 | struct drm_device *dev = nv_connector->base.dev; | ||
| 88 | 89 | ||
| 89 | NV_DEBUG_KMS(dev, "\n"); | 90 | NV_DEBUG_KMS(dev, "\n"); |
| 90 | 91 | ||
| 91 | if (!connector) | 92 | if (!nv_connector) |
| 92 | return; | 93 | return; |
| 93 | 94 | ||
| 95 | kfree(nv_connector->edid); | ||
| 94 | drm_sysfs_connector_remove(drm_connector); | 96 | drm_sysfs_connector_remove(drm_connector); |
| 95 | drm_connector_cleanup(drm_connector); | 97 | drm_connector_cleanup(drm_connector); |
| 96 | kfree(drm_connector); | 98 | kfree(drm_connector); |
| @@ -237,6 +239,13 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
| 237 | return connector_status_connected; | 239 | return connector_status_connected; |
| 238 | } | 240 | } |
| 239 | 241 | ||
| 242 | /* Cleanup the previous EDID block. */ | ||
| 243 | if (nv_connector->edid) { | ||
| 244 | drm_mode_connector_update_edid_property(connector, NULL); | ||
| 245 | kfree(nv_connector->edid); | ||
| 246 | nv_connector->edid = NULL; | ||
| 247 | } | ||
| 248 | |||
| 240 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | 249 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); |
| 241 | if (i2c) { | 250 | if (i2c) { |
| 242 | nouveau_connector_ddc_prepare(connector, &flags); | 251 | nouveau_connector_ddc_prepare(connector, &flags); |
| @@ -247,7 +256,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
| 247 | if (!nv_connector->edid) { | 256 | if (!nv_connector->edid) { |
| 248 | NV_ERROR(dev, "DDC responded, but no EDID for %s\n", | 257 | NV_ERROR(dev, "DDC responded, but no EDID for %s\n", |
| 249 | drm_get_connector_name(connector)); | 258 | drm_get_connector_name(connector)); |
| 250 | return connector_status_disconnected; | 259 | goto detect_analog; |
| 251 | } | 260 | } |
| 252 | 261 | ||
| 253 | if (nv_encoder->dcb->type == OUTPUT_DP && | 262 | if (nv_encoder->dcb->type == OUTPUT_DP && |
| @@ -281,6 +290,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
| 281 | return connector_status_connected; | 290 | return connector_status_connected; |
| 282 | } | 291 | } |
| 283 | 292 | ||
| 293 | detect_analog: | ||
| 284 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 294 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); |
| 285 | if (!nv_encoder) | 295 | if (!nv_encoder) |
| 286 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); | 296 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); |
| @@ -687,8 +697,12 @@ nouveau_connector_create_lvds(struct drm_device *dev, | |||
| 687 | */ | 697 | */ |
| 688 | if (!nv_connector->edid && !nv_connector->native_mode && | 698 | if (!nv_connector->edid && !nv_connector->native_mode && |
| 689 | !dev_priv->VBIOS.pub.fp_no_ddc) { | 699 | !dev_priv->VBIOS.pub.fp_no_ddc) { |
| 690 | nv_connector->edid = | 700 | struct edid *edid = |
| 691 | (struct edid *)nouveau_bios_embedded_edid(dev); | 701 | (struct edid *)nouveau_bios_embedded_edid(dev); |
| 702 | if (edid) { | ||
| 703 | nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
| 704 | *(nv_connector->edid) = *edid; | ||
| 705 | } | ||
| 692 | } | 706 | } |
| 693 | 707 | ||
| 694 | if (!nv_connector->edid) | 708 | if (!nv_connector->edid) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 026419fe8791..cc36866e2a9f 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
| @@ -509,6 +509,8 @@ struct drm_nouveau_private { | |||
| 509 | void __iomem *ramin; | 509 | void __iomem *ramin; |
| 510 | uint32_t ramin_size; | 510 | uint32_t ramin_size; |
| 511 | 511 | ||
| 512 | struct nouveau_bo *vga_ram; | ||
| 513 | |||
| 512 | struct workqueue_struct *wq; | 514 | struct workqueue_struct *wq; |
| 513 | struct work_struct irq_work; | 515 | struct work_struct irq_work; |
| 514 | 516 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2009db2426c3..504833044080 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
| @@ -466,13 +466,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) | |||
| 466 | static int | 466 | static int |
| 467 | nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, | 467 | nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, |
| 468 | struct drm_nouveau_gem_pushbuf_bo *bo, | 468 | struct drm_nouveau_gem_pushbuf_bo *bo, |
| 469 | int nr_relocs, uint64_t ptr_relocs, | 469 | unsigned nr_relocs, uint64_t ptr_relocs, |
| 470 | int nr_dwords, int first_dword, | 470 | unsigned nr_dwords, unsigned first_dword, |
| 471 | uint32_t *pushbuf, bool is_iomem) | 471 | uint32_t *pushbuf, bool is_iomem) |
| 472 | { | 472 | { |
| 473 | struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; | 473 | struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; |
| 474 | struct drm_device *dev = chan->dev; | 474 | struct drm_device *dev = chan->dev; |
| 475 | int ret = 0, i; | 475 | int ret = 0; |
| 476 | unsigned i; | ||
| 476 | 477 | ||
| 477 | reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); | 478 | reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); |
| 478 | if (IS_ERR(reloc)) | 479 | if (IS_ERR(reloc)) |
| @@ -667,6 +668,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, | |||
| 667 | } | 668 | } |
| 668 | pbbo = nouveau_gem_object(gem); | 669 | pbbo = nouveau_gem_object(gem); |
| 669 | 670 | ||
| 671 | if ((req->offset & 3) || req->nr_dwords < 2 || | ||
| 672 | (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size || | ||
| 673 | (unsigned long)req->nr_dwords > | ||
| 674 | ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) { | ||
| 675 | NV_ERROR(dev, "pb call misaligned or out of bounds: " | ||
| 676 | "%d + %d * 4 > %ld\n", | ||
| 677 | req->offset, req->nr_dwords, pbbo->bo.mem.size); | ||
| 678 | ret = -EINVAL; | ||
| 679 | drm_gem_object_unreference(gem); | ||
| 680 | goto out; | ||
| 681 | } | ||
| 682 | |||
| 670 | ret = ttm_bo_reserve(&pbbo->bo, false, false, true, | 683 | ret = ttm_bo_reserve(&pbbo->bo, false, false, true, |
| 671 | chan->fence.sequence); | 684 | chan->fence.sequence); |
| 672 | if (ret) { | 685 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index fb9bdd6edf1f..186f34b01f2e 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
| @@ -383,10 +383,10 @@ void nouveau_mem_close(struct drm_device *dev) | |||
| 383 | { | 383 | { |
| 384 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 384 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
| 385 | 385 | ||
| 386 | if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type) | 386 | nouveau_bo_unpin(dev_priv->vga_ram); |
| 387 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0); | 387 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); |
| 388 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | ||
| 389 | 388 | ||
| 389 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | ||
| 390 | ttm_bo_device_release(&dev_priv->ttm.bdev); | 390 | ttm_bo_device_release(&dev_priv->ttm.bdev); |
| 391 | 391 | ||
| 392 | nouveau_ttm_global_release(dev_priv); | 392 | nouveau_ttm_global_release(dev_priv); |
| @@ -622,6 +622,15 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 622 | return ret; | 622 | return ret; |
| 623 | } | 623 | } |
| 624 | 624 | ||
| 625 | ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, | ||
| 626 | 0, 0, true, true, &dev_priv->vga_ram); | ||
| 627 | if (ret == 0) | ||
| 628 | ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); | ||
| 629 | if (ret) { | ||
| 630 | NV_WARN(dev, "failed to reserve VGA memory\n"); | ||
| 631 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | ||
| 632 | } | ||
| 633 | |||
| 625 | /* GART */ | 634 | /* GART */ |
| 626 | #if !defined(__powerpc__) && !defined(__ia64__) | 635 | #if !defined(__powerpc__) && !defined(__ia64__) |
| 627 | if (drm_device_is_agp(dev) && dev->agp) { | 636 | if (drm_device_is_agp(dev) && dev->agp) { |
| @@ -653,6 +662,7 @@ nouveau_mem_init(struct drm_device *dev) | |||
| 653 | dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), | 662 | dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), |
| 654 | drm_get_resource_len(dev, 1), | 663 | drm_get_resource_len(dev, 1), |
| 655 | DRM_MTRR_WC); | 664 | DRM_MTRR_WC); |
| 665 | |||
| 656 | return 0; | 666 | return 0; |
| 657 | } | 667 | } |
| 658 | 668 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index ca79f32be44c..20319e59d368 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
| @@ -84,7 +84,7 @@ nv50_graph_init_regs__nv(struct drm_device *dev) | |||
| 84 | nv_wr32(dev, 0x400804, 0xc0000000); | 84 | nv_wr32(dev, 0x400804, 0xc0000000); |
| 85 | nv_wr32(dev, 0x406800, 0xc0000000); | 85 | nv_wr32(dev, 0x406800, 0xc0000000); |
| 86 | nv_wr32(dev, 0x400c04, 0xc0000000); | 86 | nv_wr32(dev, 0x400c04, 0xc0000000); |
| 87 | nv_wr32(dev, 0x401804, 0xc0000000); | 87 | nv_wr32(dev, 0x401800, 0xc0000000); |
| 88 | nv_wr32(dev, 0x405018, 0xc0000000); | 88 | nv_wr32(dev, 0x405018, 0xc0000000); |
| 89 | nv_wr32(dev, 0x402000, 0xc0000000); | 89 | nv_wr32(dev, 0x402000, 0xc0000000); |
| 90 | 90 | ||
| @@ -282,6 +282,7 @@ nv50_graph_unload_context(struct drm_device *dev) | |||
| 282 | return 0; | 282 | return 0; |
| 283 | inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; | 283 | inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; |
| 284 | 284 | ||
| 285 | nouveau_wait_for_idle(dev); | ||
| 285 | nv_wr32(dev, 0x400500, fifo & ~1); | 286 | nv_wr32(dev, 0x400500, fifo & ~1); |
| 286 | nv_wr32(dev, 0x400784, inst); | 287 | nv_wr32(dev, 0x400784, inst); |
| 287 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); | 288 | nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); |
