Re: [Nouveau] [PATCH 2/2] drm/nouveau/nv50: reclock memory using PMS on nv50
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
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
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
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
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
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) {