diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-25 21:59:47 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2010-01-25 21:59:47 -0500 |
commit | abefedd538f57f63199d821ade33f282e7fe0921 (patch) | |
tree | d5b442c1d504ac0ed12c2801b98b6418a7f79764 | |
parent | 840f51ffe126123e748df0f36c411a90db1efd93 (diff) | |
parent | 7087e16286913b41ba9a5186360645b57b8508dd (diff) |
Merge branch 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6
* 'drm-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/airlied/drm-2.6: (95 commits)
drm/radeon/kms: preface warning printk with driver name
drm/radeon/kms: drop unnecessary printks.
drm: fix regression in fb blank handling
drm/radeon/kms: make hibernate work on IGPs
drm/vmwgfx: Optimize memory footprint for DMA buffers.
drm/ttm: Allow system memory as a busy placement.
drm/ttm: Fix race condition in ttm_bo_delayed_delete (v3, final)
drm/nv50: prevent switching off SOR when in use for DVI-over-DP
drm/nv50: fail auxch transaction if reply count not what we expect
drm/nouveau: fix failure path if userspace specifies no valid memtypes
drm/nouveau: report LVDS as disconnected if lid closed
drm/radeon/kms: fix legacy get_engine/memory clock
drm/radeon/kms/atom: atom parser fixes
drm/radeon/kms: clean up atombios pll code
drm/radeon/kms: clean up pll struct
drm/radeon/kms/atom: fix crtc lock ordering
drm/radeon: r6xx/r7xx possible security issue, system ram access
drm/radeon/kms: r600/r700 don't test ib if ib initialization fails
drm/radeon/kms: Forbid creation of framebuffer with no valid GEM object
drm/radeon/kms: r600 handle irq vector ring overflow
...
51 files changed, 958 insertions, 520 deletions
diff --git a/drivers/gpu/drm/drm_edid.c b/drivers/gpu/drm/drm_edid.c index defcaf108460..f665b05592f3 100644 --- a/drivers/gpu/drm/drm_edid.c +++ b/drivers/gpu/drm/drm_edid.c | |||
@@ -633,8 +633,7 @@ static struct drm_display_mode *drm_mode_detailed(struct drm_device *dev, | |||
633 | return NULL; | 633 | return NULL; |
634 | } | 634 | } |
635 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { | 635 | if (!(pt->misc & DRM_EDID_PT_SEPARATE_SYNC)) { |
636 | printk(KERN_WARNING "integrated sync not supported\n"); | 636 | printk(KERN_WARNING "composite sync not supported\n"); |
637 | return NULL; | ||
638 | } | 637 | } |
639 | 638 | ||
640 | /* it is incorrect if hsync/vsync width is zero */ | 639 | /* it is incorrect if hsync/vsync width is zero */ |
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c index 1c2b7d44ec05..0f9e90552dc4 100644 --- a/drivers/gpu/drm/drm_fb_helper.c +++ b/drivers/gpu/drm/drm_fb_helper.c | |||
@@ -389,7 +389,7 @@ int drm_fb_helper_blank(int blank, struct fb_info *info) | |||
389 | break; | 389 | break; |
390 | /* Display: Off; HSync: On, VSync: On */ | 390 | /* Display: Off; HSync: On, VSync: On */ |
391 | case FB_BLANK_NORMAL: | 391 | case FB_BLANK_NORMAL: |
392 | drm_fb_helper_off(info, DRM_MODE_DPMS_ON); | 392 | drm_fb_helper_off(info, DRM_MODE_DPMS_STANDBY); |
393 | break; | 393 | break; |
394 | /* Display: Off; HSync: Off, VSync: On */ | 394 | /* Display: Off; HSync: Off, VSync: On */ |
395 | case FB_BLANK_HSYNC_SUSPEND: | 395 | case FB_BLANK_HSYNC_SUSPEND: |
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..7e6d673f3a23 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -24,9 +24,12 @@ | |||
24 | * | 24 | * |
25 | */ | 25 | */ |
26 | 26 | ||
27 | #include <acpi/button.h> | ||
28 | |||
27 | #include "drmP.h" | 29 | #include "drmP.h" |
28 | #include "drm_edid.h" | 30 | #include "drm_edid.h" |
29 | #include "drm_crtc_helper.h" | 31 | #include "drm_crtc_helper.h" |
32 | |||
30 | #include "nouveau_reg.h" | 33 | #include "nouveau_reg.h" |
31 | #include "nouveau_drv.h" | 34 | #include "nouveau_drv.h" |
32 | #include "nouveau_encoder.h" | 35 | #include "nouveau_encoder.h" |
@@ -83,14 +86,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder) | |||
83 | static void | 86 | static void |
84 | nouveau_connector_destroy(struct drm_connector *drm_connector) | 87 | nouveau_connector_destroy(struct drm_connector *drm_connector) |
85 | { | 88 | { |
86 | struct nouveau_connector *connector = nouveau_connector(drm_connector); | 89 | struct nouveau_connector *nv_connector = |
87 | struct drm_device *dev = connector->base.dev; | 90 | nouveau_connector(drm_connector); |
91 | struct drm_device *dev = nv_connector->base.dev; | ||
88 | 92 | ||
89 | NV_DEBUG_KMS(dev, "\n"); | 93 | NV_DEBUG_KMS(dev, "\n"); |
90 | 94 | ||
91 | if (!connector) | 95 | if (!nv_connector) |
92 | return; | 96 | return; |
93 | 97 | ||
98 | kfree(nv_connector->edid); | ||
94 | drm_sysfs_connector_remove(drm_connector); | 99 | drm_sysfs_connector_remove(drm_connector); |
95 | drm_connector_cleanup(drm_connector); | 100 | drm_connector_cleanup(drm_connector); |
96 | kfree(drm_connector); | 101 | kfree(drm_connector); |
@@ -233,10 +238,21 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
233 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) | 238 | if (connector->connector_type == DRM_MODE_CONNECTOR_LVDS) |
234 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | 239 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); |
235 | if (nv_encoder && nv_connector->native_mode) { | 240 | if (nv_encoder && nv_connector->native_mode) { |
241 | #ifdef CONFIG_ACPI | ||
242 | if (!nouveau_ignorelid && !acpi_lid_open()) | ||
243 | return connector_status_disconnected; | ||
244 | #endif | ||
236 | nouveau_connector_set_encoder(connector, nv_encoder); | 245 | nouveau_connector_set_encoder(connector, nv_encoder); |
237 | return connector_status_connected; | 246 | return connector_status_connected; |
238 | } | 247 | } |
239 | 248 | ||
249 | /* Cleanup the previous EDID block. */ | ||
250 | if (nv_connector->edid) { | ||
251 | drm_mode_connector_update_edid_property(connector, NULL); | ||
252 | kfree(nv_connector->edid); | ||
253 | nv_connector->edid = NULL; | ||
254 | } | ||
255 | |||
240 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); | 256 | i2c = nouveau_connector_ddc_detect(connector, &nv_encoder); |
241 | if (i2c) { | 257 | if (i2c) { |
242 | nouveau_connector_ddc_prepare(connector, &flags); | 258 | nouveau_connector_ddc_prepare(connector, &flags); |
@@ -247,7 +263,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
247 | if (!nv_connector->edid) { | 263 | if (!nv_connector->edid) { |
248 | NV_ERROR(dev, "DDC responded, but no EDID for %s\n", | 264 | NV_ERROR(dev, "DDC responded, but no EDID for %s\n", |
249 | drm_get_connector_name(connector)); | 265 | drm_get_connector_name(connector)); |
250 | return connector_status_disconnected; | 266 | goto detect_analog; |
251 | } | 267 | } |
252 | 268 | ||
253 | if (nv_encoder->dcb->type == OUTPUT_DP && | 269 | if (nv_encoder->dcb->type == OUTPUT_DP && |
@@ -281,6 +297,7 @@ nouveau_connector_detect(struct drm_connector *connector) | |||
281 | return connector_status_connected; | 297 | return connector_status_connected; |
282 | } | 298 | } |
283 | 299 | ||
300 | detect_analog: | ||
284 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 301 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); |
285 | if (!nv_encoder) | 302 | if (!nv_encoder) |
286 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); | 303 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); |
@@ -687,8 +704,12 @@ nouveau_connector_create_lvds(struct drm_device *dev, | |||
687 | */ | 704 | */ |
688 | if (!nv_connector->edid && !nv_connector->native_mode && | 705 | if (!nv_connector->edid && !nv_connector->native_mode && |
689 | !dev_priv->VBIOS.pub.fp_no_ddc) { | 706 | !dev_priv->VBIOS.pub.fp_no_ddc) { |
690 | nv_connector->edid = | 707 | struct edid *edid = |
691 | (struct edid *)nouveau_bios_embedded_edid(dev); | 708 | (struct edid *)nouveau_bios_embedded_edid(dev); |
709 | if (edid) { | ||
710 | nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL); | ||
711 | *(nv_connector->edid) = *edid; | ||
712 | } | ||
692 | } | 713 | } |
693 | 714 | ||
694 | if (!nv_connector->edid) | 715 | if (!nv_connector->edid) |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dma.c b/drivers/gpu/drm/nouveau/nouveau_dma.c index 7afbe8b40d51..50d9e67745af 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dma.c +++ b/drivers/gpu/drm/nouveau/nouveau_dma.c | |||
@@ -126,47 +126,52 @@ OUT_RINGp(struct nouveau_channel *chan, const void *data, unsigned nr_dwords) | |||
126 | chan->dma.cur += nr_dwords; | 126 | chan->dma.cur += nr_dwords; |
127 | } | 127 | } |
128 | 128 | ||
129 | static inline bool | 129 | /* Fetch and adjust GPU GET pointer |
130 | READ_GET(struct nouveau_channel *chan, uint32_t *get) | 130 | * |
131 | * Returns: | ||
132 | * value >= 0, the adjusted GET pointer | ||
133 | * -EINVAL if GET pointer currently outside main push buffer | ||
134 | * -EBUSY if timeout exceeded | ||
135 | */ | ||
136 | static inline int | ||
137 | READ_GET(struct nouveau_channel *chan, uint32_t *prev_get, uint32_t *timeout) | ||
131 | { | 138 | { |
132 | uint32_t val; | 139 | uint32_t val; |
133 | 140 | ||
134 | val = nvchan_rd32(chan, chan->user_get); | 141 | val = nvchan_rd32(chan, chan->user_get); |
135 | if (val < chan->pushbuf_base || | 142 | |
136 | val > chan->pushbuf_base + (chan->dma.max << 2)) { | 143 | /* reset counter as long as GET is still advancing, this is |
137 | /* meaningless to dma_wait() except to know whether the | 144 | * to avoid misdetecting a GPU lockup if the GPU happens to |
138 | * GPU has stalled or not | 145 | * just be processing an operation that takes a long time |
139 | */ | 146 | */ |
140 | *get = val; | 147 | if (val != *prev_get) { |
141 | return false; | 148 | *prev_get = val; |
149 | *timeout = 0; | ||
150 | } | ||
151 | |||
152 | if ((++*timeout & 0xff) == 0) { | ||
153 | DRM_UDELAY(1); | ||
154 | if (*timeout > 100000) | ||
155 | return -EBUSY; | ||
142 | } | 156 | } |
143 | 157 | ||
144 | *get = (val - chan->pushbuf_base) >> 2; | 158 | if (val < chan->pushbuf_base || |
145 | return true; | 159 | val > chan->pushbuf_base + (chan->dma.max << 2)) |
160 | return -EINVAL; | ||
161 | |||
162 | return (val - chan->pushbuf_base) >> 2; | ||
146 | } | 163 | } |
147 | 164 | ||
148 | int | 165 | int |
149 | nouveau_dma_wait(struct nouveau_channel *chan, int size) | 166 | nouveau_dma_wait(struct nouveau_channel *chan, int size) |
150 | { | 167 | { |
151 | uint32_t get, prev_get = 0, cnt = 0; | 168 | uint32_t prev_get = 0, cnt = 0; |
152 | bool get_valid; | 169 | int get; |
153 | 170 | ||
154 | while (chan->dma.free < size) { | 171 | while (chan->dma.free < size) { |
155 | /* reset counter as long as GET is still advancing, this is | 172 | get = READ_GET(chan, &prev_get, &cnt); |
156 | * to avoid misdetecting a GPU lockup if the GPU happens to | 173 | if (unlikely(get == -EBUSY)) |
157 | * just be processing an operation that takes a long time | 174 | return -EBUSY; |
158 | */ | ||
159 | get_valid = READ_GET(chan, &get); | ||
160 | if (get != prev_get) { | ||
161 | prev_get = get; | ||
162 | cnt = 0; | ||
163 | } | ||
164 | |||
165 | if ((++cnt & 0xff) == 0) { | ||
166 | DRM_UDELAY(1); | ||
167 | if (cnt > 100000) | ||
168 | return -EBUSY; | ||
169 | } | ||
170 | 175 | ||
171 | /* loop until we have a usable GET pointer. the value | 176 | /* loop until we have a usable GET pointer. the value |
172 | * we read from the GPU may be outside the main ring if | 177 | * we read from the GPU may be outside the main ring if |
@@ -177,7 +182,7 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size) | |||
177 | * from the SKIPS area, so the code below doesn't have to deal | 182 | * from the SKIPS area, so the code below doesn't have to deal |
178 | * with some fun corner cases. | 183 | * with some fun corner cases. |
179 | */ | 184 | */ |
180 | if (!get_valid || get < NOUVEAU_DMA_SKIPS) | 185 | if (unlikely(get == -EINVAL) || get < NOUVEAU_DMA_SKIPS) |
181 | continue; | 186 | continue; |
182 | 187 | ||
183 | if (get <= chan->dma.cur) { | 188 | if (get <= chan->dma.cur) { |
@@ -203,6 +208,19 @@ nouveau_dma_wait(struct nouveau_channel *chan, int size) | |||
203 | * after processing the currently pending commands. | 208 | * after processing the currently pending commands. |
204 | */ | 209 | */ |
205 | OUT_RING(chan, chan->pushbuf_base | 0x20000000); | 210 | OUT_RING(chan, chan->pushbuf_base | 0x20000000); |
211 | |||
212 | /* wait for GET to depart from the skips area. | ||
213 | * prevents writing GET==PUT and causing a race | ||
214 | * condition that causes us to think the GPU is | ||
215 | * idle when it's not. | ||
216 | */ | ||
217 | do { | ||
218 | get = READ_GET(chan, &prev_get, &cnt); | ||
219 | if (unlikely(get == -EBUSY)) | ||
220 | return -EBUSY; | ||
221 | if (unlikely(get == -EINVAL)) | ||
222 | continue; | ||
223 | } while (get <= NOUVEAU_DMA_SKIPS); | ||
206 | WRITE_PUT(NOUVEAU_DMA_SKIPS); | 224 | WRITE_PUT(NOUVEAU_DMA_SKIPS); |
207 | 225 | ||
208 | /* we're now submitting commands at the start of | 226 | /* we're now submitting commands at the start of |
diff --git a/drivers/gpu/drm/nouveau/nouveau_dp.c b/drivers/gpu/drm/nouveau/nouveau_dp.c index 9e2926c48579..dd4937224220 100644 --- a/drivers/gpu/drm/nouveau/nouveau_dp.c +++ b/drivers/gpu/drm/nouveau/nouveau_dp.c | |||
@@ -490,7 +490,8 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, | |||
490 | if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { | 490 | if (!nv_wait(NV50_AUXCH_CTRL(index), 0x00010000, 0x00000000)) { |
491 | NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", | 491 | NV_ERROR(dev, "expected bit 16 == 0, got 0x%08x\n", |
492 | nv_rd32(dev, NV50_AUXCH_CTRL(index))); | 492 | nv_rd32(dev, NV50_AUXCH_CTRL(index))); |
493 | return -EBUSY; | 493 | ret = -EBUSY; |
494 | goto out; | ||
494 | } | 495 | } |
495 | 496 | ||
496 | udelay(400); | 497 | udelay(400); |
@@ -501,6 +502,11 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, | |||
501 | break; | 502 | break; |
502 | } | 503 | } |
503 | 504 | ||
505 | if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) { | ||
506 | ret = -EREMOTEIO; | ||
507 | goto out; | ||
508 | } | ||
509 | |||
504 | if (cmd & 1) { | 510 | if (cmd & 1) { |
505 | for (i = 0; i < 4; i++) { | 511 | for (i = 0; i < 4; i++) { |
506 | data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); | 512 | data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 06eb993e0883..343ab7f17ccc 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
@@ -71,6 +71,10 @@ MODULE_PARM_DESC(uscript_tmds, "TMDS output script table ID (>=GeForce 8)"); | |||
71 | int nouveau_uscript_tmds = -1; | 71 | int nouveau_uscript_tmds = -1; |
72 | module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); | 72 | module_param_named(uscript_tmds, nouveau_uscript_tmds, int, 0400); |
73 | 73 | ||
74 | MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); | ||
75 | int nouveau_ignorelid = 0; | ||
76 | module_param_named(ignorelid, nouveau_ignorelid, int, 0400); | ||
77 | |||
74 | MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" | 78 | MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" |
75 | "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" | 79 | "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" |
76 | "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" | 80 | "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 026419fe8791..6b9690418bc7 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 | ||
@@ -675,6 +677,7 @@ extern char *nouveau_tv_norm; | |||
675 | extern int nouveau_reg_debug; | 677 | extern int nouveau_reg_debug; |
676 | extern char *nouveau_vbios; | 678 | extern char *nouveau_vbios; |
677 | extern int nouveau_ctxfw; | 679 | extern int nouveau_ctxfw; |
680 | extern int nouveau_ignorelid; | ||
678 | 681 | ||
679 | /* nouveau_state.c */ | 682 | /* nouveau_state.c */ |
680 | extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); | 683 | extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 2009db2426c3..6ac804b0c9f9 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -321,6 +321,7 @@ retry: | |||
321 | else { | 321 | else { |
322 | NV_ERROR(dev, "invalid valid domains: 0x%08x\n", | 322 | NV_ERROR(dev, "invalid valid domains: 0x%08x\n", |
323 | b->valid_domains); | 323 | b->valid_domains); |
324 | list_add_tail(&nvbo->entry, &op->both_list); | ||
324 | validate_fini(op, NULL); | 325 | validate_fini(op, NULL); |
325 | return -EINVAL; | 326 | return -EINVAL; |
326 | } | 327 | } |
@@ -466,13 +467,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size) | |||
466 | static int | 467 | static int |
467 | nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, | 468 | nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo, |
468 | struct drm_nouveau_gem_pushbuf_bo *bo, | 469 | struct drm_nouveau_gem_pushbuf_bo *bo, |
469 | int nr_relocs, uint64_t ptr_relocs, | 470 | unsigned nr_relocs, uint64_t ptr_relocs, |
470 | int nr_dwords, int first_dword, | 471 | unsigned nr_dwords, unsigned first_dword, |
471 | uint32_t *pushbuf, bool is_iomem) | 472 | uint32_t *pushbuf, bool is_iomem) |
472 | { | 473 | { |
473 | struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; | 474 | struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL; |
474 | struct drm_device *dev = chan->dev; | 475 | struct drm_device *dev = chan->dev; |
475 | int ret = 0, i; | 476 | int ret = 0; |
477 | unsigned i; | ||
476 | 478 | ||
477 | reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); | 479 | reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc)); |
478 | if (IS_ERR(reloc)) | 480 | if (IS_ERR(reloc)) |
@@ -667,6 +669,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data, | |||
667 | } | 669 | } |
668 | pbbo = nouveau_gem_object(gem); | 670 | pbbo = nouveau_gem_object(gem); |
669 | 671 | ||
672 | if ((req->offset & 3) || req->nr_dwords < 2 || | ||
673 | (unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size || | ||
674 | (unsigned long)req->nr_dwords > | ||
675 | ((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) { | ||
676 | NV_ERROR(dev, "pb call misaligned or out of bounds: " | ||
677 | "%d + %d * 4 > %ld\n", | ||
678 | req->offset, req->nr_dwords, pbbo->bo.mem.size); | ||
679 | ret = -EINVAL; | ||
680 | drm_gem_object_unreference(gem); | ||
681 | goto out; | ||
682 | } | ||
683 | |||
670 | ret = ttm_bo_reserve(&pbbo->bo, false, false, true, | 684 | ret = ttm_bo_reserve(&pbbo->bo, false, false, true, |
671 | chan->fence.sequence); | 685 | chan->fence.sequence); |
672 | if (ret) { | 686 | if (ret) { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 919a619ca7fa..3b9bad66162a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -483,6 +483,13 @@ nouveau_pgraph_intr_error(struct drm_device *dev, uint32_t nsource) | |||
483 | if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { | 483 | if (nsource & NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD) { |
484 | if (nouveau_pgraph_intr_swmthd(dev, &trap)) | 484 | if (nouveau_pgraph_intr_swmthd(dev, &trap)) |
485 | unhandled = 1; | 485 | unhandled = 1; |
486 | } else if (nsource & NV03_PGRAPH_NSOURCE_DMA_VTX_PROTECTION) { | ||
487 | uint32_t v = nv_rd32(dev, 0x402000); | ||
488 | nv_wr32(dev, 0x402000, v); | ||
489 | |||
490 | /* dump the error anyway for now: it's useful for | ||
491 | Gallium development */ | ||
492 | unhandled = 1; | ||
486 | } else { | 493 | } else { |
487 | unhandled = 1; | 494 | unhandled = 1; |
488 | } | 495 | } |
diff --git a/drivers/gpu/drm/nouveau/nouveau_mem.c b/drivers/gpu/drm/nouveau/nouveau_mem.c index fb9bdd6edf1f..8f3a12f614ed 100644 --- a/drivers/gpu/drm/nouveau/nouveau_mem.c +++ b/drivers/gpu/drm/nouveau/nouveau_mem.c | |||
@@ -383,9 +383,8 @@ 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 | ||
390 | ttm_bo_device_release(&dev_priv->ttm.bdev); | 389 | ttm_bo_device_release(&dev_priv->ttm.bdev); |
391 | 390 | ||
@@ -622,6 +621,15 @@ nouveau_mem_init(struct drm_device *dev) | |||
622 | return ret; | 621 | return ret; |
623 | } | 622 | } |
624 | 623 | ||
624 | ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM, | ||
625 | 0, 0, true, true, &dev_priv->vga_ram); | ||
626 | if (ret == 0) | ||
627 | ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM); | ||
628 | if (ret) { | ||
629 | NV_WARN(dev, "failed to reserve VGA memory\n"); | ||
630 | nouveau_bo_ref(NULL, &dev_priv->vga_ram); | ||
631 | } | ||
632 | |||
625 | /* GART */ | 633 | /* GART */ |
626 | #if !defined(__powerpc__) && !defined(__ia64__) | 634 | #if !defined(__powerpc__) && !defined(__ia64__) |
627 | if (drm_device_is_agp(dev) && dev->agp) { | 635 | if (drm_device_is_agp(dev) && dev->agp) { |
@@ -653,6 +661,7 @@ nouveau_mem_init(struct drm_device *dev) | |||
653 | dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), | 661 | dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1), |
654 | drm_get_resource_len(dev, 1), | 662 | drm_get_resource_len(dev, 1), |
655 | DRM_MTRR_WC); | 663 | DRM_MTRR_WC); |
664 | |||
656 | return 0; | 665 | return 0; |
657 | } | 666 | } |
658 | 667 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index 09b9a46dfc0e..f2d0187ba152 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -525,6 +525,7 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
525 | engine->mc.takedown(dev); | 525 | engine->mc.takedown(dev); |
526 | 526 | ||
527 | mutex_lock(&dev->struct_mutex); | 527 | mutex_lock(&dev->struct_mutex); |
528 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM); | ||
528 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); | 529 | ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_TT); |
529 | mutex_unlock(&dev->struct_mutex); | 530 | mutex_unlock(&dev->struct_mutex); |
530 | nouveau_sgdma_takedown(dev); | 531 | nouveau_sgdma_takedown(dev); |
diff --git a/drivers/gpu/drm/nouveau/nv04_instmem.c b/drivers/gpu/drm/nouveau/nv04_instmem.c index a20c206625a2..a3b9563a6f60 100644 --- a/drivers/gpu/drm/nouveau/nv04_instmem.c +++ b/drivers/gpu/drm/nouveau/nv04_instmem.c | |||
@@ -30,7 +30,7 @@ nv04_instmem_determine_amount(struct drm_device *dev) | |||
30 | * of vram. For now, only reserve a small piece until we know | 30 | * of vram. For now, only reserve a small piece until we know |
31 | * more about what each chipset requires. | 31 | * more about what each chipset requires. |
32 | */ | 32 | */ |
33 | switch (dev_priv->chipset & 0xf0) { | 33 | switch (dev_priv->chipset) { |
34 | case 0x40: | 34 | case 0x40: |
35 | case 0x47: | 35 | case 0x47: |
36 | case 0x49: | 36 | case 0x49: |
diff --git a/drivers/gpu/drm/nouveau/nv50_crtc.c b/drivers/gpu/drm/nouveau/nv50_crtc.c index 118d3285fd8c..40b7360841f8 100644 --- a/drivers/gpu/drm/nouveau/nv50_crtc.c +++ b/drivers/gpu/drm/nouveau/nv50_crtc.c | |||
@@ -432,6 +432,7 @@ nv50_crtc_prepare(struct drm_crtc *crtc) | |||
432 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); | 432 | struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); |
433 | struct drm_device *dev = crtc->dev; | 433 | struct drm_device *dev = crtc->dev; |
434 | struct drm_encoder *encoder; | 434 | struct drm_encoder *encoder; |
435 | uint32_t dac = 0, sor = 0; | ||
435 | 436 | ||
436 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); | 437 | NV_DEBUG_KMS(dev, "index %d\n", nv_crtc->index); |
437 | 438 | ||
@@ -439,9 +440,28 @@ nv50_crtc_prepare(struct drm_crtc *crtc) | |||
439 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 440 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
440 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 441 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
441 | 442 | ||
442 | if (drm_helper_encoder_in_use(encoder)) | 443 | if (!drm_helper_encoder_in_use(encoder)) |
443 | continue; | 444 | continue; |
444 | 445 | ||
446 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
447 | nv_encoder->dcb->type == OUTPUT_TV) | ||
448 | dac |= (1 << nv_encoder->or); | ||
449 | else | ||
450 | sor |= (1 << nv_encoder->or); | ||
451 | } | ||
452 | |||
453 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
454 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | ||
455 | |||
456 | if (nv_encoder->dcb->type == OUTPUT_ANALOG || | ||
457 | nv_encoder->dcb->type == OUTPUT_TV) { | ||
458 | if (dac & (1 << nv_encoder->or)) | ||
459 | continue; | ||
460 | } else { | ||
461 | if (sor & (1 << nv_encoder->or)) | ||
462 | continue; | ||
463 | } | ||
464 | |||
445 | nv_encoder->disconnect(nv_encoder); | 465 | nv_encoder->disconnect(nv_encoder); |
446 | } | 466 | } |
447 | 467 | ||
diff --git a/drivers/gpu/drm/nouveau/nv50_fifo.c b/drivers/gpu/drm/nouveau/nv50_fifo.c index 39caf167587d..32b244bcb482 100644 --- a/drivers/gpu/drm/nouveau/nv50_fifo.c +++ b/drivers/gpu/drm/nouveau/nv50_fifo.c | |||
@@ -272,7 +272,7 @@ nv50_fifo_create_context(struct nouveau_channel *chan) | |||
272 | return ret; | 272 | return ret; |
273 | ramfc = chan->ramfc->gpuobj; | 273 | ramfc = chan->ramfc->gpuobj; |
274 | 274 | ||
275 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 256, | 275 | ret = nouveau_gpuobj_new_ref(dev, chan, NULL, 0, 4096, 1024, |
276 | 0, &chan->cache); | 276 | 0, &chan->cache); |
277 | if (ret) | 277 | if (ret) |
278 | return ret; | 278 | return ret; |
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); |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index e395c16d30f5..ecf1936b8224 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -90,11 +90,24 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) | |||
90 | { | 90 | { |
91 | struct drm_device *dev = encoder->dev; | 91 | struct drm_device *dev = encoder->dev; |
92 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); | 92 | struct nouveau_encoder *nv_encoder = nouveau_encoder(encoder); |
93 | struct drm_encoder *enc; | ||
93 | uint32_t val; | 94 | uint32_t val; |
94 | int or = nv_encoder->or; | 95 | int or = nv_encoder->or; |
95 | 96 | ||
96 | NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); | 97 | NV_DEBUG_KMS(dev, "or %d mode %d\n", or, mode); |
97 | 98 | ||
99 | nv_encoder->last_dpms = mode; | ||
100 | list_for_each_entry(enc, &dev->mode_config.encoder_list, head) { | ||
101 | struct nouveau_encoder *nvenc = nouveau_encoder(enc); | ||
102 | |||
103 | if (nvenc == nv_encoder || | ||
104 | nvenc->dcb->or != nv_encoder->dcb->or) | ||
105 | continue; | ||
106 | |||
107 | if (nvenc->last_dpms == DRM_MODE_DPMS_ON) | ||
108 | return; | ||
109 | } | ||
110 | |||
98 | /* wait for it to be done */ | 111 | /* wait for it to be done */ |
99 | if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), | 112 | if (!nv_wait(NV50_PDISPLAY_SOR_DPMS_CTRL(or), |
100 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { | 113 | NV50_PDISPLAY_SOR_DPMS_CTRL_PENDING, 0)) { |
diff --git a/drivers/gpu/drm/radeon/atom.c b/drivers/gpu/drm/radeon/atom.c index 388140a7e651..e3b44562d265 100644 --- a/drivers/gpu/drm/radeon/atom.c +++ b/drivers/gpu/drm/radeon/atom.c | |||
@@ -246,6 +246,9 @@ static uint32_t atom_get_src_int(atom_exec_context *ctx, uint8_t attr, | |||
246 | case ATOM_WS_ATTRIBUTES: | 246 | case ATOM_WS_ATTRIBUTES: |
247 | val = gctx->io_attr; | 247 | val = gctx->io_attr; |
248 | break; | 248 | break; |
249 | case ATOM_WS_REGPTR: | ||
250 | val = gctx->reg_block; | ||
251 | break; | ||
249 | default: | 252 | default: |
250 | val = ctx->ws[idx]; | 253 | val = ctx->ws[idx]; |
251 | } | 254 | } |
@@ -385,6 +388,32 @@ static uint32_t atom_get_src(atom_exec_context *ctx, uint8_t attr, int *ptr) | |||
385 | return atom_get_src_int(ctx, attr, ptr, NULL, 1); | 388 | return atom_get_src_int(ctx, attr, ptr, NULL, 1); |
386 | } | 389 | } |
387 | 390 | ||
391 | static uint32_t atom_get_src_direct(atom_exec_context *ctx, uint8_t align, int *ptr) | ||
392 | { | ||
393 | uint32_t val = 0xCDCDCDCD; | ||
394 | |||
395 | switch (align) { | ||
396 | case ATOM_SRC_DWORD: | ||
397 | val = U32(*ptr); | ||
398 | (*ptr) += 4; | ||
399 | break; | ||
400 | case ATOM_SRC_WORD0: | ||
401 | case ATOM_SRC_WORD8: | ||
402 | case ATOM_SRC_WORD16: | ||
403 | val = U16(*ptr); | ||
404 | (*ptr) += 2; | ||
405 | break; | ||
406 | case ATOM_SRC_BYTE0: | ||
407 | case ATOM_SRC_BYTE8: | ||
408 | case ATOM_SRC_BYTE16: | ||
409 | case ATOM_SRC_BYTE24: | ||
410 | val = U8(*ptr); | ||
411 | (*ptr)++; | ||
412 | break; | ||
413 | } | ||
414 | return val; | ||
415 | } | ||
416 | |||
388 | static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr, | 417 | static uint32_t atom_get_dst(atom_exec_context *ctx, int arg, uint8_t attr, |
389 | int *ptr, uint32_t *saved, int print) | 418 | int *ptr, uint32_t *saved, int print) |
390 | { | 419 | { |
@@ -482,6 +511,9 @@ static void atom_put_dst(atom_exec_context *ctx, int arg, uint8_t attr, | |||
482 | case ATOM_WS_ATTRIBUTES: | 511 | case ATOM_WS_ATTRIBUTES: |
483 | gctx->io_attr = val; | 512 | gctx->io_attr = val; |
484 | break; | 513 | break; |
514 | case ATOM_WS_REGPTR: | ||
515 | gctx->reg_block = val; | ||
516 | break; | ||
485 | default: | 517 | default: |
486 | ctx->ws[idx] = val; | 518 | ctx->ws[idx] = val; |
487 | } | 519 | } |
@@ -677,7 +709,7 @@ static void atom_op_mask(atom_exec_context *ctx, int *ptr, int arg) | |||
677 | SDEBUG(" dst: "); | 709 | SDEBUG(" dst: "); |
678 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | 710 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); |
679 | SDEBUG(" src1: "); | 711 | SDEBUG(" src1: "); |
680 | src1 = atom_get_src(ctx, attr, ptr); | 712 | src1 = atom_get_src_direct(ctx, ((attr >> 3) & 7), ptr); |
681 | SDEBUG(" src2: "); | 713 | SDEBUG(" src2: "); |
682 | src2 = atom_get_src(ctx, attr, ptr); | 714 | src2 = atom_get_src(ctx, attr, ptr); |
683 | dst &= src1; | 715 | dst &= src1; |
@@ -809,6 +841,38 @@ static void atom_op_setregblock(atom_exec_context *ctx, int *ptr, int arg) | |||
809 | SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block); | 841 | SDEBUG(" base: 0x%04X\n", ctx->ctx->reg_block); |
810 | } | 842 | } |
811 | 843 | ||
844 | static void atom_op_shift_left(atom_exec_context *ctx, int *ptr, int arg) | ||
845 | { | ||
846 | uint8_t attr = U8((*ptr)++), shift; | ||
847 | uint32_t saved, dst; | ||
848 | int dptr = *ptr; | ||
849 | attr &= 0x38; | ||
850 | attr |= atom_def_dst[attr >> 3] << 6; | ||
851 | SDEBUG(" dst: "); | ||
852 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
853 | shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); | ||
854 | SDEBUG(" shift: %d\n", shift); | ||
855 | dst <<= shift; | ||
856 | SDEBUG(" dst: "); | ||
857 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
858 | } | ||
859 | |||
860 | static void atom_op_shift_right(atom_exec_context *ctx, int *ptr, int arg) | ||
861 | { | ||
862 | uint8_t attr = U8((*ptr)++), shift; | ||
863 | uint32_t saved, dst; | ||
864 | int dptr = *ptr; | ||
865 | attr &= 0x38; | ||
866 | attr |= atom_def_dst[attr >> 3] << 6; | ||
867 | SDEBUG(" dst: "); | ||
868 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | ||
869 | shift = atom_get_src_direct(ctx, ATOM_SRC_BYTE0, ptr); | ||
870 | SDEBUG(" shift: %d\n", shift); | ||
871 | dst >>= shift; | ||
872 | SDEBUG(" dst: "); | ||
873 | atom_put_dst(ctx, arg, attr, &dptr, dst, saved); | ||
874 | } | ||
875 | |||
812 | static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) | 876 | static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) |
813 | { | 877 | { |
814 | uint8_t attr = U8((*ptr)++), shift; | 878 | uint8_t attr = U8((*ptr)++), shift; |
@@ -818,7 +882,7 @@ static void atom_op_shl(atom_exec_context *ctx, int *ptr, int arg) | |||
818 | attr |= atom_def_dst[attr >> 3] << 6; | 882 | attr |= atom_def_dst[attr >> 3] << 6; |
819 | SDEBUG(" dst: "); | 883 | SDEBUG(" dst: "); |
820 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | 884 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); |
821 | shift = U8((*ptr)++); | 885 | shift = atom_get_src(ctx, attr, ptr); |
822 | SDEBUG(" shift: %d\n", shift); | 886 | SDEBUG(" shift: %d\n", shift); |
823 | dst <<= shift; | 887 | dst <<= shift; |
824 | SDEBUG(" dst: "); | 888 | SDEBUG(" dst: "); |
@@ -834,7 +898,7 @@ static void atom_op_shr(atom_exec_context *ctx, int *ptr, int arg) | |||
834 | attr |= atom_def_dst[attr >> 3] << 6; | 898 | attr |= atom_def_dst[attr >> 3] << 6; |
835 | SDEBUG(" dst: "); | 899 | SDEBUG(" dst: "); |
836 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); | 900 | dst = atom_get_dst(ctx, arg, attr, ptr, &saved, 1); |
837 | shift = U8((*ptr)++); | 901 | shift = atom_get_src(ctx, attr, ptr); |
838 | SDEBUG(" shift: %d\n", shift); | 902 | SDEBUG(" shift: %d\n", shift); |
839 | dst >>= shift; | 903 | dst >>= shift; |
840 | SDEBUG(" dst: "); | 904 | SDEBUG(" dst: "); |
@@ -937,18 +1001,18 @@ static struct { | |||
937 | atom_op_or, ATOM_ARG_FB}, { | 1001 | atom_op_or, ATOM_ARG_FB}, { |
938 | atom_op_or, ATOM_ARG_PLL}, { | 1002 | atom_op_or, ATOM_ARG_PLL}, { |
939 | atom_op_or, ATOM_ARG_MC}, { | 1003 | atom_op_or, ATOM_ARG_MC}, { |
940 | atom_op_shl, ATOM_ARG_REG}, { | 1004 | atom_op_shift_left, ATOM_ARG_REG}, { |
941 | atom_op_shl, ATOM_ARG_PS}, { | 1005 | atom_op_shift_left, ATOM_ARG_PS}, { |
942 | atom_op_shl, ATOM_ARG_WS}, { | 1006 | atom_op_shift_left, ATOM_ARG_WS}, { |
943 | atom_op_shl, ATOM_ARG_FB}, { | 1007 | atom_op_shift_left, ATOM_ARG_FB}, { |
944 | atom_op_shl, ATOM_ARG_PLL}, { | 1008 | atom_op_shift_left, ATOM_ARG_PLL}, { |
945 | atom_op_shl, ATOM_ARG_MC}, { | 1009 | atom_op_shift_left, ATOM_ARG_MC}, { |
946 | atom_op_shr, ATOM_ARG_REG}, { | 1010 | atom_op_shift_right, ATOM_ARG_REG}, { |
947 | atom_op_shr, ATOM_ARG_PS}, { | 1011 | atom_op_shift_right, ATOM_ARG_PS}, { |
948 | atom_op_shr, ATOM_ARG_WS}, { | 1012 | atom_op_shift_right, ATOM_ARG_WS}, { |
949 | atom_op_shr, ATOM_ARG_FB}, { | 1013 | atom_op_shift_right, ATOM_ARG_FB}, { |
950 | atom_op_shr, ATOM_ARG_PLL}, { | 1014 | atom_op_shift_right, ATOM_ARG_PLL}, { |
951 | atom_op_shr, ATOM_ARG_MC}, { | 1015 | atom_op_shift_right, ATOM_ARG_MC}, { |
952 | atom_op_mul, ATOM_ARG_REG}, { | 1016 | atom_op_mul, ATOM_ARG_REG}, { |
953 | atom_op_mul, ATOM_ARG_PS}, { | 1017 | atom_op_mul, ATOM_ARG_PS}, { |
954 | atom_op_mul, ATOM_ARG_WS}, { | 1018 | atom_op_mul, ATOM_ARG_WS}, { |
@@ -1058,8 +1122,6 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1058 | 1122 | ||
1059 | SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps); | 1123 | SDEBUG(">> execute %04X (len %d, WS %d, PS %d)\n", base, len, ws, ps); |
1060 | 1124 | ||
1061 | /* reset reg block */ | ||
1062 | ctx->reg_block = 0; | ||
1063 | ectx.ctx = ctx; | 1125 | ectx.ctx = ctx; |
1064 | ectx.ps_shift = ps / 4; | 1126 | ectx.ps_shift = ps / 4; |
1065 | ectx.start = base; | 1127 | ectx.start = base; |
@@ -1096,6 +1158,12 @@ static void atom_execute_table_locked(struct atom_context *ctx, int index, uint3 | |||
1096 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) | 1158 | void atom_execute_table(struct atom_context *ctx, int index, uint32_t * params) |
1097 | { | 1159 | { |
1098 | mutex_lock(&ctx->mutex); | 1160 | mutex_lock(&ctx->mutex); |
1161 | /* reset reg block */ | ||
1162 | ctx->reg_block = 0; | ||
1163 | /* reset fb window */ | ||
1164 | ctx->fb_base = 0; | ||
1165 | /* reset io mode */ | ||
1166 | ctx->io_mode = ATOM_IO_MM; | ||
1099 | atom_execute_table_locked(ctx, index, params); | 1167 | atom_execute_table_locked(ctx, index, params); |
1100 | mutex_unlock(&ctx->mutex); | 1168 | mutex_unlock(&ctx->mutex); |
1101 | } | 1169 | } |
diff --git a/drivers/gpu/drm/radeon/atom.h b/drivers/gpu/drm/radeon/atom.h index 47fd943f6d14..bc73781423a1 100644 --- a/drivers/gpu/drm/radeon/atom.h +++ b/drivers/gpu/drm/radeon/atom.h | |||
@@ -91,6 +91,7 @@ | |||
91 | #define ATOM_WS_AND_MASK 0x45 | 91 | #define ATOM_WS_AND_MASK 0x45 |
92 | #define ATOM_WS_FB_WINDOW 0x46 | 92 | #define ATOM_WS_FB_WINDOW 0x46 |
93 | #define ATOM_WS_ATTRIBUTES 0x47 | 93 | #define ATOM_WS_ATTRIBUTES 0x47 |
94 | #define ATOM_WS_REGPTR 0x48 | ||
94 | 95 | ||
95 | #define ATOM_IIO_NOP 0 | 96 | #define ATOM_IIO_NOP 0 |
96 | #define ATOM_IIO_START 1 | 97 | #define ATOM_IIO_START 1 |
diff --git a/drivers/gpu/drm/radeon/atombios_crtc.c b/drivers/gpu/drm/radeon/atombios_crtc.c index 260fcf59f00c..af464e351fbd 100644 --- a/drivers/gpu/drm/radeon/atombios_crtc.c +++ b/drivers/gpu/drm/radeon/atombios_crtc.c | |||
@@ -307,7 +307,6 @@ atombios_set_crtc_dtd_timing(struct drm_crtc *crtc, | |||
307 | args.susModeMiscInfo.usAccess = cpu_to_le16(misc); | 307 | args.susModeMiscInfo.usAccess = cpu_to_le16(misc); |
308 | args.ucCRTC = radeon_crtc->crtc_id; | 308 | args.ucCRTC = radeon_crtc->crtc_id; |
309 | 309 | ||
310 | printk("executing set crtc dtd timing\n"); | ||
311 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 310 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
312 | } | 311 | } |
313 | 312 | ||
@@ -347,7 +346,6 @@ static void atombios_crtc_set_timing(struct drm_crtc *crtc, | |||
347 | args.susModeMiscInfo.usAccess = cpu_to_le16(misc); | 346 | args.susModeMiscInfo.usAccess = cpu_to_le16(misc); |
348 | args.ucCRTC = radeon_crtc->crtc_id; | 347 | args.ucCRTC = radeon_crtc->crtc_id; |
349 | 348 | ||
350 | printk("executing set crtc timing\n"); | ||
351 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 349 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
352 | } | 350 | } |
353 | 351 | ||
@@ -409,59 +407,57 @@ static void atombios_set_ss(struct drm_crtc *crtc, int enable) | |||
409 | } | 407 | } |
410 | } | 408 | } |
411 | 409 | ||
412 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | 410 | union adjust_pixel_clock { |
411 | ADJUST_DISPLAY_PLL_PS_ALLOCATION v1; | ||
412 | }; | ||
413 | |||
414 | static u32 atombios_adjust_pll(struct drm_crtc *crtc, | ||
415 | struct drm_display_mode *mode, | ||
416 | struct radeon_pll *pll) | ||
413 | { | 417 | { |
414 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
415 | struct drm_device *dev = crtc->dev; | 418 | struct drm_device *dev = crtc->dev; |
416 | struct radeon_device *rdev = dev->dev_private; | 419 | struct radeon_device *rdev = dev->dev_private; |
417 | struct drm_encoder *encoder = NULL; | 420 | struct drm_encoder *encoder = NULL; |
418 | struct radeon_encoder *radeon_encoder = NULL; | 421 | struct radeon_encoder *radeon_encoder = NULL; |
419 | uint8_t frev, crev; | 422 | u32 adjusted_clock = mode->clock; |
420 | int index; | ||
421 | SET_PIXEL_CLOCK_PS_ALLOCATION args; | ||
422 | PIXEL_CLOCK_PARAMETERS *spc1_ptr; | ||
423 | PIXEL_CLOCK_PARAMETERS_V2 *spc2_ptr; | ||
424 | PIXEL_CLOCK_PARAMETERS_V3 *spc3_ptr; | ||
425 | uint32_t pll_clock = mode->clock; | ||
426 | uint32_t adjusted_clock; | ||
427 | uint32_t ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
428 | struct radeon_pll *pll; | ||
429 | int pll_flags = 0; | ||
430 | 423 | ||
431 | memset(&args, 0, sizeof(args)); | 424 | /* reset the pll flags */ |
425 | pll->flags = 0; | ||
432 | 426 | ||
433 | if (ASIC_IS_AVIVO(rdev)) { | 427 | if (ASIC_IS_AVIVO(rdev)) { |
434 | if ((rdev->family == CHIP_RS600) || | 428 | if ((rdev->family == CHIP_RS600) || |
435 | (rdev->family == CHIP_RS690) || | 429 | (rdev->family == CHIP_RS690) || |
436 | (rdev->family == CHIP_RS740)) | 430 | (rdev->family == CHIP_RS740)) |
437 | pll_flags |= (RADEON_PLL_USE_FRAC_FB_DIV | | 431 | pll->flags |= (RADEON_PLL_USE_FRAC_FB_DIV | |
438 | RADEON_PLL_PREFER_CLOSEST_LOWER); | 432 | RADEON_PLL_PREFER_CLOSEST_LOWER); |
439 | 433 | ||
440 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ | 434 | if (ASIC_IS_DCE32(rdev) && mode->clock > 200000) /* range limits??? */ |
441 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 435 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
442 | else | 436 | else |
443 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 437 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
444 | } else { | 438 | } else { |
445 | pll_flags |= RADEON_PLL_LEGACY; | 439 | pll->flags |= RADEON_PLL_LEGACY; |
446 | 440 | ||
447 | if (mode->clock > 200000) /* range limits??? */ | 441 | if (mode->clock > 200000) /* range limits??? */ |
448 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 442 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
449 | else | 443 | else |
450 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 444 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
451 | 445 | ||
452 | } | 446 | } |
453 | 447 | ||
454 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 448 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
455 | if (encoder->crtc == crtc) { | 449 | if (encoder->crtc == crtc) { |
456 | if (!ASIC_IS_AVIVO(rdev)) { | ||
457 | if (encoder->encoder_type != | ||
458 | DRM_MODE_ENCODER_DAC) | ||
459 | pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; | ||
460 | if (encoder->encoder_type == | ||
461 | DRM_MODE_ENCODER_LVDS) | ||
462 | pll_flags |= RADEON_PLL_USE_REF_DIV; | ||
463 | } | ||
464 | radeon_encoder = to_radeon_encoder(encoder); | 450 | radeon_encoder = to_radeon_encoder(encoder); |
451 | if (ASIC_IS_AVIVO(rdev)) { | ||
452 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | ||
453 | if (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1) | ||
454 | adjusted_clock = mode->clock * 2; | ||
455 | } else { | ||
456 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | ||
457 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; | ||
458 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) | ||
459 | pll->flags |= RADEON_PLL_USE_REF_DIV; | ||
460 | } | ||
465 | break; | 461 | break; |
466 | } | 462 | } |
467 | } | 463 | } |
@@ -471,46 +467,101 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
471 | * special hw requirements. | 467 | * special hw requirements. |
472 | */ | 468 | */ |
473 | if (ASIC_IS_DCE3(rdev)) { | 469 | if (ASIC_IS_DCE3(rdev)) { |
474 | ADJUST_DISPLAY_PLL_PS_ALLOCATION adjust_pll_args; | 470 | union adjust_pixel_clock args; |
471 | struct radeon_encoder_atom_dig *dig; | ||
472 | u8 frev, crev; | ||
473 | int index; | ||
475 | 474 | ||
476 | if (!encoder) | 475 | if (!radeon_encoder->enc_priv) |
477 | return; | 476 | return adjusted_clock; |
478 | 477 | dig = radeon_encoder->enc_priv; | |
479 | memset(&adjust_pll_args, 0, sizeof(adjust_pll_args)); | ||
480 | adjust_pll_args.usPixelClock = cpu_to_le16(mode->clock / 10); | ||
481 | adjust_pll_args.ucTransmitterID = radeon_encoder->encoder_id; | ||
482 | adjust_pll_args.ucEncodeMode = atombios_get_encoder_mode(encoder); | ||
483 | 478 | ||
484 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); | 479 | index = GetIndexIntoMasterTable(COMMAND, AdjustDisplayPll); |
485 | atom_execute_table(rdev->mode_info.atom_context, | 480 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
486 | index, (uint32_t *)&adjust_pll_args); | 481 | &crev); |
487 | adjusted_clock = le16_to_cpu(adjust_pll_args.usPixelClock) * 10; | 482 | |
488 | } else { | 483 | memset(&args, 0, sizeof(args)); |
489 | /* DVO wants 2x pixel clock if the DVO chip is in 12 bit mode */ | 484 | |
490 | if (ASIC_IS_AVIVO(rdev) && | 485 | switch (frev) { |
491 | (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DVO1)) | 486 | case 1: |
492 | adjusted_clock = mode->clock * 2; | 487 | switch (crev) { |
493 | else | 488 | case 1: |
494 | adjusted_clock = mode->clock; | 489 | case 2: |
490 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); | ||
491 | args.v1.ucTransmitterID = radeon_encoder->encoder_id; | ||
492 | args.v1.ucEncodeMode = atombios_get_encoder_mode(encoder); | ||
493 | |||
494 | atom_execute_table(rdev->mode_info.atom_context, | ||
495 | index, (uint32_t *)&args); | ||
496 | adjusted_clock = le16_to_cpu(args.v1.usPixelClock) * 10; | ||
497 | break; | ||
498 | default: | ||
499 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
500 | return adjusted_clock; | ||
501 | } | ||
502 | break; | ||
503 | default: | ||
504 | DRM_ERROR("Unknown table version %d %d\n", frev, crev); | ||
505 | return adjusted_clock; | ||
506 | } | ||
495 | } | 507 | } |
508 | return adjusted_clock; | ||
509 | } | ||
510 | |||
511 | union set_pixel_clock { | ||
512 | SET_PIXEL_CLOCK_PS_ALLOCATION base; | ||
513 | PIXEL_CLOCK_PARAMETERS v1; | ||
514 | PIXEL_CLOCK_PARAMETERS_V2 v2; | ||
515 | PIXEL_CLOCK_PARAMETERS_V3 v3; | ||
516 | }; | ||
517 | |||
518 | void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | ||
519 | { | ||
520 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
521 | struct drm_device *dev = crtc->dev; | ||
522 | struct radeon_device *rdev = dev->dev_private; | ||
523 | struct drm_encoder *encoder = NULL; | ||
524 | struct radeon_encoder *radeon_encoder = NULL; | ||
525 | u8 frev, crev; | ||
526 | int index; | ||
527 | union set_pixel_clock args; | ||
528 | u32 pll_clock = mode->clock; | ||
529 | u32 ref_div = 0, fb_div = 0, frac_fb_div = 0, post_div = 0; | ||
530 | struct radeon_pll *pll; | ||
531 | u32 adjusted_clock; | ||
532 | |||
533 | memset(&args, 0, sizeof(args)); | ||
534 | |||
535 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | ||
536 | if (encoder->crtc == crtc) { | ||
537 | radeon_encoder = to_radeon_encoder(encoder); | ||
538 | break; | ||
539 | } | ||
540 | } | ||
541 | |||
542 | if (!radeon_encoder) | ||
543 | return; | ||
496 | 544 | ||
497 | if (radeon_crtc->crtc_id == 0) | 545 | if (radeon_crtc->crtc_id == 0) |
498 | pll = &rdev->clock.p1pll; | 546 | pll = &rdev->clock.p1pll; |
499 | else | 547 | else |
500 | pll = &rdev->clock.p2pll; | 548 | pll = &rdev->clock.p2pll; |
501 | 549 | ||
550 | /* adjust pixel clock as needed */ | ||
551 | adjusted_clock = atombios_adjust_pll(crtc, mode, pll); | ||
552 | |||
502 | if (ASIC_IS_AVIVO(rdev)) { | 553 | if (ASIC_IS_AVIVO(rdev)) { |
503 | if (radeon_new_pll) | 554 | if (radeon_new_pll) |
504 | radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, | 555 | radeon_compute_pll_avivo(pll, adjusted_clock, &pll_clock, |
505 | &fb_div, &frac_fb_div, | 556 | &fb_div, &frac_fb_div, |
506 | &ref_div, &post_div, pll_flags); | 557 | &ref_div, &post_div); |
507 | else | 558 | else |
508 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, | 559 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, |
509 | &fb_div, &frac_fb_div, | 560 | &fb_div, &frac_fb_div, |
510 | &ref_div, &post_div, pll_flags); | 561 | &ref_div, &post_div); |
511 | } else | 562 | } else |
512 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, | 563 | radeon_compute_pll(pll, adjusted_clock, &pll_clock, &fb_div, &frac_fb_div, |
513 | &ref_div, &post_div, pll_flags); | 564 | &ref_div, &post_div); |
514 | 565 | ||
515 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); | 566 | index = GetIndexIntoMasterTable(COMMAND, SetPixelClock); |
516 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, | 567 | atom_parse_cmd_header(rdev->mode_info.atom_context, index, &frev, |
@@ -520,45 +571,38 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
520 | case 1: | 571 | case 1: |
521 | switch (crev) { | 572 | switch (crev) { |
522 | case 1: | 573 | case 1: |
523 | spc1_ptr = (PIXEL_CLOCK_PARAMETERS *) & args.sPCLKInput; | 574 | args.v1.usPixelClock = cpu_to_le16(mode->clock / 10); |
524 | spc1_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 575 | args.v1.usRefDiv = cpu_to_le16(ref_div); |
525 | spc1_ptr->usRefDiv = cpu_to_le16(ref_div); | 576 | args.v1.usFbDiv = cpu_to_le16(fb_div); |
526 | spc1_ptr->usFbDiv = cpu_to_le16(fb_div); | 577 | args.v1.ucFracFbDiv = frac_fb_div; |
527 | spc1_ptr->ucFracFbDiv = frac_fb_div; | 578 | args.v1.ucPostDiv = post_div; |
528 | spc1_ptr->ucPostDiv = post_div; | 579 | args.v1.ucPpll = |
529 | spc1_ptr->ucPpll = | ||
530 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 580 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
531 | spc1_ptr->ucCRTC = radeon_crtc->crtc_id; | 581 | args.v1.ucCRTC = radeon_crtc->crtc_id; |
532 | spc1_ptr->ucRefDivSrc = 1; | 582 | args.v1.ucRefDivSrc = 1; |
533 | break; | 583 | break; |
534 | case 2: | 584 | case 2: |
535 | spc2_ptr = | 585 | args.v2.usPixelClock = cpu_to_le16(mode->clock / 10); |
536 | (PIXEL_CLOCK_PARAMETERS_V2 *) & args.sPCLKInput; | 586 | args.v2.usRefDiv = cpu_to_le16(ref_div); |
537 | spc2_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 587 | args.v2.usFbDiv = cpu_to_le16(fb_div); |
538 | spc2_ptr->usRefDiv = cpu_to_le16(ref_div); | 588 | args.v2.ucFracFbDiv = frac_fb_div; |
539 | spc2_ptr->usFbDiv = cpu_to_le16(fb_div); | 589 | args.v2.ucPostDiv = post_div; |
540 | spc2_ptr->ucFracFbDiv = frac_fb_div; | 590 | args.v2.ucPpll = |
541 | spc2_ptr->ucPostDiv = post_div; | ||
542 | spc2_ptr->ucPpll = | ||
543 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 591 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
544 | spc2_ptr->ucCRTC = radeon_crtc->crtc_id; | 592 | args.v2.ucCRTC = radeon_crtc->crtc_id; |
545 | spc2_ptr->ucRefDivSrc = 1; | 593 | args.v2.ucRefDivSrc = 1; |
546 | break; | 594 | break; |
547 | case 3: | 595 | case 3: |
548 | if (!encoder) | 596 | args.v3.usPixelClock = cpu_to_le16(mode->clock / 10); |
549 | return; | 597 | args.v3.usRefDiv = cpu_to_le16(ref_div); |
550 | spc3_ptr = | 598 | args.v3.usFbDiv = cpu_to_le16(fb_div); |
551 | (PIXEL_CLOCK_PARAMETERS_V3 *) & args.sPCLKInput; | 599 | args.v3.ucFracFbDiv = frac_fb_div; |
552 | spc3_ptr->usPixelClock = cpu_to_le16(mode->clock / 10); | 600 | args.v3.ucPostDiv = post_div; |
553 | spc3_ptr->usRefDiv = cpu_to_le16(ref_div); | 601 | args.v3.ucPpll = |
554 | spc3_ptr->usFbDiv = cpu_to_le16(fb_div); | ||
555 | spc3_ptr->ucFracFbDiv = frac_fb_div; | ||
556 | spc3_ptr->ucPostDiv = post_div; | ||
557 | spc3_ptr->ucPpll = | ||
558 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; | 602 | radeon_crtc->crtc_id ? ATOM_PPLL2 : ATOM_PPLL1; |
559 | spc3_ptr->ucMiscInfo = (radeon_crtc->crtc_id << 2); | 603 | args.v3.ucMiscInfo = (radeon_crtc->crtc_id << 2); |
560 | spc3_ptr->ucTransmitterId = radeon_encoder->encoder_id; | 604 | args.v3.ucTransmitterId = radeon_encoder->encoder_id; |
561 | spc3_ptr->ucEncoderMode = | 605 | args.v3.ucEncoderMode = |
562 | atombios_get_encoder_mode(encoder); | 606 | atombios_get_encoder_mode(encoder); |
563 | break; | 607 | break; |
564 | default: | 608 | default: |
@@ -571,12 +615,11 @@ void atombios_crtc_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
571 | return; | 615 | return; |
572 | } | 616 | } |
573 | 617 | ||
574 | printk("executing set pll\n"); | ||
575 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); | 618 | atom_execute_table(rdev->mode_info.atom_context, index, (uint32_t *)&args); |
576 | } | 619 | } |
577 | 620 | ||
578 | int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 621 | static int avivo_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
579 | struct drm_framebuffer *old_fb) | 622 | struct drm_framebuffer *old_fb) |
580 | { | 623 | { |
581 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | 624 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); |
582 | struct drm_device *dev = crtc->dev; | 625 | struct drm_device *dev = crtc->dev; |
@@ -706,6 +749,42 @@ int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | |||
706 | return 0; | 749 | return 0; |
707 | } | 750 | } |
708 | 751 | ||
752 | int atombios_crtc_set_base(struct drm_crtc *crtc, int x, int y, | ||
753 | struct drm_framebuffer *old_fb) | ||
754 | { | ||
755 | struct drm_device *dev = crtc->dev; | ||
756 | struct radeon_device *rdev = dev->dev_private; | ||
757 | |||
758 | if (ASIC_IS_AVIVO(rdev)) | ||
759 | return avivo_crtc_set_base(crtc, x, y, old_fb); | ||
760 | else | ||
761 | return radeon_crtc_set_base(crtc, x, y, old_fb); | ||
762 | } | ||
763 | |||
764 | /* properly set additional regs when using atombios */ | ||
765 | static void radeon_legacy_atom_fixup(struct drm_crtc *crtc) | ||
766 | { | ||
767 | struct drm_device *dev = crtc->dev; | ||
768 | struct radeon_device *rdev = dev->dev_private; | ||
769 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
770 | u32 disp_merge_cntl; | ||
771 | |||
772 | switch (radeon_crtc->crtc_id) { | ||
773 | case 0: | ||
774 | disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); | ||
775 | disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; | ||
776 | WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); | ||
777 | break; | ||
778 | case 1: | ||
779 | disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); | ||
780 | disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; | ||
781 | WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); | ||
782 | WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); | ||
783 | WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); | ||
784 | break; | ||
785 | } | ||
786 | } | ||
787 | |||
709 | int atombios_crtc_mode_set(struct drm_crtc *crtc, | 788 | int atombios_crtc_mode_set(struct drm_crtc *crtc, |
710 | struct drm_display_mode *mode, | 789 | struct drm_display_mode *mode, |
711 | struct drm_display_mode *adjusted_mode, | 790 | struct drm_display_mode *adjusted_mode, |
@@ -727,8 +806,8 @@ int atombios_crtc_mode_set(struct drm_crtc *crtc, | |||
727 | else { | 806 | else { |
728 | if (radeon_crtc->crtc_id == 0) | 807 | if (radeon_crtc->crtc_id == 0) |
729 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); | 808 | atombios_set_crtc_dtd_timing(crtc, adjusted_mode); |
730 | radeon_crtc_set_base(crtc, x, y, old_fb); | 809 | atombios_crtc_set_base(crtc, x, y, old_fb); |
731 | radeon_legacy_atom_set_surface(crtc); | 810 | radeon_legacy_atom_fixup(crtc); |
732 | } | 811 | } |
733 | atombios_overscan_setup(crtc, mode, adjusted_mode); | 812 | atombios_overscan_setup(crtc, mode, adjusted_mode); |
734 | atombios_scaler_setup(crtc); | 813 | atombios_scaler_setup(crtc); |
@@ -746,8 +825,8 @@ static bool atombios_crtc_mode_fixup(struct drm_crtc *crtc, | |||
746 | 825 | ||
747 | static void atombios_crtc_prepare(struct drm_crtc *crtc) | 826 | static void atombios_crtc_prepare(struct drm_crtc *crtc) |
748 | { | 827 | { |
749 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | ||
750 | atombios_lock_crtc(crtc, 1); | 828 | atombios_lock_crtc(crtc, 1); |
829 | atombios_crtc_dpms(crtc, DRM_MODE_DPMS_OFF); | ||
751 | } | 830 | } |
752 | 831 | ||
753 | static void atombios_crtc_commit(struct drm_crtc *crtc) | 832 | static void atombios_crtc_commit(struct drm_crtc *crtc) |
diff --git a/drivers/gpu/drm/radeon/r100.c b/drivers/gpu/drm/radeon/r100.c index 8760d66e058a..11c9a3fe6810 100644 --- a/drivers/gpu/drm/radeon/r100.c +++ b/drivers/gpu/drm/radeon/r100.c | |||
@@ -1504,6 +1504,7 @@ static int r100_packet3_check(struct radeon_cs_parser *p, | |||
1504 | DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); | 1504 | DRM_ERROR("PRIM_WALK must be 3 for IMMD draw\n"); |
1505 | return -EINVAL; | 1505 | return -EINVAL; |
1506 | } | 1506 | } |
1507 | track->vtx_size = r100_get_vtx_size(radeon_get_ib_value(p, idx + 0)); | ||
1507 | track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); | 1508 | track->vap_vf_cntl = radeon_get_ib_value(p, idx + 1); |
1508 | track->immd_dwords = pkt->count - 1; | 1509 | track->immd_dwords = pkt->count - 1; |
1509 | r = r100_cs_track_check(p->rdev, track); | 1510 | r = r100_cs_track_check(p->rdev, track); |
@@ -3399,9 +3400,7 @@ int r100_mc_init(struct radeon_device *rdev) | |||
3399 | if (rdev->flags & RADEON_IS_AGP) { | 3400 | if (rdev->flags & RADEON_IS_AGP) { |
3400 | r = radeon_agp_init(rdev); | 3401 | r = radeon_agp_init(rdev); |
3401 | if (r) { | 3402 | if (r) { |
3402 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | 3403 | radeon_agp_disable(rdev); |
3403 | rdev->flags &= ~RADEON_IS_AGP; | ||
3404 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
3405 | } else { | 3404 | } else { |
3406 | rdev->mc.gtt_location = rdev->mc.agp_base; | 3405 | rdev->mc.gtt_location = rdev->mc.agp_base; |
3407 | } | 3406 | } |
diff --git a/drivers/gpu/drm/radeon/r200.c b/drivers/gpu/drm/radeon/r200.c index 20942127c46b..ff1e0cd608bf 100644 --- a/drivers/gpu/drm/radeon/r200.c +++ b/drivers/gpu/drm/radeon/r200.c | |||
@@ -371,13 +371,16 @@ int r200_packet0_check(struct radeon_cs_parser *p, | |||
371 | case 5: | 371 | case 5: |
372 | case 6: | 372 | case 6: |
373 | case 7: | 373 | case 7: |
374 | /* 1D/2D */ | ||
374 | track->textures[i].tex_coord_type = 0; | 375 | track->textures[i].tex_coord_type = 0; |
375 | break; | 376 | break; |
376 | case 1: | 377 | case 1: |
377 | track->textures[i].tex_coord_type = 1; | 378 | /* CUBE */ |
379 | track->textures[i].tex_coord_type = 2; | ||
378 | break; | 380 | break; |
379 | case 2: | 381 | case 2: |
380 | track->textures[i].tex_coord_type = 2; | 382 | /* 3D */ |
383 | track->textures[i].tex_coord_type = 1; | ||
381 | break; | 384 | break; |
382 | } | 385 | } |
383 | break; | 386 | break; |
diff --git a/drivers/gpu/drm/radeon/r420.c b/drivers/gpu/drm/radeon/r420.c index 053404e71a9d..4526faaacca8 100644 --- a/drivers/gpu/drm/radeon/r420.c +++ b/drivers/gpu/drm/radeon/r420.c | |||
@@ -50,9 +50,7 @@ int r420_mc_init(struct radeon_device *rdev) | |||
50 | if (rdev->flags & RADEON_IS_AGP) { | 50 | if (rdev->flags & RADEON_IS_AGP) { |
51 | r = radeon_agp_init(rdev); | 51 | r = radeon_agp_init(rdev); |
52 | if (r) { | 52 | if (r) { |
53 | printk(KERN_WARNING "[drm] Disabling AGP\n"); | 53 | radeon_agp_disable(rdev); |
54 | rdev->flags &= ~RADEON_IS_AGP; | ||
55 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
56 | } else { | 54 | } else { |
57 | rdev->mc.gtt_location = rdev->mc.agp_base; | 55 | rdev->mc.gtt_location = rdev->mc.agp_base; |
58 | } | 56 | } |
diff --git a/drivers/gpu/drm/radeon/r600.c b/drivers/gpu/drm/radeon/r600.c index f5ff3490929f..da9aa3c31bcf 100644 --- a/drivers/gpu/drm/radeon/r600.c +++ b/drivers/gpu/drm/radeon/r600.c | |||
@@ -624,7 +624,6 @@ int r600_mc_init(struct radeon_device *rdev) | |||
624 | fixed20_12 a; | 624 | fixed20_12 a; |
625 | u32 tmp; | 625 | u32 tmp; |
626 | int chansize, numchan; | 626 | int chansize, numchan; |
627 | int r; | ||
628 | 627 | ||
629 | /* Get VRAM informations */ | 628 | /* Get VRAM informations */ |
630 | rdev->mc.vram_is_ddr = true; | 629 | rdev->mc.vram_is_ddr = true; |
@@ -667,9 +666,6 @@ int r600_mc_init(struct radeon_device *rdev) | |||
667 | rdev->mc.real_vram_size = rdev->mc.aper_size; | 666 | rdev->mc.real_vram_size = rdev->mc.aper_size; |
668 | 667 | ||
669 | if (rdev->flags & RADEON_IS_AGP) { | 668 | if (rdev->flags & RADEON_IS_AGP) { |
670 | r = radeon_agp_init(rdev); | ||
671 | if (r) | ||
672 | return r; | ||
673 | /* gtt_size is setup by radeon_agp_init */ | 669 | /* gtt_size is setup by radeon_agp_init */ |
674 | rdev->mc.gtt_location = rdev->mc.agp_base; | 670 | rdev->mc.gtt_location = rdev->mc.agp_base; |
675 | tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; | 671 | tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; |
@@ -1958,14 +1954,17 @@ int r600_suspend(struct radeon_device *rdev) | |||
1958 | /* FIXME: we should wait for ring to be empty */ | 1954 | /* FIXME: we should wait for ring to be empty */ |
1959 | r600_cp_stop(rdev); | 1955 | r600_cp_stop(rdev); |
1960 | rdev->cp.ready = false; | 1956 | rdev->cp.ready = false; |
1957 | r600_irq_suspend(rdev); | ||
1961 | r600_wb_disable(rdev); | 1958 | r600_wb_disable(rdev); |
1962 | r600_pcie_gart_disable(rdev); | 1959 | r600_pcie_gart_disable(rdev); |
1963 | /* unpin shaders bo */ | 1960 | /* unpin shaders bo */ |
1964 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 1961 | if (rdev->r600_blit.shader_obj) { |
1965 | if (unlikely(r != 0)) | 1962 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); |
1966 | return r; | 1963 | if (!r) { |
1967 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | 1964 | radeon_bo_unpin(rdev->r600_blit.shader_obj); |
1968 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 1965 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
1966 | } | ||
1967 | } | ||
1969 | return 0; | 1968 | return 0; |
1970 | } | 1969 | } |
1971 | 1970 | ||
@@ -2026,6 +2025,11 @@ int r600_init(struct radeon_device *rdev) | |||
2026 | r = radeon_fence_driver_init(rdev); | 2025 | r = radeon_fence_driver_init(rdev); |
2027 | if (r) | 2026 | if (r) |
2028 | return r; | 2027 | return r; |
2028 | if (rdev->flags & RADEON_IS_AGP) { | ||
2029 | r = radeon_agp_init(rdev); | ||
2030 | if (r) | ||
2031 | radeon_agp_disable(rdev); | ||
2032 | } | ||
2029 | r = r600_mc_init(rdev); | 2033 | r = r600_mc_init(rdev); |
2030 | if (r) | 2034 | if (r) |
2031 | return r; | 2035 | return r; |
@@ -2060,13 +2064,14 @@ int r600_init(struct radeon_device *rdev) | |||
2060 | if (rdev->accel_working) { | 2064 | if (rdev->accel_working) { |
2061 | r = radeon_ib_pool_init(rdev); | 2065 | r = radeon_ib_pool_init(rdev); |
2062 | if (r) { | 2066 | if (r) { |
2063 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); | 2067 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
2064 | rdev->accel_working = false; | ||
2065 | } | ||
2066 | r = r600_ib_test(rdev); | ||
2067 | if (r) { | ||
2068 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); | ||
2069 | rdev->accel_working = false; | 2068 | rdev->accel_working = false; |
2069 | } else { | ||
2070 | r = r600_ib_test(rdev); | ||
2071 | if (r) { | ||
2072 | dev_err(rdev->dev, "IB test failed (%d).\n", r); | ||
2073 | rdev->accel_working = false; | ||
2074 | } | ||
2070 | } | 2075 | } |
2071 | } | 2076 | } |
2072 | 2077 | ||
@@ -2197,14 +2202,14 @@ void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size) | |||
2197 | rb_bufsz = drm_order(ring_size / 4); | 2202 | rb_bufsz = drm_order(ring_size / 4); |
2198 | ring_size = (1 << rb_bufsz) * 4; | 2203 | ring_size = (1 << rb_bufsz) * 4; |
2199 | rdev->ih.ring_size = ring_size; | 2204 | rdev->ih.ring_size = ring_size; |
2200 | rdev->ih.align_mask = 4 - 1; | 2205 | rdev->ih.ptr_mask = rdev->ih.ring_size - 1; |
2206 | rdev->ih.rptr = 0; | ||
2201 | } | 2207 | } |
2202 | 2208 | ||
2203 | static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) | 2209 | static int r600_ih_ring_alloc(struct radeon_device *rdev) |
2204 | { | 2210 | { |
2205 | int r; | 2211 | int r; |
2206 | 2212 | ||
2207 | rdev->ih.ring_size = ring_size; | ||
2208 | /* Allocate ring buffer */ | 2213 | /* Allocate ring buffer */ |
2209 | if (rdev->ih.ring_obj == NULL) { | 2214 | if (rdev->ih.ring_obj == NULL) { |
2210 | r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size, | 2215 | r = radeon_bo_create(rdev, NULL, rdev->ih.ring_size, |
@@ -2234,9 +2239,6 @@ static int r600_ih_ring_alloc(struct radeon_device *rdev, unsigned ring_size) | |||
2234 | return r; | 2239 | return r; |
2235 | } | 2240 | } |
2236 | } | 2241 | } |
2237 | rdev->ih.ptr_mask = (rdev->cp.ring_size / 4) - 1; | ||
2238 | rdev->ih.rptr = 0; | ||
2239 | |||
2240 | return 0; | 2242 | return 0; |
2241 | } | 2243 | } |
2242 | 2244 | ||
@@ -2386,7 +2388,7 @@ int r600_irq_init(struct radeon_device *rdev) | |||
2386 | u32 interrupt_cntl, ih_cntl, ih_rb_cntl; | 2388 | u32 interrupt_cntl, ih_cntl, ih_rb_cntl; |
2387 | 2389 | ||
2388 | /* allocate ring */ | 2390 | /* allocate ring */ |
2389 | ret = r600_ih_ring_alloc(rdev, rdev->ih.ring_size); | 2391 | ret = r600_ih_ring_alloc(rdev); |
2390 | if (ret) | 2392 | if (ret) |
2391 | return ret; | 2393 | return ret; |
2392 | 2394 | ||
@@ -2449,10 +2451,15 @@ int r600_irq_init(struct radeon_device *rdev) | |||
2449 | return ret; | 2451 | return ret; |
2450 | } | 2452 | } |
2451 | 2453 | ||
2452 | void r600_irq_fini(struct radeon_device *rdev) | 2454 | void r600_irq_suspend(struct radeon_device *rdev) |
2453 | { | 2455 | { |
2454 | r600_disable_interrupts(rdev); | 2456 | r600_disable_interrupts(rdev); |
2455 | r600_rlc_stop(rdev); | 2457 | r600_rlc_stop(rdev); |
2458 | } | ||
2459 | |||
2460 | void r600_irq_fini(struct radeon_device *rdev) | ||
2461 | { | ||
2462 | r600_irq_suspend(rdev); | ||
2456 | r600_ih_ring_fini(rdev); | 2463 | r600_ih_ring_fini(rdev); |
2457 | } | 2464 | } |
2458 | 2465 | ||
@@ -2467,8 +2474,12 @@ int r600_irq_set(struct radeon_device *rdev) | |||
2467 | return -EINVAL; | 2474 | return -EINVAL; |
2468 | } | 2475 | } |
2469 | /* don't enable anything if the ih is disabled */ | 2476 | /* don't enable anything if the ih is disabled */ |
2470 | if (!rdev->ih.enabled) | 2477 | if (!rdev->ih.enabled) { |
2478 | r600_disable_interrupts(rdev); | ||
2479 | /* force the active interrupt state to all disabled */ | ||
2480 | r600_disable_interrupt_state(rdev); | ||
2471 | return 0; | 2481 | return 0; |
2482 | } | ||
2472 | 2483 | ||
2473 | if (ASIC_IS_DCE3(rdev)) { | 2484 | if (ASIC_IS_DCE3(rdev)) { |
2474 | hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; | 2485 | hpd1 = RREG32(DC_HPD1_INT_CONTROL) & ~DC_HPDx_INT_EN; |
@@ -2638,16 +2649,18 @@ static inline u32 r600_get_ih_wptr(struct radeon_device *rdev) | |||
2638 | wptr = RREG32(IH_RB_WPTR); | 2649 | wptr = RREG32(IH_RB_WPTR); |
2639 | 2650 | ||
2640 | if (wptr & RB_OVERFLOW) { | 2651 | if (wptr & RB_OVERFLOW) { |
2641 | WARN_ON(1); | 2652 | /* When a ring buffer overflow happen start parsing interrupt |
2642 | /* XXX deal with overflow */ | 2653 | * from the last not overwritten vector (wptr + 16). Hopefully |
2643 | DRM_ERROR("IH RB overflow\n"); | 2654 | * this should allow us to catchup. |
2655 | */ | ||
2656 | dev_warn(rdev->dev, "IH ring buffer overflow (0x%08X, %d, %d)\n", | ||
2657 | wptr, rdev->ih.rptr, (wptr + 16) + rdev->ih.ptr_mask); | ||
2658 | rdev->ih.rptr = (wptr + 16) & rdev->ih.ptr_mask; | ||
2644 | tmp = RREG32(IH_RB_CNTL); | 2659 | tmp = RREG32(IH_RB_CNTL); |
2645 | tmp |= IH_WPTR_OVERFLOW_CLEAR; | 2660 | tmp |= IH_WPTR_OVERFLOW_CLEAR; |
2646 | WREG32(IH_RB_CNTL, tmp); | 2661 | WREG32(IH_RB_CNTL, tmp); |
2647 | } | 2662 | } |
2648 | wptr = wptr & WPTR_OFFSET_MASK; | 2663 | return (wptr & rdev->ih.ptr_mask); |
2649 | |||
2650 | return wptr; | ||
2651 | } | 2664 | } |
2652 | 2665 | ||
2653 | /* r600 IV Ring | 2666 | /* r600 IV Ring |
@@ -2683,12 +2696,13 @@ int r600_irq_process(struct radeon_device *rdev) | |||
2683 | u32 wptr = r600_get_ih_wptr(rdev); | 2696 | u32 wptr = r600_get_ih_wptr(rdev); |
2684 | u32 rptr = rdev->ih.rptr; | 2697 | u32 rptr = rdev->ih.rptr; |
2685 | u32 src_id, src_data; | 2698 | u32 src_id, src_data; |
2686 | u32 last_entry = rdev->ih.ring_size - 16; | ||
2687 | u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; | 2699 | u32 ring_index, disp_int, disp_int_cont, disp_int_cont2; |
2688 | unsigned long flags; | 2700 | unsigned long flags; |
2689 | bool queue_hotplug = false; | 2701 | bool queue_hotplug = false; |
2690 | 2702 | ||
2691 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); | 2703 | DRM_DEBUG("r600_irq_process start: rptr %d, wptr %d\n", rptr, wptr); |
2704 | if (!rdev->ih.enabled) | ||
2705 | return IRQ_NONE; | ||
2692 | 2706 | ||
2693 | spin_lock_irqsave(&rdev->ih.lock, flags); | 2707 | spin_lock_irqsave(&rdev->ih.lock, flags); |
2694 | 2708 | ||
@@ -2817,10 +2831,8 @@ restart_ih: | |||
2817 | } | 2831 | } |
2818 | 2832 | ||
2819 | /* wptr/rptr are in bytes! */ | 2833 | /* wptr/rptr are in bytes! */ |
2820 | if (rptr == last_entry) | 2834 | rptr += 16; |
2821 | rptr = 0; | 2835 | rptr &= rdev->ih.ptr_mask; |
2822 | else | ||
2823 | rptr += 16; | ||
2824 | } | 2836 | } |
2825 | /* make sure wptr hasn't changed while processing */ | 2837 | /* make sure wptr hasn't changed while processing */ |
2826 | wptr = r600_get_ih_wptr(rdev); | 2838 | wptr = r600_get_ih_wptr(rdev); |
diff --git a/drivers/gpu/drm/radeon/r600_blit_kms.c b/drivers/gpu/drm/radeon/r600_blit_kms.c index 8787ea89dc6e..2bedce477a97 100644 --- a/drivers/gpu/drm/radeon/r600_blit_kms.c +++ b/drivers/gpu/drm/radeon/r600_blit_kms.c | |||
@@ -512,14 +512,16 @@ void r600_blit_fini(struct radeon_device *rdev) | |||
512 | { | 512 | { |
513 | int r; | 513 | int r; |
514 | 514 | ||
515 | if (rdev->r600_blit.shader_obj == NULL) | ||
516 | return; | ||
517 | /* If we can't reserve the bo, unref should be enough to destroy | ||
518 | * it when it becomes idle. | ||
519 | */ | ||
515 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 520 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); |
516 | if (unlikely(r != 0)) { | 521 | if (!r) { |
517 | dev_err(rdev->dev, "(%d) can't finish r600 blit\n", r); | 522 | radeon_bo_unpin(rdev->r600_blit.shader_obj); |
518 | goto out_unref; | 523 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); |
519 | } | 524 | } |
520 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | ||
521 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
522 | out_unref: | ||
523 | radeon_bo_unref(&rdev->r600_blit.shader_obj); | 525 | radeon_bo_unref(&rdev->r600_blit.shader_obj); |
524 | } | 526 | } |
525 | 527 | ||
diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index 44060b92d9e6..e4c45ec16507 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c | |||
@@ -36,6 +36,10 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, | |||
36 | typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**); | 36 | typedef int (*next_reloc_t)(struct radeon_cs_parser*, struct radeon_cs_reloc**); |
37 | static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm; | 37 | static next_reloc_t r600_cs_packet_next_reloc = &r600_cs_packet_next_reloc_mm; |
38 | 38 | ||
39 | struct r600_cs_track { | ||
40 | u32 cb_color0_base_last; | ||
41 | }; | ||
42 | |||
39 | /** | 43 | /** |
40 | * r600_cs_packet_parse() - parse cp packet and point ib index to next packet | 44 | * r600_cs_packet_parse() - parse cp packet and point ib index to next packet |
41 | * @parser: parser structure holding parsing context. | 45 | * @parser: parser structure holding parsing context. |
@@ -177,6 +181,28 @@ static int r600_cs_packet_next_reloc_nomm(struct radeon_cs_parser *p, | |||
177 | } | 181 | } |
178 | 182 | ||
179 | /** | 183 | /** |
184 | * r600_cs_packet_next_is_pkt3_nop() - test if next packet is packet3 nop for reloc | ||
185 | * @parser: parser structure holding parsing context. | ||
186 | * | ||
187 | * Check next packet is relocation packet3, do bo validation and compute | ||
188 | * GPU offset using the provided start. | ||
189 | **/ | ||
190 | static inline int r600_cs_packet_next_is_pkt3_nop(struct radeon_cs_parser *p) | ||
191 | { | ||
192 | struct radeon_cs_packet p3reloc; | ||
193 | int r; | ||
194 | |||
195 | r = r600_cs_packet_parse(p, &p3reloc, p->idx); | ||
196 | if (r) { | ||
197 | return 0; | ||
198 | } | ||
199 | if (p3reloc.type != PACKET_TYPE3 || p3reloc.opcode != PACKET3_NOP) { | ||
200 | return 0; | ||
201 | } | ||
202 | return 1; | ||
203 | } | ||
204 | |||
205 | /** | ||
180 | * r600_cs_packet_next_vline() - parse userspace VLINE packet | 206 | * r600_cs_packet_next_vline() - parse userspace VLINE packet |
181 | * @parser: parser structure holding parsing context. | 207 | * @parser: parser structure holding parsing context. |
182 | * | 208 | * |
@@ -337,6 +363,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
337 | struct radeon_cs_packet *pkt) | 363 | struct radeon_cs_packet *pkt) |
338 | { | 364 | { |
339 | struct radeon_cs_reloc *reloc; | 365 | struct radeon_cs_reloc *reloc; |
366 | struct r600_cs_track *track; | ||
340 | volatile u32 *ib; | 367 | volatile u32 *ib; |
341 | unsigned idx; | 368 | unsigned idx; |
342 | unsigned i; | 369 | unsigned i; |
@@ -344,6 +371,7 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
344 | int r; | 371 | int r; |
345 | u32 idx_value; | 372 | u32 idx_value; |
346 | 373 | ||
374 | track = (struct r600_cs_track *)p->track; | ||
347 | ib = p->ib->ptr; | 375 | ib = p->ib->ptr; |
348 | idx = pkt->idx + 1; | 376 | idx = pkt->idx + 1; |
349 | idx_value = radeon_get_ib_value(p, idx); | 377 | idx_value = radeon_get_ib_value(p, idx); |
@@ -503,9 +531,60 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
503 | for (i = 0; i < pkt->count; i++) { | 531 | for (i = 0; i < pkt->count; i++) { |
504 | reg = start_reg + (4 * i); | 532 | reg = start_reg + (4 * i); |
505 | switch (reg) { | 533 | switch (reg) { |
534 | /* This register were added late, there is userspace | ||
535 | * which does provide relocation for those but set | ||
536 | * 0 offset. In order to avoid breaking old userspace | ||
537 | * we detect this and set address to point to last | ||
538 | * CB_COLOR0_BASE, note that if userspace doesn't set | ||
539 | * CB_COLOR0_BASE before this register we will report | ||
540 | * error. Old userspace always set CB_COLOR0_BASE | ||
541 | * before any of this. | ||
542 | */ | ||
543 | case R_0280E0_CB_COLOR0_FRAG: | ||
544 | case R_0280E4_CB_COLOR1_FRAG: | ||
545 | case R_0280E8_CB_COLOR2_FRAG: | ||
546 | case R_0280EC_CB_COLOR3_FRAG: | ||
547 | case R_0280F0_CB_COLOR4_FRAG: | ||
548 | case R_0280F4_CB_COLOR5_FRAG: | ||
549 | case R_0280F8_CB_COLOR6_FRAG: | ||
550 | case R_0280FC_CB_COLOR7_FRAG: | ||
551 | case R_0280C0_CB_COLOR0_TILE: | ||
552 | case R_0280C4_CB_COLOR1_TILE: | ||
553 | case R_0280C8_CB_COLOR2_TILE: | ||
554 | case R_0280CC_CB_COLOR3_TILE: | ||
555 | case R_0280D0_CB_COLOR4_TILE: | ||
556 | case R_0280D4_CB_COLOR5_TILE: | ||
557 | case R_0280D8_CB_COLOR6_TILE: | ||
558 | case R_0280DC_CB_COLOR7_TILE: | ||
559 | if (!r600_cs_packet_next_is_pkt3_nop(p)) { | ||
560 | if (!track->cb_color0_base_last) { | ||
561 | dev_err(p->dev, "Broken old userspace ? no cb_color0_base supplied before trying to write 0x%08X\n", reg); | ||
562 | return -EINVAL; | ||
563 | } | ||
564 | ib[idx+1+i] = track->cb_color0_base_last; | ||
565 | printk_once(KERN_WARNING "radeon: You have old & broken userspace " | ||
566 | "please consider updating mesa & xf86-video-ati\n"); | ||
567 | } else { | ||
568 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
569 | if (r) { | ||
570 | dev_err(p->dev, "bad SET_CONTEXT_REG 0x%04X\n", reg); | ||
571 | return -EINVAL; | ||
572 | } | ||
573 | ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | ||
574 | } | ||
575 | break; | ||
506 | case DB_DEPTH_BASE: | 576 | case DB_DEPTH_BASE: |
507 | case DB_HTILE_DATA_BASE: | 577 | case DB_HTILE_DATA_BASE: |
508 | case CB_COLOR0_BASE: | 578 | case CB_COLOR0_BASE: |
579 | r = r600_cs_packet_next_reloc(p, &reloc); | ||
580 | if (r) { | ||
581 | DRM_ERROR("bad SET_CONTEXT_REG " | ||
582 | "0x%04X\n", reg); | ||
583 | return -EINVAL; | ||
584 | } | ||
585 | ib[idx+1+i] += (u32)((reloc->lobj.gpu_offset >> 8) & 0xffffffff); | ||
586 | track->cb_color0_base_last = ib[idx+1+i]; | ||
587 | break; | ||
509 | case CB_COLOR1_BASE: | 588 | case CB_COLOR1_BASE: |
510 | case CB_COLOR2_BASE: | 589 | case CB_COLOR2_BASE: |
511 | case CB_COLOR3_BASE: | 590 | case CB_COLOR3_BASE: |
@@ -678,8 +757,11 @@ static int r600_packet3_check(struct radeon_cs_parser *p, | |||
678 | int r600_cs_parse(struct radeon_cs_parser *p) | 757 | int r600_cs_parse(struct radeon_cs_parser *p) |
679 | { | 758 | { |
680 | struct radeon_cs_packet pkt; | 759 | struct radeon_cs_packet pkt; |
760 | struct r600_cs_track *track; | ||
681 | int r; | 761 | int r; |
682 | 762 | ||
763 | track = kzalloc(sizeof(*track), GFP_KERNEL); | ||
764 | p->track = track; | ||
683 | do { | 765 | do { |
684 | r = r600_cs_packet_parse(p, &pkt, p->idx); | 766 | r = r600_cs_packet_parse(p, &pkt, p->idx); |
685 | if (r) { | 767 | if (r) { |
@@ -757,6 +839,7 @@ int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, | |||
757 | /* initialize parser */ | 839 | /* initialize parser */ |
758 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); | 840 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); |
759 | parser.filp = filp; | 841 | parser.filp = filp; |
842 | parser.dev = &dev->pdev->dev; | ||
760 | parser.rdev = NULL; | 843 | parser.rdev = NULL; |
761 | parser.family = family; | 844 | parser.family = family; |
762 | parser.ib = &fake_ib; | 845 | parser.ib = &fake_ib; |
diff --git a/drivers/gpu/drm/radeon/r600d.h b/drivers/gpu/drm/radeon/r600d.h index 05894edadab4..30480881aed1 100644 --- a/drivers/gpu/drm/radeon/r600d.h +++ b/drivers/gpu/drm/radeon/r600d.h | |||
@@ -882,4 +882,29 @@ | |||
882 | #define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17) | 882 | #define S_000E60_SOFT_RESET_VMC(x) (((x) & 1) << 17) |
883 | 883 | ||
884 | #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 | 884 | #define R_005480_HDP_MEM_COHERENCY_FLUSH_CNTL 0x5480 |
885 | |||
886 | #define R_0280E0_CB_COLOR0_FRAG 0x0280E0 | ||
887 | #define S_0280E0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) | ||
888 | #define G_0280E0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) | ||
889 | #define C_0280E0_BASE_256B 0x00000000 | ||
890 | #define R_0280E4_CB_COLOR1_FRAG 0x0280E4 | ||
891 | #define R_0280E8_CB_COLOR2_FRAG 0x0280E8 | ||
892 | #define R_0280EC_CB_COLOR3_FRAG 0x0280EC | ||
893 | #define R_0280F0_CB_COLOR4_FRAG 0x0280F0 | ||
894 | #define R_0280F4_CB_COLOR5_FRAG 0x0280F4 | ||
895 | #define R_0280F8_CB_COLOR6_FRAG 0x0280F8 | ||
896 | #define R_0280FC_CB_COLOR7_FRAG 0x0280FC | ||
897 | #define R_0280C0_CB_COLOR0_TILE 0x0280C0 | ||
898 | #define S_0280C0_BASE_256B(x) (((x) & 0xFFFFFFFF) << 0) | ||
899 | #define G_0280C0_BASE_256B(x) (((x) >> 0) & 0xFFFFFFFF) | ||
900 | #define C_0280C0_BASE_256B 0x00000000 | ||
901 | #define R_0280C4_CB_COLOR1_TILE 0x0280C4 | ||
902 | #define R_0280C8_CB_COLOR2_TILE 0x0280C8 | ||
903 | #define R_0280CC_CB_COLOR3_TILE 0x0280CC | ||
904 | #define R_0280D0_CB_COLOR4_TILE 0x0280D0 | ||
905 | #define R_0280D4_CB_COLOR5_TILE 0x0280D4 | ||
906 | #define R_0280D8_CB_COLOR6_TILE 0x0280D8 | ||
907 | #define R_0280DC_CB_COLOR7_TILE 0x0280DC | ||
908 | |||
909 | |||
885 | #endif | 910 | #endif |
diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index eb5f99b9469d..f7df1a7e4413 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h | |||
@@ -410,7 +410,6 @@ struct r600_ih { | |||
410 | unsigned wptr_old; | 410 | unsigned wptr_old; |
411 | unsigned ring_size; | 411 | unsigned ring_size; |
412 | uint64_t gpu_addr; | 412 | uint64_t gpu_addr; |
413 | uint32_t align_mask; | ||
414 | uint32_t ptr_mask; | 413 | uint32_t ptr_mask; |
415 | spinlock_t lock; | 414 | spinlock_t lock; |
416 | bool enabled; | 415 | bool enabled; |
@@ -465,6 +464,7 @@ struct radeon_cs_chunk { | |||
465 | }; | 464 | }; |
466 | 465 | ||
467 | struct radeon_cs_parser { | 466 | struct radeon_cs_parser { |
467 | struct device *dev; | ||
468 | struct radeon_device *rdev; | 468 | struct radeon_device *rdev; |
469 | struct drm_file *filp; | 469 | struct drm_file *filp; |
470 | /* chunks */ | 470 | /* chunks */ |
@@ -847,7 +847,7 @@ void r600_kms_blit_copy(struct radeon_device *rdev, | |||
847 | 847 | ||
848 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | 848 | static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) |
849 | { | 849 | { |
850 | if (reg < 0x10000) | 850 | if (reg < rdev->rmmio_size) |
851 | return readl(((void __iomem *)rdev->rmmio) + reg); | 851 | return readl(((void __iomem *)rdev->rmmio) + reg); |
852 | else { | 852 | else { |
853 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | 853 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
@@ -857,7 +857,7 @@ static inline uint32_t r100_mm_rreg(struct radeon_device *rdev, uint32_t reg) | |||
857 | 857 | ||
858 | static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) | 858 | static inline void r100_mm_wreg(struct radeon_device *rdev, uint32_t reg, uint32_t v) |
859 | { | 859 | { |
860 | if (reg < 0x10000) | 860 | if (reg < rdev->rmmio_size) |
861 | writel(v, ((void __iomem *)rdev->rmmio) + reg); | 861 | writel(v, ((void __iomem *)rdev->rmmio) + reg); |
862 | else { | 862 | else { |
863 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); | 863 | writel(reg, ((void __iomem *)rdev->rmmio) + RADEON_MM_INDEX); |
@@ -1017,6 +1017,8 @@ static inline void radeon_ring_write(struct radeon_device *rdev, uint32_t v) | |||
1017 | #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) | 1017 | #define radeon_hpd_set_polarity(rdev, hpd) (rdev)->asic->hpd_set_polarity((rdev), (hpd)) |
1018 | 1018 | ||
1019 | /* Common functions */ | 1019 | /* Common functions */ |
1020 | /* AGP */ | ||
1021 | extern void radeon_agp_disable(struct radeon_device *rdev); | ||
1020 | extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); | 1022 | extern int radeon_gart_table_vram_pin(struct radeon_device *rdev); |
1021 | extern int radeon_modeset_init(struct radeon_device *rdev); | 1023 | extern int radeon_modeset_init(struct radeon_device *rdev); |
1022 | extern void radeon_modeset_fini(struct radeon_device *rdev); | 1024 | extern void radeon_modeset_fini(struct radeon_device *rdev); |
@@ -1160,7 +1162,8 @@ extern int r600_irq_init(struct radeon_device *rdev); | |||
1160 | extern void r600_irq_fini(struct radeon_device *rdev); | 1162 | extern void r600_irq_fini(struct radeon_device *rdev); |
1161 | extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); | 1163 | extern void r600_ih_ring_init(struct radeon_device *rdev, unsigned ring_size); |
1162 | extern int r600_irq_set(struct radeon_device *rdev); | 1164 | extern int r600_irq_set(struct radeon_device *rdev); |
1163 | 1165 | extern void r600_irq_suspend(struct radeon_device *rdev); | |
1166 | /* r600 audio */ | ||
1164 | extern int r600_audio_init(struct radeon_device *rdev); | 1167 | extern int r600_audio_init(struct radeon_device *rdev); |
1165 | extern int r600_audio_tmds_index(struct drm_encoder *encoder); | 1168 | extern int r600_audio_tmds_index(struct drm_encoder *encoder); |
1166 | extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); | 1169 | extern void r600_audio_set_clock(struct drm_encoder *encoder, int clock); |
diff --git a/drivers/gpu/drm/radeon/radeon_agp.c b/drivers/gpu/drm/radeon/radeon_agp.c index 220f454ea9fa..c9ad7f5cc1ac 100644 --- a/drivers/gpu/drm/radeon/radeon_agp.c +++ b/drivers/gpu/drm/radeon/radeon_agp.c | |||
@@ -133,6 +133,13 @@ int radeon_agp_init(struct radeon_device *rdev) | |||
133 | bool is_v3; | 133 | bool is_v3; |
134 | int ret; | 134 | int ret; |
135 | 135 | ||
136 | if (rdev->ddev->agp->agp_info.aper_size < 32) { | ||
137 | dev_warn(rdev->dev, "AGP aperture to small (%dM) " | ||
138 | "need at least 32M, disabling AGP\n", | ||
139 | rdev->ddev->agp->agp_info.aper_size); | ||
140 | return -EINVAL; | ||
141 | } | ||
142 | |||
136 | /* Acquire AGP. */ | 143 | /* Acquire AGP. */ |
137 | if (!rdev->ddev->agp->acquired) { | 144 | if (!rdev->ddev->agp->acquired) { |
138 | ret = drm_agp_acquire(rdev->ddev); | 145 | ret = drm_agp_acquire(rdev->ddev); |
diff --git a/drivers/gpu/drm/radeon/radeon_clocks.c b/drivers/gpu/drm/radeon/radeon_clocks.c index 812f24dbc2a8..73c4405bf42f 100644 --- a/drivers/gpu/drm/radeon/radeon_clocks.c +++ b/drivers/gpu/drm/radeon/radeon_clocks.c | |||
@@ -56,7 +56,7 @@ uint32_t radeon_legacy_get_engine_clock(struct radeon_device *rdev) | |||
56 | else if (post_div == 3) | 56 | else if (post_div == 3) |
57 | sclk >>= 2; | 57 | sclk >>= 2; |
58 | else if (post_div == 4) | 58 | else if (post_div == 4) |
59 | sclk >>= 4; | 59 | sclk >>= 3; |
60 | 60 | ||
61 | return sclk; | 61 | return sclk; |
62 | } | 62 | } |
@@ -86,7 +86,7 @@ uint32_t radeon_legacy_get_memory_clock(struct radeon_device *rdev) | |||
86 | else if (post_div == 3) | 86 | else if (post_div == 3) |
87 | mclk >>= 2; | 87 | mclk >>= 2; |
88 | else if (post_div == 4) | 88 | else if (post_div == 4) |
89 | mclk >>= 4; | 89 | mclk >>= 3; |
90 | 90 | ||
91 | return mclk; | 91 | return mclk; |
92 | } | 92 | } |
diff --git a/drivers/gpu/drm/radeon/radeon_cs.c b/drivers/gpu/drm/radeon/radeon_cs.c index 65590a0f1d93..1496cb8658ef 100644 --- a/drivers/gpu/drm/radeon/radeon_cs.c +++ b/drivers/gpu/drm/radeon/radeon_cs.c | |||
@@ -231,6 +231,7 @@ int radeon_cs_ioctl(struct drm_device *dev, void *data, struct drm_file *filp) | |||
231 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); | 231 | memset(&parser, 0, sizeof(struct radeon_cs_parser)); |
232 | parser.filp = filp; | 232 | parser.filp = filp; |
233 | parser.rdev = rdev; | 233 | parser.rdev = rdev; |
234 | parser.dev = rdev->dev; | ||
234 | r = radeon_cs_parser_init(&parser, data); | 235 | r = radeon_cs_parser_init(&parser, data); |
235 | if (r) { | 236 | if (r) { |
236 | DRM_ERROR("Failed to initialize parser !\n"); | 237 | DRM_ERROR("Failed to initialize parser !\n"); |
diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index 0c51f8e46613..768b1509fa03 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c | |||
@@ -544,6 +544,7 @@ void radeon_agp_disable(struct radeon_device *rdev) | |||
544 | rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; | 544 | rdev->asic->gart_tlb_flush = &r100_pci_gart_tlb_flush; |
545 | rdev->asic->gart_set_page = &r100_pci_gart_set_page; | 545 | rdev->asic->gart_set_page = &r100_pci_gart_set_page; |
546 | } | 546 | } |
547 | rdev->mc.gtt_size = radeon_gart_size * 1024 * 1024; | ||
547 | } | 548 | } |
548 | 549 | ||
549 | void radeon_check_arguments(struct radeon_device *rdev) | 550 | void radeon_check_arguments(struct radeon_device *rdev) |
diff --git a/drivers/gpu/drm/radeon/radeon_display.c b/drivers/gpu/drm/radeon/radeon_display.c index 0ec491ead2ff..6a92f994cc26 100644 --- a/drivers/gpu/drm/radeon/radeon_display.c +++ b/drivers/gpu/drm/radeon/radeon_display.c | |||
@@ -357,7 +357,8 @@ int radeon_ddc_get_modes(struct radeon_connector *radeon_connector) | |||
357 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || | 357 | if ((radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_DisplayPort) || |
358 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { | 358 | (radeon_connector->base.connector_type == DRM_MODE_CONNECTOR_eDP)) { |
359 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; | 359 | struct radeon_connector_atom_dig *dig = radeon_connector->con_priv; |
360 | if (dig->dp_i2c_bus) | 360 | if ((dig->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT || |
361 | dig->dp_sink_type == CONNECTOR_OBJECT_ID_eDP) && dig->dp_i2c_bus) | ||
361 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); | 362 | radeon_connector->edid = drm_get_edid(&radeon_connector->base, &dig->dp_i2c_bus->adapter); |
362 | } | 363 | } |
363 | if (!radeon_connector->ddc_bus) | 364 | if (!radeon_connector->ddc_bus) |
@@ -410,11 +411,12 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
410 | uint32_t *fb_div_p, | 411 | uint32_t *fb_div_p, |
411 | uint32_t *frac_fb_div_p, | 412 | uint32_t *frac_fb_div_p, |
412 | uint32_t *ref_div_p, | 413 | uint32_t *ref_div_p, |
413 | uint32_t *post_div_p, | 414 | uint32_t *post_div_p) |
414 | int flags) | ||
415 | { | 415 | { |
416 | uint32_t min_ref_div = pll->min_ref_div; | 416 | uint32_t min_ref_div = pll->min_ref_div; |
417 | uint32_t max_ref_div = pll->max_ref_div; | 417 | uint32_t max_ref_div = pll->max_ref_div; |
418 | uint32_t min_post_div = pll->min_post_div; | ||
419 | uint32_t max_post_div = pll->max_post_div; | ||
418 | uint32_t min_fractional_feed_div = 0; | 420 | uint32_t min_fractional_feed_div = 0; |
419 | uint32_t max_fractional_feed_div = 0; | 421 | uint32_t max_fractional_feed_div = 0; |
420 | uint32_t best_vco = pll->best_vco; | 422 | uint32_t best_vco = pll->best_vco; |
@@ -430,7 +432,7 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
430 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); | 432 | DRM_DEBUG("PLL freq %llu %u %u\n", freq, pll->min_ref_div, pll->max_ref_div); |
431 | freq = freq * 1000; | 433 | freq = freq * 1000; |
432 | 434 | ||
433 | if (flags & RADEON_PLL_USE_REF_DIV) | 435 | if (pll->flags & RADEON_PLL_USE_REF_DIV) |
434 | min_ref_div = max_ref_div = pll->reference_div; | 436 | min_ref_div = max_ref_div = pll->reference_div; |
435 | else { | 437 | else { |
436 | while (min_ref_div < max_ref_div-1) { | 438 | while (min_ref_div < max_ref_div-1) { |
@@ -445,19 +447,22 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
445 | } | 447 | } |
446 | } | 448 | } |
447 | 449 | ||
448 | if (flags & RADEON_PLL_USE_FRAC_FB_DIV) { | 450 | if (pll->flags & RADEON_PLL_USE_POST_DIV) |
451 | min_post_div = max_post_div = pll->post_div; | ||
452 | |||
453 | if (pll->flags & RADEON_PLL_USE_FRAC_FB_DIV) { | ||
449 | min_fractional_feed_div = pll->min_frac_feedback_div; | 454 | min_fractional_feed_div = pll->min_frac_feedback_div; |
450 | max_fractional_feed_div = pll->max_frac_feedback_div; | 455 | max_fractional_feed_div = pll->max_frac_feedback_div; |
451 | } | 456 | } |
452 | 457 | ||
453 | for (post_div = pll->min_post_div; post_div <= pll->max_post_div; ++post_div) { | 458 | for (post_div = min_post_div; post_div <= max_post_div; ++post_div) { |
454 | uint32_t ref_div; | 459 | uint32_t ref_div; |
455 | 460 | ||
456 | if ((flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) | 461 | if ((pll->flags & RADEON_PLL_NO_ODD_POST_DIV) && (post_div & 1)) |
457 | continue; | 462 | continue; |
458 | 463 | ||
459 | /* legacy radeons only have a few post_divs */ | 464 | /* legacy radeons only have a few post_divs */ |
460 | if (flags & RADEON_PLL_LEGACY) { | 465 | if (pll->flags & RADEON_PLL_LEGACY) { |
461 | if ((post_div == 5) || | 466 | if ((post_div == 5) || |
462 | (post_div == 7) || | 467 | (post_div == 7) || |
463 | (post_div == 9) || | 468 | (post_div == 9) || |
@@ -504,7 +509,7 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
504 | tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; | 509 | tmp += (uint64_t)pll->reference_freq * 1000 * frac_feedback_div; |
505 | current_freq = radeon_div(tmp, ref_div * post_div); | 510 | current_freq = radeon_div(tmp, ref_div * post_div); |
506 | 511 | ||
507 | if (flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { | 512 | if (pll->flags & RADEON_PLL_PREFER_CLOSEST_LOWER) { |
508 | error = freq - current_freq; | 513 | error = freq - current_freq; |
509 | error = error < 0 ? 0xffffffff : error; | 514 | error = error < 0 ? 0xffffffff : error; |
510 | } else | 515 | } else |
@@ -531,12 +536,12 @@ void radeon_compute_pll(struct radeon_pll *pll, | |||
531 | best_freq = current_freq; | 536 | best_freq = current_freq; |
532 | best_error = error; | 537 | best_error = error; |
533 | best_vco_diff = vco_diff; | 538 | best_vco_diff = vco_diff; |
534 | } else if (((flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || | 539 | } else if (((pll->flags & RADEON_PLL_PREFER_LOW_REF_DIV) && (ref_div < best_ref_div)) || |
535 | ((flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || | 540 | ((pll->flags & RADEON_PLL_PREFER_HIGH_REF_DIV) && (ref_div > best_ref_div)) || |
536 | ((flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || | 541 | ((pll->flags & RADEON_PLL_PREFER_LOW_FB_DIV) && (feedback_div < best_feedback_div)) || |
537 | ((flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || | 542 | ((pll->flags & RADEON_PLL_PREFER_HIGH_FB_DIV) && (feedback_div > best_feedback_div)) || |
538 | ((flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || | 543 | ((pll->flags & RADEON_PLL_PREFER_LOW_POST_DIV) && (post_div < best_post_div)) || |
539 | ((flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { | 544 | ((pll->flags & RADEON_PLL_PREFER_HIGH_POST_DIV) && (post_div > best_post_div))) { |
540 | best_post_div = post_div; | 545 | best_post_div = post_div; |
541 | best_ref_div = ref_div; | 546 | best_ref_div = ref_div; |
542 | best_feedback_div = feedback_div; | 547 | best_feedback_div = feedback_div; |
@@ -572,8 +577,7 @@ void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
572 | uint32_t *fb_div_p, | 577 | uint32_t *fb_div_p, |
573 | uint32_t *frac_fb_div_p, | 578 | uint32_t *frac_fb_div_p, |
574 | uint32_t *ref_div_p, | 579 | uint32_t *ref_div_p, |
575 | uint32_t *post_div_p, | 580 | uint32_t *post_div_p) |
576 | int flags) | ||
577 | { | 581 | { |
578 | fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; | 582 | fixed20_12 m, n, frac_n, p, f_vco, f_pclk, best_freq; |
579 | fixed20_12 pll_out_max, pll_out_min; | 583 | fixed20_12 pll_out_max, pll_out_min; |
@@ -667,7 +671,6 @@ static void radeon_user_framebuffer_destroy(struct drm_framebuffer *fb) | |||
667 | radeonfb_remove(dev, fb); | 671 | radeonfb_remove(dev, fb); |
668 | 672 | ||
669 | if (radeon_fb->obj) { | 673 | if (radeon_fb->obj) { |
670 | radeon_gem_object_unpin(radeon_fb->obj); | ||
671 | mutex_lock(&dev->struct_mutex); | 674 | mutex_lock(&dev->struct_mutex); |
672 | drm_gem_object_unreference(radeon_fb->obj); | 675 | drm_gem_object_unreference(radeon_fb->obj); |
673 | mutex_unlock(&dev->struct_mutex); | 676 | mutex_unlock(&dev->struct_mutex); |
@@ -715,7 +718,11 @@ radeon_user_framebuffer_create(struct drm_device *dev, | |||
715 | struct drm_gem_object *obj; | 718 | struct drm_gem_object *obj; |
716 | 719 | ||
717 | obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); | 720 | obj = drm_gem_object_lookup(dev, file_priv, mode_cmd->handle); |
718 | 721 | if (obj == NULL) { | |
722 | dev_err(&dev->pdev->dev, "No GEM object associated to handle 0x%08X, " | ||
723 | "can't create framebuffer\n", mode_cmd->handle); | ||
724 | return NULL; | ||
725 | } | ||
719 | return radeon_framebuffer_create(dev, mode_cmd, obj); | 726 | return radeon_framebuffer_create(dev, mode_cmd, obj); |
720 | } | 727 | } |
721 | 728 | ||
diff --git a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c index cc27485a07ad..b6d8081e1246 100644 --- a/drivers/gpu/drm/radeon/radeon_legacy_crtc.c +++ b/drivers/gpu/drm/radeon/radeon_legacy_crtc.c | |||
@@ -339,69 +339,6 @@ void radeon_crtc_dpms(struct drm_crtc *crtc, int mode) | |||
339 | } | 339 | } |
340 | } | 340 | } |
341 | 341 | ||
342 | /* properly set crtc bpp when using atombios */ | ||
343 | void radeon_legacy_atom_set_surface(struct drm_crtc *crtc) | ||
344 | { | ||
345 | struct drm_device *dev = crtc->dev; | ||
346 | struct radeon_device *rdev = dev->dev_private; | ||
347 | struct radeon_crtc *radeon_crtc = to_radeon_crtc(crtc); | ||
348 | int format; | ||
349 | uint32_t crtc_gen_cntl; | ||
350 | uint32_t disp_merge_cntl; | ||
351 | uint32_t crtc_pitch; | ||
352 | |||
353 | switch (crtc->fb->bits_per_pixel) { | ||
354 | case 8: | ||
355 | format = 2; | ||
356 | break; | ||
357 | case 15: /* 555 */ | ||
358 | format = 3; | ||
359 | break; | ||
360 | case 16: /* 565 */ | ||
361 | format = 4; | ||
362 | break; | ||
363 | case 24: /* RGB */ | ||
364 | format = 5; | ||
365 | break; | ||
366 | case 32: /* xRGB */ | ||
367 | format = 6; | ||
368 | break; | ||
369 | default: | ||
370 | return; | ||
371 | } | ||
372 | |||
373 | crtc_pitch = ((((crtc->fb->pitch / (crtc->fb->bits_per_pixel / 8)) * crtc->fb->bits_per_pixel) + | ||
374 | ((crtc->fb->bits_per_pixel * 8) - 1)) / | ||
375 | (crtc->fb->bits_per_pixel * 8)); | ||
376 | crtc_pitch |= crtc_pitch << 16; | ||
377 | |||
378 | WREG32(RADEON_CRTC_PITCH + radeon_crtc->crtc_offset, crtc_pitch); | ||
379 | |||
380 | switch (radeon_crtc->crtc_id) { | ||
381 | case 0: | ||
382 | disp_merge_cntl = RREG32(RADEON_DISP_MERGE_CNTL); | ||
383 | disp_merge_cntl &= ~RADEON_DISP_RGB_OFFSET_EN; | ||
384 | WREG32(RADEON_DISP_MERGE_CNTL, disp_merge_cntl); | ||
385 | |||
386 | crtc_gen_cntl = RREG32(RADEON_CRTC_GEN_CNTL) & 0xfffff0ff; | ||
387 | crtc_gen_cntl |= (format << 8); | ||
388 | crtc_gen_cntl |= RADEON_CRTC_EXT_DISP_EN; | ||
389 | WREG32(RADEON_CRTC_GEN_CNTL, crtc_gen_cntl); | ||
390 | break; | ||
391 | case 1: | ||
392 | disp_merge_cntl = RREG32(RADEON_DISP2_MERGE_CNTL); | ||
393 | disp_merge_cntl &= ~RADEON_DISP2_RGB_OFFSET_EN; | ||
394 | WREG32(RADEON_DISP2_MERGE_CNTL, disp_merge_cntl); | ||
395 | |||
396 | crtc_gen_cntl = RREG32(RADEON_CRTC2_GEN_CNTL) & 0xfffff0ff; | ||
397 | crtc_gen_cntl |= (format << 8); | ||
398 | WREG32(RADEON_CRTC2_GEN_CNTL, crtc_gen_cntl); | ||
399 | WREG32(RADEON_FP_H2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_H_SYNC_STRT_WID)); | ||
400 | WREG32(RADEON_FP_V2_SYNC_STRT_WID, RREG32(RADEON_CRTC2_V_SYNC_STRT_WID)); | ||
401 | break; | ||
402 | } | ||
403 | } | ||
404 | |||
405 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 342 | int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
406 | struct drm_framebuffer *old_fb) | 343 | struct drm_framebuffer *old_fb) |
407 | { | 344 | { |
@@ -755,7 +692,6 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
755 | uint32_t post_divider = 0; | 692 | uint32_t post_divider = 0; |
756 | uint32_t freq = 0; | 693 | uint32_t freq = 0; |
757 | uint8_t pll_gain; | 694 | uint8_t pll_gain; |
758 | int pll_flags = RADEON_PLL_LEGACY; | ||
759 | bool use_bios_divs = false; | 695 | bool use_bios_divs = false; |
760 | /* PLL registers */ | 696 | /* PLL registers */ |
761 | uint32_t pll_ref_div = 0; | 697 | uint32_t pll_ref_div = 0; |
@@ -789,10 +725,12 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
789 | else | 725 | else |
790 | pll = &rdev->clock.p1pll; | 726 | pll = &rdev->clock.p1pll; |
791 | 727 | ||
728 | pll->flags = RADEON_PLL_LEGACY; | ||
729 | |||
792 | if (mode->clock > 200000) /* range limits??? */ | 730 | if (mode->clock > 200000) /* range limits??? */ |
793 | pll_flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; | 731 | pll->flags |= RADEON_PLL_PREFER_HIGH_FB_DIV; |
794 | else | 732 | else |
795 | pll_flags |= RADEON_PLL_PREFER_LOW_REF_DIV; | 733 | pll->flags |= RADEON_PLL_PREFER_LOW_REF_DIV; |
796 | 734 | ||
797 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { | 735 | list_for_each_entry(encoder, &dev->mode_config.encoder_list, head) { |
798 | if (encoder->crtc == crtc) { | 736 | if (encoder->crtc == crtc) { |
@@ -804,7 +742,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
804 | } | 742 | } |
805 | 743 | ||
806 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) | 744 | if (encoder->encoder_type != DRM_MODE_ENCODER_DAC) |
807 | pll_flags |= RADEON_PLL_NO_ODD_POST_DIV; | 745 | pll->flags |= RADEON_PLL_NO_ODD_POST_DIV; |
808 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { | 746 | if (encoder->encoder_type == DRM_MODE_ENCODER_LVDS) { |
809 | if (!rdev->is_atom_bios) { | 747 | if (!rdev->is_atom_bios) { |
810 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); | 748 | struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder); |
@@ -819,7 +757,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
819 | } | 757 | } |
820 | } | 758 | } |
821 | } | 759 | } |
822 | pll_flags |= RADEON_PLL_USE_REF_DIV; | 760 | pll->flags |= RADEON_PLL_USE_REF_DIV; |
823 | } | 761 | } |
824 | } | 762 | } |
825 | } | 763 | } |
@@ -829,8 +767,7 @@ static void radeon_set_pll(struct drm_crtc *crtc, struct drm_display_mode *mode) | |||
829 | if (!use_bios_divs) { | 767 | if (!use_bios_divs) { |
830 | radeon_compute_pll(pll, mode->clock, | 768 | radeon_compute_pll(pll, mode->clock, |
831 | &freq, &feedback_div, &frac_fb_div, | 769 | &freq, &feedback_div, &frac_fb_div, |
832 | &reference_div, &post_divider, | 770 | &reference_div, &post_divider); |
833 | pll_flags); | ||
834 | 771 | ||
835 | for (post_div = &post_divs[0]; post_div->divider; ++post_div) { | 772 | for (post_div = &post_divs[0]; post_div->divider; ++post_div) { |
836 | if (post_div->divider == post_divider) | 773 | if (post_div->divider == post_divider) |
diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index 91cb041cb40d..96b851f92f4c 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h | |||
@@ -125,16 +125,24 @@ struct radeon_tmds_pll { | |||
125 | #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) | 125 | #define RADEON_PLL_PREFER_HIGH_POST_DIV (1 << 9) |
126 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) | 126 | #define RADEON_PLL_USE_FRAC_FB_DIV (1 << 10) |
127 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) | 127 | #define RADEON_PLL_PREFER_CLOSEST_LOWER (1 << 11) |
128 | #define RADEON_PLL_USE_POST_DIV (1 << 12) | ||
128 | 129 | ||
129 | struct radeon_pll { | 130 | struct radeon_pll { |
130 | uint16_t reference_freq; | 131 | /* reference frequency */ |
131 | uint16_t reference_div; | 132 | uint32_t reference_freq; |
133 | |||
134 | /* fixed dividers */ | ||
135 | uint32_t reference_div; | ||
136 | uint32_t post_div; | ||
137 | |||
138 | /* pll in/out limits */ | ||
132 | uint32_t pll_in_min; | 139 | uint32_t pll_in_min; |
133 | uint32_t pll_in_max; | 140 | uint32_t pll_in_max; |
134 | uint32_t pll_out_min; | 141 | uint32_t pll_out_min; |
135 | uint32_t pll_out_max; | 142 | uint32_t pll_out_max; |
136 | uint16_t xclk; | 143 | uint32_t best_vco; |
137 | 144 | ||
145 | /* divider limits */ | ||
138 | uint32_t min_ref_div; | 146 | uint32_t min_ref_div; |
139 | uint32_t max_ref_div; | 147 | uint32_t max_ref_div; |
140 | uint32_t min_post_div; | 148 | uint32_t min_post_div; |
@@ -143,7 +151,12 @@ struct radeon_pll { | |||
143 | uint32_t max_feedback_div; | 151 | uint32_t max_feedback_div; |
144 | uint32_t min_frac_feedback_div; | 152 | uint32_t min_frac_feedback_div; |
145 | uint32_t max_frac_feedback_div; | 153 | uint32_t max_frac_feedback_div; |
146 | uint32_t best_vco; | 154 | |
155 | /* flags for the current clock */ | ||
156 | uint32_t flags; | ||
157 | |||
158 | /* pll id */ | ||
159 | uint32_t id; | ||
147 | }; | 160 | }; |
148 | 161 | ||
149 | struct radeon_i2c_chan { | 162 | struct radeon_i2c_chan { |
@@ -417,8 +430,7 @@ extern void radeon_compute_pll(struct radeon_pll *pll, | |||
417 | uint32_t *fb_div_p, | 430 | uint32_t *fb_div_p, |
418 | uint32_t *frac_fb_div_p, | 431 | uint32_t *frac_fb_div_p, |
419 | uint32_t *ref_div_p, | 432 | uint32_t *ref_div_p, |
420 | uint32_t *post_div_p, | 433 | uint32_t *post_div_p); |
421 | int flags); | ||
422 | 434 | ||
423 | extern void radeon_compute_pll_avivo(struct radeon_pll *pll, | 435 | extern void radeon_compute_pll_avivo(struct radeon_pll *pll, |
424 | uint64_t freq, | 436 | uint64_t freq, |
@@ -426,8 +438,7 @@ extern void radeon_compute_pll_avivo(struct radeon_pll *pll, | |||
426 | uint32_t *fb_div_p, | 438 | uint32_t *fb_div_p, |
427 | uint32_t *frac_fb_div_p, | 439 | uint32_t *frac_fb_div_p, |
428 | uint32_t *ref_div_p, | 440 | uint32_t *ref_div_p, |
429 | uint32_t *post_div_p, | 441 | uint32_t *post_div_p); |
430 | int flags); | ||
431 | 442 | ||
432 | extern void radeon_setup_encoder_clones(struct drm_device *dev); | 443 | extern void radeon_setup_encoder_clones(struct drm_device *dev); |
433 | 444 | ||
@@ -453,7 +464,6 @@ extern void atombios_crtc_dpms(struct drm_crtc *crtc, int mode); | |||
453 | 464 | ||
454 | extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, | 465 | extern int radeon_crtc_set_base(struct drm_crtc *crtc, int x, int y, |
455 | struct drm_framebuffer *old_fb); | 466 | struct drm_framebuffer *old_fb); |
456 | extern void radeon_legacy_atom_set_surface(struct drm_crtc *crtc); | ||
457 | 467 | ||
458 | extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, | 468 | extern int radeon_crtc_cursor_set(struct drm_crtc *crtc, |
459 | struct drm_file *file_priv, | 469 | struct drm_file *file_priv, |
diff --git a/drivers/gpu/drm/radeon/radeon_object.c b/drivers/gpu/drm/radeon/radeon_object.c index 4e636de877b2..d72a71bff218 100644 --- a/drivers/gpu/drm/radeon/radeon_object.c +++ b/drivers/gpu/drm/radeon/radeon_object.c | |||
@@ -220,7 +220,8 @@ int radeon_bo_unpin(struct radeon_bo *bo) | |||
220 | 220 | ||
221 | int radeon_bo_evict_vram(struct radeon_device *rdev) | 221 | int radeon_bo_evict_vram(struct radeon_device *rdev) |
222 | { | 222 | { |
223 | if (rdev->flags & RADEON_IS_IGP) { | 223 | /* late 2.6.33 fix IGP hibernate - we need pm ops to do this correct */ |
224 | if (0 && (rdev->flags & RADEON_IS_IGP)) { | ||
224 | if (rdev->mc.igp_sideport_enabled == false) | 225 | if (rdev->mc.igp_sideport_enabled == false) |
225 | /* Useless to evict on IGP chips */ | 226 | /* Useless to evict on IGP chips */ |
226 | return 0; | 227 | return 0; |
diff --git a/drivers/gpu/drm/radeon/reg_srcs/r200 b/drivers/gpu/drm/radeon/reg_srcs/r200 index 6021c8849a16..c29ac434ac9c 100644 --- a/drivers/gpu/drm/radeon/reg_srcs/r200 +++ b/drivers/gpu/drm/radeon/reg_srcs/r200 | |||
@@ -91,6 +91,8 @@ r200 0x3294 | |||
91 | 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL | 91 | 0x22b8 SE_TCL_TEX_CYL_WRAP_CTL |
92 | 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL | 92 | 0x22c0 SE_TCL_UCP_VERT_BLEND_CNTL |
93 | 0x22c4 SE_TCL_POINT_SPRITE_CNTL | 93 | 0x22c4 SE_TCL_POINT_SPRITE_CNTL |
94 | 0x22d0 SE_PVS_CNTL | ||
95 | 0x22d4 SE_PVS_CONST_CNTL | ||
94 | 0x2648 RE_POINTSIZE | 96 | 0x2648 RE_POINTSIZE |
95 | 0x26c0 RE_TOP_LEFT | 97 | 0x26c0 RE_TOP_LEFT |
96 | 0x26c4 RE_MISC | 98 | 0x26c4 RE_MISC |
diff --git a/drivers/gpu/drm/radeon/rv770.c b/drivers/gpu/drm/radeon/rv770.c index 59c71245fb91..55f6ffc4e58b 100644 --- a/drivers/gpu/drm/radeon/rv770.c +++ b/drivers/gpu/drm/radeon/rv770.c | |||
@@ -779,7 +779,6 @@ int rv770_mc_init(struct radeon_device *rdev) | |||
779 | fixed20_12 a; | 779 | fixed20_12 a; |
780 | u32 tmp; | 780 | u32 tmp; |
781 | int chansize, numchan; | 781 | int chansize, numchan; |
782 | int r; | ||
783 | 782 | ||
784 | /* Get VRAM informations */ | 783 | /* Get VRAM informations */ |
785 | rdev->mc.vram_is_ddr = true; | 784 | rdev->mc.vram_is_ddr = true; |
@@ -822,9 +821,6 @@ int rv770_mc_init(struct radeon_device *rdev) | |||
822 | rdev->mc.real_vram_size = rdev->mc.aper_size; | 821 | rdev->mc.real_vram_size = rdev->mc.aper_size; |
823 | 822 | ||
824 | if (rdev->flags & RADEON_IS_AGP) { | 823 | if (rdev->flags & RADEON_IS_AGP) { |
825 | r = radeon_agp_init(rdev); | ||
826 | if (r) | ||
827 | return r; | ||
828 | /* gtt_size is setup by radeon_agp_init */ | 824 | /* gtt_size is setup by radeon_agp_init */ |
829 | rdev->mc.gtt_location = rdev->mc.agp_base; | 825 | rdev->mc.gtt_location = rdev->mc.agp_base; |
830 | tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; | 826 | tmp = 0xFFFFFFFFUL - rdev->mc.agp_base - rdev->mc.gtt_size; |
@@ -972,13 +968,16 @@ int rv770_suspend(struct radeon_device *rdev) | |||
972 | /* FIXME: we should wait for ring to be empty */ | 968 | /* FIXME: we should wait for ring to be empty */ |
973 | r700_cp_stop(rdev); | 969 | r700_cp_stop(rdev); |
974 | rdev->cp.ready = false; | 970 | rdev->cp.ready = false; |
971 | r600_irq_suspend(rdev); | ||
975 | r600_wb_disable(rdev); | 972 | r600_wb_disable(rdev); |
976 | rv770_pcie_gart_disable(rdev); | 973 | rv770_pcie_gart_disable(rdev); |
977 | /* unpin shaders bo */ | 974 | /* unpin shaders bo */ |
978 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); | 975 | if (rdev->r600_blit.shader_obj) { |
979 | if (likely(r == 0)) { | 976 | r = radeon_bo_reserve(rdev->r600_blit.shader_obj, false); |
980 | radeon_bo_unpin(rdev->r600_blit.shader_obj); | 977 | if (likely(r == 0)) { |
981 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | 978 | radeon_bo_unpin(rdev->r600_blit.shader_obj); |
979 | radeon_bo_unreserve(rdev->r600_blit.shader_obj); | ||
980 | } | ||
982 | } | 981 | } |
983 | return 0; | 982 | return 0; |
984 | } | 983 | } |
@@ -1037,6 +1036,11 @@ int rv770_init(struct radeon_device *rdev) | |||
1037 | r = radeon_fence_driver_init(rdev); | 1036 | r = radeon_fence_driver_init(rdev); |
1038 | if (r) | 1037 | if (r) |
1039 | return r; | 1038 | return r; |
1039 | if (rdev->flags & RADEON_IS_AGP) { | ||
1040 | r = radeon_agp_init(rdev); | ||
1041 | if (r) | ||
1042 | radeon_agp_disable(rdev); | ||
1043 | } | ||
1040 | r = rv770_mc_init(rdev); | 1044 | r = rv770_mc_init(rdev); |
1041 | if (r) | 1045 | if (r) |
1042 | return r; | 1046 | return r; |
@@ -1071,13 +1075,14 @@ int rv770_init(struct radeon_device *rdev) | |||
1071 | if (rdev->accel_working) { | 1075 | if (rdev->accel_working) { |
1072 | r = radeon_ib_pool_init(rdev); | 1076 | r = radeon_ib_pool_init(rdev); |
1073 | if (r) { | 1077 | if (r) { |
1074 | DRM_ERROR("radeon: failed initializing IB pool (%d).\n", r); | 1078 | dev_err(rdev->dev, "IB initialization failed (%d).\n", r); |
1075 | rdev->accel_working = false; | ||
1076 | } | ||
1077 | r = r600_ib_test(rdev); | ||
1078 | if (r) { | ||
1079 | DRM_ERROR("radeon: failed testing IB (%d).\n", r); | ||
1080 | rdev->accel_working = false; | 1079 | rdev->accel_working = false; |
1080 | } else { | ||
1081 | r = r600_ib_test(rdev); | ||
1082 | if (r) { | ||
1083 | dev_err(rdev->dev, "IB test failed (%d).\n", r); | ||
1084 | rdev->accel_working = false; | ||
1085 | } | ||
1081 | } | 1086 | } |
1082 | } | 1087 | } |
1083 | return 0; | 1088 | return 0; |
diff --git a/drivers/gpu/drm/ttm/ttm_bo.c b/drivers/gpu/drm/ttm/ttm_bo.c index 2920f9a279e1..1a3e909b7bba 100644 --- a/drivers/gpu/drm/ttm/ttm_bo.c +++ b/drivers/gpu/drm/ttm/ttm_bo.c | |||
@@ -426,7 +426,8 @@ moved: | |||
426 | bdev->man[bo->mem.mem_type].gpu_offset; | 426 | bdev->man[bo->mem.mem_type].gpu_offset; |
427 | bo->cur_placement = bo->mem.placement; | 427 | bo->cur_placement = bo->mem.placement; |
428 | spin_unlock(&bo->lock); | 428 | spin_unlock(&bo->lock); |
429 | } | 429 | } else |
430 | bo->offset = 0; | ||
430 | 431 | ||
431 | return 0; | 432 | return 0; |
432 | 433 | ||
@@ -523,52 +524,44 @@ static int ttm_bo_cleanup_refs(struct ttm_buffer_object *bo, bool remove_all) | |||
523 | static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) | 524 | static int ttm_bo_delayed_delete(struct ttm_bo_device *bdev, bool remove_all) |
524 | { | 525 | { |
525 | struct ttm_bo_global *glob = bdev->glob; | 526 | struct ttm_bo_global *glob = bdev->glob; |
526 | struct ttm_buffer_object *entry, *nentry; | 527 | struct ttm_buffer_object *entry = NULL; |
527 | struct list_head *list, *next; | 528 | int ret = 0; |
528 | int ret; | ||
529 | 529 | ||
530 | spin_lock(&glob->lru_lock); | 530 | spin_lock(&glob->lru_lock); |
531 | list_for_each_safe(list, next, &bdev->ddestroy) { | 531 | if (list_empty(&bdev->ddestroy)) |
532 | entry = list_entry(list, struct ttm_buffer_object, ddestroy); | 532 | goto out_unlock; |
533 | nentry = NULL; | ||
534 | 533 | ||
535 | /* | 534 | entry = list_first_entry(&bdev->ddestroy, |
536 | * Protect the next list entry from destruction while we | 535 | struct ttm_buffer_object, ddestroy); |
537 | * unlock the lru_lock. | 536 | kref_get(&entry->list_kref); |
538 | */ | ||
539 | 537 | ||
540 | if (next != &bdev->ddestroy) { | 538 | for (;;) { |
541 | nentry = list_entry(next, struct ttm_buffer_object, | 539 | struct ttm_buffer_object *nentry = NULL; |
542 | ddestroy); | 540 | |
541 | if (entry->ddestroy.next != &bdev->ddestroy) { | ||
542 | nentry = list_first_entry(&entry->ddestroy, | ||
543 | struct ttm_buffer_object, ddestroy); | ||
543 | kref_get(&nentry->list_kref); | 544 | kref_get(&nentry->list_kref); |
544 | } | 545 | } |
545 | kref_get(&entry->list_kref); | ||
546 | 546 | ||
547 | spin_unlock(&glob->lru_lock); | 547 | spin_unlock(&glob->lru_lock); |
548 | ret = ttm_bo_cleanup_refs(entry, remove_all); | 548 | ret = ttm_bo_cleanup_refs(entry, remove_all); |
549 | kref_put(&entry->list_kref, ttm_bo_release_list); | 549 | kref_put(&entry->list_kref, ttm_bo_release_list); |
550 | entry = nentry; | ||
551 | |||
552 | if (ret || !entry) | ||
553 | goto out; | ||
550 | 554 | ||
551 | spin_lock(&glob->lru_lock); | 555 | spin_lock(&glob->lru_lock); |
552 | if (nentry) { | 556 | if (list_empty(&entry->ddestroy)) |
553 | bool next_onlist = !list_empty(next); | ||
554 | spin_unlock(&glob->lru_lock); | ||
555 | kref_put(&nentry->list_kref, ttm_bo_release_list); | ||
556 | spin_lock(&glob->lru_lock); | ||
557 | /* | ||
558 | * Someone might have raced us and removed the | ||
559 | * next entry from the list. We don't bother restarting | ||
560 | * list traversal. | ||
561 | */ | ||
562 | |||
563 | if (!next_onlist) | ||
564 | break; | ||
565 | } | ||
566 | if (ret) | ||
567 | break; | 557 | break; |
568 | } | 558 | } |
569 | ret = !list_empty(&bdev->ddestroy); | ||
570 | spin_unlock(&glob->lru_lock); | ||
571 | 559 | ||
560 | out_unlock: | ||
561 | spin_unlock(&glob->lru_lock); | ||
562 | out: | ||
563 | if (entry) | ||
564 | kref_put(&entry->list_kref, ttm_bo_release_list); | ||
572 | return ret; | 565 | return ret; |
573 | } | 566 | } |
574 | 567 | ||
@@ -950,6 +943,14 @@ int ttm_bo_mem_space(struct ttm_buffer_object *bo, | |||
950 | ttm_flag_masked(&cur_flags, placement->busy_placement[i], | 943 | ttm_flag_masked(&cur_flags, placement->busy_placement[i], |
951 | ~TTM_PL_MASK_MEMTYPE); | 944 | ~TTM_PL_MASK_MEMTYPE); |
952 | 945 | ||
946 | |||
947 | if (mem_type == TTM_PL_SYSTEM) { | ||
948 | mem->mem_type = mem_type; | ||
949 | mem->placement = cur_flags; | ||
950 | mem->mm_node = NULL; | ||
951 | return 0; | ||
952 | } | ||
953 | |||
953 | ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, | 954 | ret = ttm_bo_mem_force_space(bo, mem_type, placement, mem, |
954 | interruptible, no_wait); | 955 | interruptible, no_wait); |
955 | if (ret == 0 && mem->mm_node) { | 956 | if (ret == 0 && mem->mm_node) { |
@@ -1844,6 +1845,9 @@ static int ttm_bo_swapout(struct ttm_mem_shrink *shrink) | |||
1844 | * anyone tries to access a ttm page. | 1845 | * anyone tries to access a ttm page. |
1845 | */ | 1846 | */ |
1846 | 1847 | ||
1848 | if (bo->bdev->driver->swap_notify) | ||
1849 | bo->bdev->driver->swap_notify(bo); | ||
1850 | |||
1847 | ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage); | 1851 | ret = ttm_tt_swapout(bo->ttm, bo->persistant_swap_storage); |
1848 | out: | 1852 | out: |
1849 | 1853 | ||
@@ -1864,3 +1868,4 @@ void ttm_bo_swapout_all(struct ttm_bo_device *bdev) | |||
1864 | while (ttm_bo_swapout(&bdev->glob->shrink) == 0) | 1868 | while (ttm_bo_swapout(&bdev->glob->shrink) == 0) |
1865 | ; | 1869 | ; |
1866 | } | 1870 | } |
1871 | EXPORT_SYMBOL(ttm_bo_swapout_all); | ||
diff --git a/drivers/gpu/drm/ttm/ttm_lock.c b/drivers/gpu/drm/ttm/ttm_lock.c index f619ebcaa4ec..3d172ef04ee1 100644 --- a/drivers/gpu/drm/ttm/ttm_lock.c +++ b/drivers/gpu/drm/ttm/ttm_lock.c | |||
@@ -288,6 +288,7 @@ void ttm_suspend_unlock(struct ttm_lock *lock) | |||
288 | wake_up_all(&lock->queue); | 288 | wake_up_all(&lock->queue); |
289 | spin_unlock(&lock->lock); | 289 | spin_unlock(&lock->lock); |
290 | } | 290 | } |
291 | EXPORT_SYMBOL(ttm_suspend_unlock); | ||
291 | 292 | ||
292 | static bool __ttm_suspend_lock(struct ttm_lock *lock) | 293 | static bool __ttm_suspend_lock(struct ttm_lock *lock) |
293 | { | 294 | { |
@@ -309,3 +310,4 @@ void ttm_suspend_lock(struct ttm_lock *lock) | |||
309 | { | 310 | { |
310 | wait_event(lock->queue, __ttm_suspend_lock(lock)); | 311 | wait_event(lock->queue, __ttm_suspend_lock(lock)); |
311 | } | 312 | } |
313 | EXPORT_SYMBOL(ttm_suspend_lock); | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c index d6f2d2b882e9..825ebe3d89d5 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_buffer.c | |||
@@ -48,6 +48,15 @@ struct ttm_placement vmw_vram_placement = { | |||
48 | .busy_placement = &vram_placement_flags | 48 | .busy_placement = &vram_placement_flags |
49 | }; | 49 | }; |
50 | 50 | ||
51 | struct ttm_placement vmw_vram_sys_placement = { | ||
52 | .fpfn = 0, | ||
53 | .lpfn = 0, | ||
54 | .num_placement = 1, | ||
55 | .placement = &vram_placement_flags, | ||
56 | .num_busy_placement = 1, | ||
57 | .busy_placement = &sys_placement_flags | ||
58 | }; | ||
59 | |||
51 | struct ttm_placement vmw_vram_ne_placement = { | 60 | struct ttm_placement vmw_vram_ne_placement = { |
52 | .fpfn = 0, | 61 | .fpfn = 0, |
53 | .lpfn = 0, | 62 | .lpfn = 0, |
@@ -172,6 +181,18 @@ static int vmw_verify_access(struct ttm_buffer_object *bo, struct file *filp) | |||
172 | return 0; | 181 | return 0; |
173 | } | 182 | } |
174 | 183 | ||
184 | static void vmw_move_notify(struct ttm_buffer_object *bo, | ||
185 | struct ttm_mem_reg *new_mem) | ||
186 | { | ||
187 | if (new_mem->mem_type != TTM_PL_SYSTEM) | ||
188 | vmw_dmabuf_gmr_unbind(bo); | ||
189 | } | ||
190 | |||
191 | static void vmw_swap_notify(struct ttm_buffer_object *bo) | ||
192 | { | ||
193 | vmw_dmabuf_gmr_unbind(bo); | ||
194 | } | ||
195 | |||
175 | /** | 196 | /** |
176 | * FIXME: We're using the old vmware polling method to sync. | 197 | * FIXME: We're using the old vmware polling method to sync. |
177 | * Do this with fences instead. | 198 | * Do this with fences instead. |
@@ -225,5 +246,7 @@ struct ttm_bo_driver vmw_bo_driver = { | |||
225 | .sync_obj_wait = vmw_sync_obj_wait, | 246 | .sync_obj_wait = vmw_sync_obj_wait, |
226 | .sync_obj_flush = vmw_sync_obj_flush, | 247 | .sync_obj_flush = vmw_sync_obj_flush, |
227 | .sync_obj_unref = vmw_sync_obj_unref, | 248 | .sync_obj_unref = vmw_sync_obj_unref, |
228 | .sync_obj_ref = vmw_sync_obj_ref | 249 | .sync_obj_ref = vmw_sync_obj_ref, |
250 | .move_notify = vmw_move_notify, | ||
251 | .swap_notify = vmw_swap_notify | ||
229 | }; | 252 | }; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c index 1db1ef30be2b..dedd121d8fe7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.c | |||
@@ -147,6 +147,8 @@ static char *vmw_devname = "vmwgfx"; | |||
147 | 147 | ||
148 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); | 148 | static int vmw_probe(struct pci_dev *, const struct pci_device_id *); |
149 | static void vmw_master_init(struct vmw_master *); | 149 | static void vmw_master_init(struct vmw_master *); |
150 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | ||
151 | void *ptr); | ||
150 | 152 | ||
151 | static void vmw_print_capabilities(uint32_t capabilities) | 153 | static void vmw_print_capabilities(uint32_t capabilities) |
152 | { | 154 | { |
@@ -217,6 +219,7 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
217 | 219 | ||
218 | dev_priv->dev = dev; | 220 | dev_priv->dev = dev; |
219 | dev_priv->vmw_chipset = chipset; | 221 | dev_priv->vmw_chipset = chipset; |
222 | dev_priv->last_read_sequence = (uint32_t) -100; | ||
220 | mutex_init(&dev_priv->hw_mutex); | 223 | mutex_init(&dev_priv->hw_mutex); |
221 | mutex_init(&dev_priv->cmdbuf_mutex); | 224 | mutex_init(&dev_priv->cmdbuf_mutex); |
222 | rwlock_init(&dev_priv->resource_lock); | 225 | rwlock_init(&dev_priv->resource_lock); |
@@ -351,6 +354,9 @@ static int vmw_driver_load(struct drm_device *dev, unsigned long chipset) | |||
351 | vmw_fb_init(dev_priv); | 354 | vmw_fb_init(dev_priv); |
352 | } | 355 | } |
353 | 356 | ||
357 | dev_priv->pm_nb.notifier_call = vmwgfx_pm_notifier; | ||
358 | register_pm_notifier(&dev_priv->pm_nb); | ||
359 | |||
354 | return 0; | 360 | return 0; |
355 | 361 | ||
356 | out_no_device: | 362 | out_no_device: |
@@ -385,6 +391,8 @@ static int vmw_driver_unload(struct drm_device *dev) | |||
385 | 391 | ||
386 | DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); | 392 | DRM_INFO(VMWGFX_DRIVER_NAME " unload.\n"); |
387 | 393 | ||
394 | unregister_pm_notifier(&dev_priv->pm_nb); | ||
395 | |||
388 | if (!dev_priv->stealth) { | 396 | if (!dev_priv->stealth) { |
389 | vmw_fb_close(dev_priv); | 397 | vmw_fb_close(dev_priv); |
390 | vmw_kms_close(dev_priv); | 398 | vmw_kms_close(dev_priv); |
@@ -650,6 +658,57 @@ static void vmw_remove(struct pci_dev *pdev) | |||
650 | drm_put_dev(dev); | 658 | drm_put_dev(dev); |
651 | } | 659 | } |
652 | 660 | ||
661 | static int vmwgfx_pm_notifier(struct notifier_block *nb, unsigned long val, | ||
662 | void *ptr) | ||
663 | { | ||
664 | struct vmw_private *dev_priv = | ||
665 | container_of(nb, struct vmw_private, pm_nb); | ||
666 | struct vmw_master *vmaster = dev_priv->active_master; | ||
667 | |||
668 | switch (val) { | ||
669 | case PM_HIBERNATION_PREPARE: | ||
670 | case PM_SUSPEND_PREPARE: | ||
671 | ttm_suspend_lock(&vmaster->lock); | ||
672 | |||
673 | /** | ||
674 | * This empties VRAM and unbinds all GMR bindings. | ||
675 | * Buffer contents is moved to swappable memory. | ||
676 | */ | ||
677 | ttm_bo_swapout_all(&dev_priv->bdev); | ||
678 | break; | ||
679 | case PM_POST_HIBERNATION: | ||
680 | case PM_POST_SUSPEND: | ||
681 | ttm_suspend_unlock(&vmaster->lock); | ||
682 | break; | ||
683 | case PM_RESTORE_PREPARE: | ||
684 | break; | ||
685 | case PM_POST_RESTORE: | ||
686 | break; | ||
687 | default: | ||
688 | break; | ||
689 | } | ||
690 | return 0; | ||
691 | } | ||
692 | |||
693 | /** | ||
694 | * These might not be needed with the virtual SVGA device. | ||
695 | */ | ||
696 | |||
697 | int vmw_pci_suspend(struct pci_dev *pdev, pm_message_t state) | ||
698 | { | ||
699 | pci_save_state(pdev); | ||
700 | pci_disable_device(pdev); | ||
701 | pci_set_power_state(pdev, PCI_D3hot); | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | int vmw_pci_resume(struct pci_dev *pdev) | ||
706 | { | ||
707 | pci_set_power_state(pdev, PCI_D0); | ||
708 | pci_restore_state(pdev); | ||
709 | return pci_enable_device(pdev); | ||
710 | } | ||
711 | |||
653 | static struct drm_driver driver = { | 712 | static struct drm_driver driver = { |
654 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | | 713 | .driver_features = DRIVER_HAVE_IRQ | DRIVER_IRQ_SHARED | |
655 | DRIVER_MODESET, | 714 | DRIVER_MODESET, |
@@ -689,7 +748,9 @@ static struct drm_driver driver = { | |||
689 | .name = VMWGFX_DRIVER_NAME, | 748 | .name = VMWGFX_DRIVER_NAME, |
690 | .id_table = vmw_pci_id_list, | 749 | .id_table = vmw_pci_id_list, |
691 | .probe = vmw_probe, | 750 | .probe = vmw_probe, |
692 | .remove = vmw_remove | 751 | .remove = vmw_remove, |
752 | .suspend = vmw_pci_suspend, | ||
753 | .resume = vmw_pci_resume | ||
693 | }, | 754 | }, |
694 | .name = VMWGFX_DRIVER_NAME, | 755 | .name = VMWGFX_DRIVER_NAME, |
695 | .desc = VMWGFX_DRIVER_DESC, | 756 | .desc = VMWGFX_DRIVER_DESC, |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h index e61bd85b6975..50529a7f06fb 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_drv.h | |||
@@ -32,6 +32,7 @@ | |||
32 | #include "drmP.h" | 32 | #include "drmP.h" |
33 | #include "vmwgfx_drm.h" | 33 | #include "vmwgfx_drm.h" |
34 | #include "drm_hashtab.h" | 34 | #include "drm_hashtab.h" |
35 | #include "linux/suspend.h" | ||
35 | #include "ttm/ttm_bo_driver.h" | 36 | #include "ttm/ttm_bo_driver.h" |
36 | #include "ttm/ttm_object.h" | 37 | #include "ttm/ttm_object.h" |
37 | #include "ttm/ttm_lock.h" | 38 | #include "ttm/ttm_lock.h" |
@@ -258,6 +259,7 @@ struct vmw_private { | |||
258 | 259 | ||
259 | struct vmw_master *active_master; | 260 | struct vmw_master *active_master; |
260 | struct vmw_master fbdev_master; | 261 | struct vmw_master fbdev_master; |
262 | struct notifier_block pm_nb; | ||
261 | }; | 263 | }; |
262 | 264 | ||
263 | static inline struct vmw_private *vmw_priv(struct drm_device *dev) | 265 | static inline struct vmw_private *vmw_priv(struct drm_device *dev) |
@@ -353,6 +355,7 @@ extern int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, | |||
353 | struct vmw_dma_buffer *bo); | 355 | struct vmw_dma_buffer *bo); |
354 | extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv, | 356 | extern int vmw_dmabuf_from_vram(struct vmw_private *vmw_priv, |
355 | struct vmw_dma_buffer *bo); | 357 | struct vmw_dma_buffer *bo); |
358 | extern void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo); | ||
356 | extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, | 359 | extern int vmw_stream_claim_ioctl(struct drm_device *dev, void *data, |
357 | struct drm_file *file_priv); | 360 | struct drm_file *file_priv); |
358 | extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, | 361 | extern int vmw_stream_unref_ioctl(struct drm_device *dev, void *data, |
@@ -401,6 +404,7 @@ extern int vmw_mmap(struct file *filp, struct vm_area_struct *vma); | |||
401 | 404 | ||
402 | extern struct ttm_placement vmw_vram_placement; | 405 | extern struct ttm_placement vmw_vram_placement; |
403 | extern struct ttm_placement vmw_vram_ne_placement; | 406 | extern struct ttm_placement vmw_vram_ne_placement; |
407 | extern struct ttm_placement vmw_vram_sys_placement; | ||
404 | extern struct ttm_placement vmw_sys_placement; | 408 | extern struct ttm_placement vmw_sys_placement; |
405 | extern struct ttm_bo_driver vmw_bo_driver; | 409 | extern struct ttm_bo_driver vmw_bo_driver; |
406 | extern int vmw_dma_quiescent(struct drm_device *dev); | 410 | extern int vmw_dma_quiescent(struct drm_device *dev); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c index 2e92da567403..d69caf92ffe7 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_execbuf.c | |||
@@ -490,10 +490,29 @@ static int vmw_validate_single_buffer(struct vmw_private *dev_priv, | |||
490 | if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL) | 490 | if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL) |
491 | return 0; | 491 | return 0; |
492 | 492 | ||
493 | /** | ||
494 | * Put BO in VRAM, only if there is space. | ||
495 | */ | ||
496 | |||
497 | ret = ttm_bo_validate(bo, &vmw_vram_sys_placement, true, false); | ||
498 | if (unlikely(ret == -ERESTARTSYS)) | ||
499 | return ret; | ||
500 | |||
501 | /** | ||
502 | * Otherwise, set it up as GMR. | ||
503 | */ | ||
504 | |||
505 | if (vmw_dmabuf_gmr(bo) != SVGA_GMR_NULL) | ||
506 | return 0; | ||
507 | |||
493 | ret = vmw_gmr_bind(dev_priv, bo); | 508 | ret = vmw_gmr_bind(dev_priv, bo); |
494 | if (likely(ret == 0 || ret == -ERESTARTSYS)) | 509 | if (likely(ret == 0 || ret == -ERESTARTSYS)) |
495 | return ret; | 510 | return ret; |
496 | 511 | ||
512 | /** | ||
513 | * If that failed, try VRAM again, this time evicting | ||
514 | * previous contents. | ||
515 | */ | ||
497 | 516 | ||
498 | ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false); | 517 | ret = ttm_bo_validate(bo, &vmw_vram_placement, true, false); |
499 | return ret; | 518 | return ret; |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c index 641dde76ada1..4f4f6432be8b 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fb.c | |||
@@ -649,14 +649,6 @@ int vmw_dmabuf_to_start_of_vram(struct vmw_private *vmw_priv, | |||
649 | if (unlikely(ret != 0)) | 649 | if (unlikely(ret != 0)) |
650 | goto err_unlock; | 650 | goto err_unlock; |
651 | 651 | ||
652 | if (vmw_bo->gmr_bound) { | ||
653 | vmw_gmr_unbind(vmw_priv, vmw_bo->gmr_id); | ||
654 | spin_lock(&bo->glob->lru_lock); | ||
655 | ida_remove(&vmw_priv->gmr_ida, vmw_bo->gmr_id); | ||
656 | spin_unlock(&bo->glob->lru_lock); | ||
657 | vmw_bo->gmr_bound = NULL; | ||
658 | } | ||
659 | |||
660 | ret = ttm_bo_validate(bo, &ne_placement, false, false); | 652 | ret = ttm_bo_validate(bo, &ne_placement, false, false); |
661 | ttm_bo_unreserve(bo); | 653 | ttm_bo_unreserve(bo); |
662 | err_unlock: | 654 | err_unlock: |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c index 01feb48af333..f7d5f70b52dd 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_fifo.c | |||
@@ -98,8 +98,7 @@ int vmw_fifo_init(struct vmw_private *dev_priv, struct vmw_fifo_state *fifo) | |||
98 | (unsigned int) min, | 98 | (unsigned int) min, |
99 | (unsigned int) fifo->capabilities); | 99 | (unsigned int) fifo->capabilities); |
100 | 100 | ||
101 | dev_priv->fence_seq = (uint32_t) -100; | 101 | dev_priv->fence_seq = dev_priv->last_read_sequence; |
102 | dev_priv->last_read_sequence = (uint32_t) -100; | ||
103 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); | 102 | iowrite32(dev_priv->last_read_sequence, fifo_mem + SVGA_FIFO_FENCE); |
104 | 103 | ||
105 | return vmw_fifo_send_fence(dev_priv, &dummy); | 104 | return vmw_fifo_send_fence(dev_priv, &dummy); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c index b1af76e371c3..686692de209a 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_kms.c | |||
@@ -553,9 +553,7 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | |||
553 | } *cmd; | 553 | } *cmd; |
554 | int i, increment = 1; | 554 | int i, increment = 1; |
555 | 555 | ||
556 | if (!num_clips || | 556 | if (!num_clips) { |
557 | !(dev_priv->fifo.capabilities & | ||
558 | SVGA_FIFO_CAP_SCREEN_OBJECT)) { | ||
559 | num_clips = 1; | 557 | num_clips = 1; |
560 | clips = &norect; | 558 | clips = &norect; |
561 | norect.x1 = norect.y1 = 0; | 559 | norect.x1 = norect.y1 = 0; |
@@ -574,10 +572,10 @@ int vmw_framebuffer_dmabuf_dirty(struct drm_framebuffer *framebuffer, | |||
574 | 572 | ||
575 | for (i = 0; i < num_clips; i++, clips += increment) { | 573 | for (i = 0; i < num_clips; i++, clips += increment) { |
576 | cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE); | 574 | cmd[i].header = cpu_to_le32(SVGA_CMD_UPDATE); |
577 | cmd[i].body.x = cpu_to_le32(clips[i].x1); | 575 | cmd[i].body.x = cpu_to_le32(clips->x1); |
578 | cmd[i].body.y = cpu_to_le32(clips[i].y1); | 576 | cmd[i].body.y = cpu_to_le32(clips->y1); |
579 | cmd[i].body.width = cpu_to_le32(clips[i].x2 - clips[i].x1); | 577 | cmd[i].body.width = cpu_to_le32(clips->x2 - clips->x1); |
580 | cmd[i].body.height = cpu_to_le32(clips[i].y2 - clips[i].y1); | 578 | cmd[i].body.height = cpu_to_le32(clips->y2 - clips->y1); |
581 | } | 579 | } |
582 | 580 | ||
583 | vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); | 581 | vmw_fifo_commit(dev_priv, sizeof(*cmd) * num_clips); |
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c index bb6e6a096d25..5b6eabeb7f51 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_overlay.c | |||
@@ -104,7 +104,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, | |||
104 | bool pin, bool interruptible) | 104 | bool pin, bool interruptible) |
105 | { | 105 | { |
106 | struct ttm_buffer_object *bo = &buf->base; | 106 | struct ttm_buffer_object *bo = &buf->base; |
107 | struct ttm_bo_global *glob = bo->glob; | ||
108 | struct ttm_placement *overlay_placement = &vmw_vram_placement; | 107 | struct ttm_placement *overlay_placement = &vmw_vram_placement; |
109 | int ret; | 108 | int ret; |
110 | 109 | ||
@@ -116,14 +115,6 @@ static int vmw_dmabuf_pin_in_vram(struct vmw_private *dev_priv, | |||
116 | if (unlikely(ret != 0)) | 115 | if (unlikely(ret != 0)) |
117 | goto err; | 116 | goto err; |
118 | 117 | ||
119 | if (buf->gmr_bound) { | ||
120 | vmw_gmr_unbind(dev_priv, buf->gmr_id); | ||
121 | spin_lock(&glob->lru_lock); | ||
122 | ida_remove(&dev_priv->gmr_ida, buf->gmr_id); | ||
123 | spin_unlock(&glob->lru_lock); | ||
124 | buf->gmr_bound = NULL; | ||
125 | } | ||
126 | |||
127 | if (pin) | 118 | if (pin) |
128 | overlay_placement = &vmw_vram_ne_placement; | 119 | overlay_placement = &vmw_vram_ne_placement; |
129 | 120 | ||
diff --git a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c index c012d5927f65..e01db120efff 100644 --- a/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c +++ b/drivers/gpu/drm/vmwgfx/vmwgfx_resource.c | |||
@@ -599,6 +599,27 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
599 | if (unlikely(ret != 0)) | 599 | if (unlikely(ret != 0)) |
600 | goto out_err1; | 600 | goto out_err1; |
601 | 601 | ||
602 | |||
603 | if (srf->flags & (1 << 9) && | ||
604 | srf->num_sizes == 1 && | ||
605 | srf->sizes[0].width == 64 && | ||
606 | srf->sizes[0].height == 64 && | ||
607 | srf->format == SVGA3D_A8R8G8B8) { | ||
608 | |||
609 | srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); | ||
610 | /* clear the image */ | ||
611 | if (srf->snooper.image) { | ||
612 | memset(srf->snooper.image, 0x00, 64 * 64 * 4); | ||
613 | } else { | ||
614 | DRM_ERROR("Failed to allocate cursor_image\n"); | ||
615 | ret = -ENOMEM; | ||
616 | goto out_err1; | ||
617 | } | ||
618 | } else { | ||
619 | srf->snooper.image = NULL; | ||
620 | } | ||
621 | srf->snooper.crtc = NULL; | ||
622 | |||
602 | user_srf->base.shareable = false; | 623 | user_srf->base.shareable = false; |
603 | user_srf->base.tfile = NULL; | 624 | user_srf->base.tfile = NULL; |
604 | 625 | ||
@@ -622,24 +643,6 @@ int vmw_surface_define_ioctl(struct drm_device *dev, void *data, | |||
622 | return ret; | 643 | return ret; |
623 | } | 644 | } |
624 | 645 | ||
625 | if (srf->flags & (1 << 9) && | ||
626 | srf->num_sizes == 1 && | ||
627 | srf->sizes[0].width == 64 && | ||
628 | srf->sizes[0].height == 64 && | ||
629 | srf->format == SVGA3D_A8R8G8B8) { | ||
630 | |||
631 | srf->snooper.image = kmalloc(64 * 64 * 4, GFP_KERNEL); | ||
632 | /* clear the image */ | ||
633 | if (srf->snooper.image) | ||
634 | memset(srf->snooper.image, 0x00, 64 * 64 * 4); | ||
635 | else | ||
636 | DRM_ERROR("Failed to allocate cursor_image\n"); | ||
637 | |||
638 | } else { | ||
639 | srf->snooper.image = NULL; | ||
640 | } | ||
641 | srf->snooper.crtc = NULL; | ||
642 | |||
643 | rep->sid = user_srf->base.hash.key; | 646 | rep->sid = user_srf->base.hash.key; |
644 | if (rep->sid == SVGA3D_INVALID_ID) | 647 | if (rep->sid == SVGA3D_INVALID_ID) |
645 | DRM_ERROR("Created bad Surface ID.\n"); | 648 | DRM_ERROR("Created bad Surface ID.\n"); |
@@ -754,20 +757,29 @@ static size_t vmw_dmabuf_acc_size(struct ttm_bo_global *glob, | |||
754 | return bo_user_size + page_array_size; | 757 | return bo_user_size + page_array_size; |
755 | } | 758 | } |
756 | 759 | ||
757 | void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) | 760 | void vmw_dmabuf_gmr_unbind(struct ttm_buffer_object *bo) |
758 | { | 761 | { |
759 | struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); | 762 | struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); |
760 | struct ttm_bo_global *glob = bo->glob; | 763 | struct ttm_bo_global *glob = bo->glob; |
761 | struct vmw_private *dev_priv = | 764 | struct vmw_private *dev_priv = |
762 | container_of(bo->bdev, struct vmw_private, bdev); | 765 | container_of(bo->bdev, struct vmw_private, bdev); |
763 | 766 | ||
764 | ttm_mem_global_free(glob->mem_glob, bo->acc_size); | ||
765 | if (vmw_bo->gmr_bound) { | 767 | if (vmw_bo->gmr_bound) { |
766 | vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); | 768 | vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); |
767 | spin_lock(&glob->lru_lock); | 769 | spin_lock(&glob->lru_lock); |
768 | ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); | 770 | ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); |
769 | spin_unlock(&glob->lru_lock); | 771 | spin_unlock(&glob->lru_lock); |
772 | vmw_bo->gmr_bound = false; | ||
770 | } | 773 | } |
774 | } | ||
775 | |||
776 | void vmw_dmabuf_bo_free(struct ttm_buffer_object *bo) | ||
777 | { | ||
778 | struct vmw_dma_buffer *vmw_bo = vmw_dma_buffer(bo); | ||
779 | struct ttm_bo_global *glob = bo->glob; | ||
780 | |||
781 | vmw_dmabuf_gmr_unbind(bo); | ||
782 | ttm_mem_global_free(glob->mem_glob, bo->acc_size); | ||
771 | kfree(vmw_bo); | 783 | kfree(vmw_bo); |
772 | } | 784 | } |
773 | 785 | ||
@@ -813,18 +825,10 @@ int vmw_dmabuf_init(struct vmw_private *dev_priv, | |||
813 | static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) | 825 | static void vmw_user_dmabuf_destroy(struct ttm_buffer_object *bo) |
814 | { | 826 | { |
815 | struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); | 827 | struct vmw_user_dma_buffer *vmw_user_bo = vmw_user_dma_buffer(bo); |
816 | struct vmw_dma_buffer *vmw_bo = &vmw_user_bo->dma; | ||
817 | struct ttm_bo_global *glob = bo->glob; | 828 | struct ttm_bo_global *glob = bo->glob; |
818 | struct vmw_private *dev_priv = | ||
819 | container_of(bo->bdev, struct vmw_private, bdev); | ||
820 | 829 | ||
830 | vmw_dmabuf_gmr_unbind(bo); | ||
821 | ttm_mem_global_free(glob->mem_glob, bo->acc_size); | 831 | ttm_mem_global_free(glob->mem_glob, bo->acc_size); |
822 | if (vmw_bo->gmr_bound) { | ||
823 | vmw_gmr_unbind(dev_priv, vmw_bo->gmr_id); | ||
824 | spin_lock(&glob->lru_lock); | ||
825 | ida_remove(&dev_priv->gmr_ida, vmw_bo->gmr_id); | ||
826 | spin_unlock(&glob->lru_lock); | ||
827 | } | ||
828 | kfree(vmw_user_bo); | 832 | kfree(vmw_user_bo); |
829 | } | 833 | } |
830 | 834 | ||
@@ -868,7 +872,7 @@ int vmw_dmabuf_alloc_ioctl(struct drm_device *dev, void *data, | |||
868 | } | 872 | } |
869 | 873 | ||
870 | ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, | 874 | ret = vmw_dmabuf_init(dev_priv, &vmw_user_bo->dma, req->size, |
871 | &vmw_vram_placement, true, | 875 | &vmw_vram_sys_placement, true, |
872 | &vmw_user_dmabuf_destroy); | 876 | &vmw_user_dmabuf_destroy); |
873 | if (unlikely(ret != 0)) | 877 | if (unlikely(ret != 0)) |
874 | return ret; | 878 | return ret; |
diff --git a/include/drm/ttm/ttm_bo_driver.h b/include/drm/ttm/ttm_bo_driver.h index ff7664e0c3cd..4c4e0f8375b3 100644 --- a/include/drm/ttm/ttm_bo_driver.h +++ b/include/drm/ttm/ttm_bo_driver.h | |||
@@ -353,6 +353,11 @@ struct ttm_bo_driver { | |||
353 | /* notify the driver we are taking a fault on this BO | 353 | /* notify the driver we are taking a fault on this BO |
354 | * and have reserved it */ | 354 | * and have reserved it */ |
355 | void (*fault_reserve_notify)(struct ttm_buffer_object *bo); | 355 | void (*fault_reserve_notify)(struct ttm_buffer_object *bo); |
356 | |||
357 | /** | ||
358 | * notify the driver that we're about to swap out this bo | ||
359 | */ | ||
360 | void (*swap_notify) (struct ttm_buffer_object *bo); | ||
356 | }; | 361 | }; |
357 | 362 | ||
358 | /** | 363 | /** |