diff options
37 files changed, 323 insertions, 145 deletions
diff --git a/drivers/gpu/drm/nouveau/core/core/ramht.c b/drivers/gpu/drm/nouveau/core/core/ramht.c index 86a64045dd60..f3b9bddc3875 100644 --- a/drivers/gpu/drm/nouveau/core/core/ramht.c +++ b/drivers/gpu/drm/nouveau/core/core/ramht.c | |||
@@ -22,7 +22,6 @@ | |||
22 | 22 | ||
23 | #include <core/object.h> | 23 | #include <core/object.h> |
24 | #include <core/ramht.h> | 24 | #include <core/ramht.h> |
25 | #include <core/math.h> | ||
26 | 25 | ||
27 | #include <subdev/bar.h> | 26 | #include <subdev/bar.h> |
28 | 27 | ||
@@ -104,6 +103,6 @@ nouveau_ramht_new(struct nouveau_object *parent, struct nouveau_object *pargpu, | |||
104 | if (ret) | 103 | if (ret) |
105 | return ret; | 104 | return ret; |
106 | 105 | ||
107 | ramht->bits = log2i(nv_gpuobj(ramht)->size >> 3); | 106 | ramht->bits = order_base_2(nv_gpuobj(ramht)->size >> 3); |
108 | return 0; | 107 | return 0; |
109 | } | 108 | } |
diff --git a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c index 8bf92b0e6d82..6b089e022fd2 100644 --- a/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c | |||
@@ -19,16 +19,14 @@ | |||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * | 21 | * |
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <core/engctx.h> | 25 | #include <engine/falcon.h> |
26 | #include <core/class.h> | ||
27 | |||
28 | #include <engine/bsp.h> | 26 | #include <engine/bsp.h> |
29 | 27 | ||
30 | struct nv98_bsp_priv { | 28 | struct nv98_bsp_priv { |
31 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
32 | }; | 30 | }; |
33 | 31 | ||
34 | /******************************************************************************* | 32 | /******************************************************************************* |
@@ -37,31 +35,49 @@ struct nv98_bsp_priv { | |||
37 | 35 | ||
38 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
39 | nv98_bsp_sclass[] = { | 37 | nv98_bsp_sclass[] = { |
38 | { 0x88b1, &nouveau_object_ofuncs }, | ||
39 | { 0x85b1, &nouveau_object_ofuncs }, | ||
40 | { 0x86b1, &nouveau_object_ofuncs }, | ||
40 | {}, | 41 | {}, |
41 | }; | 42 | }; |
42 | 43 | ||
43 | /******************************************************************************* | 44 | /******************************************************************************* |
44 | * BSP context | 45 | * PBSP context |
45 | ******************************************************************************/ | 46 | ******************************************************************************/ |
46 | 47 | ||
47 | static struct nouveau_oclass | 48 | static struct nouveau_oclass |
48 | nv98_bsp_cclass = { | 49 | nv98_bsp_cclass = { |
49 | .handle = NV_ENGCTX(BSP, 0x98), | 50 | .handle = NV_ENGCTX(BSP, 0x98), |
50 | .ofuncs = &(struct nouveau_ofuncs) { | 51 | .ofuncs = &(struct nouveau_ofuncs) { |
51 | .ctor = _nouveau_engctx_ctor, | 52 | .ctor = _nouveau_falcon_context_ctor, |
52 | .dtor = _nouveau_engctx_dtor, | 53 | .dtor = _nouveau_falcon_context_dtor, |
53 | .init = _nouveau_engctx_init, | 54 | .init = _nouveau_falcon_context_init, |
54 | .fini = _nouveau_engctx_fini, | 55 | .fini = _nouveau_falcon_context_fini, |
55 | .rd32 = _nouveau_engctx_rd32, | 56 | .rd32 = _nouveau_falcon_context_rd32, |
56 | .wr32 = _nouveau_engctx_wr32, | 57 | .wr32 = _nouveau_falcon_context_wr32, |
57 | }, | 58 | }, |
58 | }; | 59 | }; |
59 | 60 | ||
60 | /******************************************************************************* | 61 | /******************************************************************************* |
61 | * BSP engine/subdev functions | 62 | * PBSP engine/subdev functions |
62 | ******************************************************************************/ | 63 | ******************************************************************************/ |
63 | 64 | ||
64 | static int | 65 | static int |
66 | nv98_bsp_init(struct nouveau_object *object) | ||
67 | { | ||
68 | struct nv98_bsp_priv *priv = (void *)object; | ||
69 | int ret; | ||
70 | |||
71 | ret = nouveau_falcon_init(&priv->base); | ||
72 | if (ret) | ||
73 | return ret; | ||
74 | |||
75 | nv_wr32(priv, 0x084010, 0x0000ffd2); | ||
76 | nv_wr32(priv, 0x08401c, 0x0000fff2); | ||
77 | return 0; | ||
78 | } | ||
79 | |||
80 | static int | ||
65 | nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 81 | nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
66 | struct nouveau_oclass *oclass, void *data, u32 size, | 82 | struct nouveau_oclass *oclass, void *data, u32 size, |
67 | struct nouveau_object **pobject) | 83 | struct nouveau_object **pobject) |
@@ -69,7 +85,7 @@ nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
69 | struct nv98_bsp_priv *priv; | 85 | struct nv98_bsp_priv *priv; |
70 | int ret; | 86 | int ret; |
71 | 87 | ||
72 | ret = nouveau_engine_create(parent, engine, oclass, true, | 88 | ret = nouveau_falcon_create(parent, engine, oclass, 0x084000, true, |
73 | "PBSP", "bsp", &priv); | 89 | "PBSP", "bsp", &priv); |
74 | *pobject = nv_object(priv); | 90 | *pobject = nv_object(priv); |
75 | if (ret) | 91 | if (ret) |
@@ -86,8 +102,10 @@ nv98_bsp_oclass = { | |||
86 | .handle = NV_ENGINE(BSP, 0x98), | 102 | .handle = NV_ENGINE(BSP, 0x98), |
87 | .ofuncs = &(struct nouveau_ofuncs) { | 103 | .ofuncs = &(struct nouveau_ofuncs) { |
88 | .ctor = nv98_bsp_ctor, | 104 | .ctor = nv98_bsp_ctor, |
89 | .dtor = _nouveau_engine_dtor, | 105 | .dtor = _nouveau_falcon_dtor, |
90 | .init = _nouveau_engine_init, | 106 | .init = nv98_bsp_init, |
91 | .fini = _nouveau_engine_fini, | 107 | .fini = _nouveau_falcon_fini, |
108 | .rd32 = _nouveau_falcon_rd32, | ||
109 | .wr32 = _nouveau_falcon_wr32, | ||
92 | }, | 110 | }, |
93 | }; | 111 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c index f02fd9f443ff..a66b27c0fcab 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c | |||
@@ -49,18 +49,23 @@ int | |||
49 | nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) | 49 | nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) |
50 | { | 50 | { |
51 | const u32 doff = (or * 0x800); | 51 | const u32 doff = (or * 0x800); |
52 | int load = -EINVAL; | 52 | |
53 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); | 53 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80150000); |
54 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); | 54 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); |
55 | |||
55 | nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); | 56 | nv_wr32(priv, 0x61a00c + doff, 0x00100000 | loadval); |
56 | mdelay(9); | 57 | mdelay(9); |
57 | udelay(500); | 58 | udelay(500); |
58 | nv_wr32(priv, 0x61a00c + doff, 0x80000000); | 59 | loadval = nv_mask(priv, 0x61a00c + doff, 0xffffffff, 0x00000000); |
59 | load = (nv_rd32(priv, 0x61a00c + doff) & 0x38000000) >> 27; | 60 | |
60 | nv_wr32(priv, 0x61a00c + doff, 0x00000000); | ||
61 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); | 61 | nv_mask(priv, 0x61a004 + doff, 0x807f0000, 0x80550000); |
62 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); | 62 | nv_wait(priv, 0x61a004 + doff, 0x80000000, 0x00000000); |
63 | return load; | 63 | |
64 | nv_debug(priv, "DAC%d sense: 0x%08x\n", or, loadval); | ||
65 | if (!(loadval & 0x80000000)) | ||
66 | return -ETIMEDOUT; | ||
67 | |||
68 | return (loadval & 0x38000000) >> 27; | ||
64 | } | 69 | } |
65 | 70 | ||
66 | int | 71 | int |
diff --git a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c index 7ffe2f309f12..c168ae3eaa97 100644 --- a/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/disp/nv50.c | |||
@@ -628,7 +628,7 @@ nv50_disp_base_init(struct nouveau_object *object) | |||
628 | } | 628 | } |
629 | 629 | ||
630 | /* ... PIOR caps */ | 630 | /* ... PIOR caps */ |
631 | for (i = 0; i < 3; i++) { | 631 | for (i = 0; i < priv->pior.nr; i++) { |
632 | tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); | 632 | tmp = nv_rd32(priv, 0x61e000 + (i * 0x800)); |
633 | nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); | 633 | nv_wr32(priv, 0x6101f0 + (i * 0x04), tmp); |
634 | } | 634 | } |
@@ -834,10 +834,11 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
834 | u8 ver, hdr, cnt, len; | 834 | u8 ver, hdr, cnt, len; |
835 | u16 data; | 835 | u16 data; |
836 | u32 ctrl = 0x00000000; | 836 | u32 ctrl = 0x00000000; |
837 | u32 reg; | ||
837 | int i; | 838 | int i; |
838 | 839 | ||
839 | /* DAC */ | 840 | /* DAC */ |
840 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 841 | for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) |
841 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); | 842 | ctrl = nv_rd32(priv, 0x610b5c + (i * 8)); |
842 | 843 | ||
843 | /* SOR */ | 844 | /* SOR */ |
@@ -845,19 +846,18 @@ exec_script(struct nv50_disp_priv *priv, int head, int id) | |||
845 | if (nv_device(priv)->chipset < 0x90 || | 846 | if (nv_device(priv)->chipset < 0x90 || |
846 | nv_device(priv)->chipset == 0x92 || | 847 | nv_device(priv)->chipset == 0x92 || |
847 | nv_device(priv)->chipset == 0xa0) { | 848 | nv_device(priv)->chipset == 0xa0) { |
848 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 849 | reg = 0x610b74; |
849 | ctrl = nv_rd32(priv, 0x610b74 + (i * 8)); | ||
850 | i += 4; | ||
851 | } else { | 850 | } else { |
852 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 851 | reg = 0x610798; |
853 | ctrl = nv_rd32(priv, 0x610798 + (i * 8)); | ||
854 | i += 4; | ||
855 | } | 852 | } |
853 | for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) | ||
854 | ctrl = nv_rd32(priv, reg + (i * 8)); | ||
855 | i += 4; | ||
856 | } | 856 | } |
857 | 857 | ||
858 | /* PIOR */ | 858 | /* PIOR */ |
859 | if (!(ctrl & (1 << head))) { | 859 | if (!(ctrl & (1 << head))) { |
860 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 860 | for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) |
861 | ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); | 861 | ctrl = nv_rd32(priv, 0x610b84 + (i * 8)); |
862 | i += 8; | 862 | i += 8; |
863 | } | 863 | } |
@@ -893,10 +893,11 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
893 | u8 ver, hdr, cnt, len; | 893 | u8 ver, hdr, cnt, len; |
894 | u32 ctrl = 0x00000000; | 894 | u32 ctrl = 0x00000000; |
895 | u32 data, conf = ~0; | 895 | u32 data, conf = ~0; |
896 | u32 reg; | ||
896 | int i; | 897 | int i; |
897 | 898 | ||
898 | /* DAC */ | 899 | /* DAC */ |
899 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 900 | for (i = 0; !(ctrl & (1 << head)) && i < priv->dac.nr; i++) |
900 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); | 901 | ctrl = nv_rd32(priv, 0x610b58 + (i * 8)); |
901 | 902 | ||
902 | /* SOR */ | 903 | /* SOR */ |
@@ -904,19 +905,18 @@ exec_clkcmp(struct nv50_disp_priv *priv, int head, int id, u32 pclk, | |||
904 | if (nv_device(priv)->chipset < 0x90 || | 905 | if (nv_device(priv)->chipset < 0x90 || |
905 | nv_device(priv)->chipset == 0x92 || | 906 | nv_device(priv)->chipset == 0x92 || |
906 | nv_device(priv)->chipset == 0xa0) { | 907 | nv_device(priv)->chipset == 0xa0) { |
907 | for (i = 0; !(ctrl & (1 << head)) && i < 2; i++) | 908 | reg = 0x610b70; |
908 | ctrl = nv_rd32(priv, 0x610b70 + (i * 8)); | ||
909 | i += 4; | ||
910 | } else { | 909 | } else { |
911 | for (i = 0; !(ctrl & (1 << head)) && i < 4; i++) | 910 | reg = 0x610794; |
912 | ctrl = nv_rd32(priv, 0x610794 + (i * 8)); | ||
913 | i += 4; | ||
914 | } | 911 | } |
912 | for (i = 0; !(ctrl & (1 << head)) && i < priv->sor.nr; i++) | ||
913 | ctrl = nv_rd32(priv, reg + (i * 8)); | ||
914 | i += 4; | ||
915 | } | 915 | } |
916 | 916 | ||
917 | /* PIOR */ | 917 | /* PIOR */ |
918 | if (!(ctrl & (1 << head))) { | 918 | if (!(ctrl & (1 << head))) { |
919 | for (i = 0; !(ctrl & (1 << head)) && i < 3; i++) | 919 | for (i = 0; !(ctrl & (1 << head)) && i < priv->pior.nr; i++) |
920 | ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); | 920 | ctrl = nv_rd32(priv, 0x610b80 + (i * 8)); |
921 | i += 8; | 921 | i += 8; |
922 | } | 922 | } |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c index e9b8217d0075..7e5dff51d3c5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c | |||
@@ -26,7 +26,6 @@ | |||
26 | #include <core/engctx.h> | 26 | #include <core/engctx.h> |
27 | #include <core/ramht.h> | 27 | #include <core/ramht.h> |
28 | #include <core/class.h> | 28 | #include <core/class.h> |
29 | #include <core/math.h> | ||
30 | 29 | ||
31 | #include <subdev/timer.h> | 30 | #include <subdev/timer.h> |
32 | #include <subdev/bar.h> | 31 | #include <subdev/bar.h> |
@@ -278,7 +277,7 @@ nv50_fifo_chan_ctor_ind(struct nouveau_object *parent, | |||
278 | return ret; | 277 | return ret; |
279 | 278 | ||
280 | ioffset = args->ioffset; | 279 | ioffset = args->ioffset; |
281 | ilength = log2i(args->ilength / 8); | 280 | ilength = order_base_2(args->ilength / 8); |
282 | 281 | ||
283 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); | 282 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); |
284 | nv_wo32(base->ramfc, 0x44, 0x01003fff); | 283 | nv_wo32(base->ramfc, 0x44, 0x01003fff); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c index 7f53196cff52..91a87cd7195a 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c | |||
@@ -28,7 +28,6 @@ | |||
28 | #include <core/ramht.h> | 28 | #include <core/ramht.h> |
29 | #include <core/event.h> | 29 | #include <core/event.h> |
30 | #include <core/class.h> | 30 | #include <core/class.h> |
31 | #include <core/math.h> | ||
32 | 31 | ||
33 | #include <subdev/timer.h> | 32 | #include <subdev/timer.h> |
34 | #include <subdev/bar.h> | 33 | #include <subdev/bar.h> |
@@ -57,6 +56,7 @@ nv84_fifo_context_attach(struct nouveau_object *parent, | |||
57 | case NVDEV_ENGINE_SW : return 0; | 56 | case NVDEV_ENGINE_SW : return 0; |
58 | case NVDEV_ENGINE_GR : addr = 0x0020; break; | 57 | case NVDEV_ENGINE_GR : addr = 0x0020; break; |
59 | case NVDEV_ENGINE_VP : addr = 0x0040; break; | 58 | case NVDEV_ENGINE_VP : addr = 0x0040; break; |
59 | case NVDEV_ENGINE_PPP : | ||
60 | case NVDEV_ENGINE_MPEG : addr = 0x0060; break; | 60 | case NVDEV_ENGINE_MPEG : addr = 0x0060; break; |
61 | case NVDEV_ENGINE_BSP : addr = 0x0080; break; | 61 | case NVDEV_ENGINE_BSP : addr = 0x0080; break; |
62 | case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; | 62 | case NVDEV_ENGINE_CRYPT: addr = 0x00a0; break; |
@@ -92,6 +92,7 @@ nv84_fifo_context_detach(struct nouveau_object *parent, bool suspend, | |||
92 | case NVDEV_ENGINE_SW : return 0; | 92 | case NVDEV_ENGINE_SW : return 0; |
93 | case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; | 93 | case NVDEV_ENGINE_GR : engn = 0; addr = 0x0020; break; |
94 | case NVDEV_ENGINE_VP : engn = 3; addr = 0x0040; break; | 94 | case NVDEV_ENGINE_VP : engn = 3; addr = 0x0040; break; |
95 | case NVDEV_ENGINE_PPP : | ||
95 | case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; | 96 | case NVDEV_ENGINE_MPEG : engn = 1; addr = 0x0060; break; |
96 | case NVDEV_ENGINE_BSP : engn = 5; addr = 0x0080; break; | 97 | case NVDEV_ENGINE_BSP : engn = 5; addr = 0x0080; break; |
97 | case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break; | 98 | case NVDEV_ENGINE_CRYPT: engn = 4; addr = 0x00a0; break; |
@@ -258,7 +259,7 @@ nv84_fifo_chan_ctor_ind(struct nouveau_object *parent, | |||
258 | nv_parent(chan)->object_detach = nv50_fifo_object_detach; | 259 | nv_parent(chan)->object_detach = nv50_fifo_object_detach; |
259 | 260 | ||
260 | ioffset = args->ioffset; | 261 | ioffset = args->ioffset; |
261 | ilength = log2i(args->ilength / 8); | 262 | ilength = order_base_2(args->ilength / 8); |
262 | 263 | ||
263 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); | 264 | nv_wo32(base->ramfc, 0x3c, 0x403f6078); |
264 | nv_wo32(base->ramfc, 0x44, 0x01003fff); | 265 | nv_wo32(base->ramfc, 0x44, 0x01003fff); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c index 46dfa68c47bb..ce92f289e751 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <core/engctx.h> | 29 | #include <core/engctx.h> |
30 | #include <core/event.h> | 30 | #include <core/event.h> |
31 | #include <core/class.h> | 31 | #include <core/class.h> |
32 | #include <core/math.h> | ||
33 | #include <core/enum.h> | 32 | #include <core/enum.h> |
34 | 33 | ||
35 | #include <subdev/timer.h> | 34 | #include <subdev/timer.h> |
@@ -200,7 +199,7 @@ nvc0_fifo_chan_ctor(struct nouveau_object *parent, | |||
200 | 199 | ||
201 | usermem = chan->base.chid * 0x1000; | 200 | usermem = chan->base.chid * 0x1000; |
202 | ioffset = args->ioffset; | 201 | ioffset = args->ioffset; |
203 | ilength = log2i(args->ilength / 8); | 202 | ilength = order_base_2(args->ilength / 8); |
204 | 203 | ||
205 | for (i = 0; i < 0x1000; i += 4) | 204 | for (i = 0; i < 0x1000; i += 4) |
206 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); | 205 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c index 09644fa9602c..8e8121abe31b 100644 --- a/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c +++ b/drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c | |||
@@ -29,7 +29,6 @@ | |||
29 | #include <core/engctx.h> | 29 | #include <core/engctx.h> |
30 | #include <core/event.h> | 30 | #include <core/event.h> |
31 | #include <core/class.h> | 31 | #include <core/class.h> |
32 | #include <core/math.h> | ||
33 | #include <core/enum.h> | 32 | #include <core/enum.h> |
34 | 33 | ||
35 | #include <subdev/timer.h> | 34 | #include <subdev/timer.h> |
@@ -240,7 +239,7 @@ nve0_fifo_chan_ctor(struct nouveau_object *parent, | |||
240 | 239 | ||
241 | usermem = chan->base.chid * 0x200; | 240 | usermem = chan->base.chid * 0x200; |
242 | ioffset = args->ioffset; | 241 | ioffset = args->ioffset; |
243 | ilength = log2i(args->ilength / 8); | 242 | ilength = order_base_2(args->ilength / 8); |
244 | 243 | ||
245 | for (i = 0; i < 0x200; i += 4) | 244 | for (i = 0; i < 0x200; i += 4) |
246 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); | 245 | nv_wo32(priv->user.mem, usermem + i, 0x00000000); |
diff --git a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h index 7da35a4e7970..ad8209377529 100644 --- a/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h +++ b/drivers/gpu/drm/nouveau/core/engine/graph/nv40.h | |||
@@ -1,6 +1,9 @@ | |||
1 | #ifndef __NV40_GRAPH_H__ | 1 | #ifndef __NV40_GRAPH_H__ |
2 | #define __NV40_GRAPH_H__ | 2 | #define __NV40_GRAPH_H__ |
3 | 3 | ||
4 | #include <core/device.h> | ||
5 | #include <core/gpuobj.h> | ||
6 | |||
4 | /* returns 1 if device is one of the nv4x using the 0x4497 object class, | 7 | /* returns 1 if device is one of the nv4x using the 0x4497 object class, |
5 | * helpful to determine a number of other hardware features | 8 | * helpful to determine a number of other hardware features |
6 | */ | 9 | */ |
diff --git a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c index 5a5b2a773ed7..13bf31c40aa1 100644 --- a/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c | |||
@@ -19,21 +19,14 @@ | |||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * | 21 | * |
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <core/engine.h> | 25 | #include <engine/falcon.h> |
26 | #include <core/engctx.h> | ||
27 | #include <core/class.h> | ||
28 | |||
29 | #include <engine/ppp.h> | 26 | #include <engine/ppp.h> |
30 | 27 | ||
31 | struct nv98_ppp_priv { | 28 | struct nv98_ppp_priv { |
32 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
33 | }; | ||
34 | |||
35 | struct nv98_ppp_chan { | ||
36 | struct nouveau_engctx base; | ||
37 | }; | 30 | }; |
38 | 31 | ||
39 | /******************************************************************************* | 32 | /******************************************************************************* |
@@ -42,6 +35,8 @@ struct nv98_ppp_chan { | |||
42 | 35 | ||
43 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
44 | nv98_ppp_sclass[] = { | 37 | nv98_ppp_sclass[] = { |
38 | { 0x88b3, &nouveau_object_ofuncs }, | ||
39 | { 0x85b3, &nouveau_object_ofuncs }, | ||
45 | {}, | 40 | {}, |
46 | }; | 41 | }; |
47 | 42 | ||
@@ -53,12 +48,12 @@ static struct nouveau_oclass | |||
53 | nv98_ppp_cclass = { | 48 | nv98_ppp_cclass = { |
54 | .handle = NV_ENGCTX(PPP, 0x98), | 49 | .handle = NV_ENGCTX(PPP, 0x98), |
55 | .ofuncs = &(struct nouveau_ofuncs) { | 50 | .ofuncs = &(struct nouveau_ofuncs) { |
56 | .ctor = _nouveau_engctx_ctor, | 51 | .ctor = _nouveau_falcon_context_ctor, |
57 | .dtor = _nouveau_engctx_dtor, | 52 | .dtor = _nouveau_falcon_context_dtor, |
58 | .init = _nouveau_engctx_init, | 53 | .init = _nouveau_falcon_context_init, |
59 | .fini = _nouveau_engctx_fini, | 54 | .fini = _nouveau_falcon_context_fini, |
60 | .rd32 = _nouveau_engctx_rd32, | 55 | .rd32 = _nouveau_falcon_context_rd32, |
61 | .wr32 = _nouveau_engctx_wr32, | 56 | .wr32 = _nouveau_falcon_context_wr32, |
62 | }, | 57 | }, |
63 | }; | 58 | }; |
64 | 59 | ||
@@ -67,6 +62,21 @@ nv98_ppp_cclass = { | |||
67 | ******************************************************************************/ | 62 | ******************************************************************************/ |
68 | 63 | ||
69 | static int | 64 | static int |
65 | nv98_ppp_init(struct nouveau_object *object) | ||
66 | { | ||
67 | struct nv98_ppp_priv *priv = (void *)object; | ||
68 | int ret; | ||
69 | |||
70 | ret = nouveau_falcon_init(&priv->base); | ||
71 | if (ret) | ||
72 | return ret; | ||
73 | |||
74 | nv_wr32(priv, 0x086010, 0x0000ffd2); | ||
75 | nv_wr32(priv, 0x08601c, 0x0000fff2); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int | ||
70 | nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 80 | nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
71 | struct nouveau_oclass *oclass, void *data, u32 size, | 81 | struct nouveau_oclass *oclass, void *data, u32 size, |
72 | struct nouveau_object **pobject) | 82 | struct nouveau_object **pobject) |
@@ -74,7 +84,7 @@ nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
74 | struct nv98_ppp_priv *priv; | 84 | struct nv98_ppp_priv *priv; |
75 | int ret; | 85 | int ret; |
76 | 86 | ||
77 | ret = nouveau_engine_create(parent, engine, oclass, true, | 87 | ret = nouveau_falcon_create(parent, engine, oclass, 0x086000, true, |
78 | "PPPP", "ppp", &priv); | 88 | "PPPP", "ppp", &priv); |
79 | *pobject = nv_object(priv); | 89 | *pobject = nv_object(priv); |
80 | if (ret) | 90 | if (ret) |
@@ -91,8 +101,10 @@ nv98_ppp_oclass = { | |||
91 | .handle = NV_ENGINE(PPP, 0x98), | 101 | .handle = NV_ENGINE(PPP, 0x98), |
92 | .ofuncs = &(struct nouveau_ofuncs) { | 102 | .ofuncs = &(struct nouveau_ofuncs) { |
93 | .ctor = nv98_ppp_ctor, | 103 | .ctor = nv98_ppp_ctor, |
94 | .dtor = _nouveau_engine_dtor, | 104 | .dtor = _nouveau_falcon_dtor, |
95 | .init = _nouveau_engine_init, | 105 | .init = nv98_ppp_init, |
96 | .fini = _nouveau_engine_fini, | 106 | .fini = _nouveau_falcon_fini, |
107 | .rd32 = _nouveau_falcon_rd32, | ||
108 | .wr32 = _nouveau_falcon_wr32, | ||
97 | }, | 109 | }, |
98 | }; | 110 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c index 8a8236bc84de..fc9ae0ff1ef5 100644 --- a/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c +++ b/drivers/gpu/drm/nouveau/core/engine/vp/nv98.c | |||
@@ -19,16 +19,14 @@ | |||
19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR | 19 | * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR |
20 | * OTHER DEALINGS IN THE SOFTWARE. | 20 | * OTHER DEALINGS IN THE SOFTWARE. |
21 | * | 21 | * |
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs, Maarten Lankhorst, Ilia Mirkin |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <core/engctx.h> | 25 | #include <engine/falcon.h> |
26 | #include <core/class.h> | ||
27 | |||
28 | #include <engine/vp.h> | 26 | #include <engine/vp.h> |
29 | 27 | ||
30 | struct nv98_vp_priv { | 28 | struct nv98_vp_priv { |
31 | struct nouveau_engine base; | 29 | struct nouveau_falcon base; |
32 | }; | 30 | }; |
33 | 31 | ||
34 | /******************************************************************************* | 32 | /******************************************************************************* |
@@ -37,6 +35,8 @@ struct nv98_vp_priv { | |||
37 | 35 | ||
38 | static struct nouveau_oclass | 36 | static struct nouveau_oclass |
39 | nv98_vp_sclass[] = { | 37 | nv98_vp_sclass[] = { |
38 | { 0x88b2, &nouveau_object_ofuncs }, | ||
39 | { 0x85b2, &nouveau_object_ofuncs }, | ||
40 | {}, | 40 | {}, |
41 | }; | 41 | }; |
42 | 42 | ||
@@ -48,12 +48,12 @@ static struct nouveau_oclass | |||
48 | nv98_vp_cclass = { | 48 | nv98_vp_cclass = { |
49 | .handle = NV_ENGCTX(VP, 0x98), | 49 | .handle = NV_ENGCTX(VP, 0x98), |
50 | .ofuncs = &(struct nouveau_ofuncs) { | 50 | .ofuncs = &(struct nouveau_ofuncs) { |
51 | .ctor = _nouveau_engctx_ctor, | 51 | .ctor = _nouveau_falcon_context_ctor, |
52 | .dtor = _nouveau_engctx_dtor, | 52 | .dtor = _nouveau_falcon_context_dtor, |
53 | .init = _nouveau_engctx_init, | 53 | .init = _nouveau_falcon_context_init, |
54 | .fini = _nouveau_engctx_fini, | 54 | .fini = _nouveau_falcon_context_fini, |
55 | .rd32 = _nouveau_engctx_rd32, | 55 | .rd32 = _nouveau_falcon_context_rd32, |
56 | .wr32 = _nouveau_engctx_wr32, | 56 | .wr32 = _nouveau_falcon_context_wr32, |
57 | }, | 57 | }, |
58 | }; | 58 | }; |
59 | 59 | ||
@@ -62,6 +62,21 @@ nv98_vp_cclass = { | |||
62 | ******************************************************************************/ | 62 | ******************************************************************************/ |
63 | 63 | ||
64 | static int | 64 | static int |
65 | nv98_vp_init(struct nouveau_object *object) | ||
66 | { | ||
67 | struct nv98_vp_priv *priv = (void *)object; | ||
68 | int ret; | ||
69 | |||
70 | ret = nouveau_falcon_init(&priv->base); | ||
71 | if (ret) | ||
72 | return ret; | ||
73 | |||
74 | nv_wr32(priv, 0x085010, 0x0000ffd2); | ||
75 | nv_wr32(priv, 0x08501c, 0x0000fff2); | ||
76 | return 0; | ||
77 | } | ||
78 | |||
79 | static int | ||
65 | nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 80 | nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
66 | struct nouveau_oclass *oclass, void *data, u32 size, | 81 | struct nouveau_oclass *oclass, void *data, u32 size, |
67 | struct nouveau_object **pobject) | 82 | struct nouveau_object **pobject) |
@@ -69,7 +84,7 @@ nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
69 | struct nv98_vp_priv *priv; | 84 | struct nv98_vp_priv *priv; |
70 | int ret; | 85 | int ret; |
71 | 86 | ||
72 | ret = nouveau_engine_create(parent, engine, oclass, true, | 87 | ret = nouveau_falcon_create(parent, engine, oclass, 0x085000, true, |
73 | "PVP", "vp", &priv); | 88 | "PVP", "vp", &priv); |
74 | *pobject = nv_object(priv); | 89 | *pobject = nv_object(priv); |
75 | if (ret) | 90 | if (ret) |
@@ -86,8 +101,10 @@ nv98_vp_oclass = { | |||
86 | .handle = NV_ENGINE(VP, 0x98), | 101 | .handle = NV_ENGINE(VP, 0x98), |
87 | .ofuncs = &(struct nouveau_ofuncs) { | 102 | .ofuncs = &(struct nouveau_ofuncs) { |
88 | .ctor = nv98_vp_ctor, | 103 | .ctor = nv98_vp_ctor, |
89 | .dtor = _nouveau_engine_dtor, | 104 | .dtor = _nouveau_falcon_dtor, |
90 | .init = _nouveau_engine_init, | 105 | .init = nv98_vp_init, |
91 | .fini = _nouveau_engine_fini, | 106 | .fini = _nouveau_falcon_fini, |
107 | .rd32 = _nouveau_falcon_rd32, | ||
108 | .wr32 = _nouveau_falcon_wr32, | ||
92 | }, | 109 | }, |
93 | }; | 110 | }; |
diff --git a/drivers/gpu/drm/nouveau/core/include/core/math.h b/drivers/gpu/drm/nouveau/core/include/core/math.h deleted file mode 100644 index f808131c5cd8..000000000000 --- a/drivers/gpu/drm/nouveau/core/include/core/math.h +++ /dev/null | |||
@@ -1,16 +0,0 @@ | |||
1 | #ifndef __NOUVEAU_MATH_H__ | ||
2 | #define __NOUVEAU_MATH_H__ | ||
3 | |||
4 | static inline int | ||
5 | log2i(u64 base) | ||
6 | { | ||
7 | u64 temp = base >> 1; | ||
8 | int log2; | ||
9 | |||
10 | for (log2 = 0; temp; log2++, temp >>= 1) { | ||
11 | } | ||
12 | |||
13 | return (base & (base - 1)) ? log2 + 1: log2; | ||
14 | } | ||
15 | |||
16 | #endif | ||
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h index 888384c0bed8..7e4e2775f249 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/i2c.h | |||
@@ -39,8 +39,8 @@ struct nouveau_i2c_func { | |||
39 | int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); | 39 | int (*drv_ctl)(struct nouveau_i2c_port *, int lane, int sw, int pe); |
40 | }; | 40 | }; |
41 | 41 | ||
42 | #define nouveau_i2c_port_create(p,e,o,i,a,d) \ | 42 | #define nouveau_i2c_port_create(p,e,o,i,a,f,d) \ |
43 | nouveau_i2c_port_create_((p), (e), (o), (i), (a), \ | 43 | nouveau_i2c_port_create_((p), (e), (o), (i), (a), (f), \ |
44 | sizeof(**d), (void **)d) | 44 | sizeof(**d), (void **)d) |
45 | #define nouveau_i2c_port_destroy(p) ({ \ | 45 | #define nouveau_i2c_port_destroy(p) ({ \ |
46 | struct nouveau_i2c_port *port = (p); \ | 46 | struct nouveau_i2c_port *port = (p); \ |
@@ -53,7 +53,9 @@ struct nouveau_i2c_func { | |||
53 | 53 | ||
54 | int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, | 54 | int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, |
55 | struct nouveau_oclass *, u8, | 55 | struct nouveau_oclass *, u8, |
56 | const struct i2c_algorithm *, int, void **); | 56 | const struct i2c_algorithm *, |
57 | const struct nouveau_i2c_func *, | ||
58 | int, void **); | ||
57 | void _nouveau_i2c_port_dtor(struct nouveau_object *); | 59 | void _nouveau_i2c_port_dtor(struct nouveau_object *); |
58 | #define _nouveau_i2c_port_init nouveau_object_init | 60 | #define _nouveau_i2c_port_init nouveau_object_init |
59 | #define _nouveau_i2c_port_fini nouveau_object_fini | 61 | #define _nouveau_i2c_port_fini nouveau_object_fini |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h index 9d2cd2006250..ce6569f365a7 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/mc.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/mc.h | |||
@@ -12,6 +12,7 @@ struct nouveau_mc_intr { | |||
12 | struct nouveau_mc { | 12 | struct nouveau_mc { |
13 | struct nouveau_subdev base; | 13 | struct nouveau_subdev base; |
14 | const struct nouveau_mc_intr *intr_map; | 14 | const struct nouveau_mc_intr *intr_map; |
15 | bool use_msi; | ||
15 | }; | 16 | }; |
16 | 17 | ||
17 | static inline struct nouveau_mc * | 18 | static inline struct nouveau_mc * |
diff --git a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h index e465d158d352..9ab70dfe5b02 100644 --- a/drivers/gpu/drm/nouveau/core/include/subdev/timer.h +++ b/drivers/gpu/drm/nouveau/core/include/subdev/timer.h | |||
@@ -22,6 +22,7 @@ bool nouveau_timer_wait_eq(void *, u64 nsec, u32 addr, u32 mask, u32 data); | |||
22 | bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); | 22 | bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); |
23 | bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); | 23 | bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); |
24 | void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); | 24 | void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); |
25 | void nouveau_timer_alarm_cancel(void *, struct nouveau_alarm *); | ||
25 | 26 | ||
26 | #define NV_WAIT_DEFAULT 2000000000ULL | 27 | #define NV_WAIT_DEFAULT 2000000000ULL |
27 | #define nv_wait(o,a,m,v) \ | 28 | #define nv_wait(o,a,m,v) \ |
@@ -35,6 +36,7 @@ struct nouveau_timer { | |||
35 | struct nouveau_subdev base; | 36 | struct nouveau_subdev base; |
36 | u64 (*read)(struct nouveau_timer *); | 37 | u64 (*read)(struct nouveau_timer *); |
37 | void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *); | 38 | void (*alarm)(struct nouveau_timer *, u64 time, struct nouveau_alarm *); |
39 | void (*alarm_cancel)(struct nouveau_timer *, struct nouveau_alarm *); | ||
38 | }; | 40 | }; |
39 | 41 | ||
40 | static inline struct nouveau_timer * | 42 | static inline struct nouveau_timer * |
diff --git a/drivers/gpu/drm/nouveau/core/os.h b/drivers/gpu/drm/nouveau/core/os.h index 3bd9be2ab37f..191e739f30d1 100644 --- a/drivers/gpu/drm/nouveau/core/os.h +++ b/drivers/gpu/drm/nouveau/core/os.h | |||
@@ -13,11 +13,13 @@ | |||
13 | #include <linux/i2c-algo-bit.h> | 13 | #include <linux/i2c-algo-bit.h> |
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/io-mapping.h> | 15 | #include <linux/io-mapping.h> |
16 | #include <linux/vmalloc.h> | ||
17 | #include <linux/acpi.h> | 16 | #include <linux/acpi.h> |
17 | #include <linux/vmalloc.h> | ||
18 | #include <linux/dmi.h> | 18 | #include <linux/dmi.h> |
19 | #include <linux/reboot.h> | 19 | #include <linux/reboot.h> |
20 | #include <linux/interrupt.h> | 20 | #include <linux/interrupt.h> |
21 | #include <linux/log2.h> | ||
22 | #include <linux/pm_runtime.h> | ||
21 | 23 | ||
22 | #include <asm/unaligned.h> | 24 | #include <asm/unaligned.h> |
23 | 25 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c index 22a20573ed1b..22ac6dbd6c8f 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c +++ b/drivers/gpu/drm/nouveau/core/subdev/bios/therm.c | |||
@@ -184,7 +184,8 @@ nvbios_therm_fan_parse(struct nouveau_bios *bios, | |||
184 | cur_trip->fan_duty = value; | 184 | cur_trip->fan_duty = value; |
185 | break; | 185 | break; |
186 | case 0x26: | 186 | case 0x26: |
187 | fan->pwm_freq = value; | 187 | if (!fan->pwm_freq) |
188 | fan->pwm_freq = value; | ||
188 | break; | 189 | break; |
189 | case 0x3b: | 190 | case 0x3b: |
190 | fan->bump_period = value; | 191 | fan->bump_period = value; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c index dec94e9d776a..4b195ac4da66 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c | |||
@@ -118,7 +118,8 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent, | |||
118 | int ret; | 118 | int ret; |
119 | 119 | ||
120 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 120 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
121 | &nouveau_i2c_aux_algo, &chan); | 121 | &nouveau_i2c_aux_algo, &anx9805_aux_func, |
122 | &chan); | ||
122 | *pobject = nv_object(chan); | 123 | *pobject = nv_object(chan); |
123 | if (ret) | 124 | if (ret) |
124 | return ret; | 125 | return ret; |
@@ -140,8 +141,6 @@ anx9805_aux_chan_ctor(struct nouveau_object *parent, | |||
140 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; | 141 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; |
141 | algo->udelay = max(algo->udelay, 40); | 142 | algo->udelay = max(algo->udelay, 40); |
142 | } | 143 | } |
143 | |||
144 | chan->base.func = &anx9805_aux_func; | ||
145 | return 0; | 144 | return 0; |
146 | } | 145 | } |
147 | 146 | ||
@@ -234,7 +233,8 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent, | |||
234 | int ret; | 233 | int ret; |
235 | 234 | ||
236 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 235 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
237 | &anx9805_i2c_algo, &port); | 236 | &anx9805_i2c_algo, &anx9805_i2c_func, |
237 | &port); | ||
238 | *pobject = nv_object(port); | 238 | *pobject = nv_object(port); |
239 | if (ret) | 239 | if (ret) |
240 | return ret; | 240 | return ret; |
@@ -256,8 +256,6 @@ anx9805_ddc_port_ctor(struct nouveau_object *parent, | |||
256 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; | 256 | struct i2c_algo_bit_data *algo = mast->adapter.algo_data; |
257 | algo->udelay = max(algo->udelay, 40); | 257 | algo->udelay = max(algo->udelay, 40); |
258 | } | 258 | } |
259 | |||
260 | port->base.func = &anx9805_i2c_func; | ||
261 | return 0; | 259 | return 0; |
262 | } | 260 | } |
263 | 261 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c index 8ae2625415e1..2895c19bb152 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/base.c | |||
@@ -95,6 +95,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent, | |||
95 | struct nouveau_object *engine, | 95 | struct nouveau_object *engine, |
96 | struct nouveau_oclass *oclass, u8 index, | 96 | struct nouveau_oclass *oclass, u8 index, |
97 | const struct i2c_algorithm *algo, | 97 | const struct i2c_algorithm *algo, |
98 | const struct nouveau_i2c_func *func, | ||
98 | int size, void **pobject) | 99 | int size, void **pobject) |
99 | { | 100 | { |
100 | struct nouveau_device *device = nv_device(parent); | 101 | struct nouveau_device *device = nv_device(parent); |
@@ -112,6 +113,7 @@ nouveau_i2c_port_create_(struct nouveau_object *parent, | |||
112 | port->adapter.owner = THIS_MODULE; | 113 | port->adapter.owner = THIS_MODULE; |
113 | port->adapter.dev.parent = &device->pdev->dev; | 114 | port->adapter.dev.parent = &device->pdev->dev; |
114 | port->index = index; | 115 | port->index = index; |
116 | port->func = func; | ||
115 | i2c_set_adapdata(&port->adapter, i2c); | 117 | i2c_set_adapdata(&port->adapter, i2c); |
116 | 118 | ||
117 | if ( algo == &nouveau_i2c_bit_algo && | 119 | if ( algo == &nouveau_i2c_bit_algo && |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c index 2ad18840fe63..860d5d2365da 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c | |||
@@ -91,12 +91,12 @@ nv04_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
91 | int ret; | 91 | int ret; |
92 | 92 | ||
93 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 93 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
94 | &nouveau_i2c_bit_algo, &port); | 94 | &nouveau_i2c_bit_algo, &nv04_i2c_func, |
95 | &port); | ||
95 | *pobject = nv_object(port); | 96 | *pobject = nv_object(port); |
96 | if (ret) | 97 | if (ret) |
97 | return ret; | 98 | return ret; |
98 | 99 | ||
99 | port->base.func = &nv04_i2c_func; | ||
100 | port->drive = info->drive; | 100 | port->drive = info->drive; |
101 | port->sense = info->sense; | 101 | port->sense = info->sense; |
102 | return 0; | 102 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c index f501ae25dbb3..0c2655a03bb4 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c | |||
@@ -84,12 +84,12 @@ nv4e_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
84 | int ret; | 84 | int ret; |
85 | 85 | ||
86 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 86 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
87 | &nouveau_i2c_bit_algo, &port); | 87 | &nouveau_i2c_bit_algo, &nv4e_i2c_func, |
88 | &port); | ||
88 | *pobject = nv_object(port); | 89 | *pobject = nv_object(port); |
89 | if (ret) | 90 | if (ret) |
90 | return ret; | 91 | return ret; |
91 | 92 | ||
92 | port->base.func = &nv4e_i2c_func; | ||
93 | port->addr = 0x600800 + info->drive; | 93 | port->addr = 0x600800 + info->drive; |
94 | return 0; | 94 | return 0; |
95 | } | 95 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c index 378dfa324e5f..a8d67a287704 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c | |||
@@ -85,7 +85,8 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
85 | int ret; | 85 | int ret; |
86 | 86 | ||
87 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 87 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
88 | &nouveau_i2c_bit_algo, &port); | 88 | &nouveau_i2c_bit_algo, &nv50_i2c_func, |
89 | &port); | ||
89 | *pobject = nv_object(port); | 90 | *pobject = nv_object(port); |
90 | if (ret) | 91 | if (ret) |
91 | return ret; | 92 | return ret; |
@@ -93,7 +94,6 @@ nv50_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
93 | if (info->drive >= nv50_i2c_addr_nr) | 94 | if (info->drive >= nv50_i2c_addr_nr) |
94 | return -EINVAL; | 95 | return -EINVAL; |
95 | 96 | ||
96 | port->base.func = &nv50_i2c_func; | ||
97 | port->state = 0x00000007; | 97 | port->state = 0x00000007; |
98 | port->addr = nv50_i2c_addr[info->drive]; | 98 | port->addr = nv50_i2c_addr[info->drive]; |
99 | return 0; | 99 | return 0; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c index 61b771670bfe..df6d3e4b68be 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c | |||
@@ -186,7 +186,8 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
186 | int ret; | 186 | int ret; |
187 | 187 | ||
188 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 188 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
189 | &nouveau_i2c_bit_algo, &port); | 189 | &nouveau_i2c_bit_algo, &nv94_i2c_func, |
190 | &port); | ||
190 | *pobject = nv_object(port); | 191 | *pobject = nv_object(port); |
191 | if (ret) | 192 | if (ret) |
192 | return ret; | 193 | return ret; |
@@ -194,7 +195,6 @@ nv94_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
194 | if (info->drive >= nv50_i2c_addr_nr) | 195 | if (info->drive >= nv50_i2c_addr_nr) |
195 | return -EINVAL; | 196 | return -EINVAL; |
196 | 197 | ||
197 | port->base.func = &nv94_i2c_func; | ||
198 | port->state = 7; | 198 | port->state = 7; |
199 | port->addr = nv50_i2c_addr[info->drive]; | 199 | port->addr = nv50_i2c_addr[info->drive]; |
200 | if (info->share != DCB_I2C_UNUSED) { | 200 | if (info->share != DCB_I2C_UNUSED) { |
@@ -221,12 +221,12 @@ nv94_aux_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
221 | int ret; | 221 | int ret; |
222 | 222 | ||
223 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 223 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
224 | &nouveau_i2c_aux_algo, &port); | 224 | &nouveau_i2c_aux_algo, &nv94_aux_func, |
225 | &port); | ||
225 | *pobject = nv_object(port); | 226 | *pobject = nv_object(port); |
226 | if (ret) | 227 | if (ret) |
227 | return ret; | 228 | return ret; |
228 | 229 | ||
229 | port->base.func = &nv94_aux_func; | ||
230 | port->addr = info->drive; | 230 | port->addr = info->drive; |
231 | if (info->share != DCB_I2C_UNUSED) { | 231 | if (info->share != DCB_I2C_UNUSED) { |
232 | port->ctrl = 0x00e500 + (info->drive * 0x50); | 232 | port->ctrl = 0x00e500 + (info->drive * 0x50); |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c index f761b8a610f1..29967d30f97c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c +++ b/drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c | |||
@@ -60,12 +60,12 @@ nvd0_i2c_port_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
60 | int ret; | 60 | int ret; |
61 | 61 | ||
62 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, | 62 | ret = nouveau_i2c_port_create(parent, engine, oclass, index, |
63 | &nouveau_i2c_bit_algo, &port); | 63 | &nouveau_i2c_bit_algo, &nvd0_i2c_func, |
64 | &port); | ||
64 | *pobject = nv_object(port); | 65 | *pobject = nv_object(port); |
65 | if (ret) | 66 | if (ret) |
66 | return ret; | 67 | return ret; |
67 | 68 | ||
68 | port->base.func = &nvd0_i2c_func; | ||
69 | port->state = 0x00000007; | 69 | port->state = 0x00000007; |
70 | port->addr = 0x00d014 + (info->drive * 0x20); | 70 | port->addr = 0x00d014 + (info->drive * 0x20); |
71 | if (info->share != DCB_I2C_UNUSED) { | 71 | if (info->share != DCB_I2C_UNUSED) { |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c index 716bf41bc3c1..b10a143787a7 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c +++ b/drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c | |||
@@ -22,15 +22,9 @@ | |||
22 | * Authors: Ben Skeggs | 22 | * Authors: Ben Skeggs |
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include "nv04.h" | 25 | #include <engine/graph/nv40.h> |
26 | 26 | ||
27 | static inline int | 27 | #include "nv04.h" |
28 | nv44_graph_class(struct nv04_instmem_priv *priv) | ||
29 | { | ||
30 | if ((nv_device(priv)->chipset & 0xf0) == 0x60) | ||
31 | return 1; | ||
32 | return !(0x0baf & (1 << (nv_device(priv)->chipset & 0x0f))); | ||
33 | } | ||
34 | 28 | ||
35 | static int | 29 | static int |
36 | nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | 30 | nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c index 20f9a538746e..37712a6df923 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/base.c | |||
@@ -23,7 +23,7 @@ | |||
23 | */ | 23 | */ |
24 | 24 | ||
25 | #include <subdev/mc.h> | 25 | #include <subdev/mc.h> |
26 | #include <linux/pm_runtime.h> | 26 | #include <core/option.h> |
27 | 27 | ||
28 | static irqreturn_t | 28 | static irqreturn_t |
29 | nouveau_mc_intr(int irq, void *arg) | 29 | nouveau_mc_intr(int irq, void *arg) |
@@ -47,6 +47,9 @@ nouveau_mc_intr(int irq, void *arg) | |||
47 | map++; | 47 | map++; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (pmc->use_msi) | ||
51 | nv_wr08(pmc->base.base.parent, 0x00088068, 0xff); | ||
52 | |||
50 | if (intr) { | 53 | if (intr) { |
51 | nv_error(pmc, "unknown intr 0x%08x\n", stat); | 54 | nv_error(pmc, "unknown intr 0x%08x\n", stat); |
52 | } | 55 | } |
@@ -81,6 +84,8 @@ _nouveau_mc_dtor(struct nouveau_object *object) | |||
81 | struct nouveau_device *device = nv_device(object); | 84 | struct nouveau_device *device = nv_device(object); |
82 | struct nouveau_mc *pmc = (void *)object; | 85 | struct nouveau_mc *pmc = (void *)object; |
83 | free_irq(device->pdev->irq, pmc); | 86 | free_irq(device->pdev->irq, pmc); |
87 | if (pmc->use_msi) | ||
88 | pci_disable_msi(device->pdev); | ||
84 | nouveau_subdev_destroy(&pmc->base); | 89 | nouveau_subdev_destroy(&pmc->base); |
85 | } | 90 | } |
86 | 91 | ||
@@ -102,6 +107,23 @@ nouveau_mc_create_(struct nouveau_object *parent, struct nouveau_object *engine, | |||
102 | 107 | ||
103 | pmc->intr_map = intr_map; | 108 | pmc->intr_map = intr_map; |
104 | 109 | ||
110 | switch (device->pdev->device & 0x0ff0) { | ||
111 | case 0x00f0: /* BR02? */ | ||
112 | case 0x02e0: /* BR02? */ | ||
113 | pmc->use_msi = false; | ||
114 | break; | ||
115 | default: | ||
116 | pmc->use_msi = nouveau_boolopt(device->cfgopt, "NvMSI", true); | ||
117 | if (pmc->use_msi) { | ||
118 | pmc->use_msi = pci_enable_msi(device->pdev) == 0; | ||
119 | if (pmc->use_msi) { | ||
120 | nv_info(pmc, "MSI interrupts enabled\n"); | ||
121 | nv_wr08(device, 0x00088068, 0xff); | ||
122 | } | ||
123 | } | ||
124 | break; | ||
125 | } | ||
126 | |||
105 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, | 127 | ret = request_irq(device->pdev->irq, nouveau_mc_intr, |
106 | IRQF_SHARED, "nouveau", pmc); | 128 | IRQF_SHARED, "nouveau", pmc); |
107 | if (ret < 0) | 129 | if (ret < 0) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c index 0d57b4d3e001..06710419a59b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c +++ b/drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c | |||
@@ -35,6 +35,7 @@ nv98_mc_intr[] = { | |||
35 | { 0x00001000, NVDEV_ENGINE_GR }, | 35 | { 0x00001000, NVDEV_ENGINE_GR }, |
36 | { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ | 36 | { 0x00004000, NVDEV_ENGINE_CRYPT }, /* NV84:NVA3 */ |
37 | { 0x00008000, NVDEV_ENGINE_BSP }, | 37 | { 0x00008000, NVDEV_ENGINE_BSP }, |
38 | { 0x00020000, NVDEV_ENGINE_VP }, | ||
38 | { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ | 39 | { 0x00080000, NVDEV_SUBDEV_THERM }, /* NVA3:NVC0 */ |
39 | { 0x00100000, NVDEV_SUBDEV_TIMER }, | 40 | { 0x00100000, NVDEV_SUBDEV_TIMER }, |
40 | { 0x00200000, NVDEV_SUBDEV_GPIO }, | 41 | { 0x00200000, NVDEV_SUBDEV_GPIO }, |
@@ -42,7 +43,7 @@ nv98_mc_intr[] = { | |||
42 | { 0x04000000, NVDEV_ENGINE_DISP }, | 43 | { 0x04000000, NVDEV_ENGINE_DISP }, |
43 | { 0x10000000, NVDEV_SUBDEV_BUS }, | 44 | { 0x10000000, NVDEV_SUBDEV_BUS }, |
44 | { 0x80000000, NVDEV_ENGINE_SW }, | 45 | { 0x80000000, NVDEV_ENGINE_SW }, |
45 | { 0x0040d101, NVDEV_SUBDEV_FB }, | 46 | { 0x0042d101, NVDEV_SUBDEV_FB }, |
46 | {}, | 47 | {}, |
47 | }; | 48 | }; |
48 | 49 | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c index a00a5a76e2d6..f1de7a9c572b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/base.c | |||
@@ -95,12 +95,14 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
95 | int duty; | 95 | int duty; |
96 | 96 | ||
97 | spin_lock_irqsave(&priv->lock, flags); | 97 | spin_lock_irqsave(&priv->lock, flags); |
98 | nv_debug(therm, "FAN speed check\n"); | ||
98 | if (mode < 0) | 99 | if (mode < 0) |
99 | mode = priv->mode; | 100 | mode = priv->mode; |
100 | priv->mode = mode; | 101 | priv->mode = mode; |
101 | 102 | ||
102 | switch (mode) { | 103 | switch (mode) { |
103 | case NOUVEAU_THERM_CTRL_MANUAL: | 104 | case NOUVEAU_THERM_CTRL_MANUAL: |
105 | ptimer->alarm_cancel(ptimer, &priv->alarm); | ||
104 | duty = nouveau_therm_fan_get(therm); | 106 | duty = nouveau_therm_fan_get(therm); |
105 | if (duty < 0) | 107 | if (duty < 0) |
106 | duty = 100; | 108 | duty = 100; |
@@ -113,6 +115,7 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
113 | break; | 115 | break; |
114 | case NOUVEAU_THERM_CTRL_NONE: | 116 | case NOUVEAU_THERM_CTRL_NONE: |
115 | default: | 117 | default: |
118 | ptimer->alarm_cancel(ptimer, &priv->alarm); | ||
116 | goto done; | 119 | goto done; |
117 | } | 120 | } |
118 | 121 | ||
@@ -122,6 +125,8 @@ nouveau_therm_update(struct nouveau_therm *therm, int mode) | |||
122 | done: | 125 | done: |
123 | if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) | 126 | if (list_empty(&priv->alarm.head) && (mode == NOUVEAU_THERM_CTRL_AUTO)) |
124 | ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); | 127 | ptimer->alarm(ptimer, 1000000000ULL, &priv->alarm); |
128 | else if (!list_empty(&priv->alarm.head)) | ||
129 | nv_debug(therm, "therm fan alarm list is not empty\n"); | ||
125 | spin_unlock_irqrestore(&priv->lock, flags); | 130 | spin_unlock_irqrestore(&priv->lock, flags); |
126 | } | 131 | } |
127 | 132 | ||
@@ -267,9 +272,15 @@ _nouveau_therm_init(struct nouveau_object *object) | |||
267 | if (ret) | 272 | if (ret) |
268 | return ret; | 273 | return ret; |
269 | 274 | ||
270 | if (priv->suspend >= 0) | 275 | if (priv->suspend >= 0) { |
271 | nouveau_therm_fan_mode(therm, priv->mode); | 276 | /* restore the pwm value only when on manual or auto mode */ |
272 | priv->sensor.program_alarms(therm); | 277 | if (priv->suspend > 0) |
278 | nouveau_therm_fan_set(therm, true, priv->fan->percent); | ||
279 | |||
280 | nouveau_therm_fan_mode(therm, priv->suspend); | ||
281 | } | ||
282 | nouveau_therm_sensor_init(therm); | ||
283 | nouveau_therm_fan_init(therm); | ||
273 | return 0; | 284 | return 0; |
274 | } | 285 | } |
275 | 286 | ||
@@ -279,6 +290,8 @@ _nouveau_therm_fini(struct nouveau_object *object, bool suspend) | |||
279 | struct nouveau_therm *therm = (void *)object; | 290 | struct nouveau_therm *therm = (void *)object; |
280 | struct nouveau_therm_priv *priv = (void *)therm; | 291 | struct nouveau_therm_priv *priv = (void *)therm; |
281 | 292 | ||
293 | nouveau_therm_fan_fini(therm, suspend); | ||
294 | nouveau_therm_sensor_fini(therm, suspend); | ||
282 | if (suspend) { | 295 | if (suspend) { |
283 | priv->suspend = priv->mode; | 296 | priv->suspend = priv->mode; |
284 | priv->mode = NOUVEAU_THERM_CTRL_NONE; | 297 | priv->mode = NOUVEAU_THERM_CTRL_NONE; |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c index c728380d3d62..39f47b950ad1 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/fan.c | |||
@@ -204,6 +204,23 @@ nouveau_therm_fan_safety_checks(struct nouveau_therm *therm) | |||
204 | } | 204 | } |
205 | 205 | ||
206 | int | 206 | int |
207 | nouveau_therm_fan_init(struct nouveau_therm *therm) | ||
208 | { | ||
209 | return 0; | ||
210 | } | ||
211 | |||
212 | int | ||
213 | nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend) | ||
214 | { | ||
215 | struct nouveau_therm_priv *priv = (void *)therm; | ||
216 | struct nouveau_timer *ptimer = nouveau_timer(therm); | ||
217 | |||
218 | if (suspend) | ||
219 | ptimer->alarm_cancel(ptimer, &priv->fan->alarm); | ||
220 | return 0; | ||
221 | } | ||
222 | |||
223 | int | ||
207 | nouveau_therm_fan_ctor(struct nouveau_therm *therm) | 224 | nouveau_therm_fan_ctor(struct nouveau_therm *therm) |
208 | { | 225 | { |
209 | struct nouveau_therm_priv *priv = (void *)therm; | 226 | struct nouveau_therm_priv *priv = (void *)therm; |
@@ -234,6 +251,9 @@ nouveau_therm_fan_ctor(struct nouveau_therm *therm) | |||
234 | 251 | ||
235 | nv_info(therm, "FAN control: %s\n", priv->fan->type); | 252 | nv_info(therm, "FAN control: %s\n", priv->fan->type); |
236 | 253 | ||
254 | /* read the current speed, it is useful when resuming */ | ||
255 | priv->fan->percent = nouveau_therm_fan_get(therm); | ||
256 | |||
237 | /* attempt to detect a tachometer connection */ | 257 | /* attempt to detect a tachometer connection */ |
238 | ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); | 258 | ret = gpio->find(gpio, 0, DCB_GPIO_FAN_SENSE, 0xff, &priv->fan->tach); |
239 | if (ret) | 259 | if (ret) |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h index 15ca64e481f1..dd38529262fb 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/priv.h | |||
@@ -113,6 +113,8 @@ void nouveau_therm_ic_ctor(struct nouveau_therm *therm); | |||
113 | int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); | 113 | int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); |
114 | 114 | ||
115 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); | 115 | int nouveau_therm_fan_ctor(struct nouveau_therm *therm); |
116 | int nouveau_therm_fan_init(struct nouveau_therm *therm); | ||
117 | int nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend); | ||
116 | int nouveau_therm_fan_get(struct nouveau_therm *therm); | 118 | int nouveau_therm_fan_get(struct nouveau_therm *therm); |
117 | int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); | 119 | int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); |
118 | int nouveau_therm_fan_user_get(struct nouveau_therm *therm); | 120 | int nouveau_therm_fan_user_get(struct nouveau_therm *therm); |
@@ -122,6 +124,8 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm); | |||
122 | 124 | ||
123 | int nouveau_therm_preinit(struct nouveau_therm *); | 125 | int nouveau_therm_preinit(struct nouveau_therm *); |
124 | 126 | ||
127 | int nouveau_therm_sensor_init(struct nouveau_therm *therm); | ||
128 | int nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend); | ||
125 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); | 129 | void nouveau_therm_sensor_preinit(struct nouveau_therm *); |
126 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, | 130 | void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, |
127 | enum nouveau_therm_thrs thrs, | 131 | enum nouveau_therm_thrs thrs, |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c index dde746c78c8a..b80a33011b93 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c +++ b/drivers/gpu/drm/nouveau/core/subdev/therm/temp.c | |||
@@ -180,6 +180,8 @@ alarm_timer_callback(struct nouveau_alarm *alarm) | |||
180 | 180 | ||
181 | spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); | 181 | spin_lock_irqsave(&priv->sensor.alarm_program_lock, flags); |
182 | 182 | ||
183 | nv_debug(therm, "polling the internal temperature\n"); | ||
184 | |||
183 | nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, | 185 | nouveau_therm_threshold_hyst_polling(therm, &sensor->thrs_fan_boost, |
184 | NOUVEAU_THERM_THRS_FANBOOST); | 186 | NOUVEAU_THERM_THRS_FANBOOST); |
185 | 187 | ||
@@ -216,6 +218,25 @@ nouveau_therm_program_alarms_polling(struct nouveau_therm *therm) | |||
216 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); | 218 | alarm_timer_callback(&priv->sensor.therm_poll_alarm); |
217 | } | 219 | } |
218 | 220 | ||
221 | int | ||
222 | nouveau_therm_sensor_init(struct nouveau_therm *therm) | ||
223 | { | ||
224 | struct nouveau_therm_priv *priv = (void *)therm; | ||
225 | priv->sensor.program_alarms(therm); | ||
226 | return 0; | ||
227 | } | ||
228 | |||
229 | int | ||
230 | nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend) | ||
231 | { | ||
232 | struct nouveau_therm_priv *priv = (void *)therm; | ||
233 | struct nouveau_timer *ptimer = nouveau_timer(therm); | ||
234 | |||
235 | if (suspend) | ||
236 | ptimer->alarm_cancel(ptimer, &priv->sensor.therm_poll_alarm); | ||
237 | return 0; | ||
238 | } | ||
239 | |||
219 | void | 240 | void |
220 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) | 241 | nouveau_therm_sensor_preinit(struct nouveau_therm *therm) |
221 | { | 242 | { |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c index 5d417cc9949b..cf8a0e0f8ee3 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/base.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/base.c | |||
@@ -85,3 +85,10 @@ nouveau_timer_alarm(void *obj, u32 nsec, struct nouveau_alarm *alarm) | |||
85 | struct nouveau_timer *ptimer = nouveau_timer(obj); | 85 | struct nouveau_timer *ptimer = nouveau_timer(obj); |
86 | ptimer->alarm(ptimer, nsec, alarm); | 86 | ptimer->alarm(ptimer, nsec, alarm); |
87 | } | 87 | } |
88 | |||
89 | void | ||
90 | nouveau_timer_alarm_cancel(void *obj, struct nouveau_alarm *alarm) | ||
91 | { | ||
92 | struct nouveau_timer *ptimer = nouveau_timer(obj); | ||
93 | ptimer->alarm_cancel(ptimer, alarm); | ||
94 | } | ||
diff --git a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c index 9469b8275675..57711ecb566c 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c +++ b/drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c | |||
@@ -36,6 +36,7 @@ struct nv04_timer_priv { | |||
36 | struct nouveau_timer base; | 36 | struct nouveau_timer base; |
37 | struct list_head alarms; | 37 | struct list_head alarms; |
38 | spinlock_t lock; | 38 | spinlock_t lock; |
39 | u64 suspend_time; | ||
39 | }; | 40 | }; |
40 | 41 | ||
41 | static u64 | 42 | static u64 |
@@ -113,6 +114,25 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time, | |||
113 | } | 114 | } |
114 | 115 | ||
115 | static void | 116 | static void |
117 | nv04_timer_alarm_cancel(struct nouveau_timer *ptimer, | ||
118 | struct nouveau_alarm *alarm) | ||
119 | { | ||
120 | struct nv04_timer_priv *priv = (void *)ptimer; | ||
121 | unsigned long flags; | ||
122 | |||
123 | /* avoid deleting an entry while the alarm intr is running */ | ||
124 | spin_lock_irqsave(&priv->lock, flags); | ||
125 | |||
126 | /* delete the alarm from the list */ | ||
127 | list_del(&alarm->head); | ||
128 | |||
129 | /* reset the head so as list_empty returns 1 */ | ||
130 | INIT_LIST_HEAD(&alarm->head); | ||
131 | |||
132 | spin_unlock_irqrestore(&priv->lock, flags); | ||
133 | } | ||
134 | |||
135 | static void | ||
116 | nv04_timer_intr(struct nouveau_subdev *subdev) | 136 | nv04_timer_intr(struct nouveau_subdev *subdev) |
117 | { | 137 | { |
118 | struct nv04_timer_priv *priv = (void *)subdev; | 138 | struct nv04_timer_priv *priv = (void *)subdev; |
@@ -146,6 +166,8 @@ nv04_timer_ctor(struct nouveau_object *parent, struct nouveau_object *engine, | |||
146 | priv->base.base.intr = nv04_timer_intr; | 166 | priv->base.base.intr = nv04_timer_intr; |
147 | priv->base.read = nv04_timer_read; | 167 | priv->base.read = nv04_timer_read; |
148 | priv->base.alarm = nv04_timer_alarm; | 168 | priv->base.alarm = nv04_timer_alarm; |
169 | priv->base.alarm_cancel = nv04_timer_alarm_cancel; | ||
170 | priv->suspend_time = 0; | ||
149 | 171 | ||
150 | INIT_LIST_HEAD(&priv->alarms); | 172 | INIT_LIST_HEAD(&priv->alarms); |
151 | spin_lock_init(&priv->lock); | 173 | spin_lock_init(&priv->lock); |
@@ -164,7 +186,7 @@ nv04_timer_init(struct nouveau_object *object) | |||
164 | { | 186 | { |
165 | struct nouveau_device *device = nv_device(object); | 187 | struct nouveau_device *device = nv_device(object); |
166 | struct nv04_timer_priv *priv = (void *)object; | 188 | struct nv04_timer_priv *priv = (void *)object; |
167 | u32 m = 1, f, n, d; | 189 | u32 m = 1, f, n, d, lo, hi; |
168 | int ret; | 190 | int ret; |
169 | 191 | ||
170 | ret = nouveau_timer_init(&priv->base); | 192 | ret = nouveau_timer_init(&priv->base); |
@@ -221,16 +243,25 @@ nv04_timer_init(struct nouveau_object *object) | |||
221 | d >>= 1; | 243 | d >>= 1; |
222 | } | 244 | } |
223 | 245 | ||
246 | /* restore the time before suspend */ | ||
247 | lo = priv->suspend_time; | ||
248 | hi = (priv->suspend_time >> 32); | ||
249 | |||
224 | nv_debug(priv, "input frequency : %dHz\n", f); | 250 | nv_debug(priv, "input frequency : %dHz\n", f); |
225 | nv_debug(priv, "input multiplier: %d\n", m); | 251 | nv_debug(priv, "input multiplier: %d\n", m); |
226 | nv_debug(priv, "numerator : 0x%08x\n", n); | 252 | nv_debug(priv, "numerator : 0x%08x\n", n); |
227 | nv_debug(priv, "denominator : 0x%08x\n", d); | 253 | nv_debug(priv, "denominator : 0x%08x\n", d); |
228 | nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); | 254 | nv_debug(priv, "timer frequency : %dHz\n", (f * m) * d / n); |
255 | nv_debug(priv, "time low : 0x%08x\n", lo); | ||
256 | nv_debug(priv, "time high : 0x%08x\n", hi); | ||
229 | 257 | ||
230 | nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); | 258 | nv_wr32(priv, NV04_PTIMER_NUMERATOR, n); |
231 | nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); | 259 | nv_wr32(priv, NV04_PTIMER_DENOMINATOR, d); |
232 | nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); | 260 | nv_wr32(priv, NV04_PTIMER_INTR_0, 0xffffffff); |
233 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); | 261 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); |
262 | nv_wr32(priv, NV04_PTIMER_TIME_1, hi); | ||
263 | nv_wr32(priv, NV04_PTIMER_TIME_0, lo); | ||
264 | |||
234 | return 0; | 265 | return 0; |
235 | } | 266 | } |
236 | 267 | ||
@@ -238,6 +269,8 @@ static int | |||
238 | nv04_timer_fini(struct nouveau_object *object, bool suspend) | 269 | nv04_timer_fini(struct nouveau_object *object, bool suspend) |
239 | { | 270 | { |
240 | struct nv04_timer_priv *priv = (void *)object; | 271 | struct nv04_timer_priv *priv = (void *)object; |
272 | if (suspend) | ||
273 | priv->suspend_time = nv04_timer_read(&priv->base); | ||
241 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); | 274 | nv_wr32(priv, NV04_PTIMER_INTR_EN_0, 0x00000000); |
242 | return nouveau_timer_fini(&priv->base, suspend); | 275 | return nouveau_timer_fini(&priv->base, suspend); |
243 | } | 276 | } |
diff --git a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c index 07dd1fe2d6fb..a4aa81a2173b 100644 --- a/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c +++ b/drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c | |||
@@ -174,6 +174,7 @@ nv50_vm_flush(struct nouveau_vm *vm) | |||
174 | case NVDEV_ENGINE_GR : vme = 0x00; break; | 174 | case NVDEV_ENGINE_GR : vme = 0x00; break; |
175 | case NVDEV_ENGINE_VP : vme = 0x01; break; | 175 | case NVDEV_ENGINE_VP : vme = 0x01; break; |
176 | case NVDEV_SUBDEV_BAR : vme = 0x06; break; | 176 | case NVDEV_SUBDEV_BAR : vme = 0x06; break; |
177 | case NVDEV_ENGINE_PPP : | ||
177 | case NVDEV_ENGINE_MPEG : vme = 0x08; break; | 178 | case NVDEV_ENGINE_MPEG : vme = 0x08; break; |
178 | case NVDEV_ENGINE_BSP : vme = 0x09; break; | 179 | case NVDEV_ENGINE_BSP : vme = 0x09; break; |
179 | case NVDEV_ENGINE_CRYPT: vme = 0x0a; break; | 180 | case NVDEV_ENGINE_CRYPT: vme = 0x0a; break; |
diff --git a/drivers/gpu/drm/nouveau/nouveau_display.c b/drivers/gpu/drm/nouveau/nouveau_display.c index 77ffded68837..d2712e6e5d31 100644 --- a/drivers/gpu/drm/nouveau/nouveau_display.c +++ b/drivers/gpu/drm/nouveau/nouveau_display.c | |||
@@ -107,6 +107,11 @@ nouveau_framebuffer_init(struct drm_device *dev, | |||
107 | return -EINVAL; | 107 | return -EINVAL; |
108 | } | 108 | } |
109 | 109 | ||
110 | if (nvbo->tile_flags & NOUVEAU_GEM_TILE_NONCONTIG) { | ||
111 | NV_ERROR(drm, "framebuffer requires contiguous bo\n"); | ||
112 | return -EINVAL; | ||
113 | } | ||
114 | |||
110 | if (nv_device(drm->device)->chipset == 0x50) | 115 | if (nv_device(drm->device)->chipset == 0x50) |
111 | nv_fb->r_format |= (tile_flags << 8); | 116 | nv_fb->r_format |= (tile_flags << 8); |
112 | 117 | ||
diff --git a/drivers/gpu/drm/nouveau/nouveau_gem.c b/drivers/gpu/drm/nouveau/nouveau_gem.c index 487242fb3fdc..f32b71238c03 100644 --- a/drivers/gpu/drm/nouveau/nouveau_gem.c +++ b/drivers/gpu/drm/nouveau/nouveau_gem.c | |||
@@ -579,18 +579,31 @@ nouveau_gem_pushbuf_validate(struct nouveau_channel *chan, | |||
579 | return 0; | 579 | return 0; |
580 | } | 580 | } |
581 | 581 | ||
582 | static inline void | ||
583 | u_free(void *addr) | ||
584 | { | ||
585 | if (!is_vmalloc_addr(addr)) | ||
586 | kfree(addr); | ||
587 | else | ||
588 | vfree(addr); | ||
589 | } | ||
590 | |||
582 | static inline void * | 591 | static inline void * |
583 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) | 592 | u_memcpya(uint64_t user, unsigned nmemb, unsigned size) |
584 | { | 593 | { |
585 | void *mem; | 594 | void *mem; |
586 | void __user *userptr = (void __force __user *)(uintptr_t)user; | 595 | void __user *userptr = (void __force __user *)(uintptr_t)user; |
587 | 596 | ||
588 | mem = kmalloc(nmemb * size, GFP_KERNEL); | 597 | size *= nmemb; |
598 | |||
599 | mem = kmalloc(size, GFP_KERNEL | __GFP_NOWARN); | ||
600 | if (!mem) | ||
601 | mem = vmalloc(size); | ||
589 | if (!mem) | 602 | if (!mem) |
590 | return ERR_PTR(-ENOMEM); | 603 | return ERR_PTR(-ENOMEM); |
591 | 604 | ||
592 | if (DRM_COPY_FROM_USER(mem, userptr, nmemb * size)) { | 605 | if (DRM_COPY_FROM_USER(mem, userptr, size)) { |
593 | kfree(mem); | 606 | u_free(mem); |
594 | return ERR_PTR(-EFAULT); | 607 | return ERR_PTR(-EFAULT); |
595 | } | 608 | } |
596 | 609 | ||
@@ -676,7 +689,7 @@ nouveau_gem_pushbuf_reloc_apply(struct nouveau_cli *cli, | |||
676 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); | 689 | nouveau_bo_wr32(nvbo, r->reloc_bo_offset >> 2, data); |
677 | } | 690 | } |
678 | 691 | ||
679 | kfree(reloc); | 692 | u_free(reloc); |
680 | return ret; | 693 | return ret; |
681 | } | 694 | } |
682 | 695 | ||
@@ -738,7 +751,7 @@ nouveau_gem_ioctl_pushbuf(struct drm_device *dev, void *data, | |||
738 | 751 | ||
739 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); | 752 | bo = u_memcpya(req->buffers, req->nr_buffers, sizeof(*bo)); |
740 | if (IS_ERR(bo)) { | 753 | if (IS_ERR(bo)) { |
741 | kfree(push); | 754 | u_free(push); |
742 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); | 755 | return nouveau_abi16_put(abi16, PTR_ERR(bo)); |
743 | } | 756 | } |
744 | 757 | ||
@@ -849,8 +862,8 @@ out: | |||
849 | nouveau_fence_unref(&fence); | 862 | nouveau_fence_unref(&fence); |
850 | 863 | ||
851 | out_prevalid: | 864 | out_prevalid: |
852 | kfree(bo); | 865 | u_free(bo); |
853 | kfree(push); | 866 | u_free(push); |
854 | 867 | ||
855 | out_next: | 868 | out_next: |
856 | if (chan->dma.ib_max) { | 869 | if (chan->dma.ib_max) { |
diff --git a/drivers/gpu/drm/nouveau/nv50_display.c b/drivers/gpu/drm/nouveau/nv50_display.c index 9d2092a5ed38..f8e66c08b11a 100644 --- a/drivers/gpu/drm/nouveau/nv50_display.c +++ b/drivers/gpu/drm/nouveau/nv50_display.c | |||
@@ -1583,7 +1583,7 @@ nv50_dac_detect(struct drm_encoder *encoder, struct drm_connector *connector) | |||
1583 | load = 340; | 1583 | load = 340; |
1584 | 1584 | ||
1585 | ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); | 1585 | ret = nv_exec(disp->core, NV50_DISP_DAC_LOAD + or, &load, sizeof(load)); |
1586 | if (ret || load != 7) | 1586 | if (ret || !load) |
1587 | return connector_status_disconnected; | 1587 | return connector_status_disconnected; |
1588 | 1588 | ||
1589 | return connector_status_connected; | 1589 | return connector_status_connected; |