1 | /*
|
---|
2 | * Copyright 2012-2013, Haiku, Inc. All Rights Reserved.
|
---|
3 | * Distributed under the terms of the MIT License.
|
---|
4 | *
|
---|
5 | * Authors:
|
---|
6 | * Alexander von Gluck IV, kallisti5@unixzen.com
|
---|
7 | */
|
---|
8 |
|
---|
9 |
|
---|
10 | #include "accelerant_protos.h"
|
---|
11 | #include "accelerant.h"
|
---|
12 |
|
---|
13 | #include <string.h>
|
---|
14 |
|
---|
15 |
|
---|
16 | status_t
|
---|
17 | intel_pm_downclock(bool enable)
|
---|
18 | {
|
---|
19 | if (!gInfo->shared_info->device_type.InGroup(GEN6_TYPE_SNB)
|
---|
20 | && !gInfo->shared_info->device_type.InGroup(GEN6_TYPE_IVB)) {
|
---|
21 | TRACE("%s: Downclocking not supported on this chipset.\n", __func__);
|
---|
22 | return B_ERROR;
|
---|
23 | }
|
---|
24 |
|
---|
25 | // TODO: Check for deep RC6
|
---|
26 | // IvyBridge, SandyBridge, and Haswell can do depth 1 atm
|
---|
27 | // Some chipsets can go deeper... but this is safe for now
|
---|
28 | // Haswell should *NOT* do over depth 1;
|
---|
29 | int depth = 1;
|
---|
30 |
|
---|
31 | /* Magical sequence of register writes to enable
|
---|
32 | * downclocking from the fine folks at Xorg
|
---|
33 | */
|
---|
34 | write32(GEN6_RC_STATE, 0);
|
---|
35 | // TODO: We may need grab rps states here
|
---|
36 | write32(GEN6_RC_CONTROL, 0);
|
---|
37 |
|
---|
38 | write32(GEN6_RC1_WAKE_RATE_LIMIT, 1000 << 16);
|
---|
39 | write32(GEN6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30);
|
---|
40 | write32(GEN6_RC6pp_WAKE_RATE_LIMIT, 30);
|
---|
41 | write32(GEN6_RC_EVALUATION_INTERVAL, 125000);
|
---|
42 | write32(GEN6_RC_IDLE_HYSTERSIS, 25);
|
---|
43 |
|
---|
44 | // TODO: Idle each ring
|
---|
45 |
|
---|
46 | write32(GEN6_RC_SLEEP, 0);
|
---|
47 | write32(GEN6_RC1e_THRESHOLD, 1000);
|
---|
48 | write32(GEN6_RC6_THRESHOLD, 50000);
|
---|
49 | write32(GEN6_RC6p_THRESHOLD, 100000);
|
---|
50 | write32(GEN6_RC6pp_THRESHOLD, 64000);
|
---|
51 |
|
---|
52 | uint32 rc6Mask = GEN6_RC_CTL_RC6_ENABLE;
|
---|
53 |
|
---|
54 | if (depth > 1)
|
---|
55 | rc6Mask |= GEN6_RC_CTL_RC6p_ENABLE;
|
---|
56 | if (depth > 2)
|
---|
57 | rc6Mask |= GEN6_RC_CTL_RC6pp_ENABLE;
|
---|
58 |
|
---|
59 | write32(GEN6_RC_CONTROL, rc6Mask |
|
---|
60 | write32(GEN6_RPNSWREQ,
|
---|
61 | write32(GEN6_RC_VIDEO_FREQ,
|
---|
62 |
|
---|
63 | write32(GEN6_RP_DOWN_TIMEOUT, 1000000);
|
---|
64 | write32(GEN6_RP_INTERRUPT_LIMITS,
|
---|
65 | maxDelay << 24 | minDelay << 16);
|
---|
66 |
|
---|
67 | write32(GEN6_RP_UP_THRESHOLD, 59400);
|
---|
68 | write32(GEN6_RP_DOWN_THRESHOLD, 245000);
|
---|
69 | write32(GEN6_RP_UP_EI, 66000);
|
---|
70 | write32(GEN6_RP_DOWN_EI, 350000);
|
---|
71 |
|
---|
72 | write32(GEN6_RP_IDLE_HYSTERSIS, 10);
|
---|
73 | write32(GEN6_RP_CONTROL, GEN6_RP_MEDIA_TURBO
|
---|
74 | | GEN6_RP_MEDIA_HW_NORMAL_MODE | GEN6_RP_MEDIA_IS_GFX
|
---|
75 | | GEN6_RP_ENABLE | GEN6_RP_UP_BUSY_AVG
|
---|
76 | | GEN6_RP_DOWN_IDLE_CONT);
|
---|
77 | // TODO: | (HASWELL ? GEN7_RP_DOWN_IDLE_AVG : GEN6_RP_DOWN_IDLE_CONT));
|
---|
78 |
|
---|
79 | // TODO: wait for (read32(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY)
|
---|
80 |
|
---|
81 | write32(GEN6_PCODE_DATA, 0);
|
---|
82 | write32(GEN6_PCODE_MAILBOX, GEN6_PCODE_READY
|
---|
83 | | GEN6_PCODE_WRITE_MIN_FREQ_TABLE);
|
---|
84 |
|
---|
85 | // TODO: wait for (read32(GEN6_PCODE_MAILBOX) & GEN6_PCODE_READY)
|
---|
86 |
|
---|
87 | // TODO: check for overclock support and set.
|
---|
88 |
|
---|
89 | }
|
---|