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 "power.h" 11 12 13 #undef TRACE 14 #define TRACE_POWER 15 #ifdef TRACE_POWER 16 # define TRACE(x...) dprintf("intel_extreme:" x) 17 #else 18 # define TRACE(x...) 19 #endif 20 21 #define ERROR(x...) dprintf("intel_extreme: " x) 22 #define CALLED(x...) TRACE("CALLED %s\n", __PRETTY_FUNCTION__) 23 24 25 status_t 26 intel_en_gating(intel_info &info) 27 { 28 CALLED(); 29 // Fix some problems on certain chips (taken from X driver) 30 // TODO: clean this up 31 if (info.pci->device_id == 0x2a02 || info.pci->device_id == 0x2a12) { 32 TRACE("i965GM/i965GME quirk\n"); 33 write32(info, 0x6204, (1L << 29)); 34 } else if (info.device_type.InGroup(INTEL_GROUP_SNB)) { 35 TRACE("SandyBridge clock gating\n"); 36 write32(info, 0x42020, (1L << 28) | (1L << 7) | (1L << 5)); 37 } else if (info.device_type.InGroup(INTEL_GROUP_IVB)) { 38 TRACE("IvyBridge clock gating\n"); 39 write32(info, 0x42020, (1L << 28)); 40 } else if (info.device_type.InGroup(INTEL_GROUP_VLV)) { 41 TRACE("ValleyView clock gating\n"); 42 write32(info, VLV_DISPLAY_BASE + 0x6200, (1L << 28)); 43 } else if (info.device_type.InGroup(INTEL_GROUP_ILK)) { 44 TRACE("IronLake clock gating\n"); 45 write32(info, 0x42020, (1L << 7) | (1L << 5)); 46 } else if (info.device_type.InGroup(INTEL_GROUP_G4x)) { 47 TRACE("G4x clock gating\n"); 48 write32(info, 0x6204, 0); 49 write32(info, 0x6208, (1L << 9) | (1L << 7) | (1L << 6)); 50 write32(info, 0x6210, 0); 51 52 uint32 gateValue = (1L << 28) | (1L << 3) | (1L << 2); 53 if ((info.device_type.type & INTEL_TYPE_MOBILE) == INTEL_TYPE_MOBILE) { 54 TRACE("G4x mobile clock gating\n"); 55 gateValue |= 1L << 18; 56 } 57 write32(info, 0x6200, gateValue); 58 } else { 59 TRACE("i965 quirk\n"); 60 write32(info, 0x6204, (1L << 29) | (1L << 23)); 61 } 62 write32(info, 0x7408, 0x10); 63 64 return B_OK; 65 } 66 67 68 status_t 69 intel_en_downclock(intel_info &info) 70 { 71 CALLED(); 72 73 if (!info.device_type.InGroup(INTEL_GROUP_SNB) 74 && !info.device_type.InGroup(INTEL_GROUP_IVB)) { 75 TRACE("%s: Downclocking not supported on this chipset.\n", __func__); 76 return B_NOT_ALLOWED; 77 } 78 79 if((info.device_type.type & INTEL_TYPE_MOBILE) == 0) { 80 // I don't see a point enabling auto-downclocking on non-mobile devices. 81 TRACE("%s: Skip GPU downclocking on non-mobile device.\n", __func__); 82 return B_NOT_ALLOWED; 83 } 84 // TODO: Check for deep RC6 85 // IvyBridge, SandyBridge, and Haswell can do depth 1 atm 86 // Some chipsets can go deeper... but this is safe for now 87 // Haswell should *NOT* do over depth 1; 88 int depth = 1; 89 90 // Lets always print this for now incase it causes regressions for someone. 91 ERROR("%s: Enabling Intel GPU auto downclocking depth %d\n", __func__, 92 depth); 93 94 /* Magical sequence of register writes to enable 95 * downclocking from the fine folks at Xorg 96 */ 97 write32(info, INTEL6_RC_STATE, 0); 98 99 uint32 rpStateCapacity = read32(info, INTEL6_RP_STATE_CAP); 100 uint32 gtPerfStatus = read32(info, INTEL6_GT_PERF_STATUS); 101 uint8 maxDelay = rpStateCapacity & 0xff; 102 uint8 minDelay = (rpStateCapacity & 0xff0000) >> 16; 103 104 write32(info, INTEL6_RC_CONTROL, 0); 105 106 write32(info, INTEL6_RC1_WAKE_RATE_LIMIT, 1000 << 16); 107 write32(info, INTEL6_RC6_WAKE_RATE_LIMIT, 40 << 16 | 30); 108 write32(info, INTEL6_RC6pp_WAKE_RATE_LIMIT, 30); 109 write32(info, INTEL6_RC_EVALUATION_INTERVAL, 125000); 110 write32(info, INTEL6_RC_IDLE_HYSTERSIS, 25); 111 112 // TODO: Idle each ring 113 114 write32(info, INTEL6_RC_SLEEP, 0); 115 write32(info, INTEL6_RC1e_THRESHOLD, 1000); 116 write32(info, INTEL6_RC6_THRESHOLD, 50000); 117 write32(info, INTEL6_RC6p_THRESHOLD, 100000); 118 write32(info, INTEL6_RC6pp_THRESHOLD, 64000); 119 120 uint32 rc6Mask = INTEL6_RC_CTL_RC6_ENABLE; 121 122 if (depth > 1) 123 rc6Mask |= INTEL6_RC_CTL_RC6p_ENABLE; 124 if (depth > 2) 125 rc6Mask |= INTEL6_RC_CTL_RC6pp_ENABLE; 126 127 write32(info, INTEL6_RC_CONTROL, rc6Mask | INTEL6_RC_CTL_EI_MODE(1) 128 | INTEL6_RC_CTL_HW_ENABLE); 129 write32(info, INTEL6_RPNSWREQ, INTEL6_FREQUENCY(10) | INTEL6_OFFSET(0) 130 | INTEL6_AGGRESSIVE_TURBO); 131 write32(info, INTEL6_RC_VIDEO_FREQ, INTEL6_FREQUENCY(12)); 132 133 write32(info, INTEL6_RP_DOWN_TIMEOUT, 1000000); 134 write32(info, INTEL6_RP_INTERRUPT_LIMITS, maxDelay << 24 | minDelay << 16); 135 136 write32(info, INTEL6_RP_UP_THRESHOLD, 59400); 137 write32(info, INTEL6_RP_DOWN_THRESHOLD, 245000); 138 write32(info, INTEL6_RP_UP_EI, 66000); 139 write32(info, INTEL6_RP_DOWN_EI, 350000); 140 141 write32(info, INTEL6_RP_IDLE_HYSTERSIS, 10); 142 write32(info, INTEL6_RP_CONTROL, INTEL6_RP_MEDIA_TURBO 143 | INTEL6_RP_MEDIA_HW_NORMAL_MODE | INTEL6_RP_MEDIA_IS_GFX 144 | INTEL6_RP_ENABLE | INTEL6_RP_UP_BUSY_AVG 145 | INTEL6_RP_DOWN_IDLE_CONT); 146 // TODO: | (HASWELL ? GEN7_RP_DOWN_IDLE_AVG : INTEL6_RP_DOWN_IDLE_CONT)); 147 148 // TODO: wait for (read32(INTEL6_PCODE_MAILBOX) & INTEL6_PCODE_READY) 149 write32(info, INTEL6_PCODE_DATA, 0); 150 write32(info, INTEL6_PCODE_MAILBOX, INTEL6_PCODE_READY 151 | INTEL6_PCODE_WRITE_MIN_FREQ_TABLE); 152 // TODO: wait for (read32(INTEL6_PCODE_MAILBOX) & INTEL6_PCODE_READY) 153 154 // TODO: check for overclock support and set. 155 156 // Calculate limits and enforce them 157 uint8 gtPerfShift = (gtPerfStatus & 0xff00) >> 8; 158 if (gtPerfShift >= maxDelay) 159 gtPerfShift = maxDelay; 160 uint32 limits = maxDelay << 24; 161 if (gtPerfShift <= minDelay) { 162 gtPerfShift = minDelay; 163 limits |= minDelay << 16; 164 } 165 write32(info, INTEL6_RP_INTERRUPT_LIMITS, limits); 166 167 write32(info, INTEL6_RPNSWREQ, INTEL6_FREQUENCY(gtPerfShift) 168 | INTEL6_OFFSET(0) | INTEL6_AGGRESSIVE_TURBO); 169 170 // Requires MSI to be enabled. 171 write32(info, INTEL6_PMIER, INTEL6_PM_DEFERRED_EVENTS); 172 // TODO: Review need for spin lock irq rps here? 173 write32(info, INTEL6_PMIMR, 0); 174 // TODO: Review need for spin unlock irq rps here? 175 write32(info, INTEL6_PMINTRMSK, 0); 176 177 return B_OK; 178 } 179