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