Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 218229
b: refs/heads/master
c: 7760fcb
h: refs/heads/master
i:
  218227: 73af88a
v: v3
  • Loading branch information
Roy Spliet authored and Ben Skeggs committed Oct 4, 2010
1 parent ee0826e commit 38ee81c
Show file tree
Hide file tree
Showing 5 changed files with 170 additions and 2 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 5b32165b044f7d2486e2815456b1b2894aaab4ee
refs/heads/master: 7760fcb020b41352af4e675ce65a6aa0e93c170f
18 changes: 18 additions & 0 deletions trunk/drivers/gpu/drm/nouveau/nouveau_drv.h
Original file line number Diff line number Diff line change
Expand Up @@ -401,10 +401,28 @@ struct nouveau_pm_threshold_temp {
s16 fan_boost;
};

struct nouveau_pm_memtiming {
u32 reg_100220;
u32 reg_100224;
u32 reg_100228;
u32 reg_10022c;
u32 reg_100230;
u32 reg_100234;
u32 reg_100238;
u32 reg_10023c;
};

struct nouveau_pm_memtimings {
bool supported;
struct nouveau_pm_memtiming *timing;
int nr_timing;
};

struct nouveau_pm_engine {
struct nouveau_pm_voltage voltage;
struct nouveau_pm_level perflvl[NOUVEAU_PM_MAX_LEVEL];
int nr_perflvl;
struct nouveau_pm_memtimings memtimings;
struct nouveau_pm_temp_sensor_constants sensor_constants;
struct nouveau_pm_threshold_temp threshold_temp;

Expand Down
144 changes: 144 additions & 0 deletions trunk/drivers/gpu/drm/nouveau/nouveau_mem.c
Original file line number Diff line number Diff line change
Expand Up @@ -648,3 +648,147 @@ nouveau_mem_gart_init(struct drm_device *dev)
return 0;
}

void
nouveau_mem_timing_init(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nouveau_pm_memtimings *memtimings = &pm->memtimings;
struct nvbios *bios = &dev_priv->vbios;
struct bit_entry P;
u8 tUNK_0, tUNK_1, tUNK_2;
u8 tRP; /* Byte 3 */
u8 tRAS; /* Byte 5 */
u8 tRFC; /* Byte 7 */
u8 tRC; /* Byte 9 */
u8 tUNK_10, tUNK_11, tUNK_12, tUNK_13, tUNK_14;
u8 tUNK_18, tUNK_19, tUNK_20, tUNK_21;
u8 *mem = NULL, *entry;
int i, recordlen, entries;

if (bios->type == NVBIOS_BIT) {
if (bit_table(dev, 'P', &P))
return;

if (P.version == 1)
mem = ROMPTR(bios, P.data[4]);
else
if (P.version == 2)
mem = ROMPTR(bios, P.data[8]);
else {
NV_WARN(dev, "unknown mem for BIT P %d\n", P.version);
}
} else {
NV_DEBUG(dev, "BMP version too old for memory\n");
return;
}

if (!mem) {
NV_DEBUG(dev, "memory timing table pointer invalid\n");
return;
}

if (mem[0] != 0x10) {
NV_WARN(dev, "memory timing table 0x%02x unknown\n", mem[0]);
return;
}

/* validate record length */
entries = mem[2];
recordlen = mem[3];
if (recordlen < 15) {
NV_ERROR(dev, "mem timing table length unknown: %d\n", mem[3]);
return;
}

/* parse vbios entries into common format */
memtimings->timing =
kcalloc(entries, sizeof(*memtimings->timing), GFP_KERNEL);
if (!memtimings->timing)
return;

entry = mem + mem[1];
for (i = 0; i < entries; i++, entry += recordlen) {
struct nouveau_pm_memtiming *timing = &pm->memtimings.timing[i];
if (entry[0] == 0)
continue;

tUNK_18 = 1;
tUNK_19 = 1;
tUNK_20 = 0;
tUNK_21 = 0;
switch (recordlen) {
case 0x21:
tUNK_21 = entry[21];
case 0x20:
tUNK_20 = entry[20];
case 0x19:
tUNK_19 = entry[19];
case 0x18:
tUNK_18 = entry[18];
default:
tUNK_0 = entry[0];
tUNK_1 = entry[1];
tUNK_2 = entry[2];
tRP = entry[3];
tRAS = entry[5];
tRFC = entry[7];
tRC = entry[9];
tUNK_10 = entry[10];
tUNK_11 = entry[11];
tUNK_12 = entry[12];
tUNK_13 = entry[13];
tUNK_14 = entry[14];
break;
}

timing->reg_100220 = (tRC << 24 | tRFC << 16 | tRAS << 8 | tRP);

/* XXX: I don't trust the -1's and +1's... they must come
* from somewhere! */
timing->reg_100224 = ((tUNK_0 + tUNK_19 + 1) << 24 |
tUNK_18 << 16 |
(tUNK_1 + tUNK_19 + 1) << 8 |
(tUNK_2 - 1));

timing->reg_100228 = (tUNK_12 << 16 | tUNK_11 << 8 | tUNK_10);
if(recordlen > 19) {
timing->reg_100228 += (tUNK_19 - 1) << 24;
} else {
timing->reg_100228 += tUNK_12 << 24;
}

/* XXX: reg_10022c */

timing->reg_100230 = (tUNK_20 << 24 | tUNK_21 << 16 |
tUNK_13 << 8 | tUNK_13);

/* XXX: +6? */
timing->reg_100234 = (tRAS << 24 | (tUNK_19 + 6) << 8 | tRC);
if(tUNK_10 > tUNK_11) {
timing->reg_100234 += tUNK_10 << 16;
} else {
timing->reg_100234 += tUNK_11 << 16;
}

/* XXX; reg_100238, reg_10023c */
NV_DEBUG(dev, "Entry %d: 220: %08x %08x %08x %08x\n", i,
timing->reg_100220, timing->reg_100224,
timing->reg_100228, timing->reg_10022c);
NV_DEBUG(dev, " 230: %08x %08x %08x %08x\n",
timing->reg_100230, timing->reg_100234,
timing->reg_100238, timing->reg_10023c);
}

memtimings->nr_timing = entries;
memtimings->supported = true;
}

void
nouveau_mem_timing_fini(struct drm_device *dev)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_memtimings *mem = &dev_priv->engine.pm.memtimings;

kfree(mem->timing);
}
4 changes: 3 additions & 1 deletion trunk/drivers/gpu/drm/nouveau/nouveau_pm.c
Original file line number Diff line number Diff line change
Expand Up @@ -451,6 +451,7 @@ nouveau_pm_init(struct drm_device *dev)
nouveau_volt_init(dev);
nouveau_perf_init(dev);
nouveau_temp_init(dev);
nouveau_mem_timing_init(dev);

NV_INFO(dev, "%d available performance level(s)\n", pm->nr_perflvl);
for (i = 0; i < pm->nr_perflvl; i++) {
Expand Down Expand Up @@ -491,9 +492,10 @@ nouveau_pm_fini(struct drm_device *dev)
if (pm->cur != &pm->boot)
nouveau_pm_perflvl_set(dev, &pm->boot);

nouveau_mem_timing_fini(dev);
nouveau_temp_fini(dev);
nouveau_perf_fini(dev);
nouveau_volt_fini(dev);
nouveau_temp_fini(dev);

nouveau_hwmon_fini(dev);
nouveau_sysfs_fini(dev);
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/gpu/drm/nouveau/nouveau_pm.h
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,10 @@ int nouveau_voltage_gpio_set(struct drm_device *, int voltage);
void nouveau_perf_init(struct drm_device *);
void nouveau_perf_fini(struct drm_device *);

/* nouveau_mem.c */
void nouveau_mem_timing_init(struct drm_device *);
void nouveau_mem_timing_fini(struct drm_device *);

/* nv04_pm.c */
int nv04_pm_clock_get(struct drm_device *, u32 id);
void *nv04_pm_clock_pre(struct drm_device *, u32 id, int khz);
Expand Down

0 comments on commit 38ee81c

Please sign in to comment.