diff options
Diffstat (limited to 'drivers/gpu/drm/nouveau/nva3_pm.c')
-rw-r--r-- | drivers/gpu/drm/nouveau/nva3_pm.c | 290 |
1 files changed, 272 insertions, 18 deletions
diff --git a/drivers/gpu/drm/nouveau/nva3_pm.c b/drivers/gpu/drm/nouveau/nva3_pm.c index 9e636e6ef6d7..798829353fb6 100644 --- a/drivers/gpu/drm/nouveau/nva3_pm.c +++ b/drivers/gpu/drm/nouveau/nva3_pm.c | |||
@@ -98,7 +98,9 @@ read_pll(struct drm_device *dev, int clk, u32 pll) | |||
98 | sclk = read_clk(dev, 0x10 + clk, false); | 98 | sclk = read_clk(dev, 0x10 + clk, false); |
99 | } | 99 | } |
100 | 100 | ||
101 | return sclk * N / (M * P); | 101 | if (M * P) |
102 | return sclk * N / (M * P); | ||
103 | return 0; | ||
102 | } | 104 | } |
103 | 105 | ||
104 | struct creg { | 106 | struct creg { |
@@ -182,23 +184,26 @@ prog_pll(struct drm_device *dev, int clk, u32 pll, struct creg *reg) | |||
182 | const u32 src1 = 0x004160 + (clk * 4); | 184 | const u32 src1 = 0x004160 + (clk * 4); |
183 | const u32 ctrl = pll + 0; | 185 | const u32 ctrl = pll + 0; |
184 | const u32 coef = pll + 4; | 186 | const u32 coef = pll + 4; |
185 | u32 cntl; | ||
186 | 187 | ||
187 | if (!reg->clk && !reg->pll) { | 188 | if (!reg->clk && !reg->pll) { |
188 | NV_DEBUG(dev, "no clock for %02x\n", clk); | 189 | NV_DEBUG(dev, "no clock for %02x\n", clk); |
189 | return; | 190 | return; |
190 | } | 191 | } |
191 | 192 | ||
192 | cntl = nv_rd32(dev, ctrl) & 0xfffffff2; | ||
193 | if (reg->pll) { | 193 | if (reg->pll) { |
194 | nv_mask(dev, src0, 0x00000101, 0x00000101); | 194 | nv_mask(dev, src0, 0x00000101, 0x00000101); |
195 | nv_wr32(dev, coef, reg->pll); | 195 | nv_wr32(dev, coef, reg->pll); |
196 | nv_wr32(dev, ctrl, cntl | 0x00000015); | 196 | nv_mask(dev, ctrl, 0x00000015, 0x00000015); |
197 | nv_mask(dev, ctrl, 0x00000010, 0x00000000); | ||
198 | nv_wait(dev, ctrl, 0x00020000, 0x00020000); | ||
199 | nv_mask(dev, ctrl, 0x00000010, 0x00000010); | ||
200 | nv_mask(dev, ctrl, 0x00000008, 0x00000000); | ||
197 | nv_mask(dev, src1, 0x00000100, 0x00000000); | 201 | nv_mask(dev, src1, 0x00000100, 0x00000000); |
198 | nv_mask(dev, src1, 0x00000001, 0x00000000); | 202 | nv_mask(dev, src1, 0x00000001, 0x00000000); |
199 | } else { | 203 | } else { |
200 | nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); | 204 | nv_mask(dev, src1, 0x003f3141, 0x00000101 | reg->clk); |
201 | nv_wr32(dev, ctrl, cntl | 0x0000001d); | 205 | nv_mask(dev, ctrl, 0x00000018, 0x00000018); |
206 | udelay(20); | ||
202 | nv_mask(dev, ctrl, 0x00000001, 0x00000000); | 207 | nv_mask(dev, ctrl, 0x00000001, 0x00000000); |
203 | nv_mask(dev, src0, 0x00000100, 0x00000000); | 208 | nv_mask(dev, src0, 0x00000100, 0x00000000); |
204 | nv_mask(dev, src0, 0x00000001, 0x00000000); | 209 | nv_mask(dev, src0, 0x00000001, 0x00000000); |
@@ -230,17 +235,28 @@ nva3_pm_clocks_get(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
230 | } | 235 | } |
231 | 236 | ||
232 | struct nva3_pm_state { | 237 | struct nva3_pm_state { |
238 | struct nouveau_pm_level *perflvl; | ||
239 | |||
233 | struct creg nclk; | 240 | struct creg nclk; |
234 | struct creg sclk; | 241 | struct creg sclk; |
235 | struct creg mclk; | ||
236 | struct creg vdec; | 242 | struct creg vdec; |
237 | struct creg unka0; | 243 | struct creg unka0; |
244 | |||
245 | struct creg mclk; | ||
246 | u8 *rammap; | ||
247 | u8 rammap_ver; | ||
248 | u8 rammap_len; | ||
249 | u8 *ramcfg; | ||
250 | u8 ramcfg_len; | ||
251 | u32 r004018; | ||
252 | u32 r100760; | ||
238 | }; | 253 | }; |
239 | 254 | ||
240 | void * | 255 | void * |
241 | nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | 256 | nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) |
242 | { | 257 | { |
243 | struct nva3_pm_state *info; | 258 | struct nva3_pm_state *info; |
259 | u8 ramcfg_cnt; | ||
244 | int ret; | 260 | int ret; |
245 | 261 | ||
246 | info = kzalloc(sizeof(*info), GFP_KERNEL); | 262 | info = kzalloc(sizeof(*info), GFP_KERNEL); |
@@ -267,6 +283,20 @@ nva3_pm_clocks_pre(struct drm_device *dev, struct nouveau_pm_level *perflvl) | |||
267 | if (ret < 0) | 283 | if (ret < 0) |
268 | goto out; | 284 | goto out; |
269 | 285 | ||
286 | info->rammap = nouveau_perf_rammap(dev, perflvl->memory, | ||
287 | &info->rammap_ver, | ||
288 | &info->rammap_len, | ||
289 | &ramcfg_cnt, &info->ramcfg_len); | ||
290 | if (info->rammap_ver != 0x10 || info->rammap_len < 5) | ||
291 | info->rammap = NULL; | ||
292 | |||
293 | info->ramcfg = nouveau_perf_ramcfg(dev, perflvl->memory, | ||
294 | &info->rammap_ver, | ||
295 | &info->ramcfg_len); | ||
296 | if (info->rammap_ver != 0x10) | ||
297 | info->ramcfg = NULL; | ||
298 | |||
299 | info->perflvl = perflvl; | ||
270 | out: | 300 | out: |
271 | if (ret < 0) { | 301 | if (ret < 0) { |
272 | kfree(info); | 302 | kfree(info); |
@@ -287,6 +317,240 @@ nva3_pm_grcp_idle(void *data) | |||
287 | return false; | 317 | return false; |
288 | } | 318 | } |
289 | 319 | ||
320 | static void | ||
321 | mclk_precharge(struct nouveau_mem_exec_func *exec) | ||
322 | { | ||
323 | nv_wr32(exec->dev, 0x1002d4, 0x00000001); | ||
324 | } | ||
325 | |||
326 | static void | ||
327 | mclk_refresh(struct nouveau_mem_exec_func *exec) | ||
328 | { | ||
329 | nv_wr32(exec->dev, 0x1002d0, 0x00000001); | ||
330 | } | ||
331 | |||
332 | static void | ||
333 | mclk_refresh_auto(struct nouveau_mem_exec_func *exec, bool enable) | ||
334 | { | ||
335 | nv_wr32(exec->dev, 0x100210, enable ? 0x80000000 : 0x00000000); | ||
336 | } | ||
337 | |||
338 | static void | ||
339 | mclk_refresh_self(struct nouveau_mem_exec_func *exec, bool enable) | ||
340 | { | ||
341 | nv_wr32(exec->dev, 0x1002dc, enable ? 0x00000001 : 0x00000000); | ||
342 | } | ||
343 | |||
344 | static void | ||
345 | mclk_wait(struct nouveau_mem_exec_func *exec, u32 nsec) | ||
346 | { | ||
347 | volatile u32 post = nv_rd32(exec->dev, 0); (void)post; | ||
348 | udelay((nsec + 500) / 1000); | ||
349 | } | ||
350 | |||
351 | static u32 | ||
352 | mclk_mrg(struct nouveau_mem_exec_func *exec, int mr) | ||
353 | { | ||
354 | if (mr <= 1) | ||
355 | return nv_rd32(exec->dev, 0x1002c0 + ((mr - 0) * 4)); | ||
356 | if (mr <= 3) | ||
357 | return nv_rd32(exec->dev, 0x1002e0 + ((mr - 2) * 4)); | ||
358 | return 0; | ||
359 | } | ||
360 | |||
361 | static void | ||
362 | mclk_mrs(struct nouveau_mem_exec_func *exec, int mr, u32 data) | ||
363 | { | ||
364 | struct drm_nouveau_private *dev_priv = exec->dev->dev_private; | ||
365 | |||
366 | if (mr <= 1) { | ||
367 | if (dev_priv->vram_rank_B) | ||
368 | nv_wr32(exec->dev, 0x1002c8 + ((mr - 0) * 4), data); | ||
369 | nv_wr32(exec->dev, 0x1002c0 + ((mr - 0) * 4), data); | ||
370 | } else | ||
371 | if (mr <= 3) { | ||
372 | if (dev_priv->vram_rank_B) | ||
373 | nv_wr32(exec->dev, 0x1002e8 + ((mr - 2) * 4), data); | ||
374 | nv_wr32(exec->dev, 0x1002e0 + ((mr - 2) * 4), data); | ||
375 | } | ||
376 | } | ||
377 | |||
378 | static void | ||
379 | mclk_clock_set(struct nouveau_mem_exec_func *exec) | ||
380 | { | ||
381 | struct drm_device *dev = exec->dev; | ||
382 | struct nva3_pm_state *info = exec->priv; | ||
383 | u32 ctrl; | ||
384 | |||
385 | ctrl = nv_rd32(dev, 0x004000); | ||
386 | if (!(ctrl & 0x00000008) && info->mclk.pll) { | ||
387 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000008)); | ||
388 | nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); | ||
389 | nv_wr32(dev, 0x004018, 0x00001000); | ||
390 | nv_wr32(dev, 0x004000, (ctrl &= ~0x00000001)); | ||
391 | nv_wr32(dev, 0x004004, info->mclk.pll); | ||
392 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000001)); | ||
393 | udelay(64); | ||
394 | nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); | ||
395 | udelay(20); | ||
396 | } else | ||
397 | if (!info->mclk.pll) { | ||
398 | nv_mask(dev, 0x004168, 0x003f3040, info->mclk.clk); | ||
399 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000008)); | ||
400 | nv_mask(dev, 0x1110e0, 0x00088000, 0x00088000); | ||
401 | nv_wr32(dev, 0x004018, 0x0000d000 | info->r004018); | ||
402 | } | ||
403 | |||
404 | if (info->rammap) { | ||
405 | if (info->ramcfg && (info->rammap[4] & 0x08)) { | ||
406 | u32 unk5a0 = (ROM16(info->ramcfg[5]) << 8) | | ||
407 | info->ramcfg[5]; | ||
408 | u32 unk5a4 = ROM16(info->ramcfg[7]); | ||
409 | u32 unk804 = (info->ramcfg[9] & 0xf0) << 16 | | ||
410 | (info->ramcfg[3] & 0x0f) << 16 | | ||
411 | (info->ramcfg[9] & 0x0f) | | ||
412 | 0x80000000; | ||
413 | nv_wr32(dev, 0x1005a0, unk5a0); | ||
414 | nv_wr32(dev, 0x1005a4, unk5a4); | ||
415 | nv_wr32(dev, 0x10f804, unk804); | ||
416 | nv_mask(dev, 0x10053c, 0x00001000, 0x00000000); | ||
417 | } else { | ||
418 | nv_mask(dev, 0x10053c, 0x00001000, 0x00001000); | ||
419 | nv_mask(dev, 0x10f804, 0x80000000, 0x00000000); | ||
420 | nv_mask(dev, 0x100760, 0x22222222, info->r100760); | ||
421 | nv_mask(dev, 0x1007a0, 0x22222222, info->r100760); | ||
422 | nv_mask(dev, 0x1007e0, 0x22222222, info->r100760); | ||
423 | } | ||
424 | } | ||
425 | |||
426 | if (info->mclk.pll) { | ||
427 | nv_mask(dev, 0x1110e0, 0x00088000, 0x00011000); | ||
428 | nv_wr32(dev, 0x004000, (ctrl &= ~0x00000008)); | ||
429 | } | ||
430 | } | ||
431 | |||
432 | static void | ||
433 | mclk_timing_set(struct nouveau_mem_exec_func *exec) | ||
434 | { | ||
435 | struct drm_device *dev = exec->dev; | ||
436 | struct nva3_pm_state *info = exec->priv; | ||
437 | struct nouveau_pm_level *perflvl = info->perflvl; | ||
438 | int i; | ||
439 | |||
440 | for (i = 0; i < 9; i++) | ||
441 | nv_wr32(dev, 0x100220 + (i * 4), perflvl->timing.reg[i]); | ||
442 | |||
443 | if (info->ramcfg) { | ||
444 | u32 data = (info->ramcfg[2] & 0x08) ? 0x00000000 : 0x00001000; | ||
445 | nv_mask(dev, 0x100200, 0x00001000, data); | ||
446 | } | ||
447 | |||
448 | if (info->ramcfg) { | ||
449 | u32 unk714 = nv_rd32(dev, 0x100714) & ~0xf0000010; | ||
450 | u32 unk718 = nv_rd32(dev, 0x100718) & ~0x00000100; | ||
451 | u32 unk71c = nv_rd32(dev, 0x10071c) & ~0x00000100; | ||
452 | if ( (info->ramcfg[2] & 0x20)) | ||
453 | unk714 |= 0xf0000000; | ||
454 | if (!(info->ramcfg[2] & 0x04)) | ||
455 | unk714 |= 0x00000010; | ||
456 | nv_wr32(dev, 0x100714, unk714); | ||
457 | |||
458 | if (info->ramcfg[2] & 0x01) | ||
459 | unk71c |= 0x00000100; | ||
460 | nv_wr32(dev, 0x10071c, unk71c); | ||
461 | |||
462 | if (info->ramcfg[2] & 0x02) | ||
463 | unk718 |= 0x00000100; | ||
464 | nv_wr32(dev, 0x100718, unk718); | ||
465 | |||
466 | if (info->ramcfg[2] & 0x10) | ||
467 | nv_wr32(dev, 0x111100, 0x48000000); /*XXX*/ | ||
468 | } | ||
469 | } | ||
470 | |||
471 | static void | ||
472 | prog_mem(struct drm_device *dev, struct nva3_pm_state *info) | ||
473 | { | ||
474 | struct nouveau_mem_exec_func exec = { | ||
475 | .dev = dev, | ||
476 | .precharge = mclk_precharge, | ||
477 | .refresh = mclk_refresh, | ||
478 | .refresh_auto = mclk_refresh_auto, | ||
479 | .refresh_self = mclk_refresh_self, | ||
480 | .wait = mclk_wait, | ||
481 | .mrg = mclk_mrg, | ||
482 | .mrs = mclk_mrs, | ||
483 | .clock_set = mclk_clock_set, | ||
484 | .timing_set = mclk_timing_set, | ||
485 | .priv = info | ||
486 | }; | ||
487 | u32 ctrl; | ||
488 | |||
489 | /* XXX: where the fuck does 750MHz come from? */ | ||
490 | if (info->perflvl->memory <= 750000) { | ||
491 | info->r004018 = 0x10000000; | ||
492 | info->r100760 = 0x22222222; | ||
493 | } | ||
494 | |||
495 | ctrl = nv_rd32(dev, 0x004000); | ||
496 | if (ctrl & 0x00000008) { | ||
497 | if (info->mclk.pll) { | ||
498 | nv_mask(dev, 0x004128, 0x00000101, 0x00000101); | ||
499 | nv_wr32(dev, 0x004004, info->mclk.pll); | ||
500 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000001)); | ||
501 | nv_wr32(dev, 0x004000, (ctrl &= 0xffffffef)); | ||
502 | nv_wait(dev, 0x004000, 0x00020000, 0x00020000); | ||
503 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000010)); | ||
504 | nv_wr32(dev, 0x004018, 0x00005000 | info->r004018); | ||
505 | nv_wr32(dev, 0x004000, (ctrl |= 0x00000004)); | ||
506 | } | ||
507 | } else { | ||
508 | u32 ssel = 0x00000101; | ||
509 | if (info->mclk.clk) | ||
510 | ssel |= info->mclk.clk; | ||
511 | else | ||
512 | ssel |= 0x00080000; /* 324MHz, shouldn't matter... */ | ||
513 | nv_mask(dev, 0x004168, 0x003f3141, ctrl); | ||
514 | } | ||
515 | |||
516 | if (info->ramcfg) { | ||
517 | if (info->ramcfg[2] & 0x10) { | ||
518 | nv_mask(dev, 0x111104, 0x00000600, 0x00000000); | ||
519 | } else { | ||
520 | nv_mask(dev, 0x111100, 0x40000000, 0x40000000); | ||
521 | nv_mask(dev, 0x111104, 0x00000180, 0x00000000); | ||
522 | } | ||
523 | } | ||
524 | if (info->rammap && !(info->rammap[4] & 0x02)) | ||
525 | nv_mask(dev, 0x100200, 0x00000800, 0x00000000); | ||
526 | nv_wr32(dev, 0x611200, 0x00003300); | ||
527 | if (!(info->ramcfg[2] & 0x10)) | ||
528 | nv_wr32(dev, 0x111100, 0x4c020000); /*XXX*/ | ||
529 | |||
530 | nouveau_mem_exec(&exec, info->perflvl); | ||
531 | |||
532 | nv_wr32(dev, 0x611200, 0x00003330); | ||
533 | if (info->rammap && (info->rammap[4] & 0x02)) | ||
534 | nv_mask(dev, 0x100200, 0x00000800, 0x00000800); | ||
535 | if (info->ramcfg) { | ||
536 | if (info->ramcfg[2] & 0x10) { | ||
537 | nv_mask(dev, 0x111104, 0x00000180, 0x00000180); | ||
538 | nv_mask(dev, 0x111100, 0x40000000, 0x00000000); | ||
539 | } else { | ||
540 | nv_mask(dev, 0x111104, 0x00000600, 0x00000600); | ||
541 | } | ||
542 | } | ||
543 | |||
544 | if (info->mclk.pll) { | ||
545 | nv_mask(dev, 0x004168, 0x00000001, 0x00000000); | ||
546 | nv_mask(dev, 0x004168, 0x00000100, 0x00000000); | ||
547 | } else { | ||
548 | nv_mask(dev, 0x004000, 0x00000001, 0x00000000); | ||
549 | nv_mask(dev, 0x004128, 0x00000001, 0x00000000); | ||
550 | nv_mask(dev, 0x004128, 0x00000100, 0x00000000); | ||
551 | } | ||
552 | } | ||
553 | |||
290 | int | 554 | int |
291 | nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) | 555 | nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) |
292 | { | 556 | { |
@@ -316,18 +580,8 @@ nva3_pm_clocks_set(struct drm_device *dev, void *pre_state) | |||
316 | prog_clk(dev, 0x20, &info->unka0); | 580 | prog_clk(dev, 0x20, &info->unka0); |
317 | prog_clk(dev, 0x21, &info->vdec); | 581 | prog_clk(dev, 0x21, &info->vdec); |
318 | 582 | ||
319 | if (info->mclk.clk || info->mclk.pll) { | 583 | if (info->mclk.clk || info->mclk.pll) |
320 | nv_wr32(dev, 0x100210, 0); | 584 | prog_mem(dev, info); |
321 | nv_wr32(dev, 0x1002dc, 1); | ||
322 | nv_wr32(dev, 0x004018, 0x00001000); | ||
323 | prog_pll(dev, 0x02, 0x004000, &info->mclk); | ||
324 | if (nv_rd32(dev, 0x4000) & 0x00000008) | ||
325 | nv_wr32(dev, 0x004018, 0x1000d000); | ||
326 | else | ||
327 | nv_wr32(dev, 0x004018, 0x10005000); | ||
328 | nv_wr32(dev, 0x1002dc, 0); | ||
329 | nv_wr32(dev, 0x100210, 0x80000000); | ||
330 | } | ||
331 | 585 | ||
332 | ret = 0; | 586 | ret = 0; |
333 | 587 | ||