diff options
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_bios.c | 6 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_connector.c | 34 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.c | 11 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_drv.h | 3 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_irq.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nouveau_state.c | 4 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv04_graph.c | 22 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv10_graph.c | 15 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv20_graph.c | 13 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_graph.c | 112 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv40_mpeg.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_graph.c | 9 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_mpeg.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv50_sor.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nv84_crypt.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nva3_copy.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_copy.c | 2 | ||||
-rw-r--r-- | drivers/gpu/drm/nouveau/nvc0_graph.c | 2 |
18 files changed, 98 insertions, 147 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_bios.c b/drivers/gpu/drm/nouveau/nouveau_bios.c index 1aa73d3957e1..b311faba34f8 100644 --- a/drivers/gpu/drm/nouveau/nouveau_bios.c +++ b/drivers/gpu/drm/nouveau/nouveau_bios.c | |||
@@ -5966,6 +5966,12 @@ apply_dcb_connector_quirks(struct nvbios *bios, int idx) | |||
5966 | if (cte->type == DCB_CONNECTOR_HDMI_1) | 5966 | if (cte->type == DCB_CONNECTOR_HDMI_1) |
5967 | cte->type = DCB_CONNECTOR_DVI_I; | 5967 | cte->type = DCB_CONNECTOR_DVI_I; |
5968 | } | 5968 | } |
5969 | |||
5970 | /* Gigabyte GV-NX86T512H */ | ||
5971 | if (nv_match_device(dev, 0x0402, 0x1458, 0x3455)) { | ||
5972 | if (cte->type == DCB_CONNECTOR_HDMI_1) | ||
5973 | cte->type = DCB_CONNECTOR_DVI_I; | ||
5974 | } | ||
5969 | } | 5975 | } |
5970 | 5976 | ||
5971 | static const u8 hpd_gpio[16] = { | 5977 | static const u8 hpd_gpio[16] = { |
diff --git a/drivers/gpu/drm/nouveau/nouveau_connector.c b/drivers/gpu/drm/nouveau/nouveau_connector.c index 1595d0b6e815..939d4df07777 100644 --- a/drivers/gpu/drm/nouveau/nouveau_connector.c +++ b/drivers/gpu/drm/nouveau/nouveau_connector.c | |||
@@ -40,7 +40,7 @@ | |||
40 | static void nouveau_connector_hotplug(void *, int); | 40 | static void nouveau_connector_hotplug(void *, int); |
41 | 41 | ||
42 | static struct nouveau_encoder * | 42 | static struct nouveau_encoder * |
43 | find_encoder_by_type(struct drm_connector *connector, int type) | 43 | find_encoder(struct drm_connector *connector, int type) |
44 | { | 44 | { |
45 | struct drm_device *dev = connector->dev; | 45 | struct drm_device *dev = connector->dev; |
46 | struct nouveau_encoder *nv_encoder; | 46 | struct nouveau_encoder *nv_encoder; |
@@ -170,8 +170,8 @@ nouveau_connector_of_detect(struct drm_connector *connector) | |||
170 | struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); | 170 | struct device_node *cn, *dn = pci_device_to_OF_node(dev->pdev); |
171 | 171 | ||
172 | if (!dn || | 172 | if (!dn || |
173 | !((nv_encoder = find_encoder_by_type(connector, OUTPUT_TMDS)) || | 173 | !((nv_encoder = find_encoder(connector, OUTPUT_TMDS)) || |
174 | (nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG)))) | 174 | (nv_encoder = find_encoder(connector, OUTPUT_ANALOG)))) |
175 | return NULL; | 175 | return NULL; |
176 | 176 | ||
177 | for_each_child_of_node(dn, cn) { | 177 | for_each_child_of_node(dn, cn) { |
@@ -233,6 +233,7 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
233 | struct drm_device *dev = connector->dev; | 233 | struct drm_device *dev = connector->dev; |
234 | struct nouveau_connector *nv_connector = nouveau_connector(connector); | 234 | struct nouveau_connector *nv_connector = nouveau_connector(connector); |
235 | struct nouveau_encoder *nv_encoder = NULL; | 235 | struct nouveau_encoder *nv_encoder = NULL; |
236 | struct nouveau_encoder *nv_partner; | ||
236 | struct nouveau_i2c_chan *i2c; | 237 | struct nouveau_i2c_chan *i2c; |
237 | int type; | 238 | int type; |
238 | 239 | ||
@@ -266,19 +267,22 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
266 | * same i2c channel so the value returned from ddc_detect | 267 | * same i2c channel so the value returned from ddc_detect |
267 | * isn't necessarily correct. | 268 | * isn't necessarily correct. |
268 | */ | 269 | */ |
269 | if (nv_connector->dcb->type == DCB_CONNECTOR_DVI_I) { | 270 | nv_partner = NULL; |
271 | if (nv_encoder->dcb->type == OUTPUT_TMDS) | ||
272 | nv_partner = find_encoder(connector, OUTPUT_ANALOG); | ||
273 | if (nv_encoder->dcb->type == OUTPUT_ANALOG) | ||
274 | nv_partner = find_encoder(connector, OUTPUT_TMDS); | ||
275 | |||
276 | if (nv_partner && ((nv_encoder->dcb->type == OUTPUT_ANALOG && | ||
277 | nv_partner->dcb->type == OUTPUT_TMDS) || | ||
278 | (nv_encoder->dcb->type == OUTPUT_TMDS && | ||
279 | nv_partner->dcb->type == OUTPUT_ANALOG))) { | ||
270 | if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) | 280 | if (nv_connector->edid->input & DRM_EDID_INPUT_DIGITAL) |
271 | type = OUTPUT_TMDS; | 281 | type = OUTPUT_TMDS; |
272 | else | 282 | else |
273 | type = OUTPUT_ANALOG; | 283 | type = OUTPUT_ANALOG; |
274 | 284 | ||
275 | nv_encoder = find_encoder_by_type(connector, type); | 285 | nv_encoder = find_encoder(connector, type); |
276 | if (!nv_encoder) { | ||
277 | NV_ERROR(dev, "Detected %d encoder on %s, " | ||
278 | "but no object!\n", type, | ||
279 | drm_get_connector_name(connector)); | ||
280 | return connector_status_disconnected; | ||
281 | } | ||
282 | } | 286 | } |
283 | 287 | ||
284 | nouveau_connector_set_encoder(connector, nv_encoder); | 288 | nouveau_connector_set_encoder(connector, nv_encoder); |
@@ -292,9 +296,9 @@ nouveau_connector_detect(struct drm_connector *connector, bool force) | |||
292 | } | 296 | } |
293 | 297 | ||
294 | detect_analog: | 298 | detect_analog: |
295 | nv_encoder = find_encoder_by_type(connector, OUTPUT_ANALOG); | 299 | nv_encoder = find_encoder(connector, OUTPUT_ANALOG); |
296 | if (!nv_encoder && !nouveau_tv_disable) | 300 | if (!nv_encoder && !nouveau_tv_disable) |
297 | nv_encoder = find_encoder_by_type(connector, OUTPUT_TV); | 301 | nv_encoder = find_encoder(connector, OUTPUT_TV); |
298 | if (nv_encoder && force) { | 302 | if (nv_encoder && force) { |
299 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); | 303 | struct drm_encoder *encoder = to_drm_encoder(nv_encoder); |
300 | struct drm_encoder_helper_funcs *helper = | 304 | struct drm_encoder_helper_funcs *helper = |
@@ -327,7 +331,7 @@ nouveau_connector_detect_lvds(struct drm_connector *connector, bool force) | |||
327 | nv_connector->edid = NULL; | 331 | nv_connector->edid = NULL; |
328 | } | 332 | } |
329 | 333 | ||
330 | nv_encoder = find_encoder_by_type(connector, OUTPUT_LVDS); | 334 | nv_encoder = find_encoder(connector, OUTPUT_LVDS); |
331 | if (!nv_encoder) | 335 | if (!nv_encoder) |
332 | return connector_status_disconnected; | 336 | return connector_status_disconnected; |
333 | 337 | ||
@@ -405,7 +409,7 @@ nouveau_connector_force(struct drm_connector *connector) | |||
405 | } else | 409 | } else |
406 | type = OUTPUT_ANY; | 410 | type = OUTPUT_ANY; |
407 | 411 | ||
408 | nv_encoder = find_encoder_by_type(connector, type); | 412 | nv_encoder = find_encoder(connector, type); |
409 | if (!nv_encoder) { | 413 | if (!nv_encoder) { |
410 | NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", | 414 | NV_ERROR(connector->dev, "can't find encoder to force %s on!\n", |
411 | drm_get_connector_name(connector)); | 415 | drm_get_connector_name(connector)); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.c b/drivers/gpu/drm/nouveau/nouveau_drv.c index 8256370e5938..b30ddd8d2e2a 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.c +++ b/drivers/gpu/drm/nouveau/nouveau_drv.c | |||
@@ -214,10 +214,13 @@ nouveau_pci_suspend(struct pci_dev *pdev, pm_message_t pm_state) | |||
214 | pfifo->unload_context(dev); | 214 | pfifo->unload_context(dev); |
215 | 215 | ||
216 | for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { | 216 | for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { |
217 | if (dev_priv->eng[e]) { | 217 | if (!dev_priv->eng[e]) |
218 | ret = dev_priv->eng[e]->fini(dev, e); | 218 | continue; |
219 | if (ret) | 219 | |
220 | goto out_abort; | 220 | ret = dev_priv->eng[e]->fini(dev, e, true); |
221 | if (ret) { | ||
222 | NV_ERROR(dev, "... engine %d failed: %d\n", i, ret); | ||
223 | goto out_abort; | ||
221 | } | 224 | } |
222 | } | 225 | } |
223 | 226 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h index 72bfc143eb47..d7d51deb34b6 100644 --- a/drivers/gpu/drm/nouveau/nouveau_drv.h +++ b/drivers/gpu/drm/nouveau/nouveau_drv.h | |||
@@ -312,7 +312,7 @@ struct nouveau_channel { | |||
312 | struct nouveau_exec_engine { | 312 | struct nouveau_exec_engine { |
313 | void (*destroy)(struct drm_device *, int engine); | 313 | void (*destroy)(struct drm_device *, int engine); |
314 | int (*init)(struct drm_device *, int engine); | 314 | int (*init)(struct drm_device *, int engine); |
315 | int (*fini)(struct drm_device *, int engine); | 315 | int (*fini)(struct drm_device *, int engine, bool suspend); |
316 | int (*context_new)(struct nouveau_channel *, int engine); | 316 | int (*context_new)(struct nouveau_channel *, int engine); |
317 | void (*context_del)(struct nouveau_channel *, int engine); | 317 | void (*context_del)(struct nouveau_channel *, int engine); |
318 | int (*object_new)(struct nouveau_channel *, int engine, | 318 | int (*object_new)(struct nouveau_channel *, int engine, |
@@ -1142,7 +1142,6 @@ extern int nvc0_fifo_unload_context(struct drm_device *); | |||
1142 | 1142 | ||
1143 | /* nv04_graph.c */ | 1143 | /* nv04_graph.c */ |
1144 | extern int nv04_graph_create(struct drm_device *); | 1144 | extern int nv04_graph_create(struct drm_device *); |
1145 | extern void nv04_graph_fifo_access(struct drm_device *, bool); | ||
1146 | extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); | 1145 | extern int nv04_graph_object_new(struct nouveau_channel *, int, u32, u16); |
1147 | extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, | 1146 | extern int nv04_graph_mthd_page_flip(struct nouveau_channel *chan, |
1148 | u32 class, u32 mthd, u32 data); | 1147 | u32 class, u32 mthd, u32 data); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_irq.c b/drivers/gpu/drm/nouveau/nouveau_irq.c index 2ba7265bc967..868c7fd74854 100644 --- a/drivers/gpu/drm/nouveau/nouveau_irq.c +++ b/drivers/gpu/drm/nouveau/nouveau_irq.c | |||
@@ -79,7 +79,7 @@ nouveau_irq_handler(DRM_IRQ_ARGS) | |||
79 | int i; | 79 | int i; |
80 | 80 | ||
81 | stat = nv_rd32(dev, NV03_PMC_INTR_0); | 81 | stat = nv_rd32(dev, NV03_PMC_INTR_0); |
82 | if (!stat) | 82 | if (stat == 0 || stat == ~0) |
83 | return IRQ_NONE; | 83 | return IRQ_NONE; |
84 | 84 | ||
85 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 85 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
diff --git a/drivers/gpu/drm/nouveau/nouveau_state.c b/drivers/gpu/drm/nouveau/nouveau_state.c index fa1e63210040..10656e430b44 100644 --- a/drivers/gpu/drm/nouveau/nouveau_state.c +++ b/drivers/gpu/drm/nouveau/nouveau_state.c | |||
@@ -694,7 +694,7 @@ out_engine: | |||
694 | for (e = e - 1; e >= 0; e--) { | 694 | for (e = e - 1; e >= 0; e--) { |
695 | if (!dev_priv->eng[e]) | 695 | if (!dev_priv->eng[e]) |
696 | continue; | 696 | continue; |
697 | dev_priv->eng[e]->fini(dev, e); | 697 | dev_priv->eng[e]->fini(dev, e, false); |
698 | dev_priv->eng[e]->destroy(dev,e ); | 698 | dev_priv->eng[e]->destroy(dev,e ); |
699 | } | 699 | } |
700 | } | 700 | } |
@@ -746,7 +746,7 @@ static void nouveau_card_takedown(struct drm_device *dev) | |||
746 | engine->fifo.takedown(dev); | 746 | engine->fifo.takedown(dev); |
747 | for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { | 747 | for (e = NVOBJ_ENGINE_NR - 1; e >= 0; e--) { |
748 | if (dev_priv->eng[e]) { | 748 | if (dev_priv->eng[e]) { |
749 | dev_priv->eng[e]->fini(dev, e); | 749 | dev_priv->eng[e]->fini(dev, e, false); |
750 | dev_priv->eng[e]->destroy(dev,e ); | 750 | dev_priv->eng[e]->destroy(dev,e ); |
751 | } | 751 | } |
752 | } | 752 | } |
diff --git a/drivers/gpu/drm/nouveau/nv04_graph.c b/drivers/gpu/drm/nouveau/nv04_graph.c index 3626ee7db3ba..dbdea8ed3925 100644 --- a/drivers/gpu/drm/nouveau/nv04_graph.c +++ b/drivers/gpu/drm/nouveau/nv04_graph.c | |||
@@ -450,13 +450,13 @@ nv04_graph_context_del(struct nouveau_channel *chan, int engine) | |||
450 | unsigned long flags; | 450 | unsigned long flags; |
451 | 451 | ||
452 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 452 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
453 | nv04_graph_fifo_access(dev, false); | 453 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); |
454 | 454 | ||
455 | /* Unload the context if it's the currently active one */ | 455 | /* Unload the context if it's the currently active one */ |
456 | if (nv04_graph_channel(dev) == chan) | 456 | if (nv04_graph_channel(dev) == chan) |
457 | nv04_graph_unload_context(dev); | 457 | nv04_graph_unload_context(dev); |
458 | 458 | ||
459 | nv04_graph_fifo_access(dev, true); | 459 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); |
460 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 460 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
461 | 461 | ||
462 | /* Free the context resources */ | 462 | /* Free the context resources */ |
@@ -538,24 +538,18 @@ nv04_graph_init(struct drm_device *dev, int engine) | |||
538 | } | 538 | } |
539 | 539 | ||
540 | static int | 540 | static int |
541 | nv04_graph_fini(struct drm_device *dev, int engine) | 541 | nv04_graph_fini(struct drm_device *dev, int engine, bool suspend) |
542 | { | 542 | { |
543 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); | ||
544 | if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { | ||
545 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); | ||
546 | return -EBUSY; | ||
547 | } | ||
543 | nv04_graph_unload_context(dev); | 548 | nv04_graph_unload_context(dev); |
544 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); | 549 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); |
545 | return 0; | 550 | return 0; |
546 | } | 551 | } |
547 | 552 | ||
548 | void | ||
549 | nv04_graph_fifo_access(struct drm_device *dev, bool enabled) | ||
550 | { | ||
551 | if (enabled) | ||
552 | nv_wr32(dev, NV04_PGRAPH_FIFO, | ||
553 | nv_rd32(dev, NV04_PGRAPH_FIFO) | 1); | ||
554 | else | ||
555 | nv_wr32(dev, NV04_PGRAPH_FIFO, | ||
556 | nv_rd32(dev, NV04_PGRAPH_FIFO) & ~1); | ||
557 | } | ||
558 | |||
559 | static int | 553 | static int |
560 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, | 554 | nv04_graph_mthd_set_ref(struct nouveau_channel *chan, |
561 | u32 class, u32 mthd, u32 data) | 555 | u32 class, u32 mthd, u32 data) |
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 0930c6cb88e0..7255e4a4d3f3 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
@@ -708,8 +708,8 @@ static void nv10_graph_load_dma_vtxbuf(struct nouveau_channel *chan, | |||
708 | 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); | 708 | 0x2c000000 | chan->id << 20 | subchan << 16 | 0x18c); |
709 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); | 709 | nv_wr32(dev, NV10_PGRAPH_FFINTFC_ST2_DL, inst); |
710 | nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); | 710 | nv_mask(dev, NV10_PGRAPH_CTX_CONTROL, 0, 0x10000); |
711 | nv04_graph_fifo_access(dev, true); | 711 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); |
712 | nv04_graph_fifo_access(dev, false); | 712 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); |
713 | 713 | ||
714 | /* Restore the FIFO state */ | 714 | /* Restore the FIFO state */ |
715 | for (i = 0; i < ARRAY_SIZE(fifo); i++) | 715 | for (i = 0; i < ARRAY_SIZE(fifo); i++) |
@@ -879,13 +879,13 @@ nv10_graph_context_del(struct nouveau_channel *chan, int engine) | |||
879 | unsigned long flags; | 879 | unsigned long flags; |
880 | 880 | ||
881 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 881 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
882 | nv04_graph_fifo_access(dev, false); | 882 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); |
883 | 883 | ||
884 | /* Unload the context if it's the currently active one */ | 884 | /* Unload the context if it's the currently active one */ |
885 | if (nv10_graph_channel(dev) == chan) | 885 | if (nv10_graph_channel(dev) == chan) |
886 | nv10_graph_unload_context(dev); | 886 | nv10_graph_unload_context(dev); |
887 | 887 | ||
888 | nv04_graph_fifo_access(dev, true); | 888 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); |
889 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 889 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
890 | 890 | ||
891 | /* Free the context resources */ | 891 | /* Free the context resources */ |
@@ -957,8 +957,13 @@ nv10_graph_init(struct drm_device *dev, int engine) | |||
957 | } | 957 | } |
958 | 958 | ||
959 | static int | 959 | static int |
960 | nv10_graph_fini(struct drm_device *dev, int engine) | 960 | nv10_graph_fini(struct drm_device *dev, int engine, bool suspend) |
961 | { | 961 | { |
962 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); | ||
963 | if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { | ||
964 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); | ||
965 | return -EBUSY; | ||
966 | } | ||
962 | nv10_graph_unload_context(dev); | 967 | nv10_graph_unload_context(dev); |
963 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); | 968 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); |
964 | return 0; | 969 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nv20_graph.c b/drivers/gpu/drm/nouveau/nv20_graph.c index affc7d7dd029..183e37512ef9 100644 --- a/drivers/gpu/drm/nouveau/nv20_graph.c +++ b/drivers/gpu/drm/nouveau/nv20_graph.c | |||
@@ -454,13 +454,13 @@ nv20_graph_context_del(struct nouveau_channel *chan, int engine) | |||
454 | unsigned long flags; | 454 | unsigned long flags; |
455 | 455 | ||
456 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 456 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
457 | nv04_graph_fifo_access(dev, false); | 457 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); |
458 | 458 | ||
459 | /* Unload the context if it's the currently active one */ | 459 | /* Unload the context if it's the currently active one */ |
460 | if (nv10_graph_channel(dev) == chan) | 460 | if (nv10_graph_channel(dev) == chan) |
461 | nv20_graph_unload_context(dev); | 461 | nv20_graph_unload_context(dev); |
462 | 462 | ||
463 | nv04_graph_fifo_access(dev, true); | 463 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); |
464 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 464 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
465 | 465 | ||
466 | /* Free the context resources */ | 466 | /* Free the context resources */ |
@@ -654,8 +654,13 @@ nv30_graph_init(struct drm_device *dev, int engine) | |||
654 | } | 654 | } |
655 | 655 | ||
656 | int | 656 | int |
657 | nv20_graph_fini(struct drm_device *dev, int engine) | 657 | nv20_graph_fini(struct drm_device *dev, int engine, bool suspend) |
658 | { | 658 | { |
659 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000000); | ||
660 | if (!nv_wait(dev, NV04_PGRAPH_STATUS, ~0, 0) && suspend) { | ||
661 | nv_mask(dev, NV04_PGRAPH_FIFO, 0x00000001, 0x00000001); | ||
662 | return -EBUSY; | ||
663 | } | ||
659 | nv20_graph_unload_context(dev); | 664 | nv20_graph_unload_context(dev); |
660 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); | 665 | nv_wr32(dev, NV03_PGRAPH_INTR_EN, 0x00000000); |
661 | return 0; | 666 | return 0; |
@@ -753,6 +758,7 @@ nv20_graph_create(struct drm_device *dev) | |||
753 | break; | 758 | break; |
754 | default: | 759 | default: |
755 | NV_ERROR(dev, "PGRAPH: unknown chipset\n"); | 760 | NV_ERROR(dev, "PGRAPH: unknown chipset\n"); |
761 | kfree(pgraph); | ||
756 | return 0; | 762 | return 0; |
757 | } | 763 | } |
758 | } else { | 764 | } else { |
@@ -774,6 +780,7 @@ nv20_graph_create(struct drm_device *dev) | |||
774 | break; | 780 | break; |
775 | default: | 781 | default: |
776 | NV_ERROR(dev, "PGRAPH: unknown chipset\n"); | 782 | NV_ERROR(dev, "PGRAPH: unknown chipset\n"); |
783 | kfree(pgraph); | ||
777 | return 0; | 784 | return 0; |
778 | } | 785 | } |
779 | } | 786 | } |
diff --git a/drivers/gpu/drm/nouveau/nv40_graph.c b/drivers/gpu/drm/nouveau/nv40_graph.c index 5beb01b8ace1..ba14a93d8afa 100644 --- a/drivers/gpu/drm/nouveau/nv40_graph.c +++ b/drivers/gpu/drm/nouveau/nv40_graph.c | |||
@@ -35,89 +35,6 @@ struct nv40_graph_engine { | |||
35 | u32 grctx_size; | 35 | u32 grctx_size; |
36 | }; | 36 | }; |
37 | 37 | ||
38 | static struct nouveau_channel * | ||
39 | nv40_graph_channel(struct drm_device *dev) | ||
40 | { | ||
41 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
42 | struct nouveau_gpuobj *grctx; | ||
43 | uint32_t inst; | ||
44 | int i; | ||
45 | |||
46 | inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); | ||
47 | if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) | ||
48 | return NULL; | ||
49 | inst = (inst & NV40_PGRAPH_CTXCTL_CUR_INSTANCE) << 4; | ||
50 | |||
51 | for (i = 0; i < dev_priv->engine.fifo.channels; i++) { | ||
52 | if (!dev_priv->channels.ptr[i]) | ||
53 | continue; | ||
54 | |||
55 | grctx = dev_priv->channels.ptr[i]->engctx[NVOBJ_ENGINE_GR]; | ||
56 | if (grctx && grctx->pinst == inst) | ||
57 | return dev_priv->channels.ptr[i]; | ||
58 | } | ||
59 | |||
60 | return NULL; | ||
61 | } | ||
62 | |||
63 | static int | ||
64 | nv40_graph_transfer_context(struct drm_device *dev, uint32_t inst, int save) | ||
65 | { | ||
66 | uint32_t old_cp, tv = 1000, tmp; | ||
67 | int i; | ||
68 | |||
69 | old_cp = nv_rd32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER); | ||
70 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, inst); | ||
71 | |||
72 | tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0310); | ||
73 | tmp |= save ? NV40_PGRAPH_CTXCTL_0310_XFER_SAVE : | ||
74 | NV40_PGRAPH_CTXCTL_0310_XFER_LOAD; | ||
75 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_0310, tmp); | ||
76 | |||
77 | tmp = nv_rd32(dev, NV40_PGRAPH_CTXCTL_0304); | ||
78 | tmp |= NV40_PGRAPH_CTXCTL_0304_XFER_CTX; | ||
79 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_0304, tmp); | ||
80 | |||
81 | nouveau_wait_for_idle(dev); | ||
82 | |||
83 | for (i = 0; i < tv; i++) { | ||
84 | if (nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C) == 0) | ||
85 | break; | ||
86 | } | ||
87 | |||
88 | nv_wr32(dev, NV20_PGRAPH_CHANNEL_CTX_POINTER, old_cp); | ||
89 | |||
90 | if (i == tv) { | ||
91 | uint32_t ucstat = nv_rd32(dev, NV40_PGRAPH_CTXCTL_UCODE_STAT); | ||
92 | NV_ERROR(dev, "Failed: Instance=0x%08x Save=%d\n", inst, save); | ||
93 | NV_ERROR(dev, "IP: 0x%02x, Opcode: 0x%08x\n", | ||
94 | ucstat >> NV40_PGRAPH_CTXCTL_UCODE_STAT_IP_SHIFT, | ||
95 | ucstat & NV40_PGRAPH_CTXCTL_UCODE_STAT_OP_MASK); | ||
96 | NV_ERROR(dev, "0x40030C = 0x%08x\n", | ||
97 | nv_rd32(dev, NV40_PGRAPH_CTXCTL_030C)); | ||
98 | return -EBUSY; | ||
99 | } | ||
100 | |||
101 | return 0; | ||
102 | } | ||
103 | |||
104 | static int | ||
105 | nv40_graph_unload_context(struct drm_device *dev) | ||
106 | { | ||
107 | uint32_t inst; | ||
108 | int ret; | ||
109 | |||
110 | inst = nv_rd32(dev, NV40_PGRAPH_CTXCTL_CUR); | ||
111 | if (!(inst & NV40_PGRAPH_CTXCTL_CUR_LOADED)) | ||
112 | return 0; | ||
113 | inst &= NV40_PGRAPH_CTXCTL_CUR_INSTANCE; | ||
114 | |||
115 | ret = nv40_graph_transfer_context(dev, inst, 1); | ||
116 | |||
117 | nv_wr32(dev, NV40_PGRAPH_CTXCTL_CUR, inst); | ||
118 | return ret; | ||
119 | } | ||
120 | |||
121 | static int | 38 | static int |
122 | nv40_graph_context_new(struct nouveau_channel *chan, int engine) | 39 | nv40_graph_context_new(struct nouveau_channel *chan, int engine) |
123 | { | 40 | { |
@@ -163,16 +80,16 @@ nv40_graph_context_del(struct nouveau_channel *chan, int engine) | |||
163 | struct nouveau_gpuobj *grctx = chan->engctx[engine]; | 80 | struct nouveau_gpuobj *grctx = chan->engctx[engine]; |
164 | struct drm_device *dev = chan->dev; | 81 | struct drm_device *dev = chan->dev; |
165 | struct drm_nouveau_private *dev_priv = dev->dev_private; | 82 | struct drm_nouveau_private *dev_priv = dev->dev_private; |
83 | u32 inst = 0x01000000 | (grctx->pinst >> 4); | ||
166 | unsigned long flags; | 84 | unsigned long flags; |
167 | 85 | ||
168 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); | 86 | spin_lock_irqsave(&dev_priv->context_switch_lock, flags); |
169 | nv04_graph_fifo_access(dev, false); | 87 | nv_mask(dev, 0x400720, 0x00000000, 0x00000001); |
170 | 88 | if (nv_rd32(dev, 0x40032c) == inst) | |
171 | /* Unload the context if it's the currently active one */ | 89 | nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); |
172 | if (nv40_graph_channel(dev) == chan) | 90 | if (nv_rd32(dev, 0x400330) == inst) |
173 | nv40_graph_unload_context(dev); | 91 | nv_mask(dev, 0x400330, 0x01000000, 0x00000000); |
174 | 92 | nv_mask(dev, 0x400720, 0x00000001, 0x00000001); | |
175 | nv04_graph_fifo_access(dev, true); | ||
176 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); | 93 | spin_unlock_irqrestore(&dev_priv->context_switch_lock, flags); |
177 | 94 | ||
178 | /* Free the context resources */ | 95 | /* Free the context resources */ |
@@ -429,9 +346,20 @@ nv40_graph_init(struct drm_device *dev, int engine) | |||
429 | } | 346 | } |
430 | 347 | ||
431 | static int | 348 | static int |
432 | nv40_graph_fini(struct drm_device *dev, int engine) | 349 | nv40_graph_fini(struct drm_device *dev, int engine, bool suspend) |
433 | { | 350 | { |
434 | nv40_graph_unload_context(dev); | 351 | u32 inst = nv_rd32(dev, 0x40032c); |
352 | if (inst & 0x01000000) { | ||
353 | nv_wr32(dev, 0x400720, 0x00000000); | ||
354 | nv_wr32(dev, 0x400784, inst); | ||
355 | nv_mask(dev, 0x400310, 0x00000020, 0x00000020); | ||
356 | nv_mask(dev, 0x400304, 0x00000001, 0x00000001); | ||
357 | if (!nv_wait(dev, 0x400300, 0x00000001, 0x00000000)) { | ||
358 | u32 insn = nv_rd32(dev, 0x400308); | ||
359 | NV_ERROR(dev, "PGRAPH: ctxprog timeout 0x%08x\n", insn); | ||
360 | } | ||
361 | nv_mask(dev, 0x40032c, 0x01000000, 0x00000000); | ||
362 | } | ||
435 | return 0; | 363 | return 0; |
436 | } | 364 | } |
437 | 365 | ||
diff --git a/drivers/gpu/drm/nouveau/nv40_mpeg.c b/drivers/gpu/drm/nouveau/nv40_mpeg.c index 6d2af292a2e3..ad03a0e1fc7d 100644 --- a/drivers/gpu/drm/nouveau/nv40_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv40_mpeg.c | |||
@@ -137,7 +137,7 @@ nv40_mpeg_init(struct drm_device *dev, int engine) | |||
137 | } | 137 | } |
138 | 138 | ||
139 | static int | 139 | static int |
140 | nv40_mpeg_fini(struct drm_device *dev, int engine) | 140 | nv40_mpeg_fini(struct drm_device *dev, int engine, bool suspend) |
141 | { | 141 | { |
142 | /*XXX: context save? */ | 142 | /*XXX: context save? */ |
143 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); | 143 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/nv50_graph.c b/drivers/gpu/drm/nouveau/nv50_graph.c index e25cbb46789a..d27dcf0790de 100644 --- a/drivers/gpu/drm/nouveau/nv50_graph.c +++ b/drivers/gpu/drm/nouveau/nv50_graph.c | |||
@@ -125,7 +125,6 @@ static void | |||
125 | nv50_graph_init_reset(struct drm_device *dev) | 125 | nv50_graph_init_reset(struct drm_device *dev) |
126 | { | 126 | { |
127 | uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); | 127 | uint32_t pmc_e = NV_PMC_ENABLE_PGRAPH | (1 << 21); |
128 | |||
129 | NV_DEBUG(dev, "\n"); | 128 | NV_DEBUG(dev, "\n"); |
130 | 129 | ||
131 | nv_wr32(dev, NV03_PMC_ENABLE, nv_rd32(dev, NV03_PMC_ENABLE) & ~pmc_e); | 130 | 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 | } | 254 | } |
256 | 255 | ||
257 | static int | 256 | static int |
258 | nv50_graph_fini(struct drm_device *dev, int engine) | 257 | nv50_graph_fini(struct drm_device *dev, int engine, bool suspend) |
259 | { | 258 | { |
260 | NV_DEBUG(dev, "\n"); | 259 | nv_mask(dev, 0x400500, 0x00010001, 0x00000000); |
260 | if (!nv_wait(dev, 0x400700, ~0, 0) && suspend) { | ||
261 | nv_mask(dev, 0x400500, 0x00010001, 0x00010001); | ||
262 | return -EBUSY; | ||
263 | } | ||
261 | nv50_graph_unload_context(dev); | 264 | nv50_graph_unload_context(dev); |
262 | nv_wr32(dev, 0x40013c, 0x00000000); | 265 | nv_wr32(dev, 0x40013c, 0x00000000); |
263 | return 0; | 266 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nv50_mpeg.c b/drivers/gpu/drm/nouveau/nv50_mpeg.c index 1dc5913f78c5..b57a2d180ad2 100644 --- a/drivers/gpu/drm/nouveau/nv50_mpeg.c +++ b/drivers/gpu/drm/nouveau/nv50_mpeg.c | |||
@@ -160,7 +160,7 @@ nv50_mpeg_init(struct drm_device *dev, int engine) | |||
160 | } | 160 | } |
161 | 161 | ||
162 | static int | 162 | static int |
163 | nv50_mpeg_fini(struct drm_device *dev, int engine) | 163 | nv50_mpeg_fini(struct drm_device *dev, int engine, bool suspend) |
164 | { | 164 | { |
165 | /*XXX: context save for s/r */ | 165 | /*XXX: context save for s/r */ |
166 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); | 166 | nv_mask(dev, 0x00b32c, 0x00000001, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/nv50_sor.c b/drivers/gpu/drm/nouveau/nv50_sor.c index c25c59386420..ffe8b483b7b0 100644 --- a/drivers/gpu/drm/nouveau/nv50_sor.c +++ b/drivers/gpu/drm/nouveau/nv50_sor.c | |||
@@ -318,6 +318,8 @@ nv50_sor_create(struct drm_connector *connector, struct dcb_entry *entry) | |||
318 | uint32_t tmp; | 318 | uint32_t tmp; |
319 | 319 | ||
320 | tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); | 320 | tmp = nv_rd32(dev, 0x61c700 + (or * 0x800)); |
321 | if (!tmp) | ||
322 | tmp = nv_rd32(dev, 0x610798 + (or * 8)); | ||
321 | 323 | ||
322 | switch ((tmp & 0x00000f00) >> 8) { | 324 | switch ((tmp & 0x00000f00) >> 8) { |
323 | case 8: | 325 | case 8: |
diff --git a/drivers/gpu/drm/nouveau/nv84_crypt.c b/drivers/gpu/drm/nouveau/nv84_crypt.c index 75b809a51748..edece9c616eb 100644 --- a/drivers/gpu/drm/nouveau/nv84_crypt.c +++ b/drivers/gpu/drm/nouveau/nv84_crypt.c | |||
@@ -138,7 +138,7 @@ nv84_crypt_isr(struct drm_device *dev) | |||
138 | } | 138 | } |
139 | 139 | ||
140 | static int | 140 | static int |
141 | nv84_crypt_fini(struct drm_device *dev, int engine) | 141 | nv84_crypt_fini(struct drm_device *dev, int engine, bool suspend) |
142 | { | 142 | { |
143 | nv_wr32(dev, 0x102140, 0x00000000); | 143 | nv_wr32(dev, 0x102140, 0x00000000); |
144 | return 0; | 144 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/nva3_copy.c b/drivers/gpu/drm/nouveau/nva3_copy.c index b86820a61220..8f356d58e409 100644 --- a/drivers/gpu/drm/nouveau/nva3_copy.c +++ b/drivers/gpu/drm/nouveau/nva3_copy.c | |||
@@ -140,7 +140,7 @@ nva3_copy_init(struct drm_device *dev, int engine) | |||
140 | } | 140 | } |
141 | 141 | ||
142 | static int | 142 | static int |
143 | nva3_copy_fini(struct drm_device *dev, int engine) | 143 | nva3_copy_fini(struct drm_device *dev, int engine, bool suspend) |
144 | { | 144 | { |
145 | nv_mask(dev, 0x104048, 0x00000003, 0x00000000); | 145 | nv_mask(dev, 0x104048, 0x00000003, 0x00000000); |
146 | 146 | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_copy.c b/drivers/gpu/drm/nouveau/nvc0_copy.c index 5ebcd74244db..dddf006f6d88 100644 --- a/drivers/gpu/drm/nouveau/nvc0_copy.c +++ b/drivers/gpu/drm/nouveau/nvc0_copy.c | |||
@@ -127,7 +127,7 @@ nvc0_copy_init(struct drm_device *dev, int engine) | |||
127 | } | 127 | } |
128 | 128 | ||
129 | static int | 129 | static int |
130 | nvc0_copy_fini(struct drm_device *dev, int engine) | 130 | nvc0_copy_fini(struct drm_device *dev, int engine, bool suspend) |
131 | { | 131 | { |
132 | struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); | 132 | struct nvc0_copy_engine *pcopy = nv_engine(dev, engine); |
133 | 133 | ||
diff --git a/drivers/gpu/drm/nouveau/nvc0_graph.c b/drivers/gpu/drm/nouveau/nvc0_graph.c index 3a97431996c5..5b2f6f420468 100644 --- a/drivers/gpu/drm/nouveau/nvc0_graph.c +++ b/drivers/gpu/drm/nouveau/nvc0_graph.c | |||
@@ -304,7 +304,7 @@ nvc0_graph_object_new(struct nouveau_channel *chan, int engine, | |||
304 | } | 304 | } |
305 | 305 | ||
306 | static int | 306 | static int |
307 | nvc0_graph_fini(struct drm_device *dev, int engine) | 307 | nvc0_graph_fini(struct drm_device *dev, int engine, bool suspend) |
308 | { | 308 | { |
309 | return 0; | 309 | return 0; |
310 | } | 310 | } |