Commit 603f2e6d authored by Dave Airlie's avatar Dave Airlie

Merge branch 'drm-nouveau-next' of...

Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6 into drm-core-next

* 'drm-nouveau-next' of git://anongit.freedesktop.org/git/nouveau/linux-2.6:
  drm/nouveau/gr: disable fifo access and idle before suspend ctx unload
  drm/nouveau: pass flag to engine fini() method on suspend
  drm/nouveau: replace nv04_graph_fifo_access() use with direct reg bashing
  drm/nv40/gr: rewrite/split context takedown functions
  drm/nouveau: detect disabled device in irq handler and return IRQ_NONE
  drm/nouveau: ignore connector type when deciding digital/analog on DVI-I
  drm/nouveau: Add a quirk for Gigabyte NX86T
  drm/nouveau: do not leak in nv20_graph_create
  drm/nv50/dp: fix hack to work for macbooks booted via EFI
parents e55b9422 9962cc6e
...@@ -5966,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) ...@@ -5966,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
if (cte->type == DCB_CONNECTOR_HDMI_1) if (cte->type == DCB_CONNECTOR_HDMI_1)
cte->type = DCB_CONNECTOR_DVI_I; cte->type = DCB_CONNECTOR_DVI_I;
} }
/* Gigabyte GV-NX86T512H */
if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) {
if (cte->type == DCB_CONNECTOR_HDMI_1)
cte->type = DCB_CONNECTOR_DVI_I;
}
} }
static const u8 hpd_gpio[16] = { static const u8 hpd_gpio[16] = {
......
...@@ -40,7 +40,7 @@ ...@@ -40,7 +40,7 @@
static void nouveau_connector_hotplug(void *, int); static void nouveau_connector_hotplug(void *, int);
static struct nouveau_encoder * static struct nouveau_encoder *
find_encoder_by_type(struct drm_connector *connector, int type) find_encoder(struct drm_connector *connector, int type)
{ {
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct nouveau_encoder *nv_encoder; struct nouveau_encoder *nv_encoder;
...@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector) ...@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);
if (!dn || if (!dn ||
!((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
(nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) (nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
return NULL; return NULL;
for_each_child_of_node(dn, cn) { for_each_child_of_node(dn, cn) {
...@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
struct drm_device *dev = connector->dev; struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector); struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL; struct nouveau_encoder *nv_encoder = NULL;
struct nouveau_encoder *nv_partner;
struct nouveau_i2c_chan *i2c; struct nouveau_i2c_chan *i2c;
int type; int type;
...@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
* same i2c channel so the value returned from ddc_detect * same i2c channel so the value returned from ddc_detect
* isn't necessarily correct. * isn't necessarily correct.
*/ */
if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { nv_partner = NULL;
if (nv_encoder->dcb->type == OUTPUT_TMDS)
nv_partner = find_encoder(connector, OUTPUT_ANALOG);
if (nv_encoder->dcb->type == OUTPUT_ANALOG)
nv_partner = find_encoder(connector, OUTPUT_TMDS);
if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG &&
nv_partner->dcb->type == OUTPUT_TMDS) ||
(nv_encoder->dcb->type == OUTPUT_TMDS &&
nv_partner->dcb->type == OUTPUT_ANALOG))) {
if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL)
type = OUTPUT_TMDS; type = OUTPUT_TMDS;
else else
type = OUTPUT_ANALOG; type = OUTPUT_ANALOG;
nv_encoder = find_encoder_by_type(connector, type); nv_encoder = find_encoder(connector, type);
if (!nv_encoder) {
NV_ERROR(dev, "Detected %d encoder on %s, "
"but no object!\n", type,
drm_get_connector_name(connector));
return connector_status_disconnected;
}
} }
nouveau_connector_set_encoder(connector, nv_encoder); nouveau_connector_set_encoder(connector, nv_encoder);
...@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) ...@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
} }
detect_analog: detect_analog:
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
if (!nv_encoder && !nouveau_tv_disable) if (!nv_encoder && !nouveau_tv_disable)
nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); nv_encoder = find_encoder(connector, OUTPUT_TV);
if (nv_encoder && force) { if (nv_encoder && force) {
struct drm_encoder *encoder = to_drm_encoder(nv_encoder); struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
struct drm_encoder_helper_funcs *helper = struct drm_encoder_helper_funcs *helper =
...@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) ...@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
nv_connector->edid = NULL; nv_connector->edid = NULL;
} }
nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); nv_encoder = find_encoder(connector, OUTPUT_LVDS);
if (!nv_encoder) if (!nv_encoder)
return connector_status_disconnected; return connector_status_disconnected;
...@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector) ...@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
} else } else
type = OUTPUT_ANY; type = OUTPUT_ANY;
nv_encoder = find_encoder_by_type(connector, type); nv_encoder = find_encoder(connector, type);
if (!nv_encoder) { if (!nv_encoder) {
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
drm_get_connector_name(connector)); drm_get_connector_name(connector));
......
...@@ -214,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) ...@@ -214,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pfifo->unload_context(dev); pfifo->unload_context(dev);
for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
if (dev_priv->eng[e]) { if (!dev_priv->eng[e])
ret = dev_priv->eng[e]->fini(dev, e); continue;
if (ret)
goto out_abort; ret = dev_priv->eng[e]->fini(dev, e, true);
if (ret) {
NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
goto out_abort;
} }
} }
......
...@@ -312,7 +312,7 @@ struct nouveau_channel { ...@@ -312,7 +312,7 @@ struct nouveau_channel {
struct nouveau_exec_engine { struct nouveau_exec_engine {
void (*destroy)(struct drm_device *, int engine); void (*destroy)(struct drm_device *, int engine);
int (*init)(struct drm_device *, int engine); int (*init)(struct drm_device *, int engine);
int (*fini)(struct drm_device *, int engine); int (*fini)(struct drm_device *, int engine, bool suspend);
int (*context_new)(struct nouveau_channel *, int engine); int (*context_new)(struct nouveau_channel *, int engine);
void (*context_del)(struct nouveau_channel *, int engine); void (*context_del)(struct nouveau_channel *, int engine);
int (*object_new)(struct nouveau_channel *, int engine, int (*object_new)(struct nouveau_channel *, int engine,
...@@ -1142,7 +1142,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); ...@@ -1142,7 +1142,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *);
/* nv04_graph.c */ /* nv04_graph.c */
extern int nv04_graph_create(struct drm_device *); extern int nv04_graph_create(struct drm_device *);
extern void nv04_graph_fifo_access(struct drm_device *, bool);
extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16);
extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data); u32 class, u32 mthd, u32 data);
......
...@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS) ...@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
int i; int i;
stat = nv_rd32(dev, NV03_PMC_INTR_0); stat = nv_rd32(dev, NV03_PMC_INTR_0);
if (!stat) if (stat == 0 || stat == ~0)
return IRQ_NONE; return IRQ_NONE;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
......
...@@ -694,7 +694,7 @@ nouveau_card_init(struct drm_device *dev) ...@@ -694,7 +694,7 @@ nouveau_card_init(struct drm_device *dev)
for (e = e - 1; e >= 0; e--) { for (e = e - 1; e >= 0; e--) {
if (!dev_priv->eng[e]) if (!dev_priv->eng[e])
continue; continue;
dev_priv->eng[e]->fini(dev, e); dev_priv->eng[e]->fini(dev, e, false);
dev_priv->eng[e]->destroy(dev,e ); dev_priv->eng[e]->destroy(dev,e );
} }
} }
...@@ -746,7 +746,7 @@ static void nouveau_card_takedown(struct drm_device *dev) ...@@ -746,7 +746,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->fifo.takedown(dev); engine->fifo.takedown(dev);
for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
if (dev_priv->eng[e]) { if (dev_priv->eng[e]) {
dev_priv->eng[e]->fini(dev, e); dev_priv->eng[e]->fini(dev, e, false);
dev_priv->eng[e]->destroy(dev,e ); dev_priv->eng[e]->destroy(dev,e );
} }
} }
......
...@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine) ...@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
nv04_graph_fifo_access(dev, false); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */ /* Unload the context if it's the currently active one */
if (nv04_graph_channel(dev) == chan) if (nv04_graph_channel(dev) == chan)
nv04_graph_unload_context(dev); nv04_graph_unload_context(dev);
nv04_graph_fifo_access(dev, true); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */ /* Free the context resources */
...@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine) ...@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine)
} }
static int static int
nv04_graph_fini(struct drm_device *dev, int engine) nv04_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
return -EBUSY;
}
nv04_graph_unload_context(dev); nv04_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0; return 0;
} }
void
nv04_graph_fifo_access(struct drm_device *dev, bool enabled)
{
if (enabled)
nv_wr32(dev, NV04_PGRAPH_FIFO,
nv_rd32(dev, NV04_PGRAPH_FIFO) | 1);
else
nv_wr32(dev, NV04_PGRAPH_FIFO,
nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1);
}
static int static int
nv04_graph_mthd_set_ref(struct nouveau_channel *chan, nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data) u32 class, u32 mthd, u32 data)
......
...@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, ...@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
nv04_graph_fifo_access(dev, true); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
nv04_graph_fifo_access(dev, false); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Restore the FIFO state */ /* Restore the FIFO state */
for (i = 0; i < ARRAY_SIZE(fifo); i++) for (i = 0; i < ARRAY_SIZE(fifo); i++)
...@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) ...@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
nv04_graph_fifo_access(dev, false); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */ /* Unload the context if it's the currently active one */
if (nv10_graph_channel(dev) == chan) if (nv10_graph_channel(dev) == chan)
nv10_graph_unload_context(dev); nv10_graph_unload_context(dev);
nv04_graph_fifo_access(dev, true); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */ /* Free the context resources */
...@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine) ...@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine)
} }
static int static int
nv10_graph_fini(struct drm_device *dev, int engine) nv10_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
return -EBUSY;
}
nv10_graph_unload_context(dev); nv10_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0; return 0;
......
...@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine) ...@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
nv04_graph_fifo_access(dev, false); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
/* Unload the context if it's the currently active one */ /* Unload the context if it's the currently active one */
if (nv10_graph_channel(dev) == chan) if (nv10_graph_channel(dev) == chan)
nv20_graph_unload_context(dev); nv20_graph_unload_context(dev);
nv04_graph_fifo_access(dev, true); nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */ /* Free the context resources */
...@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine) ...@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine)
} }
int int
nv20_graph_fini(struct drm_device *dev, int engine) nv20_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);
if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) {
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
return -EBUSY;
}
nv20_graph_unload_context(dev); nv20_graph_unload_context(dev);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0; return 0;
...@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev) ...@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev)
break; break;
default: default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n"); NV_ERROR(dev, "PGRAPH: unknown chipset\n");
kfree(pgraph);
return 0; return 0;
} }
} else { } else {
...@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev) ...@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev)
break; break;
default: default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n"); NV_ERROR(dev, "PGRAPH: unknown chipset\n");
kfree(pgraph);
return 0; return 0;
} }
} }
......
...@@ -35,89 +35,6 @@ struct nv40_graph_engine { ...@@ -35,89 +35,6 @@ struct nv40_graph_engine {
u32 grctx_size; u32 grctx_size;
}; };
static struct nouveau_channel *
nv40_graph_channel(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_gpuobj *grctx;
uint32_t inst;
int i;
inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
return NULL;
inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4;
for (i = 0; i < dev_priv->engine.fifo.channels; i++) {
if (!dev_priv->channels.ptr[i])
continue;
grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR];
if (grctx && grctx->pinst == inst)
return dev_priv->channels.ptr[i];
}
return NULL;
}
static int
nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save)
{
uint32_t old_cp, tv = 1000, tmp;
int i;
old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER);
nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst);
tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310);
tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE :
NV40_PGRAPH_CTXCTL_0310_XFER_LOAD;
nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp);
tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304);
tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX;
nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp);
nouveau_wait_for_idle(dev);
for (i = 0; i < tv; i++) {
if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0)
break;
}
nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp);
if (i == tv) {
uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT);
NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save);
NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n",
ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT,
ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK);
NV_ERROR(dev, "0x40030C = 0x%08x\n",
nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C));
return -EBUSY;
}
return 0;
}
static int
nv40_graph_unload_context(struct drm_device *dev)
{
uint32_t inst;
int ret;
inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR);
if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED))
return 0;
inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE;
ret = nv40_graph_transfer_context(dev, inst, 1);
nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst);
return ret;
}
static int static int
nv40_graph_context_new(struct nouveau_channel *chan, int engine) nv40_graph_context_new(struct nouveau_channel *chan, int engine)
{ {
...@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine) ...@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine)
struct nouveau_gpuobj *grctx = chan->engctx[engine]; struct nouveau_gpuobj *grctx = chan->engctx[engine];
struct drm_device *dev = chan->dev; struct drm_device *dev = chan->dev;
struct drm_nouveau_private *dev_priv = dev->dev_private; struct drm_nouveau_private *dev_priv = dev->dev_private;
u32 inst = 0x01000000 | (grctx->pinst >> 4);
unsigned long flags; unsigned long flags;
spin_lock_irqsave(&dev_priv->context_switch_lock, flags); spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
nv04_graph_fifo_access(dev, false); nv_mask(dev, 0x400720, 0x00000000, 0x00000001);
if (nv_rd32(dev, 0x40032c) == inst)
/* Unload the context if it's the currently active one */ nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
if (nv40_graph_channel(dev) == chan) if (nv_rd32(dev, 0x400330) == inst)
nv40_graph_unload_context(dev); nv_mask(dev, 0x400330, 0x01000000, 0x00000000);
nv_mask(dev, 0x400720, 0x00000001, 0x00000001);
nv04_graph_fifo_access(dev, true);
spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags);
/* Free the context resources */ /* Free the context resources */
...@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine) ...@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine)
} }
static int static int
nv40_graph_fini(struct drm_device *dev, int engine) nv40_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv40_graph_unload_context(dev); u32 inst = nv_rd32(dev, 0x40032c);
if (inst & 0x01000000) {
nv_wr32(dev, 0x400720, 0x00000000);
nv_wr32(dev, 0x400784, inst);
nv_mask(dev, 0x400310, 0x00000020, 0x00000020);
nv_mask(dev, 0x400304, 0x00000001, 0x00000001);
if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) {
u32 insn = nv_rd32(dev, 0x400308);
NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn);
}
nv_mask(dev, 0x40032c, 0x01000000, 0x00000000);
}
return 0; return 0;
} }
......
...@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine) ...@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine)
} }
static int static int
nv40_mpeg_fini(struct drm_device *dev, int engine) nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
{ {
/*XXX: context save? */ /*XXX: context save? */
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
......
...@@ -125,7 +125,6 @@ static void ...@@ -125,7 +125,6 @@ static void
nv50_graph_init_reset(struct drm_device *dev) nv50_graph_init_reset(struct drm_device *dev)
{ {
uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21);
NV_DEBUG(dev, "\n"); NV_DEBUG(dev, "\n");
nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e);
...@@ -255,9 +254,13 @@ nv50_graph_init(struct drm_device *dev, int engine) ...@@ -255,9 +254,13 @@ nv50_graph_init(struct drm_device *dev, int engine)
} }
static int static int
nv50_graph_fini(struct drm_device *dev, int engine) nv50_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
NV_DEBUG(dev, "\n"); nv_mask(dev, 0x400500, 0x00010001, 0x00000000);
if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) {
nv_mask(dev, 0x400500, 0x00010001, 0x00010001);
return -EBUSY;
}
nv50_graph_unload_context(dev); nv50_graph_unload_context(dev);
nv_wr32(dev, 0x40013c, 0x00000000); nv_wr32(dev, 0x40013c, 0x00000000);
return 0; return 0;
......
...@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine) ...@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine)
} }
static int static int
nv50_mpeg_fini(struct drm_device *dev, int engine) nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend)
{ {
/*XXX: context save for s/r */ /*XXX: context save for s/r */
nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000);
......
...@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) ...@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry)
uint32_t tmp; uint32_t tmp;
tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); tmp = nv_rd32(dev, 0x61c700 + (or * 0x800));
if (!tmp)
tmp = nv_rd32(dev, 0x610798 + (or * 8));
switch ((tmp & 0x00000f00) >> 8) { switch ((tmp & 0x00000f00) >> 8) {
case 8: case 8:
......
...@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev) ...@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev)
} }
static int static int
nv84_crypt_fini(struct drm_device *dev, int engine) nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv_wr32(dev, 0x102140, 0x00000000); nv_wr32(dev, 0x102140, 0x00000000);
return 0; return 0;
......
...@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine) ...@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine)
} }
static int static int
nva3_copy_fini(struct drm_device *dev, int engine) nva3_copy_fini(struct drm_device *dev, int engine, bool suspend)
{ {
nv_mask(dev, 0x104048, 0x00000003, 0x00000000); nv_mask(dev, 0x104048, 0x00000003, 0x00000000);
......
...@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine) ...@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine)
} }
static int static int
nvc0_copy_fini(struct drm_device *dev, int engine) nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend)
{ {
struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); struct nvc0_copy_engine *pcopy = nv_engine(dev, engine);
......
...@@ -304,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine, ...@@ -304,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine,
} }
static int static int
nvc0_graph_fini(struct drm_device *dev, int engine) nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend)
{ {
return 0; return 0;
} }
......
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