aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBen Skeggs <bskeggs@redhat.com>2010-09-27 10:13:23 +1000
committerBen Skeggs <bskeggs@redhat.com>2010-10-05 09:57:49 +1000
commitaee582de806c7008756df23aa444c8e7d58004a9 (patch)
tree375bf48a622d8732ddc4681dccc9fe71505bb73d
parent5c6dc6575460a0afe56d8cae7666e769e08ef942 (diff)
downloadkernel_samsung_smdk4412-aee582de806c7008756df23aa444c8e7d58004a9.zip
kernel_samsung_smdk4412-aee582de806c7008756df23aa444c8e7d58004a9.tar.gz
kernel_samsung_smdk4412-aee582de806c7008756df23aa444c8e7d58004a9.tar.bz2
drm/nouveau: run perflvl and M table scripts on mem clock change
Signed-off-by: Ben Skeggs <bskeggs@redhat.com>
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_drv.h2
-rw-r--r--drivers/gpu/drm/nouveau/nouveau_perf.c1
-rw-r--r--drivers/gpu/drm/nouveau/nv50_pm.c22
3 files changed, 25 insertions, 0 deletions
diff --git a/drivers/gpu/drm/nouveau/nouveau_drv.h b/drivers/gpu/drm/nouveau/nouveau_drv.h
index 01ee63a..ef74d40 100644
--- a/drivers/gpu/drm/nouveau/nouveau_drv.h
+++ b/drivers/gpu/drm/nouveau/nouveau_drv.h
@@ -385,6 +385,8 @@ struct nouveau_pm_level {
u8 voltage;
u8 fanspeed;
+
+ u16 memscript;
};
struct nouveau_pm_temp_sensor_constants {
diff --git a/drivers/gpu/drm/nouveau/nouveau_perf.c b/drivers/gpu/drm/nouveau/nouveau_perf.c
index 6b641b6..5a95be6 100644
--- a/drivers/gpu/drm/nouveau/nouveau_perf.c
+++ b/drivers/gpu/drm/nouveau/nouveau_perf.c
@@ -160,6 +160,7 @@ nouveau_perf_init(struct drm_device *dev)
perflvl->memory = ROM16(entry[12]) * 1000;
break;
case 0x30:
+ perflvl->memscript = ROM16(entry[2]);
case 0x35:
perflvl->fanspeed = entry[6];
perflvl->voltage = entry[7];
diff --git a/drivers/gpu/drm/nouveau/nv50_pm.c b/drivers/gpu/drm/nouveau/nv50_pm.c
index eaf69c8..2a9fabd 100644
--- a/drivers/gpu/drm/nouveau/nv50_pm.c
+++ b/drivers/gpu/drm/nouveau/nv50_pm.c
@@ -24,6 +24,7 @@
#include "drmP.h"
#include "nouveau_drv.h"
+#include "nouveau_bios.h"
#include "nouveau_pm.h"
/*XXX: boards using limits 0x40 need fixing, the register layout
@@ -33,6 +34,7 @@
*/
struct nv50_pm_state {
+ struct nouveau_pm_level *perflvl;
struct pll_lims pll;
enum pll_types type;
int N, M, P;
@@ -77,6 +79,7 @@ nv50_pm_clock_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl,
if (!state)
return ERR_PTR(-ENOMEM);
state->type = id;
+ state->perflvl = perflvl;
ret = get_pll_limits(dev, id, &state->pll);
if (ret < 0) {
@@ -98,11 +101,30 @@ void
nv50_pm_clock_set(struct drm_device *dev, void *pre_state)
{
struct nv50_pm_state *state = pre_state;
+ struct nouveau_pm_level *perflvl = state->perflvl;
u32 reg = state->pll.reg, tmp;
+ struct bit_entry BIT_M;
+ u16 script;
int N = state->N;
int M = state->M;
int P = state->P;
+ if (state->type == PLL_MEMORY && perflvl->memscript &&
+ bit_table(dev, 'M', &BIT_M) == 0 &&
+ BIT_M.version == 1 && BIT_M.length >= 0x0b) {
+ script = ROM16(BIT_M.data[0x05]);
+ if (script)
+ nouveau_bios_run_init_table(dev, script, NULL);
+ script = ROM16(BIT_M.data[0x07]);
+ if (script)
+ nouveau_bios_run_init_table(dev, script, NULL);
+ script = ROM16(BIT_M.data[0x09]);
+ if (script)
+ nouveau_bios_run_init_table(dev, script, NULL);
+
+ nouveau_bios_run_init_table(dev, perflvl->memscript, NULL);
+ }
+
if (state->pll.vco2.maxfreq) {
if (state->type == PLL_MEMORY) {
nv_wr32(dev, 0x100210, 0);