aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/gpu/drm/nouveau/core/core/ramht.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/bsp/nv98.c52
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/dacnv50.c15
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/disp/nv50.c34
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv50.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nv84.c5
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nvc0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/fifo/nve0.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/graph/nv40.h3
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/ppp/nv98.c52
-rw-r--r--drivers/gpu/drm/nouveau/core/engine/vp/nv98.c47
-rw-r--r--drivers/gpu/drm/nouveau/core/include/core/math.h16
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/i2c.h8
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/mc.h1
-rw-r--r--drivers/gpu/drm/nouveau/core/include/subdev/timer.h2
-rw-r--r--drivers/gpu/drm/nouveau/core/os.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/bios/therm.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/anx9805.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/base.c2
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv04.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv4e.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv50.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nv94.c8
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/i2c/nvd0.c4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/instmem/nv40.c10
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/base.c24
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/mc/nv98.c3
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/base.c19
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/fan.c20
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/priv.h4
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/therm/temp.c21
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/base.c7
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/timer/nv04.c35
-rw-r--r--drivers/gpu/drm/nouveau/core/subdev/vm/nv50.c1
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_display.c5
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_gem.c27
-rw-r--r--drivers/gpu/drm/nouveau/nv50_display.c2
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
30struct nv98_bsp_priv { 28struct 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
38static struct nouveau_oclass 36static struct nouveau_oclass
39nv98_bsp_sclass[] = { 37nv98_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
47static struct nouveau_oclass 48static struct nouveau_oclass
48nv98_bsp_cclass = { 49nv98_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
64static int 65static int
66nv98_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
80static int
65nv98_bsp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 81nv98_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
49nv50_dac_sense(struct nv50_disp_priv *priv, int or, u32 loadval) 49nv50_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
66int 71int
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
31struct nv98_ppp_priv { 28struct nv98_ppp_priv {
32 struct nouveau_engine base; 29 struct nouveau_falcon base;
33};
34
35struct nv98_ppp_chan {
36 struct nouveau_engctx base;
37}; 30};
38 31
39/******************************************************************************* 32/*******************************************************************************
@@ -42,6 +35,8 @@ struct nv98_ppp_chan {
42 35
43static struct nouveau_oclass 36static struct nouveau_oclass
44nv98_ppp_sclass[] = { 37nv98_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
53nv98_ppp_cclass = { 48nv98_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
69static int 64static int
65nv98_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
79static int
70nv98_ppp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 80nv98_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
30struct nv98_vp_priv { 28struct 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
38static struct nouveau_oclass 36static struct nouveau_oclass
39nv98_vp_sclass[] = { 37nv98_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
48nv98_vp_cclass = { 48nv98_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
64static int 64static int
65nv98_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
79static int
65nv98_vp_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 80nv98_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
4static inline int
5log2i(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
54int nouveau_i2c_port_create_(struct nouveau_object *, struct nouveau_object *, 54int 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 **);
57void _nouveau_i2c_port_dtor(struct nouveau_object *); 59void _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 {
12struct nouveau_mc { 12struct 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
17static inline struct nouveau_mc * 18static 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);
22bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data); 22bool nouveau_timer_wait_ne(void *, u64 nsec, u32 addr, u32 mask, u32 data);
23bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data); 23bool nouveau_timer_wait_cb(void *, u64 nsec, bool (*func)(void *), void *data);
24void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *); 24void nouveau_timer_alarm(void *, u32 nsec, struct nouveau_alarm *);
25void 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
40static inline struct nouveau_timer * 42static 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
27static inline int 27#include "nv04.h"
28nv44_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
35static int 29static int
36nv40_instmem_ctor(struct nouveau_object *parent, struct nouveau_object *engine, 30nv40_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
28static irqreturn_t 28static irqreturn_t
29nouveau_mc_intr(int irq, void *arg) 29nouveau_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)
122done: 125done:
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
206int 206int
207nouveau_therm_fan_init(struct nouveau_therm *therm)
208{
209 return 0;
210}
211
212int
213nouveau_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
223int
207nouveau_therm_fan_ctor(struct nouveau_therm *therm) 224nouveau_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);
113int nouveau_therm_sensor_ctor(struct nouveau_therm *therm); 113int nouveau_therm_sensor_ctor(struct nouveau_therm *therm);
114 114
115int nouveau_therm_fan_ctor(struct nouveau_therm *therm); 115int nouveau_therm_fan_ctor(struct nouveau_therm *therm);
116int nouveau_therm_fan_init(struct nouveau_therm *therm);
117int nouveau_therm_fan_fini(struct nouveau_therm *therm, bool suspend);
116int nouveau_therm_fan_get(struct nouveau_therm *therm); 118int nouveau_therm_fan_get(struct nouveau_therm *therm);
117int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent); 119int nouveau_therm_fan_set(struct nouveau_therm *therm, bool now, int percent);
118int nouveau_therm_fan_user_get(struct nouveau_therm *therm); 120int nouveau_therm_fan_user_get(struct nouveau_therm *therm);
@@ -122,6 +124,8 @@ int nouveau_therm_fan_sense(struct nouveau_therm *therm);
122 124
123int nouveau_therm_preinit(struct nouveau_therm *); 125int nouveau_therm_preinit(struct nouveau_therm *);
124 126
127int nouveau_therm_sensor_init(struct nouveau_therm *therm);
128int nouveau_therm_sensor_fini(struct nouveau_therm *therm, bool suspend);
125void nouveau_therm_sensor_preinit(struct nouveau_therm *); 129void nouveau_therm_sensor_preinit(struct nouveau_therm *);
126void nouveau_therm_sensor_set_threshold_state(struct nouveau_therm *therm, 130void 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
221int
222nouveau_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
229int
230nouveau_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
219void 240void
220nouveau_therm_sensor_preinit(struct nouveau_therm *therm) 241nouveau_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
89void
90nouveau_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
41static u64 42static u64
@@ -113,6 +114,25 @@ nv04_timer_alarm(struct nouveau_timer *ptimer, u64 time,
113} 114}
114 115
115static void 116static void
117nv04_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
135static void
116nv04_timer_intr(struct nouveau_subdev *subdev) 136nv04_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
238nv04_timer_fini(struct nouveau_object *object, bool suspend) 269nv04_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
582static inline void
583u_free(void *addr)
584{
585 if (!is_vmalloc_addr(addr))
586 kfree(addr);
587 else
588 vfree(addr);
589}
590
582static inline void * 591static inline void *
583u_memcpya(uint64_t user, unsigned nmemb, unsigned size) 592u_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
851out_prevalid: 864out_prevalid:
852 kfree(bo); 865 u_free(bo);
853 kfree(push); 866 u_free(push);
854 867
855out_next: 868out_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;