Re: [Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-05-07 Thread Maxim Levitsky
Just my 0.2 cent, here are PMS scripts executed by the blob (270.41.06)
with slightly better formatting (script attached)
This is trace from bare Xorg start on my NV86.


-- 
Best regards,
Maxim Levitsky

Visit my blog: http://maximlevitsky.wordpress.com
Warning: Above blog contains rants.
script1:

: e2 17 01 10 00 data 0x100117
0005: e0 0c a8 61 00 addr 0x61a80c
000a: 00 ???
000b: 40 0c a8   addr 0x61a80c
000e: 05 ??? [unknown: 05]
000f: e2 00 00 00 00 data 0
0014: 40 0c a8   addr 0x61a80c
0017: 7f exit


script2:

: e2 a7 00 10 00 data 0x1000a7
0005: e0 0c a0 61 00 addr 0x61a00c
000a: 00 ???
000b: 40 0c a0   addr 0x61a00c
000e: 05 ??? [unknown: 05]
000f: e2 00 00 00 00 data 0
0014: 40 0c a0   addr 0x61a00c
0017: 7f exit


script3:

: e2 00 33 00 00 data 0x3300
0005: e0 00 12 61 00 addr 0x611200
000a: 42 01 00   data 0x1
000d: e0 04 25 00 00 addr 0x2504
0012: 07 ??? [unknown: 07]
0013: b0 ??? [unknown: b0]
0014: 5f 00 01   unk5f [unknown: 00 00 01]
0017: e0 d4 02 10 00 addr 0x1002d4
001c: 40 d0 02   addr 0x1002d0
001f: 40 d0 02   addr 0x1002d0
0022: 42 00 00   data 0
0025: 40 10 02   addr 0x100210
0028: 42 01 00   data 0x1
002b: 40 dc 02   addr 0x1002dc
002e: 42 05 25   data 0x2505
0031: e0 0c 40 00 00 addr 0x400c
0036: e2 00 e4 59 80 data 0x8059e400
003b: 40 08 40   addr 0x4008
003e: 0d ??? [unknown: 0d]
003f: 0a ??? [unknown: 0a]
0040: 40 08 40   addr 0x4008
0043: e2 00 00 00 00 data 0
0048: e0 dc 02 10 00 addr 0x1002dc
004d: e2 00 00 00 80 data 0x8000
0052: 40 10 02   addr 0x100210
0055: 07 ??? [unknown: 07]
0056: e2 62 0a 00 00 data 0xa62
005b: 40 c0 02   addr 0x1002c0
005e: e2 04 09 01 0c data 0xc010904
0063: 40 24 02   addr 0x100224
0066: e2 18 2a 12 06 data 0x6122a18
006b: 40 20 02   addr 0x100220
006e: e2 62 0b 00 00 data 0xb62
0073: 40 c0 02   addr 0x1002c0
0076: 42 62 0a   data 0xa62
0079: 40 c0 02   addr 0x1002c0
007c: 0b ??? [unknown: 0b]
007d: d0 ??? [unknown: d0]
007e: 5f 00 00   unk5f
0081: 42 30 33   data 0x3330
0084: e0 00 12 61 00 addr 0x611200
0089: 7f exit
008a: 7f exit
008b: 7f exit


script4:
little bug here--

: 0a ??? [unknown: 0a]
0001: 7f exit
0002: e2 00 33 00 00 data 0x3300
0007: e0 00 12 61 00 addr 0x611200
000c: 42 01 00   data 0x1
000f: e0 04 25 00 00 addr 0x2504
0014: 07 ??? [unknown: 07]
0015: b0 ??? [unknown: b0]
0016: 5f 00 01   unk5f [unknown: 00 00 01]
0019: e0 d4 02 10 00 addr 0x1002d4
001e: 40 d0 02   addr 0x1002d0
0021: 40 d0 02   addr 0x1002d0
0024: 42 00 00   data 0
0027: 40 10 02   addr 0x100210
002a: 42 01 00   data 0x1
002d: 40 dc 02   addr 0x1002dc
0030: 42 05 25   data 0x2505
0033: e0 0c 40 00 00 addr 0x400c
0038: e2 00 e4 59 80 data 0x8059e400
003d: 40 08 40   addr 0x4008
0040: 0d ??? [unknown: 0d]
0041: 0a ??? [unknown: 0a]
0042: 40 08 40   addr 0x4008
0045: e2 00 00 00 00 data 0
004a: e0 dc 02 10 00 addr 0x1002dc
004f: e2 00 00 00 80 data 0x8000
0054: 40 10 02   addr 0x100210
0057: 07 ??? [unknown: 07]
0058: e2 62 0a 00 00 data 0xa62
005d: 40 c0 02   addr 0x1002c0
0060: e2 04 09 01 0c data 0xc010904
0065: 40 24 02   addr 0x100224
0068: e2 18 2a 12 06 data 0x6122a18
006d: 40 20 02   addr 0x100220
0070: e2 62 0b 00 00 data 0xb62
0075: 40 c0 02   addr 0x1002c0
0078: 42 62 0a   data 0xa62
007b: 40 c0 02   addr 0x1002c0
007e: 0b ??? [unknown: 0b]
007f: d0 ??? [unknown: d0]
0080: 5f 00 00   unk5f
0083: 42 30 33   data 0x3330
0086: e0 00 12 61 00 addr 0x611200
008b: 7f exit



script5:

: 0a ??? [unknown: 0a]
0001: 00 ???
0002: e2 00 ?? ?? ?? data 0 [incomplete]


script6:

: e2 00 33 00 00 data 0x3300
0005: e0 00 12 61 00 addr 0x611200
000a: 07 

Re: [Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-05-06 Thread Emil Velikov

On Sat, 30 Apr 2011 01:17:13 +0100, Martin Peres martin.pe...@free.fr wrote:


From: Martin Peres martin.pe...@ensi-bourges.fr

v2: Reclock memory after reclocking the other engines

Signed-off-by: Martin Peres martin.pe...@ensi-bourges.fr
---
 drivers/gpu/drm/nouveau/nouveau_pm.c  |   11 +--
 drivers/gpu/drm/nouveau/nouveau_pms.h |   98 +
 drivers/gpu/drm/nouveau/nv50_pm.c |  153 ++---
 3 files changed, 242 insertions(+), 20 deletions(-)
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pms.h

diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c 
b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 88f58b1..44d01bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -45,10 +45,6 @@ nouveau_pm_clock_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl,
if (khz == 0)
return 0;
-   /* Do no reclock the memory if the frequencies didn't change */
-   if (id == PLL_MEMORY  pm-cur-memory == khz)
-   return 0;
-
pre_state = pm-clock_pre(dev, perflvl, id, khz);
if (IS_ERR(pre_state))
return PTR_ERR(pre_state);
@@ -100,7 +96,6 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl-core);
nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl-shader);
-   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl-unk05);
/* Decrease the voltage if needed*/
@@ -110,11 +105,13 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
/* Wait for PLLs to stabilize */
udelay(100);
+   pm-unpause(dev);
+
+   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
+
pm-cur = perflvl;
ret = 0;
-   pm-unpause(dev);
-
NV_DEBUG(dev, Reclocking took %lluns\n,
 (nv04_timer_read(dev) - start));
diff --git a/drivers/gpu/drm/nouveau/nouveau_pms.h 
b/drivers/gpu/drm/nouveau/nouveau_pms.h
new file mode 100644
index 000..d7a445b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_pms.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the Software),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifndef __NOUVEAU_PMS_H__
+#define __NOUVEAU_PMS_H__
+
+struct pms_ucode {
+   u8 data[256];
+   union {
+   u8  *u08;
+   u16 *u16;
+   u32 *u32;
+   } ptr;
+   u16 len;
+
+   u32 reg;
+   u32 val;
+};
+
+static inline void
+pms_init(struct pms_ucode *pms)
+{
+   pms-ptr.u08 = pms-data;
+   pms-reg = 0x;
+   pms-val = 0x;
+}
+
+static inline void
+pms_fini(struct pms_ucode *pms)
+{
+   do {
+   *pms-ptr.u08++ = 0x7f;
+   pms-len = pms-ptr.u08 - pms-data;
+   } while (pms-len  3);
+   pms-ptr.u08 = pms-data;
+}
+
+static inline void
+pms_unkn(struct pms_ucode *pms, u8 v0)
+{
+   *pms-ptr.u08++ = v0;
+}
+
+static inline void
+pms_op5f(struct pms_ucode *pms, u8 v0, u8 v1)
+{
+   *pms-ptr.u08++ = 0x5f;
+   *pms-ptr.u08++ = v0;
+   *pms-ptr.u08++ = v1;
+}
+
+static inline void
+pms_wr32(struct pms_ucode *pms, u32 reg, u32 val)
+{
+   if (val != pms-val) {
+   if ((val  0x) == (pms-val  0x)) {
+   *pms-ptr.u08++ = 0x42;
+   *pms-ptr.u16++ = (val  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe2;
+   *pms-ptr.u32++ = val;
+   }
+
+   pms-val = val;
+   }
+
+   if ((reg  0x) == (pms-reg  0x)) {
+   *pms-ptr.u08++ = 0x40;
+   *pms-ptr.u16++ = (reg  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe0;
+ 

Re: [Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-05-06 Thread Martin Peres

Le 07/05/2011 01:42, Emil Velikov a écrit :
On Sat, 30 Apr 2011 01:17:13 +0100, Martin Peres 
martin.pe...@free.fr wrote:



From: Martin Peres martin.pe...@ensi-bourges.fr

v2: Reclock memory after reclocking the other engines

Signed-off-by: Martin Peres martin.pe...@ensi-bourges.fr
---
 drivers/gpu/drm/nouveau/nouveau_pm.c  |   11 +--
 drivers/gpu/drm/nouveau/nouveau_pms.h |   98 +
 drivers/gpu/drm/nouveau/nv50_pm.c |  153 
++---

 3 files changed, 242 insertions(+), 20 deletions(-)
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pms.h

diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c 
b/drivers/gpu/drm/nouveau/nouveau_pm.c

index 88f58b1..44d01bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -45,10 +45,6 @@ nouveau_pm_clock_set(struct drm_device *dev, 
struct nouveau_pm_level *perflvl,

 if (khz == 0)
 return 0;
-/* Do no reclock the memory if the frequencies didn't change */
-if (id == PLL_MEMORY  pm-cur-memory == khz)
-return 0;
-
 pre_state = pm-clock_pre(dev, perflvl, id, khz);
 if (IS_ERR(pre_state))
 return PTR_ERR(pre_state);
@@ -100,7 +96,6 @@ nouveau_pm_perflvl_set(struct drm_device *dev, 
struct nouveau_pm_level *perflvl)

nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl-core);
 nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl-shader);
-nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
 nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl-unk05);
/* Decrease the voltage if needed*/
@@ -110,11 +105,13 @@ nouveau_pm_perflvl_set(struct drm_device *dev, 
struct nouveau_pm_level *perflvl)

 /* Wait for PLLs to stabilize */
 udelay(100);
+pm-unpause(dev);
+
+nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
+
 pm-cur = perflvl;
 ret = 0;
-pm-unpause(dev);
-
 NV_DEBUG(dev, Reclocking took %lluns\n,
  (nv04_timer_read(dev) - start));
diff --git a/drivers/gpu/drm/nouveau/nouveau_pms.h 
b/drivers/gpu/drm/nouveau/nouveau_pms.h

new file mode 100644
index 000..d7a445b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_pms.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person 
obtaining a
+ * copy of this software and associated documentation files (the 
Software),
+ * to deal in the Software without restriction, including without 
limitation
+ * the rights to use, copy, modify, merge, publish, distribute, 
sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom 
the

+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be 
included in

+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, 
EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 
MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO 
EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, 
DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 
OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 
USE OR

+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifndef __NOUVEAU_PMS_H__
+#define __NOUVEAU_PMS_H__
+
+struct pms_ucode {
+u8 data[256];
+union {
+u8  *u08;
+u16 *u16;
+u32 *u32;
+} ptr;
+u16 len;
+
+u32 reg;
+u32 val;
+};
+
+static inline void
+pms_init(struct pms_ucode *pms)
+{
+pms-ptr.u08 = pms-data;
+pms-reg = 0x;
+pms-val = 0x;
+}
+
+static inline void
+pms_fini(struct pms_ucode *pms)
+{
+do {
+*pms-ptr.u08++ = 0x7f;
+pms-len = pms-ptr.u08 - pms-data;
+} while (pms-len  3);
+pms-ptr.u08 = pms-data;
+}
+
+static inline void
+pms_unkn(struct pms_ucode *pms, u8 v0)
+{
+*pms-ptr.u08++ = v0;
+}
+
+static inline void
+pms_op5f(struct pms_ucode *pms, u8 v0, u8 v1)
+{
+*pms-ptr.u08++ = 0x5f;
+*pms-ptr.u08++ = v0;
+*pms-ptr.u08++ = v1;
+}
+
+static inline void
+pms_wr32(struct pms_ucode *pms, u32 reg, u32 val)
+{
+if (val != pms-val) {
+if ((val  0x) == (pms-val  0x)) {
+*pms-ptr.u08++ = 0x42;
+*pms-ptr.u16++ = (val  0x);
+} else {
+*pms-ptr.u08++ = 0xe2;
+*pms-ptr.u32++ = val;
+}
+
+pms-val = val;
+}
+
+if ((reg  0x) == (pms-reg  0x)) {
+*pms-ptr.u08++ = 0x40;
+*pms-ptr.u16++ = (reg  0x);
+} else {
+*pms-ptr.u08++ = 0xe0;
+*pms-ptr.u32++ = reg;
+}
+pms-reg = reg;
+}
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c 
b/drivers/gpu/drm/nouveau/nv50_pm.c

index 4dd2d76..9b81f03 100644
--- 

[Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-04-29 Thread Martin Peres
From: Martin Peres martin.pe...@ensi-bourges.fr

v2: Reclock memory after reclocking the other engines

Signed-off-by: Martin Peres martin.pe...@ensi-bourges.fr
---
 drivers/gpu/drm/nouveau/nouveau_pm.c  |   11 +--
 drivers/gpu/drm/nouveau/nouveau_pms.h |   98 +
 drivers/gpu/drm/nouveau/nv50_pm.c |  153 ++---
 3 files changed, 242 insertions(+), 20 deletions(-)
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pms.h

diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c 
b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 88f58b1..44d01bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -45,10 +45,6 @@ nouveau_pm_clock_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl,
if (khz == 0)
return 0;
 
-   /* Do no reclock the memory if the frequencies didn't change */
-   if (id == PLL_MEMORY  pm-cur-memory == khz)
-   return 0;
-
pre_state = pm-clock_pre(dev, perflvl, id, khz);
if (IS_ERR(pre_state))
return PTR_ERR(pre_state);
@@ -100,7 +96,6 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
 
nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl-core);
nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl-shader);
-   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl-unk05);
 
/* Decrease the voltage if needed*/
@@ -110,11 +105,13 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
/* Wait for PLLs to stabilize */
udelay(100);
 
+   pm-unpause(dev);
+
+   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
+
pm-cur = perflvl;
ret = 0;
 
-   pm-unpause(dev);
-
NV_DEBUG(dev, Reclocking took %lluns\n,
 (nv04_timer_read(dev) - start));
 
diff --git a/drivers/gpu/drm/nouveau/nouveau_pms.h 
b/drivers/gpu/drm/nouveau/nouveau_pms.h
new file mode 100644
index 000..d7a445b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_pms.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the Software),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifndef __NOUVEAU_PMS_H__
+#define __NOUVEAU_PMS_H__
+
+struct pms_ucode {
+   u8 data[256];
+   union {
+   u8  *u08;
+   u16 *u16;
+   u32 *u32;
+   } ptr;
+   u16 len;
+
+   u32 reg;
+   u32 val;
+};
+
+static inline void
+pms_init(struct pms_ucode *pms)
+{
+   pms-ptr.u08 = pms-data;
+   pms-reg = 0x;
+   pms-val = 0x;
+}
+
+static inline void
+pms_fini(struct pms_ucode *pms)
+{
+   do {
+   *pms-ptr.u08++ = 0x7f;
+   pms-len = pms-ptr.u08 - pms-data;
+   } while (pms-len  3);
+   pms-ptr.u08 = pms-data;
+}
+
+static inline void
+pms_unkn(struct pms_ucode *pms, u8 v0)
+{
+   *pms-ptr.u08++ = v0;
+}
+
+static inline void
+pms_op5f(struct pms_ucode *pms, u8 v0, u8 v1)
+{
+   *pms-ptr.u08++ = 0x5f;
+   *pms-ptr.u08++ = v0;
+   *pms-ptr.u08++ = v1;
+}
+
+static inline void
+pms_wr32(struct pms_ucode *pms, u32 reg, u32 val)
+{
+   if (val != pms-val) {
+   if ((val  0x) == (pms-val  0x)) {
+   *pms-ptr.u08++ = 0x42;
+   *pms-ptr.u16++ = (val  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe2;
+   *pms-ptr.u32++ = val;
+   }
+
+   pms-val = val;
+   }
+
+   if ((reg  0x) == (pms-reg  0x)) {
+   *pms-ptr.u08++ = 0x40;
+   *pms-ptr.u16++ = (reg  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe0;
+   *pms-ptr.u32++ = reg;
+   }
+   pms-reg = 

[Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-04-28 Thread Martin Peres
From: Martin Peres martin.pe...@ensi-bourges.fr

v2: Reclock memory after reclocking the other engines

Signed-off-by: Martin Peres martin.pe...@ensi-bourges.fr
---
 drivers/gpu/drm/nouveau/nouveau_pm.c |   11 +--
 drivers/gpu/drm/nouveau/nv50_pm.c|  153 +++---
 2 files changed, 144 insertions(+), 20 deletions(-)

diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c 
b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 88f58b1..44d01bb 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -45,10 +45,6 @@ nouveau_pm_clock_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl,
if (khz == 0)
return 0;
 
-   /* Do no reclock the memory if the frequencies didn't change */
-   if (id == PLL_MEMORY  pm-cur-memory == khz)
-   return 0;
-
pre_state = pm-clock_pre(dev, perflvl, id, khz);
if (IS_ERR(pre_state))
return PTR_ERR(pre_state);
@@ -100,7 +96,6 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
 
nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl-core);
nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl-shader);
-   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl-unk05);
 
/* Decrease the voltage if needed*/
@@ -110,11 +105,13 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
/* Wait for PLLs to stabilize */
udelay(100);
 
+   pm-unpause(dev);
+
+   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
+
pm-cur = perflvl;
ret = 0;
 
-   pm-unpause(dev);
-
NV_DEBUG(dev, Reclocking took %lluns\n,
 (nv04_timer_read(dev) - start));
 
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c 
b/drivers/gpu/drm/nouveau/nv50_pm.c
index 4dd2d76..9b81f03 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -26,9 +26,11 @@
 #include nouveau_drv.h
 #include nouveau_bios.h
 #include nouveau_pm.h
+#include nouveau_pms.h
 
 struct nv50_pm_state {
struct nouveau_pm_level *perflvl;
+   struct pms_ucode ucode;
struct pll_lims pll;
enum pll_types type;
int N, M, P;
@@ -73,14 +75,20 @@ void *
 nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
  u32 id, int khz)
 {
+   struct drm_nouveau_private *dev_priv = dev-dev_private;
struct nv50_pm_state *state;
-   int dummy, ret;
+   struct pms_ucode *pms;
+   u32 reg0_old, reg0_new;
+   u32 crtc_mask;
+   u32 reg_c040;
+   int ret, dummy, i;
 
state = kzalloc(sizeof(*state), GFP_KERNEL);
if (!state)
return ERR_PTR(-ENOMEM);
state-type = id;
state-perflvl = perflvl;
+   pms = state-ucode;
 
ret = get_pll_limits(dev, id, state-pll);
if (ret  0) {
@@ -95,20 +103,88 @@ nv50_pm_clock_pre(struct drm_device *dev, struct 
nouveau_pm_level *perflvl,
return ERR_PTR(ret);
}
 
+   reg0_old = nv_rd32(dev, state-pll.reg + 0);
+   reg0_new = 0x8000 | (state-P  16) | (reg0_old  0xfff8);
+
+   reg_c040 = nv_rd32(dev, 0xc040);
+
+   crtc_mask = 0;
+   for (i = 0; i  2; i++) {
+   if (nv_rd32(dev, NV50_PDISPLAY_CRTC_C(i, CLOCK)))
+   crtc_mask |= (1  i);
+   }
+
+   pms_init(pms);
+
+   switch (state-type) {
+   case PLL_MEMORY:
+   /* Wait for vblank on all the CRTCs */
+   if (crtc_mask) {
+   pms_op5f(pms, crtc_mask, 0x00);
+   pms_op5f(pms, crtc_mask, 0x01);
+   }
+
+   pms_wr32(pms, 0x002504, 0x0001);
+   pms_unkn(pms, 0x06); /* unknown */
+   pms_unkn(pms, 0xb0); /* Disable bus access */
+   pms_op5f(pms, 0x00, 0x01);
+
+   pms_wr32(pms, 0x1002d4, 0x0001);
+   pms_wr32(pms, 0x1002d0, 0x0001);
+
+   pms_wr32(pms, 0x100210, 0x);
+   pms_wr32(pms, 0x1002dc, 0x0001);
+   pms_wr32(pms, state-pll.reg + 0, reg0_old);
+   pms_wr32(pms, state-pll.reg + 4, (state-N  8) | state-M);
+
+   pms_wr32(pms, state-pll.reg + 0, reg0_new);
+   pms_wr32(pms, 0x1002dc, 0x);
+   pms_wr32(pms, 0x100210, 0x8000);
+   pms_unkn(pms, 0x07); /* unknown */
+
+   pms_unkn(pms, 0x0b);
+   pms_unkn(pms, 0xd0); /* Enable bus access again */
+   pms_op5f(pms, 0x00, 0x01);
+   pms_wr32(pms, 0x002504, 0x);
+   break;
+   default:
+   pms_unkn(pms, 0xb0); /* Disable bus access */
+
+   pms_wr32(pms, 0xc040,
+   (reg_c040  ~(1  5 | 1  4)) | (1  

[Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50

2011-04-27 Thread Martin Peres
From: Martin Peres martin.pe...@ensi-bourges.fr

Signed-off-by: Martin Peres martin.pe...@ensi-bourges.fr
---
 drivers/gpu/drm/nouveau/nouveau_pm.c  |7 +-
 drivers/gpu/drm/nouveau/nouveau_pms.h |   98 +
 drivers/gpu/drm/nouveau/nv50_pm.c |  153 ++---
 3 files changed, 243 insertions(+), 15 deletions(-)
 create mode 100644 drivers/gpu/drm/nouveau/nouveau_pms.h

diff --git a/drivers/gpu/drm/nouveau/nouveau_pm.c 
b/drivers/gpu/drm/nouveau/nouveau_pm.c
index 3bffe60..abc0ef9 100644
--- a/drivers/gpu/drm/nouveau/nouveau_pm.c
+++ b/drivers/gpu/drm/nouveau/nouveau_pm.c
@@ -79,13 +79,16 @@ nouveau_pm_perflvl_set(struct drm_device *dev, struct 
nouveau_pm_level *perflvl)
}
}
 
+   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
+
ret = pm-pause(dev);
-   if (ret)
+   if (ret) {
+   nouveau_pm_clock_set(dev, pm-cur, PLL_MEMORY, perflvl-memory);
return ret;
+   }
 
nouveau_pm_clock_set(dev, perflvl, PLL_CORE, perflvl-core);
nouveau_pm_clock_set(dev, perflvl, PLL_SHADER, perflvl-shader);
-   nouveau_pm_clock_set(dev, perflvl, PLL_MEMORY, perflvl-memory);
nouveau_pm_clock_set(dev, perflvl, PLL_UNK05, perflvl-unk05);
 
/* Wait for PLLs to stabilize */
diff --git a/drivers/gpu/drm/nouveau/nouveau_pms.h 
b/drivers/gpu/drm/nouveau/nouveau_pms.h
new file mode 100644
index 000..d7a445b
--- /dev/null
+++ b/drivers/gpu/drm/nouveau/nouveau_pms.h
@@ -0,0 +1,98 @@
+/*
+ * Copyright 2010 Red Hat Inc.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the Software),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED AS IS, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ *
+ * Authors: Ben Skeggs
+ */
+
+#ifndef __NOUVEAU_PMS_H__
+#define __NOUVEAU_PMS_H__
+
+struct pms_ucode {
+   u8 data[256];
+   union {
+   u8  *u08;
+   u16 *u16;
+   u32 *u32;
+   } ptr;
+   u16 len;
+
+   u32 reg;
+   u32 val;
+};
+
+static inline void
+pms_init(struct pms_ucode *pms)
+{
+   pms-ptr.u08 = pms-data;
+   pms-reg = 0x;
+   pms-val = 0x;
+}
+
+static inline void
+pms_fini(struct pms_ucode *pms)
+{
+   do {
+   *pms-ptr.u08++ = 0x7f;
+   pms-len = pms-ptr.u08 - pms-data;
+   } while (pms-len  3);
+   pms-ptr.u08 = pms-data;
+}
+
+static inline void
+pms_unkn(struct pms_ucode *pms, u8 v0)
+{
+   *pms-ptr.u08++ = v0;
+}
+
+static inline void
+pms_op5f(struct pms_ucode *pms, u8 v0, u8 v1)
+{
+   *pms-ptr.u08++ = 0x5f;
+   *pms-ptr.u08++ = v0;
+   *pms-ptr.u08++ = v1;
+}
+
+static inline void
+pms_wr32(struct pms_ucode *pms, u32 reg, u32 val)
+{
+   if (val != pms-val) {
+   if ((val  0x) == (pms-val  0x)) {
+   *pms-ptr.u08++ = 0x42;
+   *pms-ptr.u16++ = (val  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe2;
+   *pms-ptr.u32++ = val;
+   }
+
+   pms-val = val;
+   }
+
+   if ((reg  0x) == (pms-reg  0x)) {
+   *pms-ptr.u08++ = 0x40;
+   *pms-ptr.u16++ = (reg  0x);
+   } else {
+   *pms-ptr.u08++ = 0xe0;
+   *pms-ptr.u32++ = reg;
+   }
+   pms-reg = reg;
+}
+
+#endif
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c 
b/drivers/gpu/drm/nouveau/nv50_pm.c
index 4dd2d76..9b81f03 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -26,9 +26,11 @@
 #include nouveau_drv.h
 #include nouveau_bios.h
 #include nouveau_pm.h
+#include nouveau_pms.h
 
 struct nv50_pm_state {
struct nouveau_pm_level *perflvl;
+   struct pms_ucode ucode;
struct pll_lims pll;
enum pll_types type;
int N, M, P;
@@ -73,14 +75,20 @@ void *
 nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
  u32 id, int khz)
 {