mirror of https://gitee.com/openkylin/linux.git
Merge remote branch 'nouveau/for-airlied' of ../drm-nouveau-next into drm-linus
* 'nouveau/for-airlied' of ../drm-nouveau-next: (44 commits) drm/nouveau: check pushbuffer bounds in ioctl drm/nouveau: reserve VGA area for the moment drm/nouveau: Unset the EDID connector property when the EDID block goes away. drm/nouveau: Fallback to analog load detection when the EDID block is invalid. drm/nouveau: fix edid memleak in nouveau_connector drm/nouveau: Break some long lines. drm/nouveau: add NV18 device id to call_lvds_manufacturer_script drm/nv50: Fix typo in PGRAPH initialisation. drm/nouveau: less magic DCB 1.5 parsing drm/nouveau: assume no nv04 board has a DCB table drm/nouveau: remove PRIV0 check in nouveau_mem_close() drm/nouveau: wait on fence after bo move if validating for another channel drm/nouveau: trust init table registers are safe drm/nv50: wait for pgraph to idle before unloading the context
This commit is contained in:
commit
1c974dc218
|
@ -310,63 +310,22 @@ valid_reg(struct nvbios *bios, uint32_t reg)
|
|||
struct drm_device *dev = bios->dev;
|
||||
|
||||
/* C51 has misaligned regs on purpose. Marvellous */
|
||||
if (reg & 0x2 || (reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51)) {
|
||||
NV_ERROR(dev, "========== misaligned reg 0x%08X ==========\n",
|
||||
reg);
|
||||
return 0;
|
||||
}
|
||||
/*
|
||||
* Warn on C51 regs that have not been verified accessible in
|
||||
* mmiotracing
|
||||
*/
|
||||
if (reg & 0x2 ||
|
||||
(reg & 0x1 && dev_priv->VBIOS.pub.chip_version != 0x51))
|
||||
NV_ERROR(dev, "======= misaligned reg 0x%08X =======\n", reg);
|
||||
|
||||
/* warn on C51 regs that haven't been verified accessible in tracing */
|
||||
if (reg & 0x1 && dev_priv->VBIOS.pub.chip_version == 0x51 &&
|
||||
reg != 0x130d && reg != 0x1311 && reg != 0x60081d)
|
||||
NV_WARN(dev, "=== C51 misaligned reg 0x%08X not verified ===\n",
|
||||
reg);
|
||||
|
||||
/* Trust the init scripts on G80 */
|
||||
if (dev_priv->card_type >= NV_50)
|
||||
return 1;
|
||||
|
||||
#define WITHIN(x, y, z) ((x >= y) && (x < y + z))
|
||||
if (WITHIN(reg, NV_PMC_OFFSET, NV_PMC_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PBUS_OFFSET, NV_PBUS_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PFIFO_OFFSET, NV_PFIFO_SIZE))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x30 &&
|
||||
(WITHIN(reg, 0x4000, 0x600) || reg == 0x00004600))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x40 &&
|
||||
WITHIN(reg, 0xc000, 0x48))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0000d204)
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x40) {
|
||||
if (reg == 0x00011014 || reg == 0x00020328)
|
||||
return 1;
|
||||
if (WITHIN(reg, 0x88000, NV_PBUS_SIZE)) /* new PBUS */
|
||||
return 1;
|
||||
if (reg >= (8*1024*1024)) {
|
||||
NV_ERROR(dev, "=== reg 0x%08x out of mapped bounds ===\n", reg);
|
||||
return 0;
|
||||
}
|
||||
if (WITHIN(reg, NV_PFB_OFFSET, NV_PFB_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PEXTDEV_OFFSET, NV_PEXTDEV_SIZE))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PCRTC0_OFFSET, NV_PCRTC0_SIZE * 2))
|
||||
return 1;
|
||||
if (WITHIN(reg, NV_PRAMDAC0_OFFSET, NV_PRAMDAC0_SIZE * 2))
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version >= 0x17 && reg == 0x0070fff0)
|
||||
return 1;
|
||||
if (dev_priv->VBIOS.pub.chip_version == 0x51 &&
|
||||
WITHIN(reg, NV_PRAMIN_OFFSET, NV_PRAMIN_SIZE))
|
||||
return 1;
|
||||
#undef WITHIN
|
||||
|
||||
NV_ERROR(dev, "========== unknown reg 0x%08X ==========\n", reg);
|
||||
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static bool
|
||||
|
@ -3196,16 +3155,25 @@ static int call_lvds_manufacturer_script(struct drm_device *dev, struct dcb_entr
|
|||
}
|
||||
#ifdef __powerpc__
|
||||
/* Powerbook specific quirks */
|
||||
if (script == LVDS_RESET && ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0329))
|
||||
nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
|
||||
if ((dev->pci_device & 0xffff) == 0x0179 || (dev->pci_device & 0xffff) == 0x0189 || (dev->pci_device & 0xffff) == 0x0329) {
|
||||
if (script == LVDS_PANEL_ON) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) | (1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
|
||||
}
|
||||
if (script == LVDS_PANEL_OFF) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL, bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL) & ~(1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT, bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
|
||||
if ((dev->pci_device & 0xffff) == 0x0179 ||
|
||||
(dev->pci_device & 0xffff) == 0x0189 ||
|
||||
(dev->pci_device & 0xffff) == 0x0329) {
|
||||
if (script == LVDS_RESET) {
|
||||
nv_write_tmds(dev, dcbent->or, 0, 0x02, 0x72);
|
||||
|
||||
} else if (script == LVDS_PANEL_ON) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
|
||||
bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
|
||||
| (1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT,
|
||||
bios_rd32(bios, NV_PCRTC_GPIO_EXT) | 1);
|
||||
|
||||
} else if (script == LVDS_PANEL_OFF) {
|
||||
bios_wr32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL,
|
||||
bios_rd32(bios, NV_PBUS_DEBUG_DUALHEAD_CTL)
|
||||
& ~(1 << 31));
|
||||
bios_wr32(bios, NV_PCRTC_GPIO_EXT,
|
||||
bios_rd32(bios, NV_PCRTC_GPIO_EXT) & ~3);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
@ -5434,52 +5402,49 @@ static bool
|
|||
parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
||||
uint32_t conn, uint32_t conf, struct dcb_entry *entry)
|
||||
{
|
||||
if (conn != 0xf0003f00 && conn != 0xf2247f10 && conn != 0xf2204001 &&
|
||||
conn != 0xf2204301 && conn != 0xf2204311 && conn != 0xf2208001 &&
|
||||
conn != 0xf2244001 && conn != 0xf2244301 && conn != 0xf2244311 &&
|
||||
conn != 0xf4204011 && conn != 0xf4208011 && conn != 0xf4248011 &&
|
||||
conn != 0xf2045ff2 && conn != 0xf2045f14 && conn != 0xf207df14 &&
|
||||
conn != 0xf2205004 && conn != 0xf2209004) {
|
||||
NV_ERROR(dev, "Unknown DCB 1.5 entry, please report\n");
|
||||
|
||||
/* cause output setting to fail for !TV, so message is seen */
|
||||
if ((conn & 0xf) != 0x1)
|
||||
dcb->entries = 0;
|
||||
|
||||
switch (conn & 0x0000000f) {
|
||||
case 0:
|
||||
entry->type = OUTPUT_ANALOG;
|
||||
break;
|
||||
case 1:
|
||||
entry->type = OUTPUT_TV;
|
||||
break;
|
||||
case 2:
|
||||
case 3:
|
||||
entry->type = OUTPUT_LVDS;
|
||||
break;
|
||||
case 4:
|
||||
switch ((conn & 0x000000f0) >> 4) {
|
||||
case 0:
|
||||
entry->type = OUTPUT_TMDS;
|
||||
break;
|
||||
case 1:
|
||||
entry->type = OUTPUT_LVDS;
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "Unknown DCB subtype 4/%d\n",
|
||||
(conn & 0x000000f0) >> 4);
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
NV_ERROR(dev, "Unknown DCB type %d\n", conn & 0x0000000f);
|
||||
return false;
|
||||
}
|
||||
/* most of the below is a "best guess" atm */
|
||||
entry->type = conn & 0xf;
|
||||
if (entry->type == 2)
|
||||
/* another way of specifying straps based lvds... */
|
||||
entry->type = OUTPUT_LVDS;
|
||||
if (entry->type == 4) { /* digital */
|
||||
if (conn & 0x10)
|
||||
entry->type = OUTPUT_LVDS;
|
||||
else
|
||||
entry->type = OUTPUT_TMDS;
|
||||
}
|
||||
/* what's in bits 5-13? could be some encoder maker thing, in tv case */
|
||||
entry->i2c_index = (conn >> 14) & 0xf;
|
||||
/* raw heads field is in range 0-1, so move to 1-2 */
|
||||
entry->heads = ((conn >> 18) & 0x7) + 1;
|
||||
entry->location = (conn >> 21) & 0xf;
|
||||
/* unused: entry->bus = (conn >> 25) & 0x7; */
|
||||
/* set or to be same as heads -- hopefully safe enough */
|
||||
entry->or = entry->heads;
|
||||
|
||||
entry->i2c_index = (conn & 0x0003c000) >> 14;
|
||||
entry->heads = ((conn & 0x001c0000) >> 18) + 1;
|
||||
entry->or = entry->heads; /* same as heads, hopefully safe enough */
|
||||
entry->location = (conn & 0x01e00000) >> 21;
|
||||
entry->bus = (conn & 0x0e000000) >> 25;
|
||||
entry->duallink_possible = false;
|
||||
|
||||
switch (entry->type) {
|
||||
case OUTPUT_ANALOG:
|
||||
entry->crtconf.maxfreq = (conf & 0xffff) * 10;
|
||||
break;
|
||||
case OUTPUT_LVDS:
|
||||
/*
|
||||
* This is probably buried in conn's unknown bits.
|
||||
* This will upset EDID-ful models, if they exist
|
||||
*/
|
||||
entry->lvdsconf.use_straps_for_mode = true;
|
||||
entry->lvdsconf.use_power_scripts = true;
|
||||
case OUTPUT_TV:
|
||||
entry->tvconf.has_component_output = false;
|
||||
break;
|
||||
case OUTPUT_TMDS:
|
||||
/*
|
||||
|
@ -5488,8 +5453,12 @@ parse_dcb15_entry(struct drm_device *dev, struct parsed_dcb *dcb,
|
|||
*/
|
||||
fabricate_vga_output(dcb, entry->i2c_index, entry->heads);
|
||||
break;
|
||||
case OUTPUT_TV:
|
||||
entry->tvconf.has_component_output = false;
|
||||
case OUTPUT_LVDS:
|
||||
if ((conn & 0x00003f00) != 0x10)
|
||||
entry->lvdsconf.use_straps_for_mode = true;
|
||||
entry->lvdsconf.use_power_scripts = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -5564,11 +5533,13 @@ void merge_like_dcb_entries(struct drm_device *dev, struct parsed_dcb *dcb)
|
|||
dcb->entries = newentries;
|
||||
}
|
||||
|
||||
static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||
static int
|
||||
parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool twoHeads)
|
||||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
struct bios_parsed_dcb *bdcb = &bios->bdcb;
|
||||
struct parsed_dcb *dcb;
|
||||
uint16_t dcbptr, i2ctabptr = 0;
|
||||
uint16_t dcbptr = 0, i2ctabptr = 0;
|
||||
uint8_t *dcbtable;
|
||||
uint8_t headerlen = 0x4, entries = DCB_MAX_NUM_ENTRIES;
|
||||
bool configblock = true;
|
||||
|
@ -5579,16 +5550,18 @@ static int parse_dcb_table(struct drm_device *dev, struct nvbios *bios, bool two
|
|||
dcb->entries = 0;
|
||||
|
||||
/* get the offset from 0x36 */
|
||||
dcbptr = ROM16(bios->data[0x36]);
|
||||
if (dev_priv->card_type > NV_04) {
|
||||
dcbptr = ROM16(bios->data[0x36]);
|
||||
if (dcbptr == 0x0000)
|
||||
NV_WARN(dev, "No output data (DCB) found in BIOS\n");
|
||||
}
|
||||
|
||||
/* this situation likely means a really old card, pre DCB */
|
||||
if (dcbptr == 0x0) {
|
||||
NV_WARN(dev, "No output data (DCB) found in BIOS, "
|
||||
"assuming a CRT output exists\n");
|
||||
/* this situation likely means a really old card, pre DCB */
|
||||
NV_INFO(dev, "Assuming a CRT output exists\n");
|
||||
fabricate_vga_output(dcb, LEGACY_I2C_CRT, 1);
|
||||
|
||||
if (nv04_tv_identify(dev,
|
||||
bios->legacy.i2c_indices.tv) >= 0)
|
||||
if (nv04_tv_identify(dev, bios->legacy.i2c_indices.tv) >= 0)
|
||||
fabricate_tv_output(dcb, twoHeads);
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -469,6 +469,8 @@ nouveau_bo_move_accel_cleanup(struct nouveau_channel *chan,
|
|||
|
||||
ret = ttm_bo_move_accel_cleanup(&nvbo->bo, fence, NULL,
|
||||
evict, no_wait, new_mem);
|
||||
if (nvbo->channel && nvbo->channel != chan)
|
||||
ret = nouveau_fence_wait(fence, NULL, false, false);
|
||||
nouveau_fence_unref((void *)&fence);
|
||||
return ret;
|
||||
}
|
||||
|
|
|
@ -83,14 +83,16 @@ nouveau_encoder_connector_get(struct nouveau_encoder *encoder)
|
|||
static void
|
||||
nouveau_connector_destroy(struct drm_connector *drm_connector)
|
||||
{
|
||||
struct nouveau_connector *connector = nouveau_connector(drm_connector);
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct nouveau_connector *nv_connector =
|
||||
nouveau_connector(drm_connector);
|
||||
struct drm_device *dev = nv_connector->base.dev;
|
||||
|
||||
NV_DEBUG_KMS(dev, "\n");
|
||||
|
||||
if (!connector)
|
||||
if (!nv_connector)
|
||||
return;
|
||||
|
||||
kfree(nv_connector->edid);
|
||||
drm_sysfs_connector_remove(drm_connector);
|
||||
drm_connector_cleanup(drm_connector);
|
||||
kfree(drm_connector);
|
||||
|
@ -237,6 +239,13 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
return connector_status_connected;
|
||||
}
|
||||
|
||||
/* Cleanup the previous EDID block. */
|
||||
if (nv_connector->edid) {
|
||||
drm_mode_connector_update_edid_property(connector, NULL);
|
||||
kfree(nv_connector->edid);
|
||||
nv_connector->edid = NULL;
|
||||
}
|
||||
|
||||
i2c = nouveau_connector_ddc_detect(connector, &nv_encoder);
|
||||
if (i2c) {
|
||||
nouveau_connector_ddc_prepare(connector, &flags);
|
||||
|
@ -247,7 +256,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
if (!nv_connector->edid) {
|
||||
NV_ERROR(dev, "DDC responded, but no EDID for %s\n",
|
||||
drm_get_connector_name(connector));
|
||||
return connector_status_disconnected;
|
||||
goto detect_analog;
|
||||
}
|
||||
|
||||
if (nv_encoder->dcb->type == OUTPUT_DP &&
|
||||
|
@ -281,6 +290,7 @@ nouveau_connector_detect(struct drm_connector *connector)
|
|||
return connector_status_connected;
|
||||
}
|
||||
|
||||
detect_analog:
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
|
||||
if (!nv_encoder)
|
||||
nv_encoder = find_encoder_by_type(connector, OUTPUT_TV);
|
||||
|
@ -687,8 +697,12 @@ nouveau_connector_create_lvds(struct drm_device *dev,
|
|||
*/
|
||||
if (!nv_connector->edid && !nv_connector->native_mode &&
|
||||
!dev_priv->VBIOS.pub.fp_no_ddc) {
|
||||
nv_connector->edid =
|
||||
struct edid *edid =
|
||||
(struct edid *)nouveau_bios_embedded_edid(dev);
|
||||
if (edid) {
|
||||
nv_connector->edid = kmalloc(EDID_LENGTH, GFP_KERNEL);
|
||||
*(nv_connector->edid) = *edid;
|
||||
}
|
||||
}
|
||||
|
||||
if (!nv_connector->edid)
|
||||
|
|
|
@ -509,6 +509,8 @@ struct drm_nouveau_private {
|
|||
void __iomem *ramin;
|
||||
uint32_t ramin_size;
|
||||
|
||||
struct nouveau_bo *vga_ram;
|
||||
|
||||
struct workqueue_struct *wq;
|
||||
struct work_struct irq_work;
|
||||
|
||||
|
|
|
@ -466,13 +466,14 @@ u_memcpya(uint64_t user, unsigned nmemb, unsigned size)
|
|||
static int
|
||||
nouveau_gem_pushbuf_reloc_apply(struct nouveau_channel *chan, int nr_bo,
|
||||
struct drm_nouveau_gem_pushbuf_bo *bo,
|
||||
int nr_relocs, uint64_t ptr_relocs,
|
||||
int nr_dwords, int first_dword,
|
||||
unsigned nr_relocs, uint64_t ptr_relocs,
|
||||
unsigned nr_dwords, unsigned first_dword,
|
||||
uint32_t *pushbuf, bool is_iomem)
|
||||
{
|
||||
struct drm_nouveau_gem_pushbuf_reloc *reloc = NULL;
|
||||
struct drm_device *dev = chan->dev;
|
||||
int ret = 0, i;
|
||||
int ret = 0;
|
||||
unsigned i;
|
||||
|
||||
reloc = u_memcpya(ptr_relocs, nr_relocs, sizeof(*reloc));
|
||||
if (IS_ERR(reloc))
|
||||
|
@ -667,6 +668,18 @@ nouveau_gem_ioctl_pushbuf_call(struct drm_device *dev, void *data,
|
|||
}
|
||||
pbbo = nouveau_gem_object(gem);
|
||||
|
||||
if ((req->offset & 3) || req->nr_dwords < 2 ||
|
||||
(unsigned long)req->offset > (unsigned long)pbbo->bo.mem.size ||
|
||||
(unsigned long)req->nr_dwords >
|
||||
((unsigned long)(pbbo->bo.mem.size - req->offset ) >> 2)) {
|
||||
NV_ERROR(dev, "pb call misaligned or out of bounds: "
|
||||
"%d + %d * 4 > %ld\n",
|
||||
req->offset, req->nr_dwords, pbbo->bo.mem.size);
|
||||
ret = -EINVAL;
|
||||
drm_gem_object_unreference(gem);
|
||||
goto out;
|
||||
}
|
||||
|
||||
ret = ttm_bo_reserve(&pbbo->bo, false, false, true,
|
||||
chan->fence.sequence);
|
||||
if (ret) {
|
||||
|
|
|
@ -383,10 +383,10 @@ void nouveau_mem_close(struct drm_device *dev)
|
|||
{
|
||||
struct drm_nouveau_private *dev_priv = dev->dev_private;
|
||||
|
||||
if (dev_priv->ttm.bdev.man[TTM_PL_PRIV0].has_type)
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_PRIV0);
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
nouveau_bo_unpin(dev_priv->vga_ram);
|
||||
nouveau_bo_ref(NULL, &dev_priv->vga_ram);
|
||||
|
||||
ttm_bo_clean_mm(&dev_priv->ttm.bdev, TTM_PL_VRAM);
|
||||
ttm_bo_device_release(&dev_priv->ttm.bdev);
|
||||
|
||||
nouveau_ttm_global_release(dev_priv);
|
||||
|
@ -622,6 +622,15 @@ nouveau_mem_init(struct drm_device *dev)
|
|||
return ret;
|
||||
}
|
||||
|
||||
ret = nouveau_bo_new(dev, NULL, 256*1024, 0, TTM_PL_FLAG_VRAM,
|
||||
0, 0, true, true, &dev_priv->vga_ram);
|
||||
if (ret == 0)
|
||||
ret = nouveau_bo_pin(dev_priv->vga_ram, TTM_PL_FLAG_VRAM);
|
||||
if (ret) {
|
||||
NV_WARN(dev, "failed to reserve VGA memory\n");
|
||||
nouveau_bo_ref(NULL, &dev_priv->vga_ram);
|
||||
}
|
||||
|
||||
/* GART */
|
||||
#if !defined(__powerpc__) && !defined(__ia64__)
|
||||
if (drm_device_is_agp(dev) && dev->agp) {
|
||||
|
@ -653,6 +662,7 @@ nouveau_mem_init(struct drm_device *dev)
|
|||
dev_priv->fb_mtrr = drm_mtrr_add(drm_get_resource_start(dev, 1),
|
||||
drm_get_resource_len(dev, 1),
|
||||
DRM_MTRR_WC);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
|
@ -84,7 +84,7 @@ nv50_graph_init_regs__nv(struct drm_device *dev)
|
|||
nv_wr32(dev, 0x400804, 0xc0000000);
|
||||
nv_wr32(dev, 0x406800, 0xc0000000);
|
||||
nv_wr32(dev, 0x400c04, 0xc0000000);
|
||||
nv_wr32(dev, 0x401804, 0xc0000000);
|
||||
nv_wr32(dev, 0x401800, 0xc0000000);
|
||||
nv_wr32(dev, 0x405018, 0xc0000000);
|
||||
nv_wr32(dev, 0x402000, 0xc0000000);
|
||||
|
||||
|
@ -282,6 +282,7 @@ nv50_graph_unload_context(struct drm_device *dev)
|
|||
return 0;
|
||||
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);
|
||||
|
|
Loading…
Reference in New Issue