char name[32];
int id;
- u32 core;
u32 memory;
+ u16 memscript;
+ struct nouveau_pm_memtiming timing;
+
+ u32 core;
u32 shader;
u32 rop;
u32 copy;
u32 volt_min; /* microvolts */
u32 volt_max;
u8 fanspeed;
-
- u16 memscript;
- struct nouveau_pm_memtiming *timing;
};
struct nouveau_pm_temp_sensor_constants {
struct nouveau_pm_threshold_temp threshold_temp;
struct nouveau_pm_fan fan;
- struct nouveau_pm_memtiming boot_timing;
struct nouveau_pm_level boot;
struct nouveau_pm_level *cur;
extern int nouveau_mem_reset_agp(struct drm_device *);
extern void nouveau_mem_close(struct drm_device *);
extern bool nouveau_mem_flags_valid(struct drm_device *, u32 tile_flags);
+extern int nouveau_mem_timing_calc(struct drm_device *, u32 freq,
+ struct nouveau_pm_memtiming *);
extern void nouveau_mem_timing_read(struct drm_device *,
struct nouveau_pm_memtiming *);
-extern struct nouveau_pm_memtiming *
-nouveau_mem_timing(struct drm_device *, u32 freq);
extern int nouveau_mem_vbios_type(struct drm_device *);
extern struct nouveau_tile_reg *nv10_mem_set_tiling(
struct drm_device *dev, uint32_t addr, uint32_t size,
return 0;
}
-struct nouveau_pm_memtiming *
-nouveau_mem_timing(struct drm_device *dev, u32 freq)
+int
+nouveau_mem_timing_calc(struct drm_device *dev, u32 freq,
+ struct nouveau_pm_memtiming *t)
{
struct drm_nouveau_private *dev_priv = dev->dev_private;
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
- struct nouveau_pm_memtiming *boot = &pm->boot_timing;
- struct nouveau_pm_memtiming *t;
+ struct nouveau_pm_memtiming *boot = &pm->boot.timing;
struct nouveau_pm_tbl_entry *e;
u8 ver, len, *ptr;
int ret;
ptr = nouveau_perf_timing(dev, freq, &ver, &len);
- if (!ptr || ptr[0] == 0x00)
- return boot;
+ if (!ptr || ptr[0] == 0x00) {
+ *t = *boot;
+ return 0;
+ }
e = (struct nouveau_pm_tbl_entry *)ptr;
- t = kzalloc(sizeof(*t), GFP_KERNEL);
- if (t) {
- t->tCWL = boot->tCWL;
-
- switch (dev_priv->card_type) {
- case NV_40:
- ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t);
- break;
- case NV_50:
- ret = nv50_mem_timing_calc(dev, freq, e, len, boot, t);
- break;
- case NV_C0:
- ret = nvc0_mem_timing_calc(dev, freq, e, len, boot, t);
- break;
- default:
- ret = -ENODEV;
- break;
- }
+ t->tCWL = boot->tCWL;
- switch (dev_priv->vram_type * !ret) {
- case NV_MEM_TYPE_GDDR3:
- ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t);
- break;
- case NV_MEM_TYPE_GDDR5:
- ret = nouveau_mem_gddr5_mr(dev, freq, e, len, boot, t);
- break;
- case NV_MEM_TYPE_DDR2:
- ret = nouveau_mem_ddr2_mr(dev, freq, e, len, boot, t);
- break;
- case NV_MEM_TYPE_DDR3:
- ret = nouveau_mem_ddr3_mr(dev, freq, e, len, boot, t);
- break;
- }
+ switch (dev_priv->card_type) {
+ case NV_40:
+ ret = nv40_mem_timing_calc(dev, freq, e, len, boot, t);
+ break;
+ case NV_50:
+ ret = nv50_mem_timing_calc(dev, freq, e, len, boot, t);
+ break;
+ case NV_C0:
+ ret = nvc0_mem_timing_calc(dev, freq, e, len, boot, t);
+ break;
+ default:
+ ret = -ENODEV;
+ break;
+ }
- if (ret) {
- kfree(t);
- t = NULL;
- }
+ switch (dev_priv->vram_type * !ret) {
+ case NV_MEM_TYPE_GDDR3:
+ ret = nouveau_mem_gddr3_mr(dev, freq, e, len, boot, t);
+ break;
+ case NV_MEM_TYPE_GDDR5:
+ ret = nouveau_mem_gddr5_mr(dev, freq, e, len, boot, t);
+ break;
+ case NV_MEM_TYPE_DDR2:
+ ret = nouveau_mem_ddr2_mr(dev, freq, e, len, boot, t);
+ break;
+ case NV_MEM_TYPE_DDR3:
+ ret = nouveau_mem_ddr3_mr(dev, freq, e, len, boot, t);
+ break;
+ default:
+ ret = -EINVAL;
}
- return t;
+ return ret;
}
void
struct nouveau_pm_engine *pm = &dev_priv->engine.pm;
struct nvbios *bios = &dev_priv->vbios;
u8 *perf, ver, hdr, cnt, len;
- int vid, i = -1;
+ int ret, vid, i = -1;
if (bios->type == NVBIOS_BMP && bios->data[bios->offset + 6] < 0x25) {
legacy_perf_init(dev);
}
/* get the corresponding memory timings */
- perflvl->timing = nouveau_mem_timing(dev, perflvl->memory);
+ ret = nouveau_mem_timing_calc(dev, perflvl->memory,
+ &perflvl->timing);
+ if (ret) {
+ NV_DEBUG(dev, "perflvl %d, bad timing: %d\n", i, ret);
+ continue;
+ }
snprintf(perflvl->name, sizeof(perflvl->name),
"performance_level_%d", i);
static void
nouveau_pm_perflvl_info(struct nouveau_pm_level *perflvl, char *ptr, int len)
{
- char c[16], s[16], v[32], f[16], t[16], m[16];
+ char c[16], s[16], v[32], f[16], m[16];
c[0] = '\0';
if (perflvl->core)
if (perflvl->fanspeed)
snprintf(f, sizeof(f), " fanspeed %d%%", perflvl->fanspeed);
- t[0] = '\0';
- if (perflvl->timing)
- snprintf(t, sizeof(t), " timing %d", perflvl->timing->id);
-
- snprintf(ptr, len, "%s%s%s%s%s%s\n", c, s, m, t, v, f);
+ snprintf(ptr, len, "%s%s%s%s%s\n", c, s, m, v, f);
}
static ssize_t