diff options
| -rw-r--r-- | drivers/gpu/drm/nouveau/nv10_graph.c | 197 |
1 files changed, 154 insertions, 43 deletions
diff --git a/drivers/gpu/drm/nouveau/nv10_graph.c b/drivers/gpu/drm/nouveau/nv10_graph.c index 6bf6804bb0ef..6870e0ee2e7e 100644 --- a/drivers/gpu/drm/nouveau/nv10_graph.c +++ b/drivers/gpu/drm/nouveau/nv10_graph.c | |||
| @@ -389,49 +389,50 @@ struct graph_state { | |||
| 389 | int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; | 389 | int nv10[ARRAY_SIZE(nv10_graph_ctx_regs)]; |
| 390 | int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; | 390 | int nv17[ARRAY_SIZE(nv17_graph_ctx_regs)]; |
| 391 | struct pipe_state pipe_state; | 391 | struct pipe_state pipe_state; |
| 392 | uint32_t lma_window[4]; | ||
| 392 | }; | 393 | }; |
| 393 | 394 | ||
| 395 | #define PIPE_SAVE(dev, state, addr) \ | ||
| 396 | do { \ | ||
| 397 | int __i; \ | ||
| 398 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ | ||
| 399 | for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ | ||
| 400 | state[__i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ | ||
| 401 | } while (0) | ||
| 402 | |||
| 403 | #define PIPE_RESTORE(dev, state, addr) \ | ||
| 404 | do { \ | ||
| 405 | int __i; \ | ||
| 406 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ | ||
| 407 | for (__i = 0; __i < ARRAY_SIZE(state); __i++) \ | ||
| 408 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, state[__i]); \ | ||
| 409 | } while (0) | ||
| 410 | |||
| 394 | static void nv10_graph_save_pipe(struct nouveau_channel *chan) | 411 | static void nv10_graph_save_pipe(struct nouveau_channel *chan) |
| 395 | { | 412 | { |
| 396 | struct drm_device *dev = chan->dev; | 413 | struct drm_device *dev = chan->dev; |
| 397 | struct graph_state *pgraph_ctx = chan->pgraph_ctx; | 414 | struct graph_state *pgraph_ctx = chan->pgraph_ctx; |
| 398 | struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; | 415 | struct pipe_state *pipe = &pgraph_ctx->pipe_state; |
| 399 | int i; | 416 | |
| 400 | #define PIPE_SAVE(addr) \ | 417 | PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); |
| 401 | do { \ | 418 | PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); |
| 402 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ | 419 | PIPE_SAVE(dev, pipe->pipe_0x6400, 0x6400); |
| 403 | for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ | 420 | PIPE_SAVE(dev, pipe->pipe_0x6800, 0x6800); |
| 404 | fifo_pipe_state->pipe_##addr[i] = nv_rd32(dev, NV10_PGRAPH_PIPE_DATA); \ | 421 | PIPE_SAVE(dev, pipe->pipe_0x6c00, 0x6c00); |
| 405 | } while (0) | 422 | PIPE_SAVE(dev, pipe->pipe_0x7000, 0x7000); |
| 406 | 423 | PIPE_SAVE(dev, pipe->pipe_0x7400, 0x7400); | |
| 407 | PIPE_SAVE(0x4400); | 424 | PIPE_SAVE(dev, pipe->pipe_0x7800, 0x7800); |
| 408 | PIPE_SAVE(0x0200); | 425 | PIPE_SAVE(dev, pipe->pipe_0x0040, 0x0040); |
| 409 | PIPE_SAVE(0x6400); | 426 | PIPE_SAVE(dev, pipe->pipe_0x0000, 0x0000); |
| 410 | PIPE_SAVE(0x6800); | ||
| 411 | PIPE_SAVE(0x6c00); | ||
| 412 | PIPE_SAVE(0x7000); | ||
| 413 | PIPE_SAVE(0x7400); | ||
| 414 | PIPE_SAVE(0x7800); | ||
| 415 | PIPE_SAVE(0x0040); | ||
| 416 | PIPE_SAVE(0x0000); | ||
| 417 | |||
| 418 | #undef PIPE_SAVE | ||
| 419 | } | 427 | } |
| 420 | 428 | ||
| 421 | static void nv10_graph_load_pipe(struct nouveau_channel *chan) | 429 | static void nv10_graph_load_pipe(struct nouveau_channel *chan) |
| 422 | { | 430 | { |
| 423 | struct drm_device *dev = chan->dev; | 431 | struct drm_device *dev = chan->dev; |
| 424 | struct graph_state *pgraph_ctx = chan->pgraph_ctx; | 432 | struct graph_state *pgraph_ctx = chan->pgraph_ctx; |
| 425 | struct pipe_state *fifo_pipe_state = &pgraph_ctx->pipe_state; | 433 | struct pipe_state *pipe = &pgraph_ctx->pipe_state; |
| 426 | int i; | ||
| 427 | uint32_t xfmode0, xfmode1; | 434 | uint32_t xfmode0, xfmode1; |
| 428 | #define PIPE_RESTORE(addr) \ | 435 | int i; |
| 429 | do { \ | ||
| 430 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, addr); \ | ||
| 431 | for (i = 0; i < ARRAY_SIZE(fifo_pipe_state->pipe_##addr); i++) \ | ||
| 432 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, fifo_pipe_state->pipe_##addr[i]); \ | ||
| 433 | } while (0) | ||
| 434 | |||
| 435 | 436 | ||
| 436 | nouveau_wait_for_idle(dev); | 437 | nouveau_wait_for_idle(dev); |
| 437 | /* XXX check haiku comments */ | 438 | /* XXX check haiku comments */ |
| @@ -457,24 +458,22 @@ static void nv10_graph_load_pipe(struct nouveau_channel *chan) | |||
| 457 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); | 458 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); |
| 458 | 459 | ||
| 459 | 460 | ||
| 460 | PIPE_RESTORE(0x0200); | 461 | PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); |
| 461 | nouveau_wait_for_idle(dev); | 462 | nouveau_wait_for_idle(dev); |
| 462 | 463 | ||
| 463 | /* restore XFMODE */ | 464 | /* restore XFMODE */ |
| 464 | nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); | 465 | nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); |
| 465 | nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); | 466 | nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); |
| 466 | PIPE_RESTORE(0x6400); | 467 | PIPE_RESTORE(dev, pipe->pipe_0x6400, 0x6400); |
| 467 | PIPE_RESTORE(0x6800); | 468 | PIPE_RESTORE(dev, pipe->pipe_0x6800, 0x6800); |
| 468 | PIPE_RESTORE(0x6c00); | 469 | PIPE_RESTORE(dev, pipe->pipe_0x6c00, 0x6c00); |
| 469 | PIPE_RESTORE(0x7000); | 470 | PIPE_RESTORE(dev, pipe->pipe_0x7000, 0x7000); |
| 470 | PIPE_RESTORE(0x7400); | 471 | PIPE_RESTORE(dev, pipe->pipe_0x7400, 0x7400); |
| 471 | PIPE_RESTORE(0x7800); | 472 | PIPE_RESTORE(dev, pipe->pipe_0x7800, 0x7800); |
| 472 | PIPE_RESTORE(0x4400); | 473 | PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); |
| 473 | PIPE_RESTORE(0x0000); | 474 | PIPE_RESTORE(dev, pipe->pipe_0x0000, 0x0000); |
| 474 | PIPE_RESTORE(0x0040); | 475 | PIPE_RESTORE(dev, pipe->pipe_0x0040, 0x0040); |
| 475 | nouveau_wait_for_idle(dev); | 476 | nouveau_wait_for_idle(dev); |
| 476 | |||
| 477 | #undef PIPE_RESTORE | ||
| 478 | } | 477 | } |
| 479 | 478 | ||
| 480 | static void nv10_graph_create_pipe(struct nouveau_channel *chan) | 479 | static void nv10_graph_create_pipe(struct nouveau_channel *chan) |
| @@ -832,6 +831,9 @@ int nv10_graph_init(struct drm_device *dev) | |||
| 832 | (1<<31)); | 831 | (1<<31)); |
| 833 | if (dev_priv->chipset >= 0x17) { | 832 | if (dev_priv->chipset >= 0x17) { |
| 834 | nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); | 833 | nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x1f000000); |
| 834 | nv_wr32(dev, 0x400a10, 0x3ff3fb6); | ||
| 835 | nv_wr32(dev, 0x400838, 0x2f8684); | ||
| 836 | nv_wr32(dev, 0x40083c, 0x115f3f); | ||
| 835 | nv_wr32(dev, 0x004006b0, 0x40000020); | 837 | nv_wr32(dev, 0x004006b0, 0x40000020); |
| 836 | } else | 838 | } else |
| 837 | nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); | 839 | nv_wr32(dev, NV10_PGRAPH_DEBUG_4, 0x00000000); |
| @@ -867,6 +869,115 @@ void nv10_graph_takedown(struct drm_device *dev) | |||
| 867 | { | 869 | { |
| 868 | } | 870 | } |
| 869 | 871 | ||
| 872 | static int | ||
| 873 | nv17_graph_mthd_lma_window(struct nouveau_channel *chan, int grclass, | ||
| 874 | int mthd, uint32_t data) | ||
| 875 | { | ||
| 876 | struct drm_device *dev = chan->dev; | ||
| 877 | struct graph_state *ctx = chan->pgraph_ctx; | ||
| 878 | struct pipe_state *pipe = &ctx->pipe_state; | ||
| 879 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 880 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 881 | uint32_t pipe_0x0040[1], pipe_0x64c0[8], pipe_0x6a80[3], pipe_0x6ab0[3]; | ||
| 882 | uint32_t xfmode0, xfmode1; | ||
| 883 | int i; | ||
| 884 | |||
| 885 | ctx->lma_window[(mthd - 0x1638) / 4] = data; | ||
| 886 | |||
| 887 | if (mthd != 0x1644) | ||
| 888 | return 0; | ||
| 889 | |||
| 890 | nouveau_wait_for_idle(dev); | ||
| 891 | |||
| 892 | PIPE_SAVE(dev, pipe_0x0040, 0x0040); | ||
| 893 | PIPE_SAVE(dev, pipe->pipe_0x0200, 0x0200); | ||
| 894 | |||
| 895 | PIPE_RESTORE(dev, ctx->lma_window, 0x6790); | ||
| 896 | |||
| 897 | nouveau_wait_for_idle(dev); | ||
| 898 | |||
| 899 | xfmode0 = nv_rd32(dev, NV10_PGRAPH_XFMODE0); | ||
| 900 | xfmode1 = nv_rd32(dev, NV10_PGRAPH_XFMODE1); | ||
| 901 | |||
| 902 | PIPE_SAVE(dev, pipe->pipe_0x4400, 0x4400); | ||
| 903 | PIPE_SAVE(dev, pipe_0x64c0, 0x64c0); | ||
| 904 | PIPE_SAVE(dev, pipe_0x6ab0, 0x6ab0); | ||
| 905 | PIPE_SAVE(dev, pipe_0x6a80, 0x6a80); | ||
| 906 | |||
| 907 | nouveau_wait_for_idle(dev); | ||
| 908 | |||
| 909 | nv_wr32(dev, NV10_PGRAPH_XFMODE0, 0x10000000); | ||
| 910 | nv_wr32(dev, NV10_PGRAPH_XFMODE1, 0x00000000); | ||
| 911 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000064c0); | ||
| 912 | for (i = 0; i < 4; i++) | ||
| 913 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); | ||
| 914 | for (i = 0; i < 4; i++) | ||
| 915 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); | ||
| 916 | |||
| 917 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006ab0); | ||
| 918 | for (i = 0; i < 3; i++) | ||
| 919 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x3f800000); | ||
| 920 | |||
| 921 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00006a80); | ||
| 922 | for (i = 0; i < 3; i++) | ||
| 923 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); | ||
| 924 | |||
| 925 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x00000040); | ||
| 926 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000008); | ||
| 927 | |||
| 928 | PIPE_RESTORE(dev, pipe->pipe_0x0200, 0x0200); | ||
| 929 | |||
| 930 | nouveau_wait_for_idle(dev); | ||
| 931 | |||
| 932 | PIPE_RESTORE(dev, pipe_0x0040, 0x0040); | ||
| 933 | |||
| 934 | nv_wr32(dev, NV10_PGRAPH_XFMODE0, xfmode0); | ||
| 935 | nv_wr32(dev, NV10_PGRAPH_XFMODE1, xfmode1); | ||
| 936 | |||
| 937 | PIPE_RESTORE(dev, pipe_0x64c0, 0x64c0); | ||
| 938 | PIPE_RESTORE(dev, pipe_0x6ab0, 0x6ab0); | ||
| 939 | PIPE_RESTORE(dev, pipe_0x6a80, 0x6a80); | ||
| 940 | PIPE_RESTORE(dev, pipe->pipe_0x4400, 0x4400); | ||
| 941 | |||
| 942 | nv_wr32(dev, NV10_PGRAPH_PIPE_ADDRESS, 0x000000c0); | ||
| 943 | nv_wr32(dev, NV10_PGRAPH_PIPE_DATA, 0x00000000); | ||
| 944 | |||
| 945 | nouveau_wait_for_idle(dev); | ||
| 946 | |||
| 947 | pgraph->fifo_access(dev, true); | ||
| 948 | |||
| 949 | return 0; | ||
| 950 | } | ||
| 951 | |||
| 952 | static int | ||
| 953 | nv17_graph_mthd_lma_enable(struct nouveau_channel *chan, int grclass, | ||
| 954 | int mthd, uint32_t data) | ||
| 955 | { | ||
| 956 | struct drm_device *dev = chan->dev; | ||
| 957 | struct drm_nouveau_private *dev_priv = dev->dev_private; | ||
| 958 | struct nouveau_pgraph_engine *pgraph = &dev_priv->engine.graph; | ||
| 959 | |||
| 960 | nouveau_wait_for_idle(dev); | ||
| 961 | |||
| 962 | nv_wr32(dev, NV10_PGRAPH_DEBUG_4, | ||
| 963 | nv_rd32(dev, NV10_PGRAPH_DEBUG_4) | 0x1 << 8); | ||
| 964 | nv_wr32(dev, 0x004006b0, | ||
| 965 | nv_rd32(dev, 0x004006b0) | 0x8 << 24); | ||
| 966 | |||
| 967 | pgraph->fifo_access(dev, true); | ||
| 968 | |||
| 969 | return 0; | ||
| 970 | } | ||
| 971 | |||
| 972 | static struct nouveau_pgraph_object_method nv17_graph_celsius_mthds[] = { | ||
| 973 | { 0x1638, nv17_graph_mthd_lma_window }, | ||
| 974 | { 0x163c, nv17_graph_mthd_lma_window }, | ||
| 975 | { 0x1640, nv17_graph_mthd_lma_window }, | ||
| 976 | { 0x1644, nv17_graph_mthd_lma_window }, | ||
| 977 | { 0x1658, nv17_graph_mthd_lma_enable }, | ||
| 978 | {} | ||
| 979 | }; | ||
| 980 | |||
| 870 | struct nouveau_pgraph_object_class nv10_graph_grclass[] = { | 981 | struct nouveau_pgraph_object_class nv10_graph_grclass[] = { |
| 871 | { 0x0030, false, NULL }, /* null */ | 982 | { 0x0030, false, NULL }, /* null */ |
| 872 | { 0x0039, false, NULL }, /* m2mf */ | 983 | { 0x0039, false, NULL }, /* m2mf */ |
| @@ -887,6 +998,6 @@ struct nouveau_pgraph_object_class nv10_graph_grclass[] = { | |||
| 887 | { 0x0095, false, NULL }, /* multitex_tri */ | 998 | { 0x0095, false, NULL }, /* multitex_tri */ |
| 888 | { 0x0056, false, NULL }, /* celcius (nv10) */ | 999 | { 0x0056, false, NULL }, /* celcius (nv10) */ |
| 889 | { 0x0096, false, NULL }, /* celcius (nv11) */ | 1000 | { 0x0096, false, NULL }, /* celcius (nv11) */ |
| 890 | { 0x0099, false, NULL }, /* celcius (nv17) */ | 1001 | { 0x0099, false, nv17_graph_celsius_mthds }, /* celcius (nv17) */ |
| 891 | {} | 1002 | {} |
| 892 | }; | 1003 | }; |
