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
This commit is contained in:
commit
e8a47c10b2
@ -90,21 +90,21 @@ int nouveau_hybrid_setup(struct drm_device *dev)
|
||||
{
|
||||
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))
|
||||
return -ENODEV;
|
||||
|
||||
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,
|
||||
NULL);
|
||||
nouveau_dsm(dev, NOUVEAU_DSM_POWER, NOUVEAU_DSM_POWER_STAMINA,
|
||||
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;
|
||||
|
@ -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;
|
||||
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
if (dev_priv->card_type >= NV_40)
|
||||
return 1;
|
||||
|
||||
/*
|
||||
@ -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 init_exec iexec = {true, false};
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
uint8_t *table = &bios->data[bios->display.script_table_ptr];
|
||||
uint8_t *otable = NULL;
|
||||
@ -3845,8 +3844,6 @@ nouveau_bios_run_display_table(struct drm_device *dev, struct dcb_entry *dcbent,
|
||||
}
|
||||
}
|
||||
|
||||
bios->display.output = dcbent;
|
||||
|
||||
if (pxclk == 0) {
|
||||
script = ROM16(otable[6]);
|
||||
if (!script) {
|
||||
@ -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);
|
||||
parse_init_table(bios, script, &iexec);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk == -1) {
|
||||
script = ROM16(otable[8]);
|
||||
@ -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);
|
||||
parse_init_table(bios, script, &iexec);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk == -2) {
|
||||
if (table[4] >= 12)
|
||||
@ -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);
|
||||
parse_init_table(bios, script, &iexec);
|
||||
nouveau_bios_run_init_table(dev, script, dcbent);
|
||||
} else
|
||||
if (pxclk > 0) {
|
||||
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,
|
||||
}
|
||||
|
||||
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
|
||||
if (pxclk < 0) {
|
||||
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,
|
||||
}
|
||||
|
||||
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;
|
||||
@ -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 nvbios *bios = &dev_priv->VBIOS;
|
||||
struct init_exec iexec = { true, false };
|
||||
unsigned long flags;
|
||||
|
||||
spin_lock_irqsave(&bios->lock, flags);
|
||||
bios->display.output = dcbent;
|
||||
parse_init_table(bios, table, &iexec);
|
||||
bios->display.output = NULL;
|
||||
spin_unlock_irqrestore(&bios->lock, flags);
|
||||
}
|
||||
|
||||
static bool NVInitVBIOS(struct drm_device *dev)
|
||||
@ -5876,6 +5876,7 @@ static bool NVInitVBIOS(struct drm_device *dev)
|
||||
struct nvbios *bios = &dev_priv->VBIOS;
|
||||
|
||||
memset(bios, 0, sizeof(struct nvbios));
|
||||
spin_lock_init(&bios->lock);
|
||||
bios->dev = dev;
|
||||
|
||||
if (!NVShadowVBIOS(dev, bios->data))
|
||||
|
@ -205,6 +205,8 @@ struct nvbios {
|
||||
struct drm_device *dev;
|
||||
struct nouveau_bios_info pub;
|
||||
|
||||
spinlock_t lock;
|
||||
|
||||
uint8_t data[NV_PROM_SIZE];
|
||||
unsigned int length;
|
||||
bool execute;
|
||||
|
@ -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,
|
||||
* align to to that as well as the page size. Overallocate memory to
|
||||
* avoid corruption of other buffer objects.
|
||||
* align to to that as well as the page size. Align the size to the
|
||||
* 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) {
|
||||
uint32_t block_size = nouveau_mem_fb_amount(dev) >> 15;
|
||||
@ -77,22 +79,20 @@ nouveau_bo_fixup_align(struct drm_device *dev,
|
||||
case 0x2800:
|
||||
case 0x4800:
|
||||
case 0x7a00:
|
||||
*size = roundup(*size, block_size);
|
||||
if (is_power_of_2(block_size)) {
|
||||
*size += 3 * block_size;
|
||||
for (i = 1; i < 10; i++) {
|
||||
*align = 12 * i * block_size;
|
||||
if (!(*align % 65536))
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
*size += 6 * block_size;
|
||||
for (i = 1; i < 10; i++) {
|
||||
*align = 8 * i * block_size;
|
||||
if (!(*align % 65536))
|
||||
break;
|
||||
}
|
||||
}
|
||||
*size = roundup(*size, *align);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -278,12 +278,11 @@ nouveau_channel_free(struct nouveau_channel *chan)
|
||||
/* Ensure the channel is no longer active on the GPU */
|
||||
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->fifo_access(dev, true);
|
||||
}
|
||||
pgraph->destroy_context(chan);
|
||||
pgraph->fifo_access(dev, true);
|
||||
|
||||
if (pfifo->channel_id(dev) == chan->id) {
|
||||
pfifo->disable(dev);
|
||||
|
@ -88,13 +88,14 @@ nouveau_connector_destroy(struct drm_connector *drm_connector)
|
||||
{
|
||||
struct nouveau_connector *nv_connector =
|
||||
nouveau_connector(drm_connector);
|
||||
struct drm_device *dev = nv_connector->base.dev;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
struct drm_device *dev;
|
||||
|
||||
if (!nv_connector)
|
||||
return;
|
||||
|
||||
dev = nv_connector->base.dev;
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
kfree(nv_connector->edid);
|
||||
drm_sysfs_connector_remove(drm_connector);
|
||||
drm_connector_cleanup(drm_connector);
|
||||
|
@ -502,12 +502,12 @@ nouveau_dp_auxch(struct nouveau_i2c_chan *auxch, int cmd, int addr,
|
||||
break;
|
||||
}
|
||||
|
||||
if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (cmd & 1) {
|
||||
if ((stat & NV50_AUXCH_STAT_COUNT) != data_nr) {
|
||||
ret = -EREMOTEIO;
|
||||
goto out;
|
||||
}
|
||||
|
||||
for (i = 0; i < 4; i++) {
|
||||
data32[i] = nv_rd32(dev, NV50_AUXCH_DATA_IN(index, i));
|
||||
NV_DEBUG_KMS(dev, "rd %d: 0x%08x\n", i, data32[i]);
|
||||
|
@ -56,7 +56,7 @@ int nouveau_vram_pushbuf;
|
||||
module_param_named(vram_pushbuf, nouveau_vram_pushbuf, int, 0400);
|
||||
|
||||
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_PARM_DESC(duallink, "Allow dual-link TMDS (>=GeForce 8)");
|
||||
@ -75,6 +75,14 @@ MODULE_PARM_DESC(ignorelid, "Ignore ACPI lid status");
|
||||
int nouveau_ignorelid = 0;
|
||||
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"
|
||||
"\t\tSupported: PAL, PAL-M, PAL-N, PAL-Nc, NTSC-M, NTSC-J,\n"
|
||||
"\t\t\thd480i, hd480p, hd576i, hd576p, hd720p, hd1080i.\n"
|
||||
|
@ -678,6 +678,8 @@ extern int nouveau_reg_debug;
|
||||
extern char *nouveau_vbios;
|
||||
extern int nouveau_ctxfw;
|
||||
extern int nouveau_ignorelid;
|
||||
extern int nouveau_nofbaccel;
|
||||
extern int nouveau_noaccel;
|
||||
|
||||
/* nouveau_state.c */
|
||||
extern void nouveau_preclose(struct drm_device *dev, struct drm_file *);
|
||||
|
@ -107,6 +107,34 @@ static struct fb_ops nouveau_fbcon_ops = {
|
||||
.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,
|
||||
u16 blue, int regno)
|
||||
{
|
||||
@ -267,8 +295,12 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
|
||||
dev_priv->fbdev_info = info;
|
||||
|
||||
strcpy(info->fix.id, "nouveaufb");
|
||||
info->flags = FBINFO_DEFAULT | FBINFO_HWACCEL_COPYAREA |
|
||||
FBINFO_HWACCEL_FILLRECT | FBINFO_HWACCEL_IMAGEBLIT;
|
||||
if (nouveau_nofbaccel)
|
||||
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->fix.smem_start = dev->mode_config.fb_base + nvbo->bo.offset -
|
||||
dev_priv->vm_vram_base;
|
||||
@ -316,13 +348,15 @@ nouveau_fbcon_create(struct drm_device *dev, uint32_t fb_width,
|
||||
par->nouveau_fb = nouveau_fb;
|
||||
par->dev = dev;
|
||||
|
||||
if (dev_priv->channel) {
|
||||
if (dev_priv->channel && !nouveau_nofbaccel) {
|
||||
switch (dev_priv->card_type) {
|
||||
case NV_50:
|
||||
nv50_fbcon_accel_init(info);
|
||||
info->fbops = &nv50_fbcon_ops;
|
||||
break;
|
||||
default:
|
||||
nv04_fbcon_accel_init(info);
|
||||
info->fbops = &nv04_fbcon_ops;
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
@ -40,7 +40,13 @@ int nouveau_fbcon_remove(struct drm_device *dev, struct drm_framebuffer *fb);
|
||||
void nouveau_fbcon_restore(void);
|
||||
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);
|
||||
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);
|
||||
|
||||
void nouveau_fbcon_gpu_lockup(struct fb_info *info);
|
||||
|
@ -925,7 +925,9 @@ nouveau_gem_ioctl_cpu_prep(struct drm_device *dev, void *data,
|
||||
}
|
||||
|
||||
if (req->flags & NOUVEAU_GEM_CPU_PREP_NOBLOCK) {
|
||||
spin_lock(&nvbo->bo.lock);
|
||||
ret = ttm_bo_wait(&nvbo->bo, false, false, no_wait);
|
||||
spin_unlock(&nvbo->bo.lock);
|
||||
} else {
|
||||
ret = ttm_bo_synccpu_write_grab(&nvbo->bo, no_wait);
|
||||
if (ret == 0)
|
||||
|
@ -97,8 +97,8 @@ nouveau_grctx_prog_load(struct drm_device *dev)
|
||||
}
|
||||
|
||||
pgraph->ctxvals = kmalloc(fw->size, GFP_KERNEL);
|
||||
if (!pgraph->ctxprog) {
|
||||
NV_ERROR(dev, "OOM copying ctxprog\n");
|
||||
if (!pgraph->ctxvals) {
|
||||
NV_ERROR(dev, "OOM copying ctxvals\n");
|
||||
release_firmware(fw);
|
||||
nouveau_grctx_fini(dev);
|
||||
return -ENOMEM;
|
||||
|
@ -211,6 +211,20 @@ nouveau_fifo_irq_handler(struct drm_device *dev)
|
||||
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) {
|
||||
NV_INFO(dev, "PFIFO_INTR 0x%08x - Ch %d\n",
|
||||
status, chid);
|
||||
@ -566,86 +580,99 @@ nouveau_pgraph_irq_handler(struct drm_device *dev)
|
||||
static void
|
||||
nv50_pgraph_irq_handler(struct drm_device *dev)
|
||||
{
|
||||
uint32_t status, nsource;
|
||||
uint32_t status;
|
||||
|
||||
status = nv_rd32(dev, NV03_PGRAPH_INTR);
|
||||
nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
|
||||
while ((status = nv_rd32(dev, NV03_PGRAPH_INTR))) {
|
||||
uint32_t nsource = nv_rd32(dev, NV03_PGRAPH_NSOURCE);
|
||||
|
||||
if (status & 0x00000001) {
|
||||
nouveau_pgraph_intr_notify(dev, nsource);
|
||||
status &= ~0x00000001;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
|
||||
}
|
||||
if (status & 0x00000001) {
|
||||
nouveau_pgraph_intr_notify(dev, nsource);
|
||||
status &= ~0x00000001;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000001);
|
||||
}
|
||||
|
||||
if (status & 0x00000010) {
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
|
||||
if (status & 0x00000010) {
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_ILLEGAL_MTHD);
|
||||
|
||||
status &= ~0x00000010;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
|
||||
}
|
||||
status &= ~0x00000010;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00000010);
|
||||
}
|
||||
|
||||
if (status & 0x00001000) {
|
||||
nv_wr32(dev, 0x400500, 0x00000000);
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, NV_PGRAPH_INTR_CONTEXT_SWITCH);
|
||||
nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
|
||||
NV40_PGRAPH_INTR_EN) & ~NV_PGRAPH_INTR_CONTEXT_SWITCH);
|
||||
nv_wr32(dev, 0x400500, 0x00010001);
|
||||
if (status & 0x00001000) {
|
||||
nv_wr32(dev, 0x400500, 0x00000000);
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR,
|
||||
NV_PGRAPH_INTR_CONTEXT_SWITCH);
|
||||
nv_wr32(dev, NV40_PGRAPH_INTR_EN, nv_rd32(dev,
|
||||
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) {
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_DATA_ERROR);
|
||||
if (status & 0x00100000) {
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_DATA_ERROR);
|
||||
|
||||
status &= ~0x00100000;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
|
||||
}
|
||||
status &= ~0x00100000;
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00100000);
|
||||
}
|
||||
|
||||
if (status & 0x00200000) {
|
||||
int r;
|
||||
if (status & 0x00200000) {
|
||||
int r;
|
||||
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
|
||||
nouveau_pgraph_intr_error(dev, nsource |
|
||||
NV03_PGRAPH_NSOURCE_PROTECTION_ERROR);
|
||||
|
||||
NV_ERROR(dev, "magic set 1:\n");
|
||||
for (r = 0x408900; r <= 0x408910; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x408900, nv_rd32(dev, 0x408904) | 0xc0000000);
|
||||
for (r = 0x408e08; r <= 0x408e24; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x408e08, nv_rd32(dev, 0x408e08) | 0xc0000000);
|
||||
NV_ERROR(dev, "magic set 1:\n");
|
||||
for (r = 0x408900; r <= 0x408910; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
|
||||
nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x408900,
|
||||
nv_rd32(dev, 0x408904) | 0xc0000000);
|
||||
for (r = 0x408e08; r <= 0x408e24; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
|
||||
nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x408e08,
|
||||
nv_rd32(dev, 0x408e08) | 0xc0000000);
|
||||
|
||||
NV_ERROR(dev, "magic set 2:\n");
|
||||
for (r = 0x409900; r <= 0x409910; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r, nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x409900, nv_rd32(dev, 0x409904) | 0xc0000000);
|
||||
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);
|
||||
NV_ERROR(dev, "magic set 2:\n");
|
||||
for (r = 0x409900; r <= 0x409910; r += 4)
|
||||
NV_ERROR(dev, "\t0x%08x: 0x%08x\n", r,
|
||||
nv_rd32(dev, r));
|
||||
nv_wr32(dev, 0x409900,
|
||||
nv_rd32(dev, 0x409904) | 0xc0000000);
|
||||
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);
|
||||
}
|
||||
status &= ~0x00200000;
|
||||
nv_wr32(dev, NV03_PGRAPH_NSOURCE, nsource);
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, 0x00200000);
|
||||
}
|
||||
|
||||
if (status) {
|
||||
NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n", status);
|
||||
nv_wr32(dev, NV03_PGRAPH_INTR, status);
|
||||
}
|
||||
if (status) {
|
||||
NV_INFO(dev, "Unhandled PGRAPH_INTR - 0x%08x\n",
|
||||
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)
|
||||
nv_wr32(dev, 0x400500, nv_rd32(dev, 0x400500) | isb);
|
||||
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) & ~(1 << 31));
|
||||
if ((nv_rd32(dev, 0x400500) & isb) != isb)
|
||||
nv_wr32(dev, 0x400500,
|
||||
nv_rd32(dev, 0x400500) | isb);
|
||||
}
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -34,15 +34,20 @@ nouveau_notifier_init_channel(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_bo *ntfy = NULL;
|
||||
uint32_t flags;
|
||||
int ret;
|
||||
|
||||
ret = nouveau_gem_new(dev, NULL, PAGE_SIZE, 0, nouveau_vram_notify ?
|
||||
TTM_PL_FLAG_VRAM : TTM_PL_FLAG_TT,
|
||||
if (nouveau_vram_notify)
|
||||
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);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = nouveau_bo_pin(ntfy, TTM_PL_FLAG_VRAM);
|
||||
ret = nouveau_bo_pin(ntfy, flags);
|
||||
if (ret)
|
||||
goto out_err;
|
||||
|
||||
@ -128,6 +133,8 @@ nouveau_notifier_alloc(struct nouveau_channel *chan, uint32_t handle,
|
||||
target = NV_DMA_TARGET_PCI;
|
||||
} else {
|
||||
target = NV_DMA_TARGET_AGP;
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
offset += dev_priv->vm_gart_base;
|
||||
}
|
||||
} else {
|
||||
NV_ERROR(dev, "Bad DMA target, mem_type %d!\n",
|
||||
|
@ -885,11 +885,12 @@ int
|
||||
nouveau_gpuobj_sw_new(struct nouveau_channel *chan, int class,
|
||||
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;
|
||||
|
||||
if (!chan || !gpuobj_ret || *gpuobj_ret != NULL)
|
||||
return -EINVAL;
|
||||
dev_priv = chan->dev->dev_private;
|
||||
|
||||
gpuobj = kzalloc(sizeof(*gpuobj), GFP_KERNEL);
|
||||
if (!gpuobj)
|
||||
|
@ -99,6 +99,7 @@
|
||||
* the card will hang early on in the X init process.
|
||||
*/
|
||||
# define NV_PMC_ENABLE_UNK13 (1<<13)
|
||||
#define NV40_PMC_GRAPH_UNITS 0x00001540
|
||||
#define NV40_PMC_BACKLIGHT 0x000015f0
|
||||
# define NV40_PMC_BACKLIGHT_MASK 0x001f0000
|
||||
#define NV40_PMC_1700 0x00001700
|
||||
|
@ -54,11 +54,12 @@ static void
|
||||
nouveau_sgdma_clear(struct ttm_backend *be)
|
||||
{
|
||||
struct nouveau_sgdma_be *nvbe = (struct nouveau_sgdma_be *)be;
|
||||
struct drm_device *dev = nvbe->dev;
|
||||
|
||||
NV_DEBUG(nvbe->dev, "\n");
|
||||
struct drm_device *dev;
|
||||
|
||||
if (nvbe && nvbe->pages) {
|
||||
dev = nvbe->dev;
|
||||
NV_DEBUG(dev, "\n");
|
||||
|
||||
if (nvbe->bound)
|
||||
be->func->unbind(be);
|
||||
|
||||
|
@ -310,6 +310,14 @@ static int nouveau_init_engine_ptrs(struct drm_device *dev)
|
||||
static unsigned int
|
||||
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)
|
||||
return VGA_RSRC_LEGACY_IO | VGA_RSRC_LEGACY_MEM |
|
||||
VGA_RSRC_NORMAL_IO | VGA_RSRC_NORMAL_MEM;
|
||||
@ -427,15 +435,19 @@ nouveau_card_init(struct drm_device *dev)
|
||||
if (ret)
|
||||
goto out_timer;
|
||||
|
||||
/* PGRAPH */
|
||||
ret = engine->graph.init(dev);
|
||||
if (ret)
|
||||
goto out_fb;
|
||||
if (nouveau_noaccel)
|
||||
engine->graph.accel_blocked = true;
|
||||
else {
|
||||
/* PGRAPH */
|
||||
ret = engine->graph.init(dev);
|
||||
if (ret)
|
||||
goto out_fb;
|
||||
|
||||
/* PFIFO */
|
||||
ret = engine->fifo.init(dev);
|
||||
if (ret)
|
||||
goto out_graph;
|
||||
/* PFIFO */
|
||||
ret = engine->fifo.init(dev);
|
||||
if (ret)
|
||||
goto out_graph;
|
||||
}
|
||||
|
||||
/* this call irq_preinstall, register irq handler and
|
||||
* call irq_postinstall
|
||||
@ -479,9 +491,11 @@ nouveau_card_init(struct drm_device *dev)
|
||||
out_irq:
|
||||
drm_irq_uninstall(dev);
|
||||
out_fifo:
|
||||
engine->fifo.takedown(dev);
|
||||
if (!nouveau_noaccel)
|
||||
engine->fifo.takedown(dev);
|
||||
out_graph:
|
||||
engine->graph.takedown(dev);
|
||||
if (!nouveau_noaccel)
|
||||
engine->graph.takedown(dev);
|
||||
out_fb:
|
||||
engine->fb.takedown(dev);
|
||||
out_timer:
|
||||
@ -518,8 +532,10 @@ static void nouveau_card_takedown(struct drm_device *dev)
|
||||
dev_priv->channel = NULL;
|
||||
}
|
||||
|
||||
engine->fifo.takedown(dev);
|
||||
engine->graph.takedown(dev);
|
||||
if (!nouveau_noaccel) {
|
||||
engine->fifo.takedown(dev);
|
||||
engine->graph.takedown(dev);
|
||||
}
|
||||
engine->fb.takedown(dev);
|
||||
engine->timer.takedown(dev);
|
||||
engine->mc.takedown(dev);
|
||||
@ -817,6 +833,15 @@ int nouveau_ioctl_getparam(struct drm_device *dev, void *data,
|
||||
case NOUVEAU_GETPARAM_VM_VRAM_BASE:
|
||||
getparam->value = dev_priv->vm_vram_base;
|
||||
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:
|
||||
NV_ERROR(dev, "unknown parameter %lld\n", getparam->param);
|
||||
return -EINVAL;
|
||||
|
@ -27,7 +27,7 @@
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_fbcon.h"
|
||||
|
||||
static void
|
||||
void
|
||||
nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -54,7 +54,7 @@ nv04_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
FIRE_RING(chan);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -88,7 +88,7 @@ nv04_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
FIRE_RING(chan);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv04_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -307,9 +307,6 @@ nv04_fbcon_accel_init(struct fb_info *info)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -298,14 +298,17 @@ nv50_crtc_set_clock(struct drm_device *dev, int head, int pclk)
|
||||
static void
|
||||
nv50_crtc_destroy(struct drm_crtc *crtc)
|
||||
{
|
||||
struct drm_device *dev = crtc->dev;
|
||||
struct nouveau_crtc *nv_crtc = nouveau_crtc(crtc);
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
struct drm_device *dev;
|
||||
struct nouveau_crtc *nv_crtc;
|
||||
|
||||
if (!crtc)
|
||||
return;
|
||||
|
||||
dev = crtc->dev;
|
||||
nv_crtc = nouveau_crtc(crtc);
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
drm_crtc_cleanup(&nv_crtc->base);
|
||||
|
||||
nv50_cursor_fini(nv_crtc);
|
||||
|
@ -3,7 +3,7 @@
|
||||
#include "nouveau_dma.h"
|
||||
#include "nouveau_fbcon.h"
|
||||
|
||||
static void
|
||||
void
|
||||
nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -46,7 +46,7 @@ nv50_fbcon_fillrect(struct fb_info *info, const struct fb_fillrect *rect)
|
||||
FIRE_RING(chan);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -81,7 +81,7 @@ nv50_fbcon_copyarea(struct fb_info *info, const struct fb_copyarea *region)
|
||||
FIRE_RING(chan);
|
||||
}
|
||||
|
||||
static void
|
||||
void
|
||||
nv50_fbcon_imageblit(struct fb_info *info, const struct fb_image *image)
|
||||
{
|
||||
struct nouveau_fbcon_par *par = info->par;
|
||||
@ -262,9 +262,6 @@ nv50_fbcon_accel_init(struct fb_info *info)
|
||||
OUT_RING(chan, info->fix.smem_start - dev_priv->fb_phys +
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -317,17 +317,20 @@ void
|
||||
nv50_fifo_destroy_context(struct nouveau_channel *chan)
|
||||
{
|
||||
struct drm_device *dev = chan->dev;
|
||||
struct nouveau_gpuobj_ref *ramfc = chan->ramfc;
|
||||
|
||||
NV_DEBUG(dev, "ch%d\n", chan->id);
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &chan->ramfc);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->cache);
|
||||
|
||||
/* This will ensure the channel is seen as disabled. */
|
||||
chan->ramfc = NULL;
|
||||
nv50_fifo_channel_disable(dev, chan->id, false);
|
||||
|
||||
/* Dummy channel, also used on ch 127 */
|
||||
if (chan->id == 0)
|
||||
nv50_fifo_channel_disable(dev, 127, false);
|
||||
|
||||
nouveau_gpuobj_ref_del(dev, &ramfc);
|
||||
nouveau_gpuobj_ref_del(dev, &chan->cache);
|
||||
}
|
||||
|
||||
int
|
||||
|
@ -165,6 +165,12 @@ nv50_graph_channel(struct drm_device *dev)
|
||||
uint32_t inst;
|
||||
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);
|
||||
if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
|
||||
return NULL;
|
||||
@ -275,7 +281,7 @@ nv50_graph_load_context(struct nouveau_channel *chan)
|
||||
int
|
||||
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);
|
||||
if (!(inst & NV50_PGRAPH_CTXCTL_CUR_LOADED))
|
||||
@ -283,12 +289,10 @@ nv50_graph_unload_context(struct drm_device *dev)
|
||||
inst &= NV50_PGRAPH_CTXCTL_CUR_INSTANCE;
|
||||
|
||||
nouveau_wait_for_idle(dev);
|
||||
nv_wr32(dev, 0x400500, fifo & ~1);
|
||||
nv_wr32(dev, 0x400784, inst);
|
||||
nv_wr32(dev, 0x400824, nv_rd32(dev, 0x400824) | 0x20);
|
||||
nv_wr32(dev, 0x400304, nv_rd32(dev, 0x400304) | 0x01);
|
||||
nouveau_wait_for_idle(dev);
|
||||
nv_wr32(dev, 0x400500, fifo);
|
||||
|
||||
nv_wr32(dev, NV50_PGRAPH_CTXCTL_CUR, inst);
|
||||
return 0;
|
||||
|
@ -101,6 +101,7 @@ nv50_sor_dpms(struct drm_encoder *encoder, int mode)
|
||||
struct nouveau_encoder *nvenc = nouveau_encoder(enc);
|
||||
|
||||
if (nvenc == nv_encoder ||
|
||||
nvenc->disconnect != nv50_sor_disconnect ||
|
||||
nvenc->dcb->or != nv_encoder->dcb->or)
|
||||
continue;
|
||||
|
||||
|
@ -77,6 +77,7 @@ struct drm_nouveau_gpuobj_free {
|
||||
#define NOUVEAU_GETPARAM_PCI_PHYSICAL 10
|
||||
#define NOUVEAU_GETPARAM_CHIPSET_ID 11
|
||||
#define NOUVEAU_GETPARAM_VM_VRAM_BASE 12
|
||||
#define NOUVEAU_GETPARAM_GRAPH_UNITS 13
|
||||
struct drm_nouveau_getparam {
|
||||
uint64_t param;
|
||||
uint64_t value;
|
||||
|
Loading…
Reference in New Issue
Block a user