Commit e8a47c10 authored by Dave Airlie's avatar Dave Airlie

Merge remote branch 'nouveau/for-airlied' of nouveau-2.6

* 'nouveau/for-airlied' of /home/airlied/kernel/drm-next:
  nouveau: fix state detection with switchable graphics
  drm/nouveau: move dereferences after null checks
  drm/nv50: make the pgraph irq handler loop like the pre-nv50 version
  drm/nv50: delete ramfc object after disabling fifo, not before
  drm/nv50: avoid unloading pgraph context when ctxprog is running
  drm/nv50: align size of buffer object to the right boundaries.
  drm/nv50: disregard dac outputs in nv50_sor_dpms()
  drm/nv50: prevent multiple init tables being parsed at the same time
  drm/nouveau: make dp auxch xfer len check for reads only
  drm/nv40: make INIT_COMPUTE_MEM a NOP, just like nv50
  drm/nouveau: Add proper vgaarb support.
  drm/nouveau: Fix fbcon on mixed pre-NV50 + NV50 multicard.
  drivers/gpu/drm/nouveau/nouveau_grctx.c: correct NULL test
  drm/nouveau: call ttm_bo_wait with the bo lock held to prevent hang
  drm/nouveau: Fixup semaphores on pre-nv50 cards.
  drm/nouveau: Add getparam to get available PGRAPH units.
  drm/nouveau: Add module options to disable acceleration.
  drm/nouveau: fix non-vram notifier blocks
parents 85b9e487 13876c6e
...@@ -90,21 +90,21 @@ int nouveau_hybrid_setup(struct drm_device *dev) ...@@ -90,21 +90,21 @@ int nouveau_hybrid_setup(struct drm_device *dev)
{ {
int result; int result;
if (nouveau_dsm(dev, NOUVEAU_DSM_ACTIVE, NOUVEAU_DSM_ACTIVE_QUERY, if (nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STATE,
&result)) &result))
return -ENODEV; return -ENODEV;
NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result); NV_INFO(dev, "_DSM hardware status gave 0x%x\n", result);
if (result & 0x1) { /* Stamina mode - disable the external GPU */ if (result) { /* Ensure that the external GPU is enabled */
nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL);
nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED,
NULL);
} else { /* Stamina mode - disable the external GPU */
nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA, nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_STAMINA,
NULL); NULL);
nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA, nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA,
NULL); NULL);
} else { /* Ensure that the external GPU is enabled */
nouveau_dsm(dev, NOUVEAU_DSM_LED, NOUVEAU_DSM_LED_SPEED, NULL);
nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_SPEED,
NULL);
} }
return 0; return 0;
......
...@@ -1865,7 +1865,7 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec) ...@@ -1865,7 +1865,7 @@ init_compute_mem(struct nvbios *bios, uint16_t offset, struct init_exec *iexec)
struct drm_nouveau_private *dev_priv = bios->dev->dev_private; struct drm_nouveau_private *dev_priv = bios->dev->dev_private;
if (dev_priv->card_type >= NV_50) if (dev_priv->card_type >= NV_40)
return 1; return 1;
/* /*
...@@ -3765,7 +3765,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3765,7 +3765,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
*/ */
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct init_exec iexec = {true, false};
struct nvbios *bios = &dev_priv->VBIOS; struct nvbios *bios = &dev_priv->VBIOS;
uint8_t *table = &bios->data[bios->display.script_table_ptr]; uint8_t *table = &bios->data[bios->display.script_table_ptr];
uint8_t *otable = NULL; uint8_t *otable = NULL;
...@@ -3845,8 +3844,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3845,8 +3844,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
} }
bios->display.output = dcbent;
if (pxclk == 0) { if (pxclk == 0) {
script = ROM16(otable[6]); script = ROM16(otable[6]);
if (!script) { if (!script) {
...@@ -3855,7 +3852,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3855,7 +3852,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
NV_TRACE(dev, "0x%04X: parsing output script 0\n", script); NV_TRACE(dev, "0x%04X: parsing output script 0\n", script);
parse_init_table(bios, script, &iexec); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk == -1) { if (pxclk == -1) {
script = ROM16(otable[8]); script = ROM16(otable[8]);
...@@ -3865,7 +3862,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3865,7 +3862,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
NV_TRACE(dev, "0x%04X: parsing output script 1\n", script); NV_TRACE(dev, "0x%04X: parsing output script 1\n", script);
parse_init_table(bios, script, &iexec); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk == -2) { if (pxclk == -2) {
if (table[4] >= 12) if (table[4] >= 12)
...@@ -3878,7 +3875,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3878,7 +3875,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
NV_TRACE(dev, "0x%04X: parsing output script 2\n", script); NV_TRACE(dev, "0x%04X: parsing output script 2\n", script);
parse_init_table(bios, script, &iexec); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk > 0) { if (pxclk > 0) {
script = ROM16(otable[table[4] + i*6 + 2]); script = ROM16(otable[table[4] + i*6 + 2]);
...@@ -3890,7 +3887,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3890,7 +3887,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script); NV_TRACE(dev, "0x%04X: parsing clock script 0\n", script);
parse_init_table(bios, script, &iexec); nouveau_bios_run_init_table(dev, script, dcbent);
} else } else
if (pxclk < 0) { if (pxclk < 0) {
script = ROM16(otable[table[4] + i*6 + 4]); script = ROM16(otable[table[4] + i*6 + 4]);
...@@ -3902,7 +3899,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent, ...@@ -3902,7 +3899,7 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
} }
NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script); NV_TRACE(dev, "0x%04X: parsing clock script 1\n", script);
parse_init_table(bios, script, &iexec); nouveau_bios_run_init_table(dev, script, dcbent);
} }
return 0; return 0;
...@@ -5864,10 +5861,13 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table, ...@@ -5864,10 +5861,13 @@ nouveau_bios_run_init_table(struct drm_device *dev, uint16_t table,
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nvbios *bios = &dev_priv->VBIOS; struct nvbios *bios = &dev_priv->VBIOS;
struct init_exec iexec = { true, false }; struct init_exec iexec = { true, false };
unsigned long flags;
spin_lock_irqsave(&bios->lock, flags);
bios->display.output = dcbent; bios->display.output = dcbent;
parse_init_table(bios, table, &iexec); parse_init_table(bios, table, &iexec);
bios->display.output = NULL; bios->display.output = NULL;
spin_unlock_irqrestore(&bios->lock, flags);
} }
static bool NVInitVBIOS(struct drm_device *dev) static bool NVInitVBIOS(struct drm_device *dev)
...@@ -5876,6 +5876,7 @@ static bool NVInitVBIOS(struct drm_device *dev) ...@@ -5876,6 +5876,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
struct nvbios *bios = &dev_priv->VBIOS; struct nvbios *bios = &dev_priv->VBIOS;
memset(bios, 0, sizeof(struct nvbios)); memset(bios, 0, sizeof(struct nvbios));
spin_lock_init(&bios->lock);
bios->dev = dev; bios->dev = dev;
if (!NVShadowVBIOS(dev, bios->data)) if (!NVShadowVBIOS(dev, bios->data))
......
...@@ -205,6 +205,8 @@ struct nvbios { ...@@ -205,6 +205,8 @@ struct nvbios {
struct drm_device *dev; struct drm_device *dev;
struct nouveau_bios_info pub; struct nouveau_bios_info pub;
spinlock_t lock;
uint8_t data[NV_PROM_SIZE]; uint8_t data[NV_PROM_SIZE];
unsigned int length; unsigned int length;
bool execute; bool execute;
......
...@@ -65,8 +65,10 @@ nouveau_bo_fixup_align(struct drm_device *dev, ...@@ -65,8 +65,10 @@ nouveau_bo_fixup_align(struct drm_device *dev,
/* /*
* Some of the tile_flags have a periodic structure of N*4096 bytes, * Some of the tile_flags have a periodic structure of N*4096 bytes,
* align to to that as well as the page size. Overallocate memory to * align to to that as well as the page size. Align the size to the
* avoid corruption of other buffer objects. * appropriate boundaries. This does imply that sizes are rounded up
* 3-7 pages, so be aware of this and do not waste memory by allocating
* many small buffers.
*/ */
if (dev_priv->card_type == NV_50) { if (dev_priv->card_type == NV_50) {
uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15; uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15;
...@@ -77,22 +79,20 @@ nouveau_bo_fixup_align(struct drm_device *dev, ...@@ -77,22 +79,20 @@ nouveau_bo_fixup_align(struct drm_device *dev,
case 0x2800: case 0x2800:
case 0x4800: case 0x4800:
case 0x7a00: case 0x7a00:
*size = roundup(*size, block_size);
if (is_power_of_2(block_size)) { if (is_power_of_2(block_size)) {
*size += 3 * block_size;
for (i = 1; i < 10; i++) { for (i = 1; i < 10; i++) {
*align = 12 * i * block_size; *align = 12 * i * block_size;
if (!(*align % 65536)) if (!(*align % 65536))
break; break;
} }
} else { } else {
*size += 6 * block_size;
for (i = 1; i < 10; i++) { for (i = 1; i < 10; i++) {
*align = 8 * i * block_size; *align = 8 * i * block_size;
if (!(*align % 65536)) if (!(*align % 65536))
break; break;
} }
} }
*size = roundup(*size, *align);
break; break;
default: default:
break; break;
......
...@@ -278,12 +278,11 @@ nouveau_channel_free(struct nouveau_channel *chan) ...@@ -278,12 +278,11 @@ nouveau_channel_free(struct nouveau_channel *chan)
/* Ensure the channel is no longer active on the GPU */ /* Ensure the channel is no longer active on the GPU */
pfifo->reassign(dev, false); pfifo->reassign(dev, false);
if (pgraph->channel(dev) == chan) { pgraph->fifo_access(dev, false);
pgraph->fifo_access(dev, false); if (pgraph->channel(dev) == chan)
pgraph->unload_context(dev); pgraph->unload_context(dev);
pgraph->fifo_access(dev, true);
}
pgraph->destroy_context(chan); pgraph->destroy_context(chan);
pgraph->fifo_access(dev, true);
if (pfifo->channel_id(dev) == chan->id) { if (pfifo->channel_id(dev) == chan->id) {
pfifo->disable(dev); pfifo->disable(dev);
......
...@@ -88,13 +88,14 @@ nouveau_connector_destroy(struct drm_connector *drm_connector) ...@@ -88,13 +88,14 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
{ {
struct nouveau_connector *nv_connector = struct nouveau_connector *nv_connector =
nouveau_connector(drm_connector); nouveau_connector(drm_connector);
struct drm_device *dev = nv_connector->base.dev; struct drm_device *dev;
NV_DEBUG_KMS(dev, "\n");
if (!nv_connector) if (!nv_connector)
return; return;
dev = nv_connector->base.dev;
NV_DEBUG_KMS(dev, "\n");
kfree(nv_connector->edid); kfree(nv_connector->edid);
drm_sysfs_connector_remove(drm_connector); drm_sysfs_connector_remove(drm_connector);
drm_connector_cleanup(drm_connector); drm_connector_cleanup(drm_connector);
......
...@@ -502,12 +502,12 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr, ...@@ -502,12 +502,12 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
break; break;
} }
if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
ret = -EREMOTEIO;
goto out;
}
if (cmd & 1) { if (cmd & 1) {
if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
ret = -EREMOTEIO;
goto out;
}
for (i = 0; i < 4; i++) { for (i = 0; i < 4; i++) {
data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i)); data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]); NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
......
...@@ -56,7 +56,7 @@ int nouveau_vram_pushbuf; ...@@ -56,7 +56,7 @@ int nouveau_vram_pushbuf;
module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400); module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM"); MODULE_PARM_DESC(vram_notify, "Force DMA notifiers to be in VRAM");
int nouveau_vram_notify; int nouveau_vram_notify = 1;
module_param_named(vram_notify, nouveau_vram_notify, int, 0400); module_param_named(vram_notify, nouveau_vram_notify, int, 0400);
MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)"); MODULE_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
...@@ -75,6 +75,14 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status"); ...@@ -75,6 +75,14 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
int nouveau_ignorelid = 0; int nouveau_ignorelid = 0;
module_param_named(ignorelid, nouveau_ignorelid, int, 0400); module_param_named(ignorelid, nouveau_ignorelid, int, 0400);
MODULE_PARM_DESC(noagp, "Disable all acceleration");
int nouveau_noaccel = 0;
module_param_named(noaccel, nouveau_noaccel, int, 0400);
MODULE_PARM_DESC(noagp, "Disable fbcon acceleration");
int nouveau_nofbaccel = 0;
module_param_named(nofbaccel, nouveau_nofbaccel, int, 0400);
MODULE_PARM_DESC(tv_norm, "Default TV norm.\n" MODULE_PARM_DESC(tv_norm, "Default TV norm.\n"
"\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n" "\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
"\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n" "\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
......
...@@ -678,6 +678,8 @@ extern int nouveau_reg_debug; ...@@ -678,6 +678,8 @@ extern int nouveau_reg_debug;
extern char *nouveau_vbios; extern char *nouveau_vbios;
extern int nouveau_ctxfw; extern int nouveau_ctxfw;
extern int nouveau_ignorelid; extern int nouveau_ignorelid;
extern int nouveau_nofbaccel;
extern int nouveau_noaccel;
/* nouveau_state.c */ /* nouveau_state.c */
extern void nouveau_preclose(struct drm_device *dev, struct drm_file *); extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
......
...@@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = { ...@@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = {
.fb_setcmap = drm_fb_helper_setcmap, .fb_setcmap = drm_fb_helper_setcmap,
}; };
static struct fb_ops nv04_fbcon_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_setcolreg = drm_fb_helper_setcolreg,
.fb_fillrect = nv04_fbcon_fillrect,
.fb_copyarea = nv04_fbcon_copyarea,
.fb_imageblit = nv04_fbcon_imageblit,
.fb_sync = nouveau_fbcon_sync,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap,
};
static struct fb_ops nv50_fbcon_ops = {
.owner = THIS_MODULE,
.fb_check_var = drm_fb_helper_check_var,
.fb_set_par = drm_fb_helper_set_par,
.fb_setcolreg = drm_fb_helper_setcolreg,
.fb_fillrect = nv50_fbcon_fillrect,
.fb_copyarea = nv50_fbcon_copyarea,
.fb_imageblit = nv50_fbcon_imageblit,
.fb_sync = nouveau_fbcon_sync,
.fb_pan_display = drm_fb_helper_pan_display,
.fb_blank = drm_fb_helper_blank,
.fb_setcmap = drm_fb_helper_setcmap,
};
static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green, static void nouveau_fbcon_gamma_set(struct drm_crtc *crtc, u16 red, u16 green,
u16 blue, int regno) u16 blue, int regno)
{ {
...@@ -267,8 +295,12 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -267,8 +295,12 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
dev_priv->fbdev_info = info; dev_priv->fbdev_info = info;
strcpy(info->fix.id, "nouveaufb"); strcpy(info->fix.id, "nouveaufb");
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA | if (nouveau_nofbaccel)
FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT; info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_DISABLED;
else
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
FBINFO_HWACCEL_FILLRECT |
FBINFO_HWACCEL_IMAGEBLIT;
info->fbops = &nouveau_fbcon_ops; info->fbops = &nouveau_fbcon_ops;
info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset - info->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
dev_priv->vm_vram_base; dev_priv->vm_vram_base;
...@@ -316,13 +348,15 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width, ...@@ -316,13 +348,15 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
par->nouveau_fb = nouveau_fb; par->nouveau_fb = nouveau_fb;
par->dev = dev; par->dev = dev;
if (dev_priv->channel) { if (dev_priv->channel && !nouveau_nofbaccel) {
switch (dev_priv->card_type) { switch (dev_priv->card_type) {
case NV_50: case NV_50:
nv50_fbcon_accel_init(info); nv50_fbcon_accel_init(info);
info->fbops = &nv50_fbcon_ops;
break; break;
default: default:
nv04_fbcon_accel_init(info); nv04_fbcon_accel_init(info);
info->fbops = &nv04_fbcon_ops;
break; break;
}; };
} }
......
...@@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb); ...@@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb);
void nouveau_fbcon_restore(void); void nouveau_fbcon_restore(void);
void nouveau_fbcon_zfill(struct drm_device *dev); void nouveau_fbcon_zfill(struct drm_device *dev);
void nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
void nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
int nv04_fbcon_accel_init(struct fb_info *info); int nv04_fbcon_accel_init(struct fb_info *info);
void nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect);
void nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region);
void nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image);
int nv50_fbcon_accel_init(struct fb_info *info); int nv50_fbcon_accel_init(struct fb_info *info);
void nouveau_fbcon_gpu_lockup(struct fb_info *info); void nouveau_fbcon_gpu_lockup(struct fb_info *info);
......
...@@ -925,7 +925,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data, ...@@ -925,7 +925,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
} }
if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) { if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
spin_lock(&nvbo->bo.lock);
ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait); ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
spin_unlock(&nvbo->bo.lock);
} else { } else {
ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait); ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
if (ret == 0) if (ret == 0)
......
...@@ -97,8 +97,8 @@ nouveau_grctx_prog_load(struct drm_device *dev) ...@@ -97,8 +97,8 @@ nouveau_grctx_prog_load(struct drm_device *dev)
} }
pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL); pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL);
if (!pgraph->ctxprog) { if (!pgraph->ctxvals) {
NV_ERROR(dev, "OOM copying ctxprog\n"); NV_ERROR(dev, "OOM copying ctxvals\n");
release_firmware(fw); release_firmware(fw);
nouveau_grctx_fini(dev); nouveau_grctx_fini(dev);
return -ENOMEM; return -ENOMEM;
......
...@@ -211,6 +211,20 @@ nouveau_fifo_irq_handler(struct drm_device *dev) ...@@ -211,6 +211,20 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
get + 4); get + 4);
} }
if (status & NV_PFIFO_INTR_SEMAPHORE) {
uint32_t sem;
status &= ~NV_PFIFO_INTR_SEMAPHORE;
nv_wr32(dev, NV03_PFIFO_INTR_0,
NV_PFIFO_INTR_SEMAPHORE);
sem = nv_rd32(dev, NV10_PFIFO_CACHE1_SEMAPHORE);
nv_wr32(dev, NV10_PFIFO_CACHE1_SEMAPHORE, sem | 0x1);
nv_wr32(dev, NV03_PFIFO_CACHE1_GET, get + 4);
nv_wr32(dev, NV04_PFIFO_CACHE1_PULL0, 1);
}
if (status) { if (status) {
NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n", NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
status, chid); status, chid);
...@@ -566,86 +580,99 @@ nouveau_pgraph_irq_handler(struct drm_device *dev) ...@@ -566,86 +580,99 @@ nouveau_pgraph_irq_handler(struct drm_device *dev)
static void static void
nv50_pgraph_irq_handler(struct drm_device *dev) nv50_pgraph_irq_handler(struct drm_device *dev)
{ {
uint32_t status, nsource; uint32_t status;
status = nv_rd32(dev, NV03_PGRAPH_INTR); while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE); uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
if (status & 0x00000001) { if (status & 0x00000001) {
nouveau_pgraph_intr_notify(dev, nsource); nouveau_pgraph_intr_notify(dev, nsource);
status &= ~0x00000001; status &= ~0x00000001;
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001); nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
} }
if (status & 0x00000010) { if (status & 0x00000010) {
nouveau_pgraph_intr_error(dev, nsource | nouveau_pgraph_intr_error(dev, nsource |
NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD); NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
status &= ~0x00000010; status &= ~0x00000010;
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010); nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
} }
if (status & 0x00001000) { if (status & 0x00001000) {
nv_wr32(dev, 0x400500, 0x00000000); nv_wr32(dev, 0x400500, 0x00000000);
nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH); nv_wr32(dev, NV03_PGRAPH_INTR,
nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev, NV_PGRAPH_INTR_CONTEXT_SWITCH);
NV40_PGRAPH_INTR_EN) & ~NV_PGRAPH_INTR_CONTEXT_SWITCH); nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
nv_wr32(dev, 0x400500, 0x00010001); NV40_PGRAPH_INTR_EN) &
~NV_PGRAPH_INTR_CONTEXT_SWITCH);
nv_wr32(dev, 0x400500, 0x00010001);
nv50_graph_context_switch(dev); nv50_graph_context_switch(dev);
status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH; status &= ~NV_PGRAPH_INTR_CONTEXT_SWITCH;
} }
if (status & 0x00100000) { if (status & 0x00100000) {
nouveau_pgraph_intr_error(dev, nsource | nouveau_pgraph_intr_error(dev, nsource |
NV03_PGRAPH_NSOURCE_DATA_ERROR); NV03_PGRAPH_NSOURCE_DATA_ERROR);
status &= ~0x00100000; status &= ~0x00100000;
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000); nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
} }
if (status & 0x00200000) { if (status & 0x00200000) {
int r; int r;
nouveau_pgraph_intr_error(dev, nsource | nouveau_pgraph_intr_error(dev, nsource |
NV03_PGRAPH_NSOURCE_PROTECTION_ERROR); NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
NV_ERROR(dev, "magic set 1:\n"); NV_ERROR(dev, "magic set 1:\n");
for (r = 0x408900; r <= 0x408910; r += 4) for (r = 0x408900; r <= 0x408910; r += 4)
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
nv_wr32(dev, 0x408900, nv_rd32(dev, 0x408904) | 0xc0000000); nv_rd32(dev, r));
for (r = 0x408e08; r <= 0x408e24; r += 4) nv_wr32(dev, 0x408900,
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); nv_rd32(dev, 0x408904) | 0xc0000000);
nv_wr32(dev, 0x408e08, nv_rd32(dev, 0x408e08) | 0xc0000000); for (r = 0x408e08; r <= 0x408e24; r += 4)
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
NV_ERROR(dev, "magic set 2:\n"); nv_rd32(dev, r));
for (r = 0x409900; r <= 0x409910; r += 4) nv_wr32(dev, 0x408e08,
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); nv_rd32(dev, 0x408e08) | 0xc0000000);
nv_wr32(dev, 0x409900, nv_rd32(dev, 0x409904) | 0xc0000000);
for (r = 0x409e08; r <= 0x409e24; r += 4) NV_ERROR(dev, "magic set 2:\n");
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r)); for (r = 0x409900; r <= 0x409910; r += 4)
nv_wr32(dev, 0x409e08, nv_rd32(dev, 0x409e08) | 0xc0000000); NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
nv_rd32(dev, r));
status &= ~0x00200000; nv_wr32(dev, 0x409900,
nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource); nv_rd32(dev, 0x409904) | 0xc0000000);
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000); for (r = 0x409e08; r <= 0x409e24; r += 4)
} NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
nv_rd32(dev, r));
nv_wr32(dev, 0x409e08,
nv_rd32(dev, 0x409e08) | 0xc0000000);
status &= ~0x00200000;
nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource);
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
}
if (status) { if (status) {
NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status); NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
nv_wr32(dev, NV03_PGRAPH_INTR, status); status);
} nv_wr32(dev, NV03_PGRAPH_INTR, status);
}
{ {
const int isb = (1 << 16) | (1 << 0); const int isb = (1 << 16) | (1 << 0);
if ((nv_rd32(dev, 0x400500) & isb) != isb) if ((nv_rd32(dev, 0x400500) & isb) != isb)
nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb); nv_wr32(dev, 0x400500,
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31)); nv_rd32(dev, 0x400500) | isb);
}
} }
nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING); nv_wr32(dev, NV03_PMC_INTR_0, NV_PMC_INTR_0_PGRAPH_PENDING);
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
} }
static void static void
......
...@@ -34,15 +34,20 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan) ...@@ -34,15 +34,20 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
{ {
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct nouveau_bo *ntfy = NULL; struct nouveau_bo *ntfy = NULL;
uint32_t flags;
int ret; int ret;
ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, nouveau_vram_notify ? if (nouveau_vram_notify)
TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT, flags = TTM_PL_FLAG_VRAM;
else
flags = TTM_PL_FLAG_TT;
ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, flags,
0, 0x0000, false, true, &ntfy); 0, 0x0000, false, true, &ntfy);
if (ret) if (ret)
return ret; return ret;
ret = nouveau_bo_pin(ntfy, TTM_PL_FLAG_VRAM); ret = nouveau_bo_pin(ntfy, flags);
if (ret) if (ret)
goto out_err; goto out_err;
...@@ -128,6 +133,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle, ...@@ -128,6 +133,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
target = NV_DMA_TARGET_PCI; target = NV_DMA_TARGET_PCI;
} else { } else {
target = NV_DMA_TARGET_AGP; target = NV_DMA_TARGET_AGP;
if (dev_priv->card_type >= NV_50)
offset += dev_priv->vm_gart_base;
} }
} else { } else {
NV_ERROR(dev, "Bad DMA target, mem_type %d!\n", NV_ERROR(dev, "Bad DMA target, mem_type %d!\n",
......
...@@ -885,11 +885,12 @@ int ...@@ -885,11 +885,12 @@ int
nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class, nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
struct nouveau_gpuobj **gpuobj_ret) struct nouveau_gpuobj **gpuobj_ret)
{ {
struct drm_nouveau_private *dev_priv = chan->dev->dev_private; struct drm_nouveau_private *dev_priv;
struct nouveau_gpuobj *gpuobj; struct nouveau_gpuobj *gpuobj;
if (!chan || !gpuobj_ret || *gpuobj_ret != NULL) if (!chan || !gpuobj_ret || *gpuobj_ret != NULL)
return -EINVAL; return -EINVAL;
dev_priv = chan->dev->dev_private;
gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL); gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
if (!gpuobj) if (!gpuobj)
......
...@@ -99,6 +99,7 @@ ...@@ -99,6 +99,7 @@
* the card will hang early on in the X init process. * the card will hang early on in the X init process.
*/ */
# define NV_PMC_ENABLE_UNK13 (1<<13) # define NV_PMC_ENABLE_UNK13 (1<<13)
#define NV40_PMC_GRAPH_UNITS 0x00001540
#define NV40_PMC_BACKLIGHT 0x000015f0 #define NV40_PMC_BACKLIGHT 0x000015f0
# define NV40_PMC_BACKLIGHT_MASK 0x001f0000 # define NV40_PMC_BACKLIGHT_MASK 0x001f0000
#define NV40_PMC_1700 0x00001700 #define NV40_PMC_1700 0x00001700
......
...@@ -54,11 +54,12 @@ static void ...@@ -54,11 +54,12 @@ static void
nouveau_sgdma_clear(struct ttm_backend *be) nouveau_sgdma_clear(struct ttm_backend *be)
{ {
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be; struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
struct drm_device *dev = nvbe->dev; struct drm_device *dev;
NV_DEBUG(nvbe->dev, "\n");
if (nvbe && nvbe->pages) { if (nvbe && nvbe->pages) {
dev = nvbe->dev;
NV_DEBUG(dev, "\n");
if (nvbe->bound) if (nvbe->bound)
be->func->unbind(be); be->func->unbind(be);
......
...@@ -310,6 +310,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev) ...@@ -310,6 +310,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
static unsigned int static unsigned int
nouveau_vga_set_decode(void *priv, bool state) nouveau_vga_set_decode(void *priv, bool state)
{ {
struct drm_device *dev = priv;
struct drm_nouveau_private *dev_priv = dev->dev_private;
if (dev_priv->chipset >= 0x40)
nv_wr32(dev, 0x88054, state);
else
nv_wr32(dev, 0x1854, state);
if (state) if (state)
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM | return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM; VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
...@@ -427,15 +435,19 @@ nouveau_card_init(struct drm_device *dev) ...@@ -427,15 +435,19 @@ nouveau_card_init(struct drm_device *dev)
if (ret) if (ret)
goto out_timer; goto out_timer;
/* PGRAPH */ if (nouveau_noaccel)
ret = engine->graph.init(dev); engine->graph.accel_blocked = true;
if (ret) else {
goto out_fb; /* PGRAPH */
ret = engine->graph.init(dev);
if (ret)
goto out_fb;
/* PFIFO */ /* PFIFO */
ret = engine->fifo.init(dev); ret = engine->fifo.init(dev);
if (ret) if (ret)
goto out_graph; goto out_graph;
}
/* this call irq_preinstall, register irq handler and /* this call irq_preinstall, register irq handler and
* call irq_postinstall * call irq_postinstall
...@@ -479,9 +491,11 @@ nouveau_card_init(struct drm_device *dev) ...@@ -479,9 +491,11 @@ nouveau_card_init(struct drm_device *dev)
out_irq: out_irq:
drm_irq_uninstall(dev); drm_irq_uninstall(dev);
out_fifo: out_fifo:
engine->fifo.takedown(dev); if (!nouveau_noaccel)
engine->fifo.takedown(dev);
out_graph: out_graph:
engine->graph.takedown(dev); if (!nouveau_noaccel)
engine->graph.takedown(dev);
out_fb: out_fb:
engine->fb.takedown(dev); engine->fb.takedown(dev);
out_timer: out_timer:
...@@ -518,8 +532,10 @@ static void nouveau_card_takedown(struct drm_device *dev) ...@@ -518,8 +532,10 @@ static void nouveau_card_takedown(struct drm_device *dev)
dev_priv->channel = NULL; dev_priv->channel = NULL;
} }
engine->fifo.takedown(dev); if (!nouveau_noaccel) {
engine->graph.takedown(dev); engine->fifo.takedown(dev);
engine->graph.takedown(dev);
}
engine->fb.takedown(dev); engine->fb.takedown(dev);
engine->timer.takedown(dev); engine->timer.takedown(dev);
engine->mc.takedown(dev); engine->mc.takedown(dev);
...@@ -817,6 +833,15 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data, ...@@ -817,6 +833,15 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
case NOUVEAU_GETPARAM_VM_VRAM_BASE: case NOUVEAU_GETPARAM_VM_VRAM_BASE:
getparam->value = dev_priv->vm_vram_base; getparam->value = dev_priv->vm_vram_base;
break; break;
case NOUVEAU_GETPARAM_GRAPH_UNITS:
/* NV40 and NV50 versions are quite different, but register
* address is the same. User is supposed to know the card
* family anyway... */
if (dev_priv->chipset >= 0x40) {
getparam->value = nv_rd32(dev, NV40_PMC_GRAPH_UNITS);
break;
}
/* FALLTHRU */
default: default:
NV_ERROR(dev, "unknown parameter %lld\n", getparam->param); NV_ERROR(dev, "unknown parameter %lld\n", getparam->param);
return -EINVAL; return -EINVAL;
......
...@@ -27,7 +27,7 @@ ...@@ -27,7 +27,7 @@
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_fbcon.h" #include "nouveau_fbcon.h"
static void void
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info) ...@@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info)
FIRE_RING(chan); FIRE_RING(chan);
info->fbops->fb_fillrect = nv04_fbcon_fillrect;
info->fbops->fb_copyarea = nv04_fbcon_copyarea;
info->fbops->fb_imageblit = nv04_fbcon_imageblit;
return 0; return 0;
} }
...@@ -298,14 +298,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk) ...@@ -298,14 +298,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
static void static void
nv50_crtc_destroy(struct drm_crtc *crtc) nv50_crtc_destroy(struct drm_crtc *crtc)
{ {
struct drm_device *dev = crtc->dev; struct drm_device *dev;
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc); struct nouveau_crtc *nv_crtc;
NV_DEBUG_KMS(dev, "\n");
if (!crtc) if (!crtc)
return; return;
dev = crtc->dev;
nv_crtc = nouveau_crtc(crtc);
NV_DEBUG_KMS(dev, "\n");
drm_crtc_cleanup(&nv_crtc->base); drm_crtc_cleanup(&nv_crtc->base);
nv50_cursor_fini(nv_crtc); nv50_cursor_fini(nv_crtc);
......
...@@ -3,7 +3,7 @@ ...@@ -3,7 +3,7 @@
#include "nouveau_dma.h" #include "nouveau_dma.h"
#include "nouveau_fbcon.h" #include "nouveau_fbcon.h"
static void void
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect) ...@@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region) ...@@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
FIRE_RING(chan); FIRE_RING(chan);
} }
static void void
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image) nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
{ {
struct nouveau_fbcon_par *par = info->par; struct nouveau_fbcon_par *par = info->par;
...@@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info) ...@@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info)
OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys + OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys +
dev_priv->vm_vram_base); dev_priv->vm_vram_base);
info->fbops->fb_fillrect = nv50_fbcon_fillrect;
info->fbops->fb_copyarea = nv50_fbcon_copyarea;
info->fbops->fb_imageblit = nv50_fbcon_imageblit;
return 0; return 0;
} }
...@@ -317,17 +317,20 @@ void ...@@ -317,17 +317,20 @@ void
nv50_fifo_destroy_context(struct nouveau_channel *chan) nv50_fifo_destroy_context(struct nouveau_channel *chan)
{ {
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct nouveau_gpuobj_ref *ramfc = chan->ramfc;
NV_DEBUG(dev, "ch%d\n", chan->id); NV_DEBUG(dev, "ch%d\n", chan->id);
nouveau_gpuobj_ref_del(dev, &chan->ramfc); /* This will ensure the channel is seen as disabled. */
nouveau_gpuobj_ref_del(dev, &chan->cache); chan->ramfc = NULL;
nv50_fifo_channel_disable(dev, chan->id, false); nv50_fifo_channel_disable(dev, chan->id, false);
/* Dummy channel, also used on ch 127 */ /* Dummy channel, also used on ch 127 */
if (chan->id == 0) if (chan->id == 0)
nv50_fifo_channel_disable(dev, 127, false); nv50_fifo_channel_disable(dev, 127, false);
nouveau_gpuobj_ref_del(dev, &ramfc);
nouveau_gpuobj_ref_del(dev, &chan->cache);
} }
int int
......
...@@ -165,6 +165,12 @@ nv50_graph_channel(struct drm_device *dev) ...@@ -165,6 +165,12 @@ nv50_graph_channel(struct drm_device *dev)
uint32_t inst; uint32_t inst;
int i; int i;
/* Be sure we're not in the middle of a context switch or bad things
* will happen, such as unloading the wrong pgraph context.
*/
if (!nv_wait(0x400300, 0x00000001, 0x00000000))
NV_ERROR(dev, "Ctxprog is still running\n");
inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
return NULL; return NULL;
...@@ -275,7 +281,7 @@ nv50_graph_load_context(struct nouveau_channel *chan) ...@@ -275,7 +281,7 @@ nv50_graph_load_context(struct nouveau_channel *chan)
int int
nv50_graph_unload_context(struct drm_device *dev) nv50_graph_unload_context(struct drm_device *dev)
{ {
uint32_t inst, fifo = nv_rd32(dev, 0x400500); uint32_t inst;
inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR); inst = nv_rd32(dev, NV50_PGRAPH_CTXCTL_CUR);
if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED)) if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
...@@ -283,12 +289,10 @@ nv50_graph_unload_context(struct drm_device *dev) ...@@ -283,12 +289,10 @@ nv50_graph_unload_context(struct drm_device *dev)
inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE; inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
nouveau_wait_for_idle(dev); nouveau_wait_for_idle(dev);
nv_wr32(dev, 0x400500, fifo & ~1);
nv_wr32(dev, 0x400784, inst); nv_wr32(dev, 0x400784, inst);
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20); nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01); nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01);
nouveau_wait_for_idle(dev); nouveau_wait_for_idle(dev);
nv_wr32(dev, 0x400500, fifo);
nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst); nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst);
return 0; return 0;
......
...@@ -101,6 +101,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode) ...@@ -101,6 +101,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
struct nouveau_encoder *nvenc = nouveau_encoder(enc); struct nouveau_encoder *nvenc = nouveau_encoder(enc);
if (nvenc == nv_encoder || if (nvenc == nv_encoder ||
nvenc->disconnect != nv50_sor_disconnect ||
nvenc->dcb->or != nv_encoder->dcb->or) nvenc->dcb->or != nv_encoder->dcb->or)
continue; continue;
......
...@@ -77,6 +77,7 @@ struct drm_nouveau_gpuobj_free { ...@@ -77,6 +77,7 @@ struct drm_nouveau_gpuobj_free {
#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10 #define NOUVEAU_GETPARAM_PCI_PHYSICAL 10
#define NOUVEAU_GETPARAM_CHIPSET_ID 11 #define NOUVEAU_GETPARAM_CHIPSET_ID 11
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12 #define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
struct drm_nouveau_getparam { struct drm_nouveau_getparam {
uint64_t param; uint64_t param;
uint64_t value; uint64_t value;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment