Skip to content

Commit

Permalink
Merge branch 'drm-nouveau-next' of git://anongit.freedesktop.org/git/…
Browse files Browse the repository at this point in the history
…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
  • Loading branch information
Dave Airlie committed Jul 25, 2011
2 parents e55b942 + 9962cc6 commit 603f2e6
Show file tree
Hide file tree
Showing 18 changed files with 98 additions and 147 deletions.
6 changes: 6 additions & 0 deletions drivers/gpu/drm/nouveau/nouveau_bios.c
Original file line number Diff line number Diff line change
Expand Up @@ -5966,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx)
if (cte->type == DCB_CONNECTOR_HDMI_1)
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] = {
Expand Down
34 changes: 19 additions & 15 deletions drivers/gpu/drm/nouveau/nouveau_connector.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@
static void nouveau_connector_hotplug(void *, int);

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 nouveau_encoder *nv_encoder;
Expand Down Expand Up @@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector)
struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev);

if (!dn ||
!((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) ||
(nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG))))
!((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) ||
(nv_encoder = find_encoder(connector, OUTPUT_ANALOG))))
return NULL;

for_each_child_of_node(dn, cn) {
Expand Down Expand Up @@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
struct drm_device *dev = connector->dev;
struct nouveau_connector *nv_connector = nouveau_connector(connector);
struct nouveau_encoder *nv_encoder = NULL;
struct nouveau_encoder *nv_partner;
struct nouveau_i2c_chan *i2c;
int type;

Expand Down Expand Up @@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
* same i2c channel so the value returned from ddc_detect
* 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)
type = OUTPUT_TMDS;
else
type = OUTPUT_ANALOG;

nv_encoder = find_encoder_by_type(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;
}
nv_encoder = find_encoder(connector, type);
}

nouveau_connector_set_encoder(connector, nv_encoder);
Expand All @@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force)
}

detect_analog:
nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG);
nv_encoder = find_encoder(connector, OUTPUT_ANALOG);
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) {
struct drm_encoder *encoder = to_drm_encoder(nv_encoder);
struct drm_encoder_helper_funcs *helper =
Expand Down Expand Up @@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force)
nv_connector->edid = NULL;
}

nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS);
nv_encoder = find_encoder(connector, OUTPUT_LVDS);
if (!nv_encoder)
return connector_status_disconnected;

Expand Down Expand Up @@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector)
} else
type = OUTPUT_ANY;

nv_encoder = find_encoder_by_type(connector, type);
nv_encoder = find_encoder(connector, type);
if (!nv_encoder) {
NV_ERROR(connector->dev, "can't find encoder to force %s on!\n",
drm_get_connector_name(connector));
Expand Down
11 changes: 7 additions & 4 deletions drivers/gpu/drm/nouveau/nouveau_drv.c
Original file line number Diff line number Diff line change
Expand Up @@ -214,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state)
pfifo->unload_context(dev);

for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) {
if (dev_priv->eng[e]) {
ret = dev_priv->eng[e]->fini(dev, e);
if (ret)
goto out_abort;
if (!dev_priv->eng[e])
continue;

ret = dev_priv->eng[e]->fini(dev, e, true);
if (ret) {
NV_ERROR(dev, "... engine %d failed: %d\n", i, ret);
goto out_abort;
}
}

Expand Down
3 changes: 1 addition & 2 deletions drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ struct nouveau_channel {
struct nouveau_exec_engine {
void (*destroy)(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);
void (*context_del)(struct nouveau_channel *, int engine);
int (*object_new)(struct nouveau_channel *, int engine,
Expand Down Expand Up @@ -1142,7 +1142,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *);

/* nv04_graph.c */
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_mthd_page_flip(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data);
Expand Down
2 changes: 1 addition & 1 deletion drivers/gpu/drm/nouveau/nouveau_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS)
int i;

stat = nv_rd32(dev, NV03_PMC_INTR_0);
if (!stat)
if (stat == 0 || stat == ~0)
return IRQ_NONE;

spin_lock_irqsave(&dev_priv->context_switch_lock, flags);
Expand Down
4 changes: 2 additions & 2 deletions drivers/gpu/drm/nouveau/nouveau_state.c
Original file line number Diff line number Diff line change
Expand Up @@ -694,7 +694,7 @@ nouveau_card_init(struct drm_device *dev)
for (e = e - 1; e >= 0; e--) {
if (!dev_priv->eng[e])
continue;
dev_priv->eng[e]->fini(dev, e);
dev_priv->eng[e]->fini(dev, e, false);
dev_priv->eng[e]->destroy(dev,e );
}
}
Expand Down Expand Up @@ -746,7 +746,7 @@ static void nouveau_card_takedown(struct drm_device *dev)
engine->fifo.takedown(dev);
for (e = NVOBJ_ENGINE_NR - 1; e >= 0; 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 );
}
}
Expand Down
22 changes: 8 additions & 14 deletions drivers/gpu/drm/nouveau/nv04_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long 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 */
if (nv04_graph_channel(dev) == chan)
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);

/* Free the context resources */
Expand Down Expand Up @@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine)
}

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);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
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
nv04_graph_mthd_set_ref(struct nouveau_channel *chan,
u32 class, u32 mthd, u32 data)
Expand Down
15 changes: 10 additions & 5 deletions drivers/gpu/drm/nouveau/nv10_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan,
0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c);
nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst);
nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000);
nv04_graph_fifo_access(dev, true);
nv04_graph_fifo_access(dev, false);
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001);
nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000);

/* Restore the FIFO state */
for (i = 0; i < ARRAY_SIZE(fifo); i++)
Expand Down Expand Up @@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long 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 */
if (nv10_graph_channel(dev) == chan)
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);

/* Free the context resources */
Expand Down Expand Up @@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine)
}

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);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0;
Expand Down
13 changes: 10 additions & 3 deletions drivers/gpu/drm/nouveau/nv20_graph.c
Original file line number Diff line number Diff line change
Expand Up @@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine)
unsigned long 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 */
if (nv10_graph_channel(dev) == chan)
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);

/* Free the context resources */
Expand Down Expand Up @@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine)
}

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);
nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000);
return 0;
Expand Down Expand Up @@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev)
break;
default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n");
kfree(pgraph);
return 0;
}
} else {
Expand All @@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev)
break;
default:
NV_ERROR(dev, "PGRAPH: unknown chipset\n");
kfree(pgraph);
return 0;
}
}
Expand Down
Loading

0 comments on commit 603f2e6

Please sign in to comment.