162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * Copyright 2012 Advanced Micro Devices, Inc. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Permission is hereby granted, free of charge, to any person obtaining a 562306a36Sopenharmony_ci * copy of this software and associated documentation files (the "Software"), 662306a36Sopenharmony_ci * to deal in the Software without restriction, including without limitation 762306a36Sopenharmony_ci * the rights to use, copy, modify, merge, publish, distribute, sublicense, 862306a36Sopenharmony_ci * and/or sell copies of the Software, and to permit persons to whom the 962306a36Sopenharmony_ci * Software is furnished to do so, subject to the following conditions: 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * The above copyright notice and this permission notice shall be included in 1262306a36Sopenharmony_ci * all copies or substantial portions of the Software. 1362306a36Sopenharmony_ci * 1462306a36Sopenharmony_ci * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 1562306a36Sopenharmony_ci * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 1662306a36Sopenharmony_ci * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 1762306a36Sopenharmony_ci * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR 1862306a36Sopenharmony_ci * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 1962306a36Sopenharmony_ci * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 2062306a36Sopenharmony_ci * OTHER DEALINGS IN THE SOFTWARE. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/pci.h> 2562306a36Sopenharmony_ci#include <linux/seq_file.h> 2662306a36Sopenharmony_ci 2762306a36Sopenharmony_ci#include "r600_dpm.h" 2862306a36Sopenharmony_ci#include "radeon.h" 2962306a36Sopenharmony_ci#include "radeon_asic.h" 3062306a36Sopenharmony_ci#include "trinity_dpm.h" 3162306a36Sopenharmony_ci#include "trinityd.h" 3262306a36Sopenharmony_ci#include "vce.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci#define TRINITY_MAX_DEEPSLEEP_DIVIDER_ID 5 3562306a36Sopenharmony_ci#define TRINITY_MINIMUM_ENGINE_CLOCK 800 3662306a36Sopenharmony_ci#define SCLK_MIN_DIV_INTV_SHIFT 12 3762306a36Sopenharmony_ci#define TRINITY_DISPCLK_BYPASS_THRESHOLD 10000 3862306a36Sopenharmony_ci 3962306a36Sopenharmony_ci#ifndef TRINITY_MGCG_SEQUENCE 4062306a36Sopenharmony_ci#define TRINITY_MGCG_SEQUENCE 100 4162306a36Sopenharmony_ci 4262306a36Sopenharmony_cistatic const u32 trinity_mgcg_shls_default[] = 4362306a36Sopenharmony_ci{ 4462306a36Sopenharmony_ci /* Register, Value, Mask */ 4562306a36Sopenharmony_ci 0x0000802c, 0xc0000000, 0xffffffff, 4662306a36Sopenharmony_ci 0x00003fc4, 0xc0000000, 0xffffffff, 4762306a36Sopenharmony_ci 0x00005448, 0x00000100, 0xffffffff, 4862306a36Sopenharmony_ci 0x000055e4, 0x00000100, 0xffffffff, 4962306a36Sopenharmony_ci 0x0000160c, 0x00000100, 0xffffffff, 5062306a36Sopenharmony_ci 0x00008984, 0x06000100, 0xffffffff, 5162306a36Sopenharmony_ci 0x0000c164, 0x00000100, 0xffffffff, 5262306a36Sopenharmony_ci 0x00008a18, 0x00000100, 0xffffffff, 5362306a36Sopenharmony_ci 0x0000897c, 0x06000100, 0xffffffff, 5462306a36Sopenharmony_ci 0x00008b28, 0x00000100, 0xffffffff, 5562306a36Sopenharmony_ci 0x00009144, 0x00800200, 0xffffffff, 5662306a36Sopenharmony_ci 0x00009a60, 0x00000100, 0xffffffff, 5762306a36Sopenharmony_ci 0x00009868, 0x00000100, 0xffffffff, 5862306a36Sopenharmony_ci 0x00008d58, 0x00000100, 0xffffffff, 5962306a36Sopenharmony_ci 0x00009510, 0x00000100, 0xffffffff, 6062306a36Sopenharmony_ci 0x0000949c, 0x00000100, 0xffffffff, 6162306a36Sopenharmony_ci 0x00009654, 0x00000100, 0xffffffff, 6262306a36Sopenharmony_ci 0x00009030, 0x00000100, 0xffffffff, 6362306a36Sopenharmony_ci 0x00009034, 0x00000100, 0xffffffff, 6462306a36Sopenharmony_ci 0x00009038, 0x00000100, 0xffffffff, 6562306a36Sopenharmony_ci 0x0000903c, 0x00000100, 0xffffffff, 6662306a36Sopenharmony_ci 0x00009040, 0x00000100, 0xffffffff, 6762306a36Sopenharmony_ci 0x0000a200, 0x00000100, 0xffffffff, 6862306a36Sopenharmony_ci 0x0000a204, 0x00000100, 0xffffffff, 6962306a36Sopenharmony_ci 0x0000a208, 0x00000100, 0xffffffff, 7062306a36Sopenharmony_ci 0x0000a20c, 0x00000100, 0xffffffff, 7162306a36Sopenharmony_ci 0x00009744, 0x00000100, 0xffffffff, 7262306a36Sopenharmony_ci 0x00003f80, 0x00000100, 0xffffffff, 7362306a36Sopenharmony_ci 0x0000a210, 0x00000100, 0xffffffff, 7462306a36Sopenharmony_ci 0x0000a214, 0x00000100, 0xffffffff, 7562306a36Sopenharmony_ci 0x000004d8, 0x00000100, 0xffffffff, 7662306a36Sopenharmony_ci 0x00009664, 0x00000100, 0xffffffff, 7762306a36Sopenharmony_ci 0x00009698, 0x00000100, 0xffffffff, 7862306a36Sopenharmony_ci 0x000004d4, 0x00000200, 0xffffffff, 7962306a36Sopenharmony_ci 0x000004d0, 0x00000000, 0xffffffff, 8062306a36Sopenharmony_ci 0x000030cc, 0x00000104, 0xffffffff, 8162306a36Sopenharmony_ci 0x0000d0c0, 0x00000100, 0xffffffff, 8262306a36Sopenharmony_ci 0x0000d8c0, 0x00000100, 0xffffffff, 8362306a36Sopenharmony_ci 0x0000951c, 0x00010000, 0xffffffff, 8462306a36Sopenharmony_ci 0x00009160, 0x00030002, 0xffffffff, 8562306a36Sopenharmony_ci 0x00009164, 0x00050004, 0xffffffff, 8662306a36Sopenharmony_ci 0x00009168, 0x00070006, 0xffffffff, 8762306a36Sopenharmony_ci 0x00009178, 0x00070000, 0xffffffff, 8862306a36Sopenharmony_ci 0x0000917c, 0x00030002, 0xffffffff, 8962306a36Sopenharmony_ci 0x00009180, 0x00050004, 0xffffffff, 9062306a36Sopenharmony_ci 0x0000918c, 0x00010006, 0xffffffff, 9162306a36Sopenharmony_ci 0x00009190, 0x00090008, 0xffffffff, 9262306a36Sopenharmony_ci 0x00009194, 0x00070000, 0xffffffff, 9362306a36Sopenharmony_ci 0x00009198, 0x00030002, 0xffffffff, 9462306a36Sopenharmony_ci 0x0000919c, 0x00050004, 0xffffffff, 9562306a36Sopenharmony_ci 0x000091a8, 0x00010006, 0xffffffff, 9662306a36Sopenharmony_ci 0x000091ac, 0x00090008, 0xffffffff, 9762306a36Sopenharmony_ci 0x000091b0, 0x00070000, 0xffffffff, 9862306a36Sopenharmony_ci 0x000091b4, 0x00030002, 0xffffffff, 9962306a36Sopenharmony_ci 0x000091b8, 0x00050004, 0xffffffff, 10062306a36Sopenharmony_ci 0x000091c4, 0x00010006, 0xffffffff, 10162306a36Sopenharmony_ci 0x000091c8, 0x00090008, 0xffffffff, 10262306a36Sopenharmony_ci 0x000091cc, 0x00070000, 0xffffffff, 10362306a36Sopenharmony_ci 0x000091d0, 0x00030002, 0xffffffff, 10462306a36Sopenharmony_ci 0x000091d4, 0x00050004, 0xffffffff, 10562306a36Sopenharmony_ci 0x000091e0, 0x00010006, 0xffffffff, 10662306a36Sopenharmony_ci 0x000091e4, 0x00090008, 0xffffffff, 10762306a36Sopenharmony_ci 0x000091e8, 0x00000000, 0xffffffff, 10862306a36Sopenharmony_ci 0x000091ec, 0x00070000, 0xffffffff, 10962306a36Sopenharmony_ci 0x000091f0, 0x00030002, 0xffffffff, 11062306a36Sopenharmony_ci 0x000091f4, 0x00050004, 0xffffffff, 11162306a36Sopenharmony_ci 0x00009200, 0x00010006, 0xffffffff, 11262306a36Sopenharmony_ci 0x00009204, 0x00090008, 0xffffffff, 11362306a36Sopenharmony_ci 0x00009208, 0x00070000, 0xffffffff, 11462306a36Sopenharmony_ci 0x0000920c, 0x00030002, 0xffffffff, 11562306a36Sopenharmony_ci 0x00009210, 0x00050004, 0xffffffff, 11662306a36Sopenharmony_ci 0x0000921c, 0x00010006, 0xffffffff, 11762306a36Sopenharmony_ci 0x00009220, 0x00090008, 0xffffffff, 11862306a36Sopenharmony_ci 0x00009294, 0x00000000, 0xffffffff 11962306a36Sopenharmony_ci}; 12062306a36Sopenharmony_ci#endif 12162306a36Sopenharmony_ci 12262306a36Sopenharmony_ci#ifndef TRINITY_SYSLS_SEQUENCE 12362306a36Sopenharmony_ci#define TRINITY_SYSLS_SEQUENCE 100 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_cistatic const u32 trinity_sysls_disable[] = 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci /* Register, Value, Mask */ 12862306a36Sopenharmony_ci 0x0000d0c0, 0x00000000, 0xffffffff, 12962306a36Sopenharmony_ci 0x0000d8c0, 0x00000000, 0xffffffff, 13062306a36Sopenharmony_ci 0x000055e8, 0x00000000, 0xffffffff, 13162306a36Sopenharmony_ci 0x0000d0bc, 0x00000000, 0xffffffff, 13262306a36Sopenharmony_ci 0x0000d8bc, 0x00000000, 0xffffffff, 13362306a36Sopenharmony_ci 0x000015c0, 0x00041401, 0xffffffff, 13462306a36Sopenharmony_ci 0x0000264c, 0x00040400, 0xffffffff, 13562306a36Sopenharmony_ci 0x00002648, 0x00040400, 0xffffffff, 13662306a36Sopenharmony_ci 0x00002650, 0x00040400, 0xffffffff, 13762306a36Sopenharmony_ci 0x000020b8, 0x00040400, 0xffffffff, 13862306a36Sopenharmony_ci 0x000020bc, 0x00040400, 0xffffffff, 13962306a36Sopenharmony_ci 0x000020c0, 0x00040c80, 0xffffffff, 14062306a36Sopenharmony_ci 0x0000f4a0, 0x000000c0, 0xffffffff, 14162306a36Sopenharmony_ci 0x0000f4a4, 0x00680000, 0xffffffff, 14262306a36Sopenharmony_ci 0x00002f50, 0x00000404, 0xffffffff, 14362306a36Sopenharmony_ci 0x000004c8, 0x00000001, 0xffffffff, 14462306a36Sopenharmony_ci 0x0000641c, 0x00007ffd, 0xffffffff, 14562306a36Sopenharmony_ci 0x00000c7c, 0x0000ff00, 0xffffffff, 14662306a36Sopenharmony_ci 0x00006dfc, 0x0000007f, 0xffffffff 14762306a36Sopenharmony_ci}; 14862306a36Sopenharmony_ci 14962306a36Sopenharmony_cistatic const u32 trinity_sysls_enable[] = 15062306a36Sopenharmony_ci{ 15162306a36Sopenharmony_ci /* Register, Value, Mask */ 15262306a36Sopenharmony_ci 0x000055e8, 0x00000001, 0xffffffff, 15362306a36Sopenharmony_ci 0x0000d0bc, 0x00000100, 0xffffffff, 15462306a36Sopenharmony_ci 0x0000d8bc, 0x00000100, 0xffffffff, 15562306a36Sopenharmony_ci 0x000015c0, 0x000c1401, 0xffffffff, 15662306a36Sopenharmony_ci 0x0000264c, 0x000c0400, 0xffffffff, 15762306a36Sopenharmony_ci 0x00002648, 0x000c0400, 0xffffffff, 15862306a36Sopenharmony_ci 0x00002650, 0x000c0400, 0xffffffff, 15962306a36Sopenharmony_ci 0x000020b8, 0x000c0400, 0xffffffff, 16062306a36Sopenharmony_ci 0x000020bc, 0x000c0400, 0xffffffff, 16162306a36Sopenharmony_ci 0x000020c0, 0x000c0c80, 0xffffffff, 16262306a36Sopenharmony_ci 0x0000f4a0, 0x000000c0, 0xffffffff, 16362306a36Sopenharmony_ci 0x0000f4a4, 0x00680fff, 0xffffffff, 16462306a36Sopenharmony_ci 0x00002f50, 0x00000903, 0xffffffff, 16562306a36Sopenharmony_ci 0x000004c8, 0x00000000, 0xffffffff, 16662306a36Sopenharmony_ci 0x0000641c, 0x00000000, 0xffffffff, 16762306a36Sopenharmony_ci 0x00000c7c, 0x00000000, 0xffffffff, 16862306a36Sopenharmony_ci 0x00006dfc, 0x00000000, 0xffffffff 16962306a36Sopenharmony_ci}; 17062306a36Sopenharmony_ci#endif 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_cistatic const u32 trinity_override_mgpg_sequences[] = 17362306a36Sopenharmony_ci{ 17462306a36Sopenharmony_ci /* Register, Value */ 17562306a36Sopenharmony_ci 0x00000200, 0xE030032C, 17662306a36Sopenharmony_ci 0x00000204, 0x00000FFF, 17762306a36Sopenharmony_ci 0x00000200, 0xE0300058, 17862306a36Sopenharmony_ci 0x00000204, 0x00030301, 17962306a36Sopenharmony_ci 0x00000200, 0xE0300054, 18062306a36Sopenharmony_ci 0x00000204, 0x500010FF, 18162306a36Sopenharmony_ci 0x00000200, 0xE0300074, 18262306a36Sopenharmony_ci 0x00000204, 0x00030301, 18362306a36Sopenharmony_ci 0x00000200, 0xE0300070, 18462306a36Sopenharmony_ci 0x00000204, 0x500010FF, 18562306a36Sopenharmony_ci 0x00000200, 0xE0300090, 18662306a36Sopenharmony_ci 0x00000204, 0x00030301, 18762306a36Sopenharmony_ci 0x00000200, 0xE030008C, 18862306a36Sopenharmony_ci 0x00000204, 0x500010FF, 18962306a36Sopenharmony_ci 0x00000200, 0xE03000AC, 19062306a36Sopenharmony_ci 0x00000204, 0x00030301, 19162306a36Sopenharmony_ci 0x00000200, 0xE03000A8, 19262306a36Sopenharmony_ci 0x00000204, 0x500010FF, 19362306a36Sopenharmony_ci 0x00000200, 0xE03000C8, 19462306a36Sopenharmony_ci 0x00000204, 0x00030301, 19562306a36Sopenharmony_ci 0x00000200, 0xE03000C4, 19662306a36Sopenharmony_ci 0x00000204, 0x500010FF, 19762306a36Sopenharmony_ci 0x00000200, 0xE03000E4, 19862306a36Sopenharmony_ci 0x00000204, 0x00030301, 19962306a36Sopenharmony_ci 0x00000200, 0xE03000E0, 20062306a36Sopenharmony_ci 0x00000204, 0x500010FF, 20162306a36Sopenharmony_ci 0x00000200, 0xE0300100, 20262306a36Sopenharmony_ci 0x00000204, 0x00030301, 20362306a36Sopenharmony_ci 0x00000200, 0xE03000FC, 20462306a36Sopenharmony_ci 0x00000204, 0x500010FF, 20562306a36Sopenharmony_ci 0x00000200, 0xE0300058, 20662306a36Sopenharmony_ci 0x00000204, 0x00030303, 20762306a36Sopenharmony_ci 0x00000200, 0xE0300054, 20862306a36Sopenharmony_ci 0x00000204, 0x600010FF, 20962306a36Sopenharmony_ci 0x00000200, 0xE0300074, 21062306a36Sopenharmony_ci 0x00000204, 0x00030303, 21162306a36Sopenharmony_ci 0x00000200, 0xE0300070, 21262306a36Sopenharmony_ci 0x00000204, 0x600010FF, 21362306a36Sopenharmony_ci 0x00000200, 0xE0300090, 21462306a36Sopenharmony_ci 0x00000204, 0x00030303, 21562306a36Sopenharmony_ci 0x00000200, 0xE030008C, 21662306a36Sopenharmony_ci 0x00000204, 0x600010FF, 21762306a36Sopenharmony_ci 0x00000200, 0xE03000AC, 21862306a36Sopenharmony_ci 0x00000204, 0x00030303, 21962306a36Sopenharmony_ci 0x00000200, 0xE03000A8, 22062306a36Sopenharmony_ci 0x00000204, 0x600010FF, 22162306a36Sopenharmony_ci 0x00000200, 0xE03000C8, 22262306a36Sopenharmony_ci 0x00000204, 0x00030303, 22362306a36Sopenharmony_ci 0x00000200, 0xE03000C4, 22462306a36Sopenharmony_ci 0x00000204, 0x600010FF, 22562306a36Sopenharmony_ci 0x00000200, 0xE03000E4, 22662306a36Sopenharmony_ci 0x00000204, 0x00030303, 22762306a36Sopenharmony_ci 0x00000200, 0xE03000E0, 22862306a36Sopenharmony_ci 0x00000204, 0x600010FF, 22962306a36Sopenharmony_ci 0x00000200, 0xE0300100, 23062306a36Sopenharmony_ci 0x00000204, 0x00030303, 23162306a36Sopenharmony_ci 0x00000200, 0xE03000FC, 23262306a36Sopenharmony_ci 0x00000204, 0x600010FF, 23362306a36Sopenharmony_ci 0x00000200, 0xE0300058, 23462306a36Sopenharmony_ci 0x00000204, 0x00030303, 23562306a36Sopenharmony_ci 0x00000200, 0xE0300054, 23662306a36Sopenharmony_ci 0x00000204, 0x700010FF, 23762306a36Sopenharmony_ci 0x00000200, 0xE0300074, 23862306a36Sopenharmony_ci 0x00000204, 0x00030303, 23962306a36Sopenharmony_ci 0x00000200, 0xE0300070, 24062306a36Sopenharmony_ci 0x00000204, 0x700010FF, 24162306a36Sopenharmony_ci 0x00000200, 0xE0300090, 24262306a36Sopenharmony_ci 0x00000204, 0x00030303, 24362306a36Sopenharmony_ci 0x00000200, 0xE030008C, 24462306a36Sopenharmony_ci 0x00000204, 0x700010FF, 24562306a36Sopenharmony_ci 0x00000200, 0xE03000AC, 24662306a36Sopenharmony_ci 0x00000204, 0x00030303, 24762306a36Sopenharmony_ci 0x00000200, 0xE03000A8, 24862306a36Sopenharmony_ci 0x00000204, 0x700010FF, 24962306a36Sopenharmony_ci 0x00000200, 0xE03000C8, 25062306a36Sopenharmony_ci 0x00000204, 0x00030303, 25162306a36Sopenharmony_ci 0x00000200, 0xE03000C4, 25262306a36Sopenharmony_ci 0x00000204, 0x700010FF, 25362306a36Sopenharmony_ci 0x00000200, 0xE03000E4, 25462306a36Sopenharmony_ci 0x00000204, 0x00030303, 25562306a36Sopenharmony_ci 0x00000200, 0xE03000E0, 25662306a36Sopenharmony_ci 0x00000204, 0x700010FF, 25762306a36Sopenharmony_ci 0x00000200, 0xE0300100, 25862306a36Sopenharmony_ci 0x00000204, 0x00030303, 25962306a36Sopenharmony_ci 0x00000200, 0xE03000FC, 26062306a36Sopenharmony_ci 0x00000204, 0x700010FF, 26162306a36Sopenharmony_ci 0x00000200, 0xE0300058, 26262306a36Sopenharmony_ci 0x00000204, 0x00010303, 26362306a36Sopenharmony_ci 0x00000200, 0xE0300054, 26462306a36Sopenharmony_ci 0x00000204, 0x800010FF, 26562306a36Sopenharmony_ci 0x00000200, 0xE0300074, 26662306a36Sopenharmony_ci 0x00000204, 0x00010303, 26762306a36Sopenharmony_ci 0x00000200, 0xE0300070, 26862306a36Sopenharmony_ci 0x00000204, 0x800010FF, 26962306a36Sopenharmony_ci 0x00000200, 0xE0300090, 27062306a36Sopenharmony_ci 0x00000204, 0x00010303, 27162306a36Sopenharmony_ci 0x00000200, 0xE030008C, 27262306a36Sopenharmony_ci 0x00000204, 0x800010FF, 27362306a36Sopenharmony_ci 0x00000200, 0xE03000AC, 27462306a36Sopenharmony_ci 0x00000204, 0x00010303, 27562306a36Sopenharmony_ci 0x00000200, 0xE03000A8, 27662306a36Sopenharmony_ci 0x00000204, 0x800010FF, 27762306a36Sopenharmony_ci 0x00000200, 0xE03000C4, 27862306a36Sopenharmony_ci 0x00000204, 0x800010FF, 27962306a36Sopenharmony_ci 0x00000200, 0xE03000C8, 28062306a36Sopenharmony_ci 0x00000204, 0x00010303, 28162306a36Sopenharmony_ci 0x00000200, 0xE03000E4, 28262306a36Sopenharmony_ci 0x00000204, 0x00010303, 28362306a36Sopenharmony_ci 0x00000200, 0xE03000E0, 28462306a36Sopenharmony_ci 0x00000204, 0x800010FF, 28562306a36Sopenharmony_ci 0x00000200, 0xE0300100, 28662306a36Sopenharmony_ci 0x00000204, 0x00010303, 28762306a36Sopenharmony_ci 0x00000200, 0xE03000FC, 28862306a36Sopenharmony_ci 0x00000204, 0x800010FF, 28962306a36Sopenharmony_ci 0x00000200, 0x0001f198, 29062306a36Sopenharmony_ci 0x00000204, 0x0003ffff, 29162306a36Sopenharmony_ci 0x00000200, 0x0001f19C, 29262306a36Sopenharmony_ci 0x00000204, 0x3fffffff, 29362306a36Sopenharmony_ci 0x00000200, 0xE030032C, 29462306a36Sopenharmony_ci 0x00000204, 0x00000000, 29562306a36Sopenharmony_ci}; 29662306a36Sopenharmony_ci 29762306a36Sopenharmony_cistatic void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 29862306a36Sopenharmony_ci const u32 *seq, u32 count); 29962306a36Sopenharmony_cistatic void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev); 30062306a36Sopenharmony_cistatic void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 30162306a36Sopenharmony_ci struct radeon_ps *new_rps, 30262306a36Sopenharmony_ci struct radeon_ps *old_rps); 30362306a36Sopenharmony_ci 30462306a36Sopenharmony_cistatic struct trinity_ps *trinity_get_ps(struct radeon_ps *rps) 30562306a36Sopenharmony_ci{ 30662306a36Sopenharmony_ci struct trinity_ps *ps = rps->ps_priv; 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return ps; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_cistatic struct trinity_power_info *trinity_get_pi(struct radeon_device *rdev) 31262306a36Sopenharmony_ci{ 31362306a36Sopenharmony_ci struct trinity_power_info *pi = rdev->pm.dpm.priv; 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci return pi; 31662306a36Sopenharmony_ci} 31762306a36Sopenharmony_ci 31862306a36Sopenharmony_cistatic void trinity_gfx_powergating_initialize(struct radeon_device *rdev) 31962306a36Sopenharmony_ci{ 32062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 32162306a36Sopenharmony_ci u32 p, u; 32262306a36Sopenharmony_ci u32 value; 32362306a36Sopenharmony_ci struct atom_clock_dividers dividers; 32462306a36Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 32562306a36Sopenharmony_ci u32 sssd = 1; 32662306a36Sopenharmony_ci int ret; 32762306a36Sopenharmony_ci u32 hw_rev = (RREG32(HW_REV) & ATI_REV_ID_MASK) >> ATI_REV_ID_SHIFT; 32862306a36Sopenharmony_ci 32962306a36Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 33062306a36Sopenharmony_ci 25000, false, ÷rs); 33162306a36Sopenharmony_ci if (ret) 33262306a36Sopenharmony_ci return; 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci value = RREG32_SMC(GFX_POWER_GATING_CNTL); 33562306a36Sopenharmony_ci value &= ~(SSSD_MASK | PDS_DIV_MASK); 33662306a36Sopenharmony_ci if (sssd) 33762306a36Sopenharmony_ci value |= SSSD(1); 33862306a36Sopenharmony_ci value |= PDS_DIV(dividers.post_div); 33962306a36Sopenharmony_ci WREG32_SMC(GFX_POWER_GATING_CNTL, value); 34062306a36Sopenharmony_ci 34162306a36Sopenharmony_ci r600_calculate_u_and_p(500, xclk, 16, &p, &u); 34262306a36Sopenharmony_ci 34362306a36Sopenharmony_ci WREG32(CG_PG_CTRL, SP(p) | SU(u)); 34462306a36Sopenharmony_ci 34562306a36Sopenharmony_ci WREG32_P(CG_GIPOTS, CG_GIPOT(p), ~CG_GIPOT_MASK); 34662306a36Sopenharmony_ci 34762306a36Sopenharmony_ci /* XXX double check hw_rev */ 34862306a36Sopenharmony_ci if (pi->override_dynamic_mgpg && (hw_rev == 0)) 34962306a36Sopenharmony_ci trinity_override_dynamic_mg_powergating(rdev); 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_ci} 35262306a36Sopenharmony_ci 35362306a36Sopenharmony_ci#define CGCG_CGTT_LOCAL0_MASK 0xFFFF33FF 35462306a36Sopenharmony_ci#define CGCG_CGTT_LOCAL1_MASK 0xFFFB0FFE 35562306a36Sopenharmony_ci#define CGTS_SM_CTRL_REG_DISABLE 0x00600000 35662306a36Sopenharmony_ci#define CGTS_SM_CTRL_REG_ENABLE 0x96944200 35762306a36Sopenharmony_ci 35862306a36Sopenharmony_cistatic void trinity_mg_clockgating_enable(struct radeon_device *rdev, 35962306a36Sopenharmony_ci bool enable) 36062306a36Sopenharmony_ci{ 36162306a36Sopenharmony_ci u32 local0; 36262306a36Sopenharmony_ci u32 local1; 36362306a36Sopenharmony_ci 36462306a36Sopenharmony_ci if (enable) { 36562306a36Sopenharmony_ci local0 = RREG32_CG(CG_CGTT_LOCAL_0); 36662306a36Sopenharmony_ci local1 = RREG32_CG(CG_CGTT_LOCAL_1); 36762306a36Sopenharmony_ci 36862306a36Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_0, 36962306a36Sopenharmony_ci (0x00380000 & CGCG_CGTT_LOCAL0_MASK) | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 37062306a36Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_1, 37162306a36Sopenharmony_ci (0x0E000000 & CGCG_CGTT_LOCAL1_MASK) | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 37262306a36Sopenharmony_ci 37362306a36Sopenharmony_ci WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_ENABLE); 37462306a36Sopenharmony_ci } else { 37562306a36Sopenharmony_ci WREG32(CGTS_SM_CTRL_REG, CGTS_SM_CTRL_REG_DISABLE); 37662306a36Sopenharmony_ci 37762306a36Sopenharmony_ci local0 = RREG32_CG(CG_CGTT_LOCAL_0); 37862306a36Sopenharmony_ci local1 = RREG32_CG(CG_CGTT_LOCAL_1); 37962306a36Sopenharmony_ci 38062306a36Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_0, 38162306a36Sopenharmony_ci CGCG_CGTT_LOCAL0_MASK | (local0 & ~CGCG_CGTT_LOCAL0_MASK) ); 38262306a36Sopenharmony_ci WREG32_CG(CG_CGTT_LOCAL_1, 38362306a36Sopenharmony_ci CGCG_CGTT_LOCAL1_MASK | (local1 & ~CGCG_CGTT_LOCAL1_MASK) ); 38462306a36Sopenharmony_ci } 38562306a36Sopenharmony_ci} 38662306a36Sopenharmony_ci 38762306a36Sopenharmony_cistatic void trinity_mg_clockgating_initialize(struct radeon_device *rdev) 38862306a36Sopenharmony_ci{ 38962306a36Sopenharmony_ci u32 count; 39062306a36Sopenharmony_ci const u32 *seq = NULL; 39162306a36Sopenharmony_ci 39262306a36Sopenharmony_ci seq = &trinity_mgcg_shls_default[0]; 39362306a36Sopenharmony_ci count = sizeof(trinity_mgcg_shls_default) / (3 * sizeof(u32)); 39462306a36Sopenharmony_ci 39562306a36Sopenharmony_ci trinity_program_clk_gating_hw_sequence(rdev, seq, count); 39662306a36Sopenharmony_ci} 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_cistatic void trinity_gfx_clockgating_enable(struct radeon_device *rdev, 39962306a36Sopenharmony_ci bool enable) 40062306a36Sopenharmony_ci{ 40162306a36Sopenharmony_ci if (enable) { 40262306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_GFX_CLK_OFF_EN, ~DYN_GFX_CLK_OFF_EN); 40362306a36Sopenharmony_ci } else { 40462306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_GFX_CLK_OFF_EN); 40562306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, GFX_CLK_FORCE_ON, ~GFX_CLK_FORCE_ON); 40662306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~GFX_CLK_FORCE_ON); 40762306a36Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci} 41062306a36Sopenharmony_ci 41162306a36Sopenharmony_cistatic void trinity_program_clk_gating_hw_sequence(struct radeon_device *rdev, 41262306a36Sopenharmony_ci const u32 *seq, u32 count) 41362306a36Sopenharmony_ci{ 41462306a36Sopenharmony_ci u32 i, length = count * 3; 41562306a36Sopenharmony_ci 41662306a36Sopenharmony_ci for (i = 0; i < length; i += 3) 41762306a36Sopenharmony_ci WREG32_P(seq[i], seq[i+1], ~seq[i+2]); 41862306a36Sopenharmony_ci} 41962306a36Sopenharmony_ci 42062306a36Sopenharmony_cistatic void trinity_program_override_mgpg_sequences(struct radeon_device *rdev, 42162306a36Sopenharmony_ci const u32 *seq, u32 count) 42262306a36Sopenharmony_ci{ 42362306a36Sopenharmony_ci u32 i, length = count * 2; 42462306a36Sopenharmony_ci 42562306a36Sopenharmony_ci for (i = 0; i < length; i += 2) 42662306a36Sopenharmony_ci WREG32(seq[i], seq[i+1]); 42762306a36Sopenharmony_ci 42862306a36Sopenharmony_ci} 42962306a36Sopenharmony_ci 43062306a36Sopenharmony_cistatic void trinity_override_dynamic_mg_powergating(struct radeon_device *rdev) 43162306a36Sopenharmony_ci{ 43262306a36Sopenharmony_ci u32 count; 43362306a36Sopenharmony_ci const u32 *seq = NULL; 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci seq = &trinity_override_mgpg_sequences[0]; 43662306a36Sopenharmony_ci count = sizeof(trinity_override_mgpg_sequences) / (2 * sizeof(u32)); 43762306a36Sopenharmony_ci 43862306a36Sopenharmony_ci trinity_program_override_mgpg_sequences(rdev, seq, count); 43962306a36Sopenharmony_ci} 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_cistatic void trinity_ls_clockgating_enable(struct radeon_device *rdev, 44262306a36Sopenharmony_ci bool enable) 44362306a36Sopenharmony_ci{ 44462306a36Sopenharmony_ci u32 count; 44562306a36Sopenharmony_ci const u32 *seq = NULL; 44662306a36Sopenharmony_ci 44762306a36Sopenharmony_ci if (enable) { 44862306a36Sopenharmony_ci seq = &trinity_sysls_enable[0]; 44962306a36Sopenharmony_ci count = sizeof(trinity_sysls_enable) / (3 * sizeof(u32)); 45062306a36Sopenharmony_ci } else { 45162306a36Sopenharmony_ci seq = &trinity_sysls_disable[0]; 45262306a36Sopenharmony_ci count = sizeof(trinity_sysls_disable) / (3 * sizeof(u32)); 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci trinity_program_clk_gating_hw_sequence(rdev, seq, count); 45662306a36Sopenharmony_ci} 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic void trinity_gfx_powergating_enable(struct radeon_device *rdev, 45962306a36Sopenharmony_ci bool enable) 46062306a36Sopenharmony_ci{ 46162306a36Sopenharmony_ci if (enable) { 46262306a36Sopenharmony_ci if (RREG32_SMC(CC_SMU_TST_EFUSE1_MISC) & RB_BACKEND_DISABLE_MASK) 46362306a36Sopenharmony_ci WREG32_SMC(SMU_SCRATCH_A, (RREG32_SMC(SMU_SCRATCH_A) | 0x01)); 46462306a36Sopenharmony_ci 46562306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, DYN_PWR_DOWN_EN, ~DYN_PWR_DOWN_EN); 46662306a36Sopenharmony_ci } else { 46762306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~DYN_PWR_DOWN_EN); 46862306a36Sopenharmony_ci RREG32(GB_ADDR_CONFIG); 46962306a36Sopenharmony_ci } 47062306a36Sopenharmony_ci} 47162306a36Sopenharmony_ci 47262306a36Sopenharmony_cistatic void trinity_gfx_dynamic_mgpg_enable(struct radeon_device *rdev, 47362306a36Sopenharmony_ci bool enable) 47462306a36Sopenharmony_ci{ 47562306a36Sopenharmony_ci u32 value; 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci if (enable) { 47862306a36Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 47962306a36Sopenharmony_ci value &= ~DS_PG_CNTL_MASK; 48062306a36Sopenharmony_ci value |= DS_PG_CNTL(1); 48162306a36Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 48262306a36Sopenharmony_ci 48362306a36Sopenharmony_ci value = RREG32_SMC(SMU_S_PG_CNTL); 48462306a36Sopenharmony_ci value &= ~DS_PG_EN_MASK; 48562306a36Sopenharmony_ci value |= DS_PG_EN(1); 48662306a36Sopenharmony_ci WREG32_SMC(SMU_S_PG_CNTL, value); 48762306a36Sopenharmony_ci } else { 48862306a36Sopenharmony_ci value = RREG32_SMC(SMU_S_PG_CNTL); 48962306a36Sopenharmony_ci value &= ~DS_PG_EN_MASK; 49062306a36Sopenharmony_ci WREG32_SMC(SMU_S_PG_CNTL, value); 49162306a36Sopenharmony_ci 49262306a36Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 49362306a36Sopenharmony_ci value &= ~DS_PG_CNTL_MASK; 49462306a36Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 49562306a36Sopenharmony_ci } 49662306a36Sopenharmony_ci 49762306a36Sopenharmony_ci trinity_gfx_dynamic_mgpg_config(rdev); 49862306a36Sopenharmony_ci 49962306a36Sopenharmony_ci} 50062306a36Sopenharmony_ci 50162306a36Sopenharmony_cistatic void trinity_enable_clock_power_gating(struct radeon_device *rdev) 50262306a36Sopenharmony_ci{ 50362306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 50462306a36Sopenharmony_ci 50562306a36Sopenharmony_ci if (pi->enable_gfx_clock_gating) 50662306a36Sopenharmony_ci sumo_gfx_clockgating_initialize(rdev); 50762306a36Sopenharmony_ci if (pi->enable_mg_clock_gating) 50862306a36Sopenharmony_ci trinity_mg_clockgating_initialize(rdev); 50962306a36Sopenharmony_ci if (pi->enable_gfx_power_gating) 51062306a36Sopenharmony_ci trinity_gfx_powergating_initialize(rdev); 51162306a36Sopenharmony_ci if (pi->enable_mg_clock_gating) { 51262306a36Sopenharmony_ci trinity_ls_clockgating_enable(rdev, true); 51362306a36Sopenharmony_ci trinity_mg_clockgating_enable(rdev, true); 51462306a36Sopenharmony_ci } 51562306a36Sopenharmony_ci if (pi->enable_gfx_clock_gating) 51662306a36Sopenharmony_ci trinity_gfx_clockgating_enable(rdev, true); 51762306a36Sopenharmony_ci if (pi->enable_gfx_dynamic_mgpg) 51862306a36Sopenharmony_ci trinity_gfx_dynamic_mgpg_enable(rdev, true); 51962306a36Sopenharmony_ci if (pi->enable_gfx_power_gating) 52062306a36Sopenharmony_ci trinity_gfx_powergating_enable(rdev, true); 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_cistatic void trinity_disable_clock_power_gating(struct radeon_device *rdev) 52462306a36Sopenharmony_ci{ 52562306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 52662306a36Sopenharmony_ci 52762306a36Sopenharmony_ci if (pi->enable_gfx_power_gating) 52862306a36Sopenharmony_ci trinity_gfx_powergating_enable(rdev, false); 52962306a36Sopenharmony_ci if (pi->enable_gfx_dynamic_mgpg) 53062306a36Sopenharmony_ci trinity_gfx_dynamic_mgpg_enable(rdev, false); 53162306a36Sopenharmony_ci if (pi->enable_gfx_clock_gating) 53262306a36Sopenharmony_ci trinity_gfx_clockgating_enable(rdev, false); 53362306a36Sopenharmony_ci if (pi->enable_mg_clock_gating) { 53462306a36Sopenharmony_ci trinity_mg_clockgating_enable(rdev, false); 53562306a36Sopenharmony_ci trinity_ls_clockgating_enable(rdev, false); 53662306a36Sopenharmony_ci } 53762306a36Sopenharmony_ci} 53862306a36Sopenharmony_ci 53962306a36Sopenharmony_cistatic void trinity_set_divider_value(struct radeon_device *rdev, 54062306a36Sopenharmony_ci u32 index, u32 sclk) 54162306a36Sopenharmony_ci{ 54262306a36Sopenharmony_ci struct atom_clock_dividers dividers; 54362306a36Sopenharmony_ci int ret; 54462306a36Sopenharmony_ci u32 value; 54562306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 54862306a36Sopenharmony_ci sclk, false, ÷rs); 54962306a36Sopenharmony_ci if (ret) 55062306a36Sopenharmony_ci return; 55162306a36Sopenharmony_ci 55262306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 55362306a36Sopenharmony_ci value &= ~CLK_DIVIDER_MASK; 55462306a36Sopenharmony_ci value |= CLK_DIVIDER(dividers.post_div); 55562306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 55662306a36Sopenharmony_ci 55762306a36Sopenharmony_ci ret = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM, 55862306a36Sopenharmony_ci sclk/2, false, ÷rs); 55962306a36Sopenharmony_ci if (ret) 56062306a36Sopenharmony_ci return; 56162306a36Sopenharmony_ci 56262306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix); 56362306a36Sopenharmony_ci value &= ~PD_SCLK_DIVIDER_MASK; 56462306a36Sopenharmony_ci value |= PD_SCLK_DIVIDER(dividers.post_div); 56562306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_PG_CNTL + ix, value); 56662306a36Sopenharmony_ci} 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic void trinity_set_ds_dividers(struct radeon_device *rdev, 56962306a36Sopenharmony_ci u32 index, u32 divider) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci u32 value; 57262306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 57362306a36Sopenharmony_ci 57462306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 57562306a36Sopenharmony_ci value &= ~DS_DIV_MASK; 57662306a36Sopenharmony_ci value |= DS_DIV(divider); 57762306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 57862306a36Sopenharmony_ci} 57962306a36Sopenharmony_ci 58062306a36Sopenharmony_cistatic void trinity_set_ss_dividers(struct radeon_device *rdev, 58162306a36Sopenharmony_ci u32 index, u32 divider) 58262306a36Sopenharmony_ci{ 58362306a36Sopenharmony_ci u32 value; 58462306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 58562306a36Sopenharmony_ci 58662306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 58762306a36Sopenharmony_ci value &= ~DS_SH_DIV_MASK; 58862306a36Sopenharmony_ci value |= DS_SH_DIV(divider); 58962306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 59062306a36Sopenharmony_ci} 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_cistatic void trinity_set_vid(struct radeon_device *rdev, u32 index, u32 vid) 59362306a36Sopenharmony_ci{ 59462306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 59562306a36Sopenharmony_ci u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid); 59662306a36Sopenharmony_ci u32 value; 59762306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 60062306a36Sopenharmony_ci value &= ~VID_MASK; 60162306a36Sopenharmony_ci value |= VID(vid_7bit); 60262306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 60362306a36Sopenharmony_ci 60462306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 60562306a36Sopenharmony_ci value &= ~LVRT_MASK; 60662306a36Sopenharmony_ci value |= LVRT(0); 60762306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 60862306a36Sopenharmony_ci} 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_cistatic void trinity_set_allos_gnb_slow(struct radeon_device *rdev, 61162306a36Sopenharmony_ci u32 index, u32 gnb_slow) 61262306a36Sopenharmony_ci{ 61362306a36Sopenharmony_ci u32 value; 61462306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 61762306a36Sopenharmony_ci value &= ~GNB_SLOW_MASK; 61862306a36Sopenharmony_ci value |= GNB_SLOW(gnb_slow); 61962306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 62062306a36Sopenharmony_ci} 62162306a36Sopenharmony_ci 62262306a36Sopenharmony_cistatic void trinity_set_force_nbp_state(struct radeon_device *rdev, 62362306a36Sopenharmony_ci u32 index, u32 force_nbp_state) 62462306a36Sopenharmony_ci{ 62562306a36Sopenharmony_ci u32 value; 62662306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix); 62962306a36Sopenharmony_ci value &= ~FORCE_NBPS1_MASK; 63062306a36Sopenharmony_ci value |= FORCE_NBPS1(force_nbp_state); 63162306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_3 + ix, value); 63262306a36Sopenharmony_ci} 63362306a36Sopenharmony_ci 63462306a36Sopenharmony_cistatic void trinity_set_display_wm(struct radeon_device *rdev, 63562306a36Sopenharmony_ci u32 index, u32 wm) 63662306a36Sopenharmony_ci{ 63762306a36Sopenharmony_ci u32 value; 63862306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 63962306a36Sopenharmony_ci 64062306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 64162306a36Sopenharmony_ci value &= ~DISPLAY_WM_MASK; 64262306a36Sopenharmony_ci value |= DISPLAY_WM(wm); 64362306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 64462306a36Sopenharmony_ci} 64562306a36Sopenharmony_ci 64662306a36Sopenharmony_cistatic void trinity_set_vce_wm(struct radeon_device *rdev, 64762306a36Sopenharmony_ci u32 index, u32 wm) 64862306a36Sopenharmony_ci{ 64962306a36Sopenharmony_ci u32 value; 65062306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 65162306a36Sopenharmony_ci 65262306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix); 65362306a36Sopenharmony_ci value &= ~VCE_WM_MASK; 65462306a36Sopenharmony_ci value |= VCE_WM(wm); 65562306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_1 + ix, value); 65662306a36Sopenharmony_ci} 65762306a36Sopenharmony_ci 65862306a36Sopenharmony_cistatic void trinity_set_at(struct radeon_device *rdev, 65962306a36Sopenharmony_ci u32 index, u32 at) 66062306a36Sopenharmony_ci{ 66162306a36Sopenharmony_ci u32 value; 66262306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix); 66562306a36Sopenharmony_ci value &= ~AT_MASK; 66662306a36Sopenharmony_ci value |= AT(at); 66762306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_AT + ix, value); 66862306a36Sopenharmony_ci} 66962306a36Sopenharmony_ci 67062306a36Sopenharmony_cistatic void trinity_program_power_level(struct radeon_device *rdev, 67162306a36Sopenharmony_ci struct trinity_pl *pl, u32 index) 67262306a36Sopenharmony_ci{ 67362306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 67462306a36Sopenharmony_ci 67562306a36Sopenharmony_ci if (index >= SUMO_MAX_HARDWARE_POWERLEVELS) 67662306a36Sopenharmony_ci return; 67762306a36Sopenharmony_ci 67862306a36Sopenharmony_ci trinity_set_divider_value(rdev, index, pl->sclk); 67962306a36Sopenharmony_ci trinity_set_vid(rdev, index, pl->vddc_index); 68062306a36Sopenharmony_ci trinity_set_ss_dividers(rdev, index, pl->ss_divider_index); 68162306a36Sopenharmony_ci trinity_set_ds_dividers(rdev, index, pl->ds_divider_index); 68262306a36Sopenharmony_ci trinity_set_allos_gnb_slow(rdev, index, pl->allow_gnb_slow); 68362306a36Sopenharmony_ci trinity_set_force_nbp_state(rdev, index, pl->force_nbp_state); 68462306a36Sopenharmony_ci trinity_set_display_wm(rdev, index, pl->display_wm); 68562306a36Sopenharmony_ci trinity_set_vce_wm(rdev, index, pl->vce_wm); 68662306a36Sopenharmony_ci trinity_set_at(rdev, index, pi->at[index]); 68762306a36Sopenharmony_ci} 68862306a36Sopenharmony_ci 68962306a36Sopenharmony_cistatic void trinity_power_level_enable_disable(struct radeon_device *rdev, 69062306a36Sopenharmony_ci u32 index, bool enable) 69162306a36Sopenharmony_ci{ 69262306a36Sopenharmony_ci u32 value; 69362306a36Sopenharmony_ci u32 ix = index * TRINITY_SIZEOF_DPM_STATE_TABLE; 69462306a36Sopenharmony_ci 69562306a36Sopenharmony_ci value = RREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix); 69662306a36Sopenharmony_ci value &= ~STATE_VALID_MASK; 69762306a36Sopenharmony_ci if (enable) 69862306a36Sopenharmony_ci value |= STATE_VALID(1); 69962306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_STATE_0_CNTL_0 + ix, value); 70062306a36Sopenharmony_ci} 70162306a36Sopenharmony_ci 70262306a36Sopenharmony_cistatic bool trinity_dpm_enabled(struct radeon_device *rdev) 70362306a36Sopenharmony_ci{ 70462306a36Sopenharmony_ci if (RREG32_SMC(SMU_SCLK_DPM_CNTL) & SCLK_DPM_EN(1)) 70562306a36Sopenharmony_ci return true; 70662306a36Sopenharmony_ci else 70762306a36Sopenharmony_ci return false; 70862306a36Sopenharmony_ci} 70962306a36Sopenharmony_ci 71062306a36Sopenharmony_cistatic void trinity_start_dpm(struct radeon_device *rdev) 71162306a36Sopenharmony_ci{ 71262306a36Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_CNTL); 71362306a36Sopenharmony_ci 71462306a36Sopenharmony_ci value &= ~(SCLK_DPM_EN_MASK | SCLK_DPM_BOOT_STATE_MASK | VOLTAGE_CHG_EN_MASK); 71562306a36Sopenharmony_ci value |= SCLK_DPM_EN(1) | SCLK_DPM_BOOT_STATE(0) | VOLTAGE_CHG_EN(1); 71662306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_CNTL, value); 71762306a36Sopenharmony_ci 71862306a36Sopenharmony_ci WREG32_P(GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, ~GLOBAL_PWRMGT_EN); 71962306a36Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, 0, ~EN); 72062306a36Sopenharmony_ci 72162306a36Sopenharmony_ci trinity_dpm_config(rdev, true); 72262306a36Sopenharmony_ci} 72362306a36Sopenharmony_ci 72462306a36Sopenharmony_cistatic void trinity_wait_for_dpm_enabled(struct radeon_device *rdev) 72562306a36Sopenharmony_ci{ 72662306a36Sopenharmony_ci int i; 72762306a36Sopenharmony_ci 72862306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 72962306a36Sopenharmony_ci if (RREG32(SCLK_PWRMGT_CNTL) & DYNAMIC_PM_EN) 73062306a36Sopenharmony_ci break; 73162306a36Sopenharmony_ci udelay(1); 73262306a36Sopenharmony_ci } 73362306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 73462306a36Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & TARGET_STATE_MASK) == 0) 73562306a36Sopenharmony_ci break; 73662306a36Sopenharmony_ci udelay(1); 73762306a36Sopenharmony_ci } 73862306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 73962306a36Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 74062306a36Sopenharmony_ci break; 74162306a36Sopenharmony_ci udelay(1); 74262306a36Sopenharmony_ci } 74362306a36Sopenharmony_ci} 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_cistatic void trinity_stop_dpm(struct radeon_device *rdev) 74662306a36Sopenharmony_ci{ 74762306a36Sopenharmony_ci u32 sclk_dpm_cntl; 74862306a36Sopenharmony_ci 74962306a36Sopenharmony_ci WREG32_P(CG_CG_VOLTAGE_CNTL, EN, ~EN); 75062306a36Sopenharmony_ci 75162306a36Sopenharmony_ci sclk_dpm_cntl = RREG32_SMC(SMU_SCLK_DPM_CNTL); 75262306a36Sopenharmony_ci sclk_dpm_cntl &= ~(SCLK_DPM_EN_MASK | VOLTAGE_CHG_EN_MASK); 75362306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_CNTL, sclk_dpm_cntl); 75462306a36Sopenharmony_ci 75562306a36Sopenharmony_ci trinity_dpm_config(rdev, false); 75662306a36Sopenharmony_ci} 75762306a36Sopenharmony_ci 75862306a36Sopenharmony_cistatic void trinity_start_am(struct radeon_device *rdev) 75962306a36Sopenharmony_ci{ 76062306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, 0, ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 76162306a36Sopenharmony_ci} 76262306a36Sopenharmony_ci 76362306a36Sopenharmony_cistatic void trinity_reset_am(struct radeon_device *rdev) 76462306a36Sopenharmony_ci{ 76562306a36Sopenharmony_ci WREG32_P(SCLK_PWRMGT_CNTL, RESET_SCLK_CNT | RESET_BUSY_CNT, 76662306a36Sopenharmony_ci ~(RESET_SCLK_CNT | RESET_BUSY_CNT)); 76762306a36Sopenharmony_ci} 76862306a36Sopenharmony_ci 76962306a36Sopenharmony_cistatic void trinity_wait_for_level_0(struct radeon_device *rdev) 77062306a36Sopenharmony_ci{ 77162306a36Sopenharmony_ci int i; 77262306a36Sopenharmony_ci 77362306a36Sopenharmony_ci for (i = 0; i < rdev->usec_timeout; i++) { 77462306a36Sopenharmony_ci if ((RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) == 0) 77562306a36Sopenharmony_ci break; 77662306a36Sopenharmony_ci udelay(1); 77762306a36Sopenharmony_ci } 77862306a36Sopenharmony_ci} 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_cistatic void trinity_enable_power_level_0(struct radeon_device *rdev) 78162306a36Sopenharmony_ci{ 78262306a36Sopenharmony_ci trinity_power_level_enable_disable(rdev, 0, true); 78362306a36Sopenharmony_ci} 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_cistatic void trinity_force_level_0(struct radeon_device *rdev) 78662306a36Sopenharmony_ci{ 78762306a36Sopenharmony_ci trinity_dpm_force_state(rdev, 0); 78862306a36Sopenharmony_ci} 78962306a36Sopenharmony_ci 79062306a36Sopenharmony_cistatic void trinity_unforce_levels(struct radeon_device *rdev) 79162306a36Sopenharmony_ci{ 79262306a36Sopenharmony_ci trinity_dpm_no_forced_level(rdev); 79362306a36Sopenharmony_ci} 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_cistatic void trinity_program_power_levels_0_to_n(struct radeon_device *rdev, 79662306a36Sopenharmony_ci struct radeon_ps *new_rps, 79762306a36Sopenharmony_ci struct radeon_ps *old_rps) 79862306a36Sopenharmony_ci{ 79962306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 80062306a36Sopenharmony_ci struct trinity_ps *old_ps = trinity_get_ps(old_rps); 80162306a36Sopenharmony_ci u32 i; 80262306a36Sopenharmony_ci u32 n_current_state_levels = (old_ps == NULL) ? 1 : old_ps->num_levels; 80362306a36Sopenharmony_ci 80462306a36Sopenharmony_ci for (i = 0; i < new_ps->num_levels; i++) { 80562306a36Sopenharmony_ci trinity_program_power_level(rdev, &new_ps->levels[i], i); 80662306a36Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, true); 80762306a36Sopenharmony_ci } 80862306a36Sopenharmony_ci 80962306a36Sopenharmony_ci for (i = new_ps->num_levels; i < n_current_state_levels; i++) 81062306a36Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, false); 81162306a36Sopenharmony_ci} 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_cistatic void trinity_program_bootup_state(struct radeon_device *rdev) 81462306a36Sopenharmony_ci{ 81562306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 81662306a36Sopenharmony_ci u32 i; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci trinity_program_power_level(rdev, &pi->boot_pl, 0); 81962306a36Sopenharmony_ci trinity_power_level_enable_disable(rdev, 0, true); 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci for (i = 1; i < 8; i++) 82262306a36Sopenharmony_ci trinity_power_level_enable_disable(rdev, i, false); 82362306a36Sopenharmony_ci} 82462306a36Sopenharmony_ci 82562306a36Sopenharmony_cistatic void trinity_setup_uvd_clock_table(struct radeon_device *rdev, 82662306a36Sopenharmony_ci struct radeon_ps *rps) 82762306a36Sopenharmony_ci{ 82862306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 82962306a36Sopenharmony_ci u32 uvdstates = (ps->vclk_low_divider | 83062306a36Sopenharmony_ci ps->vclk_high_divider << 8 | 83162306a36Sopenharmony_ci ps->dclk_low_divider << 16 | 83262306a36Sopenharmony_ci ps->dclk_high_divider << 24); 83362306a36Sopenharmony_ci 83462306a36Sopenharmony_ci WREG32_SMC(SMU_UVD_DPM_STATES, uvdstates); 83562306a36Sopenharmony_ci} 83662306a36Sopenharmony_ci 83762306a36Sopenharmony_cistatic void trinity_setup_uvd_dpm_interval(struct radeon_device *rdev, 83862306a36Sopenharmony_ci u32 interval) 83962306a36Sopenharmony_ci{ 84062306a36Sopenharmony_ci u32 p, u; 84162306a36Sopenharmony_ci u32 tp = RREG32_SMC(PM_TP); 84262306a36Sopenharmony_ci u32 val; 84362306a36Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 84462306a36Sopenharmony_ci 84562306a36Sopenharmony_ci r600_calculate_u_and_p(interval, xclk, 16, &p, &u); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci val = (p + tp - 1) / tp; 84862306a36Sopenharmony_ci 84962306a36Sopenharmony_ci WREG32_SMC(SMU_UVD_DPM_CNTL, val); 85062306a36Sopenharmony_ci} 85162306a36Sopenharmony_ci 85262306a36Sopenharmony_cistatic bool trinity_uvd_clocks_zero(struct radeon_ps *rps) 85362306a36Sopenharmony_ci{ 85462306a36Sopenharmony_ci if ((rps->vclk == 0) && (rps->dclk == 0)) 85562306a36Sopenharmony_ci return true; 85662306a36Sopenharmony_ci else 85762306a36Sopenharmony_ci return false; 85862306a36Sopenharmony_ci} 85962306a36Sopenharmony_ci 86062306a36Sopenharmony_cistatic bool trinity_uvd_clocks_equal(struct radeon_ps *rps1, 86162306a36Sopenharmony_ci struct radeon_ps *rps2) 86262306a36Sopenharmony_ci{ 86362306a36Sopenharmony_ci struct trinity_ps *ps1 = trinity_get_ps(rps1); 86462306a36Sopenharmony_ci struct trinity_ps *ps2 = trinity_get_ps(rps2); 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_ci if ((rps1->vclk == rps2->vclk) && 86762306a36Sopenharmony_ci (rps1->dclk == rps2->dclk) && 86862306a36Sopenharmony_ci (ps1->vclk_low_divider == ps2->vclk_low_divider) && 86962306a36Sopenharmony_ci (ps1->vclk_high_divider == ps2->vclk_high_divider) && 87062306a36Sopenharmony_ci (ps1->dclk_low_divider == ps2->dclk_low_divider) && 87162306a36Sopenharmony_ci (ps1->dclk_high_divider == ps2->dclk_high_divider)) 87262306a36Sopenharmony_ci return true; 87362306a36Sopenharmony_ci else 87462306a36Sopenharmony_ci return false; 87562306a36Sopenharmony_ci} 87662306a36Sopenharmony_ci 87762306a36Sopenharmony_cistatic void trinity_setup_uvd_clocks(struct radeon_device *rdev, 87862306a36Sopenharmony_ci struct radeon_ps *new_rps, 87962306a36Sopenharmony_ci struct radeon_ps *old_rps) 88062306a36Sopenharmony_ci{ 88162306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci if (pi->enable_gfx_power_gating) { 88462306a36Sopenharmony_ci trinity_gfx_powergating_enable(rdev, false); 88562306a36Sopenharmony_ci } 88662306a36Sopenharmony_ci 88762306a36Sopenharmony_ci if (pi->uvd_dpm) { 88862306a36Sopenharmony_ci if (trinity_uvd_clocks_zero(new_rps) && 88962306a36Sopenharmony_ci !trinity_uvd_clocks_zero(old_rps)) { 89062306a36Sopenharmony_ci trinity_setup_uvd_dpm_interval(rdev, 0); 89162306a36Sopenharmony_ci } else if (!trinity_uvd_clocks_zero(new_rps)) { 89262306a36Sopenharmony_ci trinity_setup_uvd_clock_table(rdev, new_rps); 89362306a36Sopenharmony_ci 89462306a36Sopenharmony_ci if (trinity_uvd_clocks_zero(old_rps)) { 89562306a36Sopenharmony_ci u32 tmp = RREG32(CG_MISC_REG); 89662306a36Sopenharmony_ci tmp &= 0xfffffffd; 89762306a36Sopenharmony_ci WREG32(CG_MISC_REG, tmp); 89862306a36Sopenharmony_ci 89962306a36Sopenharmony_ci radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 90062306a36Sopenharmony_ci 90162306a36Sopenharmony_ci trinity_setup_uvd_dpm_interval(rdev, 3000); 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci } 90462306a36Sopenharmony_ci trinity_uvd_dpm_config(rdev); 90562306a36Sopenharmony_ci } else { 90662306a36Sopenharmony_ci if (trinity_uvd_clocks_zero(new_rps) || 90762306a36Sopenharmony_ci trinity_uvd_clocks_equal(new_rps, old_rps)) 90862306a36Sopenharmony_ci return; 90962306a36Sopenharmony_ci 91062306a36Sopenharmony_ci radeon_set_uvd_clocks(rdev, new_rps->vclk, new_rps->dclk); 91162306a36Sopenharmony_ci } 91262306a36Sopenharmony_ci 91362306a36Sopenharmony_ci if (pi->enable_gfx_power_gating) { 91462306a36Sopenharmony_ci trinity_gfx_powergating_enable(rdev, true); 91562306a36Sopenharmony_ci } 91662306a36Sopenharmony_ci} 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_cistatic void trinity_set_uvd_clock_before_set_eng_clock(struct radeon_device *rdev, 91962306a36Sopenharmony_ci struct radeon_ps *new_rps, 92062306a36Sopenharmony_ci struct radeon_ps *old_rps) 92162306a36Sopenharmony_ci{ 92262306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 92362306a36Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(new_rps); 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk >= 92662306a36Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 92762306a36Sopenharmony_ci return; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 93062306a36Sopenharmony_ci} 93162306a36Sopenharmony_ci 93262306a36Sopenharmony_cistatic void trinity_set_uvd_clock_after_set_eng_clock(struct radeon_device *rdev, 93362306a36Sopenharmony_ci struct radeon_ps *new_rps, 93462306a36Sopenharmony_ci struct radeon_ps *old_rps) 93562306a36Sopenharmony_ci{ 93662306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(new_rps); 93762306a36Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(old_rps); 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci if (new_ps->levels[new_ps->num_levels - 1].sclk < 94062306a36Sopenharmony_ci current_ps->levels[current_ps->num_levels - 1].sclk) 94162306a36Sopenharmony_ci return; 94262306a36Sopenharmony_ci 94362306a36Sopenharmony_ci trinity_setup_uvd_clocks(rdev, new_rps, old_rps); 94462306a36Sopenharmony_ci} 94562306a36Sopenharmony_ci 94662306a36Sopenharmony_cistatic void trinity_set_vce_clock(struct radeon_device *rdev, 94762306a36Sopenharmony_ci struct radeon_ps *new_rps, 94862306a36Sopenharmony_ci struct radeon_ps *old_rps) 94962306a36Sopenharmony_ci{ 95062306a36Sopenharmony_ci if ((old_rps->evclk != new_rps->evclk) || 95162306a36Sopenharmony_ci (old_rps->ecclk != new_rps->ecclk)) { 95262306a36Sopenharmony_ci /* turn the clocks on when encoding, off otherwise */ 95362306a36Sopenharmony_ci if (new_rps->evclk || new_rps->ecclk) 95462306a36Sopenharmony_ci vce_v1_0_enable_mgcg(rdev, false); 95562306a36Sopenharmony_ci else 95662306a36Sopenharmony_ci vce_v1_0_enable_mgcg(rdev, true); 95762306a36Sopenharmony_ci radeon_set_vce_clocks(rdev, new_rps->evclk, new_rps->ecclk); 95862306a36Sopenharmony_ci } 95962306a36Sopenharmony_ci} 96062306a36Sopenharmony_ci 96162306a36Sopenharmony_cistatic void trinity_program_ttt(struct radeon_device *rdev) 96262306a36Sopenharmony_ci{ 96362306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 96462306a36Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_TTT); 96562306a36Sopenharmony_ci 96662306a36Sopenharmony_ci value &= ~(HT_MASK | LT_MASK); 96762306a36Sopenharmony_ci value |= HT((pi->thermal_auto_throttling + 49) * 8); 96862306a36Sopenharmony_ci value |= LT((pi->thermal_auto_throttling + 49 - pi->sys_info.htc_hyst_lmt) * 8); 96962306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_TTT, value); 97062306a36Sopenharmony_ci} 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_cistatic void trinity_enable_att(struct radeon_device *rdev) 97362306a36Sopenharmony_ci{ 97462306a36Sopenharmony_ci u32 value = RREG32_SMC(SMU_SCLK_DPM_TT_CNTL); 97562306a36Sopenharmony_ci 97662306a36Sopenharmony_ci value &= ~SCLK_TT_EN_MASK; 97762306a36Sopenharmony_ci value |= SCLK_TT_EN(1); 97862306a36Sopenharmony_ci WREG32_SMC(SMU_SCLK_DPM_TT_CNTL, value); 97962306a36Sopenharmony_ci} 98062306a36Sopenharmony_ci 98162306a36Sopenharmony_cistatic void trinity_program_sclk_dpm(struct radeon_device *rdev) 98262306a36Sopenharmony_ci{ 98362306a36Sopenharmony_ci u32 p, u; 98462306a36Sopenharmony_ci u32 tp = RREG32_SMC(PM_TP); 98562306a36Sopenharmony_ci u32 ni; 98662306a36Sopenharmony_ci u32 xclk = radeon_get_xclk(rdev); 98762306a36Sopenharmony_ci u32 value; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci r600_calculate_u_and_p(400, xclk, 16, &p, &u); 99062306a36Sopenharmony_ci 99162306a36Sopenharmony_ci ni = (p + tp - 1) / tp; 99262306a36Sopenharmony_ci 99362306a36Sopenharmony_ci value = RREG32_SMC(PM_I_CNTL_1); 99462306a36Sopenharmony_ci value &= ~SCLK_DPM_MASK; 99562306a36Sopenharmony_ci value |= SCLK_DPM(ni); 99662306a36Sopenharmony_ci WREG32_SMC(PM_I_CNTL_1, value); 99762306a36Sopenharmony_ci} 99862306a36Sopenharmony_ci 99962306a36Sopenharmony_cistatic int trinity_set_thermal_temperature_range(struct radeon_device *rdev, 100062306a36Sopenharmony_ci int min_temp, int max_temp) 100162306a36Sopenharmony_ci{ 100262306a36Sopenharmony_ci int low_temp = 0 * 1000; 100362306a36Sopenharmony_ci int high_temp = 255 * 1000; 100462306a36Sopenharmony_ci 100562306a36Sopenharmony_ci if (low_temp < min_temp) 100662306a36Sopenharmony_ci low_temp = min_temp; 100762306a36Sopenharmony_ci if (high_temp > max_temp) 100862306a36Sopenharmony_ci high_temp = max_temp; 100962306a36Sopenharmony_ci if (high_temp < low_temp) { 101062306a36Sopenharmony_ci DRM_ERROR("invalid thermal range: %d - %d\n", low_temp, high_temp); 101162306a36Sopenharmony_ci return -EINVAL; 101262306a36Sopenharmony_ci } 101362306a36Sopenharmony_ci 101462306a36Sopenharmony_ci WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTH(49 + (high_temp / 1000)), ~DIG_THERM_INTH_MASK); 101562306a36Sopenharmony_ci WREG32_P(CG_THERMAL_INT_CTRL, DIG_THERM_INTL(49 + (low_temp / 1000)), ~DIG_THERM_INTL_MASK); 101662306a36Sopenharmony_ci 101762306a36Sopenharmony_ci rdev->pm.dpm.thermal.min_temp = low_temp; 101862306a36Sopenharmony_ci rdev->pm.dpm.thermal.max_temp = high_temp; 101962306a36Sopenharmony_ci 102062306a36Sopenharmony_ci return 0; 102162306a36Sopenharmony_ci} 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_cistatic void trinity_update_current_ps(struct radeon_device *rdev, 102462306a36Sopenharmony_ci struct radeon_ps *rps) 102562306a36Sopenharmony_ci{ 102662306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 102762306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci pi->current_rps = *rps; 103062306a36Sopenharmony_ci pi->current_ps = *new_ps; 103162306a36Sopenharmony_ci pi->current_rps.ps_priv = &pi->current_ps; 103262306a36Sopenharmony_ci} 103362306a36Sopenharmony_ci 103462306a36Sopenharmony_cistatic void trinity_update_requested_ps(struct radeon_device *rdev, 103562306a36Sopenharmony_ci struct radeon_ps *rps) 103662306a36Sopenharmony_ci{ 103762306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 103862306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 103962306a36Sopenharmony_ci 104062306a36Sopenharmony_ci pi->requested_rps = *rps; 104162306a36Sopenharmony_ci pi->requested_ps = *new_ps; 104262306a36Sopenharmony_ci pi->requested_rps.ps_priv = &pi->requested_ps; 104362306a36Sopenharmony_ci} 104462306a36Sopenharmony_ci 104562306a36Sopenharmony_civoid trinity_dpm_enable_bapm(struct radeon_device *rdev, bool enable) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 104862306a36Sopenharmony_ci 104962306a36Sopenharmony_ci if (pi->enable_bapm) { 105062306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 105162306a36Sopenharmony_ci trinity_dpm_bapm_enable(rdev, enable); 105262306a36Sopenharmony_ci trinity_release_mutex(rdev); 105362306a36Sopenharmony_ci } 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ciint trinity_dpm_enable(struct radeon_device *rdev) 105762306a36Sopenharmony_ci{ 105862306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 105962306a36Sopenharmony_ci 106062306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 106162306a36Sopenharmony_ci 106262306a36Sopenharmony_ci if (trinity_dpm_enabled(rdev)) { 106362306a36Sopenharmony_ci trinity_release_mutex(rdev); 106462306a36Sopenharmony_ci return -EINVAL; 106562306a36Sopenharmony_ci } 106662306a36Sopenharmony_ci 106762306a36Sopenharmony_ci trinity_program_bootup_state(rdev); 106862306a36Sopenharmony_ci sumo_program_vc(rdev, 0x00C00033); 106962306a36Sopenharmony_ci trinity_start_am(rdev); 107062306a36Sopenharmony_ci if (pi->enable_auto_thermal_throttling) { 107162306a36Sopenharmony_ci trinity_program_ttt(rdev); 107262306a36Sopenharmony_ci trinity_enable_att(rdev); 107362306a36Sopenharmony_ci } 107462306a36Sopenharmony_ci trinity_program_sclk_dpm(rdev); 107562306a36Sopenharmony_ci trinity_start_dpm(rdev); 107662306a36Sopenharmony_ci trinity_wait_for_dpm_enabled(rdev); 107762306a36Sopenharmony_ci trinity_dpm_bapm_enable(rdev, false); 107862306a36Sopenharmony_ci trinity_release_mutex(rdev); 107962306a36Sopenharmony_ci 108062306a36Sopenharmony_ci trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 108162306a36Sopenharmony_ci 108262306a36Sopenharmony_ci return 0; 108362306a36Sopenharmony_ci} 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ciint trinity_dpm_late_enable(struct radeon_device *rdev) 108662306a36Sopenharmony_ci{ 108762306a36Sopenharmony_ci int ret; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 109062306a36Sopenharmony_ci trinity_enable_clock_power_gating(rdev); 109162306a36Sopenharmony_ci 109262306a36Sopenharmony_ci if (rdev->irq.installed && 109362306a36Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 109462306a36Sopenharmony_ci ret = trinity_set_thermal_temperature_range(rdev, R600_TEMP_RANGE_MIN, R600_TEMP_RANGE_MAX); 109562306a36Sopenharmony_ci if (ret) { 109662306a36Sopenharmony_ci trinity_release_mutex(rdev); 109762306a36Sopenharmony_ci return ret; 109862306a36Sopenharmony_ci } 109962306a36Sopenharmony_ci rdev->irq.dpm_thermal = true; 110062306a36Sopenharmony_ci radeon_irq_set(rdev); 110162306a36Sopenharmony_ci } 110262306a36Sopenharmony_ci trinity_release_mutex(rdev); 110362306a36Sopenharmony_ci 110462306a36Sopenharmony_ci return 0; 110562306a36Sopenharmony_ci} 110662306a36Sopenharmony_ci 110762306a36Sopenharmony_civoid trinity_dpm_disable(struct radeon_device *rdev) 110862306a36Sopenharmony_ci{ 110962306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 111062306a36Sopenharmony_ci if (!trinity_dpm_enabled(rdev)) { 111162306a36Sopenharmony_ci trinity_release_mutex(rdev); 111262306a36Sopenharmony_ci return; 111362306a36Sopenharmony_ci } 111462306a36Sopenharmony_ci trinity_dpm_bapm_enable(rdev, false); 111562306a36Sopenharmony_ci trinity_disable_clock_power_gating(rdev); 111662306a36Sopenharmony_ci sumo_clear_vc(rdev); 111762306a36Sopenharmony_ci trinity_wait_for_level_0(rdev); 111862306a36Sopenharmony_ci trinity_stop_dpm(rdev); 111962306a36Sopenharmony_ci trinity_reset_am(rdev); 112062306a36Sopenharmony_ci trinity_release_mutex(rdev); 112162306a36Sopenharmony_ci 112262306a36Sopenharmony_ci if (rdev->irq.installed && 112362306a36Sopenharmony_ci r600_is_internal_thermal_sensor(rdev->pm.int_thermal_type)) { 112462306a36Sopenharmony_ci rdev->irq.dpm_thermal = false; 112562306a36Sopenharmony_ci radeon_irq_set(rdev); 112662306a36Sopenharmony_ci } 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci trinity_update_current_ps(rdev, rdev->pm.dpm.boot_ps); 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic void trinity_get_min_sclk_divider(struct radeon_device *rdev) 113262306a36Sopenharmony_ci{ 113362306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 113462306a36Sopenharmony_ci 113562306a36Sopenharmony_ci pi->min_sclk_did = 113662306a36Sopenharmony_ci (RREG32_SMC(CC_SMU_MISC_FUSES) & MinSClkDid_MASK) >> MinSClkDid_SHIFT; 113762306a36Sopenharmony_ci} 113862306a36Sopenharmony_ci 113962306a36Sopenharmony_cistatic void trinity_setup_nbp_sim(struct radeon_device *rdev, 114062306a36Sopenharmony_ci struct radeon_ps *rps) 114162306a36Sopenharmony_ci{ 114262306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 114362306a36Sopenharmony_ci struct trinity_ps *new_ps = trinity_get_ps(rps); 114462306a36Sopenharmony_ci u32 nbpsconfig; 114562306a36Sopenharmony_ci 114662306a36Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 114762306a36Sopenharmony_ci nbpsconfig = RREG32_SMC(NB_PSTATE_CONFIG); 114862306a36Sopenharmony_ci nbpsconfig &= ~(Dpm0PgNbPsLo_MASK | Dpm0PgNbPsHi_MASK | DpmXNbPsLo_MASK | DpmXNbPsHi_MASK); 114962306a36Sopenharmony_ci nbpsconfig |= (Dpm0PgNbPsLo(new_ps->Dpm0PgNbPsLo) | 115062306a36Sopenharmony_ci Dpm0PgNbPsHi(new_ps->Dpm0PgNbPsHi) | 115162306a36Sopenharmony_ci DpmXNbPsLo(new_ps->DpmXNbPsLo) | 115262306a36Sopenharmony_ci DpmXNbPsHi(new_ps->DpmXNbPsHi)); 115362306a36Sopenharmony_ci WREG32_SMC(NB_PSTATE_CONFIG, nbpsconfig); 115462306a36Sopenharmony_ci } 115562306a36Sopenharmony_ci} 115662306a36Sopenharmony_ci 115762306a36Sopenharmony_ciint trinity_dpm_force_performance_level(struct radeon_device *rdev, 115862306a36Sopenharmony_ci enum radeon_dpm_forced_level level) 115962306a36Sopenharmony_ci{ 116062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 116162306a36Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 116262306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 116362306a36Sopenharmony_ci int i, ret; 116462306a36Sopenharmony_ci 116562306a36Sopenharmony_ci if (ps->num_levels <= 1) 116662306a36Sopenharmony_ci return 0; 116762306a36Sopenharmony_ci 116862306a36Sopenharmony_ci if (level == RADEON_DPM_FORCED_LEVEL_HIGH) { 116962306a36Sopenharmony_ci /* not supported by the hw */ 117062306a36Sopenharmony_ci return -EINVAL; 117162306a36Sopenharmony_ci } else if (level == RADEON_DPM_FORCED_LEVEL_LOW) { 117262306a36Sopenharmony_ci ret = trinity_dpm_n_levels_disabled(rdev, ps->num_levels - 1); 117362306a36Sopenharmony_ci if (ret) 117462306a36Sopenharmony_ci return ret; 117562306a36Sopenharmony_ci } else { 117662306a36Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 117762306a36Sopenharmony_ci ret = trinity_dpm_n_levels_disabled(rdev, 0); 117862306a36Sopenharmony_ci if (ret) 117962306a36Sopenharmony_ci return ret; 118062306a36Sopenharmony_ci } 118162306a36Sopenharmony_ci } 118262306a36Sopenharmony_ci 118362306a36Sopenharmony_ci rdev->pm.dpm.forced_level = level; 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci return 0; 118662306a36Sopenharmony_ci} 118762306a36Sopenharmony_ci 118862306a36Sopenharmony_ciint trinity_dpm_pre_set_power_state(struct radeon_device *rdev) 118962306a36Sopenharmony_ci{ 119062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 119162306a36Sopenharmony_ci struct radeon_ps requested_ps = *rdev->pm.dpm.requested_ps; 119262306a36Sopenharmony_ci struct radeon_ps *new_ps = &requested_ps; 119362306a36Sopenharmony_ci 119462306a36Sopenharmony_ci trinity_update_requested_ps(rdev, new_ps); 119562306a36Sopenharmony_ci 119662306a36Sopenharmony_ci trinity_apply_state_adjust_rules(rdev, 119762306a36Sopenharmony_ci &pi->requested_rps, 119862306a36Sopenharmony_ci &pi->current_rps); 119962306a36Sopenharmony_ci 120062306a36Sopenharmony_ci return 0; 120162306a36Sopenharmony_ci} 120262306a36Sopenharmony_ci 120362306a36Sopenharmony_ciint trinity_dpm_set_power_state(struct radeon_device *rdev) 120462306a36Sopenharmony_ci{ 120562306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 120662306a36Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 120762306a36Sopenharmony_ci struct radeon_ps *old_ps = &pi->current_rps; 120862306a36Sopenharmony_ci 120962306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 121062306a36Sopenharmony_ci if (pi->enable_dpm) { 121162306a36Sopenharmony_ci if (pi->enable_bapm) 121262306a36Sopenharmony_ci trinity_dpm_bapm_enable(rdev, rdev->pm.dpm.ac_power); 121362306a36Sopenharmony_ci trinity_set_uvd_clock_before_set_eng_clock(rdev, new_ps, old_ps); 121462306a36Sopenharmony_ci trinity_enable_power_level_0(rdev); 121562306a36Sopenharmony_ci trinity_force_level_0(rdev); 121662306a36Sopenharmony_ci trinity_wait_for_level_0(rdev); 121762306a36Sopenharmony_ci trinity_setup_nbp_sim(rdev, new_ps); 121862306a36Sopenharmony_ci trinity_program_power_levels_0_to_n(rdev, new_ps, old_ps); 121962306a36Sopenharmony_ci trinity_force_level_0(rdev); 122062306a36Sopenharmony_ci trinity_unforce_levels(rdev); 122162306a36Sopenharmony_ci trinity_set_uvd_clock_after_set_eng_clock(rdev, new_ps, old_ps); 122262306a36Sopenharmony_ci trinity_set_vce_clock(rdev, new_ps, old_ps); 122362306a36Sopenharmony_ci } 122462306a36Sopenharmony_ci trinity_release_mutex(rdev); 122562306a36Sopenharmony_ci 122662306a36Sopenharmony_ci return 0; 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_civoid trinity_dpm_post_set_power_state(struct radeon_device *rdev) 123062306a36Sopenharmony_ci{ 123162306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 123262306a36Sopenharmony_ci struct radeon_ps *new_ps = &pi->requested_rps; 123362306a36Sopenharmony_ci 123462306a36Sopenharmony_ci trinity_update_current_ps(rdev, new_ps); 123562306a36Sopenharmony_ci} 123662306a36Sopenharmony_ci 123762306a36Sopenharmony_civoid trinity_dpm_setup_asic(struct radeon_device *rdev) 123862306a36Sopenharmony_ci{ 123962306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 124062306a36Sopenharmony_ci sumo_program_sstp(rdev); 124162306a36Sopenharmony_ci sumo_take_smu_control(rdev, true); 124262306a36Sopenharmony_ci trinity_get_min_sclk_divider(rdev); 124362306a36Sopenharmony_ci trinity_release_mutex(rdev); 124462306a36Sopenharmony_ci} 124562306a36Sopenharmony_ci 124662306a36Sopenharmony_ci#if 0 124762306a36Sopenharmony_civoid trinity_dpm_reset_asic(struct radeon_device *rdev) 124862306a36Sopenharmony_ci{ 124962306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 125062306a36Sopenharmony_ci 125162306a36Sopenharmony_ci trinity_acquire_mutex(rdev); 125262306a36Sopenharmony_ci if (pi->enable_dpm) { 125362306a36Sopenharmony_ci trinity_enable_power_level_0(rdev); 125462306a36Sopenharmony_ci trinity_force_level_0(rdev); 125562306a36Sopenharmony_ci trinity_wait_for_level_0(rdev); 125662306a36Sopenharmony_ci trinity_program_bootup_state(rdev); 125762306a36Sopenharmony_ci trinity_force_level_0(rdev); 125862306a36Sopenharmony_ci trinity_unforce_levels(rdev); 125962306a36Sopenharmony_ci } 126062306a36Sopenharmony_ci trinity_release_mutex(rdev); 126162306a36Sopenharmony_ci} 126262306a36Sopenharmony_ci#endif 126362306a36Sopenharmony_ci 126462306a36Sopenharmony_cistatic u16 trinity_convert_voltage_index_to_value(struct radeon_device *rdev, 126562306a36Sopenharmony_ci u32 vid_2bit) 126662306a36Sopenharmony_ci{ 126762306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 126862306a36Sopenharmony_ci u32 vid_7bit = sumo_convert_vid2_to_vid7(rdev, &pi->sys_info.vid_mapping_table, vid_2bit); 126962306a36Sopenharmony_ci u32 svi_mode = (RREG32_SMC(PM_CONFIG) & SVI_Mode) ? 1 : 0; 127062306a36Sopenharmony_ci u32 step = (svi_mode == 0) ? 1250 : 625; 127162306a36Sopenharmony_ci u32 delta = vid_7bit * step + 50; 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci if (delta > 155000) 127462306a36Sopenharmony_ci return 0; 127562306a36Sopenharmony_ci 127662306a36Sopenharmony_ci return (155000 - delta) / 100; 127762306a36Sopenharmony_ci} 127862306a36Sopenharmony_ci 127962306a36Sopenharmony_cistatic void trinity_patch_boot_state(struct radeon_device *rdev, 128062306a36Sopenharmony_ci struct trinity_ps *ps) 128162306a36Sopenharmony_ci{ 128262306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 128362306a36Sopenharmony_ci 128462306a36Sopenharmony_ci ps->num_levels = 1; 128562306a36Sopenharmony_ci ps->nbps_flags = 0; 128662306a36Sopenharmony_ci ps->bapm_flags = 0; 128762306a36Sopenharmony_ci ps->levels[0] = pi->boot_pl; 128862306a36Sopenharmony_ci} 128962306a36Sopenharmony_ci 129062306a36Sopenharmony_cistatic u8 trinity_calculate_vce_wm(struct radeon_device *rdev, u32 sclk) 129162306a36Sopenharmony_ci{ 129262306a36Sopenharmony_ci if (sclk < 20000) 129362306a36Sopenharmony_ci return 1; 129462306a36Sopenharmony_ci return 0; 129562306a36Sopenharmony_ci} 129662306a36Sopenharmony_ci 129762306a36Sopenharmony_cistatic void trinity_construct_boot_state(struct radeon_device *rdev) 129862306a36Sopenharmony_ci{ 129962306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci pi->boot_pl.sclk = pi->sys_info.bootup_sclk; 130262306a36Sopenharmony_ci pi->boot_pl.vddc_index = pi->sys_info.bootup_nb_voltage_index; 130362306a36Sopenharmony_ci pi->boot_pl.ds_divider_index = 0; 130462306a36Sopenharmony_ci pi->boot_pl.ss_divider_index = 0; 130562306a36Sopenharmony_ci pi->boot_pl.allow_gnb_slow = 1; 130662306a36Sopenharmony_ci pi->boot_pl.force_nbp_state = 0; 130762306a36Sopenharmony_ci pi->boot_pl.display_wm = 0; 130862306a36Sopenharmony_ci pi->boot_pl.vce_wm = 0; 130962306a36Sopenharmony_ci pi->current_ps.num_levels = 1; 131062306a36Sopenharmony_ci pi->current_ps.levels[0] = pi->boot_pl; 131162306a36Sopenharmony_ci} 131262306a36Sopenharmony_ci 131362306a36Sopenharmony_cistatic u8 trinity_get_sleep_divider_id_from_clock(struct radeon_device *rdev, 131462306a36Sopenharmony_ci u32 sclk, u32 min_sclk_in_sr) 131562306a36Sopenharmony_ci{ 131662306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 131762306a36Sopenharmony_ci u32 i; 131862306a36Sopenharmony_ci u32 temp; 131962306a36Sopenharmony_ci u32 min = (min_sclk_in_sr > TRINITY_MINIMUM_ENGINE_CLOCK) ? 132062306a36Sopenharmony_ci min_sclk_in_sr : TRINITY_MINIMUM_ENGINE_CLOCK; 132162306a36Sopenharmony_ci 132262306a36Sopenharmony_ci if (sclk < min) 132362306a36Sopenharmony_ci return 0; 132462306a36Sopenharmony_ci 132562306a36Sopenharmony_ci if (!pi->enable_sclk_ds) 132662306a36Sopenharmony_ci return 0; 132762306a36Sopenharmony_ci 132862306a36Sopenharmony_ci for (i = TRINITY_MAX_DEEPSLEEP_DIVIDER_ID; ; i--) { 132962306a36Sopenharmony_ci temp = sclk / sumo_get_sleep_divider_from_id(i); 133062306a36Sopenharmony_ci if (temp >= min || i == 0) 133162306a36Sopenharmony_ci break; 133262306a36Sopenharmony_ci } 133362306a36Sopenharmony_ci 133462306a36Sopenharmony_ci return (u8)i; 133562306a36Sopenharmony_ci} 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_cistatic u32 trinity_get_valid_engine_clock(struct radeon_device *rdev, 133862306a36Sopenharmony_ci u32 lower_limit) 133962306a36Sopenharmony_ci{ 134062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 134162306a36Sopenharmony_ci u32 i; 134262306a36Sopenharmony_ci 134362306a36Sopenharmony_ci for (i = 0; i < pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries; i++) { 134462306a36Sopenharmony_ci if (pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency >= lower_limit) 134562306a36Sopenharmony_ci return pi->sys_info.sclk_voltage_mapping_table.entries[i].sclk_frequency; 134662306a36Sopenharmony_ci } 134762306a36Sopenharmony_ci 134862306a36Sopenharmony_ci if (i == pi->sys_info.sclk_voltage_mapping_table.num_max_dpm_entries) 134962306a36Sopenharmony_ci DRM_ERROR("engine clock out of range!"); 135062306a36Sopenharmony_ci 135162306a36Sopenharmony_ci return 0; 135262306a36Sopenharmony_ci} 135362306a36Sopenharmony_ci 135462306a36Sopenharmony_cistatic void trinity_patch_thermal_state(struct radeon_device *rdev, 135562306a36Sopenharmony_ci struct trinity_ps *ps, 135662306a36Sopenharmony_ci struct trinity_ps *current_ps) 135762306a36Sopenharmony_ci{ 135862306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 135962306a36Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 136062306a36Sopenharmony_ci u32 current_vddc; 136162306a36Sopenharmony_ci u32 current_sclk; 136262306a36Sopenharmony_ci u32 current_index = 0; 136362306a36Sopenharmony_ci 136462306a36Sopenharmony_ci if (current_ps) { 136562306a36Sopenharmony_ci current_vddc = current_ps->levels[current_index].vddc_index; 136662306a36Sopenharmony_ci current_sclk = current_ps->levels[current_index].sclk; 136762306a36Sopenharmony_ci } else { 136862306a36Sopenharmony_ci current_vddc = pi->boot_pl.vddc_index; 136962306a36Sopenharmony_ci current_sclk = pi->boot_pl.sclk; 137062306a36Sopenharmony_ci } 137162306a36Sopenharmony_ci 137262306a36Sopenharmony_ci ps->levels[0].vddc_index = current_vddc; 137362306a36Sopenharmony_ci 137462306a36Sopenharmony_ci if (ps->levels[0].sclk > current_sclk) 137562306a36Sopenharmony_ci ps->levels[0].sclk = current_sclk; 137662306a36Sopenharmony_ci 137762306a36Sopenharmony_ci ps->levels[0].ds_divider_index = 137862306a36Sopenharmony_ci trinity_get_sleep_divider_id_from_clock(rdev, ps->levels[0].sclk, sclk_in_sr); 137962306a36Sopenharmony_ci ps->levels[0].ss_divider_index = ps->levels[0].ds_divider_index; 138062306a36Sopenharmony_ci ps->levels[0].allow_gnb_slow = 1; 138162306a36Sopenharmony_ci ps->levels[0].force_nbp_state = 0; 138262306a36Sopenharmony_ci ps->levels[0].display_wm = 0; 138362306a36Sopenharmony_ci ps->levels[0].vce_wm = 138462306a36Sopenharmony_ci trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 138562306a36Sopenharmony_ci} 138662306a36Sopenharmony_ci 138762306a36Sopenharmony_cistatic u8 trinity_calculate_display_wm(struct radeon_device *rdev, 138862306a36Sopenharmony_ci struct trinity_ps *ps, u32 index) 138962306a36Sopenharmony_ci{ 139062306a36Sopenharmony_ci if (ps == NULL || ps->num_levels <= 1) 139162306a36Sopenharmony_ci return 0; 139262306a36Sopenharmony_ci else if (ps->num_levels == 2) { 139362306a36Sopenharmony_ci if (index == 0) 139462306a36Sopenharmony_ci return 0; 139562306a36Sopenharmony_ci else 139662306a36Sopenharmony_ci return 1; 139762306a36Sopenharmony_ci } else { 139862306a36Sopenharmony_ci if (index == 0) 139962306a36Sopenharmony_ci return 0; 140062306a36Sopenharmony_ci else if (ps->levels[index].sclk < 30000) 140162306a36Sopenharmony_ci return 0; 140262306a36Sopenharmony_ci else 140362306a36Sopenharmony_ci return 1; 140462306a36Sopenharmony_ci } 140562306a36Sopenharmony_ci} 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_cistatic u32 trinity_get_uvd_clock_index(struct radeon_device *rdev, 140862306a36Sopenharmony_ci struct radeon_ps *rps) 140962306a36Sopenharmony_ci{ 141062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 141162306a36Sopenharmony_ci u32 i = 0; 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 141462306a36Sopenharmony_ci if ((rps->vclk == pi->sys_info.uvd_clock_table_entries[i].vclk) && 141562306a36Sopenharmony_ci (rps->dclk == pi->sys_info.uvd_clock_table_entries[i].dclk)) 141662306a36Sopenharmony_ci break; 141762306a36Sopenharmony_ci } 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci if (i >= 4) { 142062306a36Sopenharmony_ci DRM_ERROR("UVD clock index not found!\n"); 142162306a36Sopenharmony_ci i = 3; 142262306a36Sopenharmony_ci } 142362306a36Sopenharmony_ci return i; 142462306a36Sopenharmony_ci} 142562306a36Sopenharmony_ci 142662306a36Sopenharmony_cistatic void trinity_adjust_uvd_state(struct radeon_device *rdev, 142762306a36Sopenharmony_ci struct radeon_ps *rps) 142862306a36Sopenharmony_ci{ 142962306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 143062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 143162306a36Sopenharmony_ci u32 high_index = 0; 143262306a36Sopenharmony_ci u32 low_index = 0; 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci if (pi->uvd_dpm && r600_is_uvd_state(rps->class, rps->class2)) { 143562306a36Sopenharmony_ci high_index = trinity_get_uvd_clock_index(rdev, rps); 143662306a36Sopenharmony_ci 143762306a36Sopenharmony_ci switch(high_index) { 143862306a36Sopenharmony_ci case 3: 143962306a36Sopenharmony_ci case 2: 144062306a36Sopenharmony_ci low_index = 1; 144162306a36Sopenharmony_ci break; 144262306a36Sopenharmony_ci case 1: 144362306a36Sopenharmony_ci case 0: 144462306a36Sopenharmony_ci default: 144562306a36Sopenharmony_ci low_index = 0; 144662306a36Sopenharmony_ci break; 144762306a36Sopenharmony_ci } 144862306a36Sopenharmony_ci 144962306a36Sopenharmony_ci ps->vclk_low_divider = 145062306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[high_index].vclk_did; 145162306a36Sopenharmony_ci ps->dclk_low_divider = 145262306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[high_index].dclk_did; 145362306a36Sopenharmony_ci ps->vclk_high_divider = 145462306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[low_index].vclk_did; 145562306a36Sopenharmony_ci ps->dclk_high_divider = 145662306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[low_index].dclk_did; 145762306a36Sopenharmony_ci } 145862306a36Sopenharmony_ci} 145962306a36Sopenharmony_ci 146062306a36Sopenharmony_cistatic int trinity_get_vce_clock_voltage(struct radeon_device *rdev, 146162306a36Sopenharmony_ci u32 evclk, u32 ecclk, u16 *voltage) 146262306a36Sopenharmony_ci{ 146362306a36Sopenharmony_ci u32 i; 146462306a36Sopenharmony_ci int ret = -EINVAL; 146562306a36Sopenharmony_ci struct radeon_vce_clock_voltage_dependency_table *table = 146662306a36Sopenharmony_ci &rdev->pm.dpm.dyn_state.vce_clock_voltage_dependency_table; 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci if (((evclk == 0) && (ecclk == 0)) || 146962306a36Sopenharmony_ci (table && (table->count == 0))) { 147062306a36Sopenharmony_ci *voltage = 0; 147162306a36Sopenharmony_ci return 0; 147262306a36Sopenharmony_ci } 147362306a36Sopenharmony_ci 147462306a36Sopenharmony_ci for (i = 0; i < table->count; i++) { 147562306a36Sopenharmony_ci if ((evclk <= table->entries[i].evclk) && 147662306a36Sopenharmony_ci (ecclk <= table->entries[i].ecclk)) { 147762306a36Sopenharmony_ci *voltage = table->entries[i].v; 147862306a36Sopenharmony_ci ret = 0; 147962306a36Sopenharmony_ci break; 148062306a36Sopenharmony_ci } 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci 148362306a36Sopenharmony_ci /* if no match return the highest voltage */ 148462306a36Sopenharmony_ci if (ret) 148562306a36Sopenharmony_ci *voltage = table->entries[table->count - 1].v; 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_ci return ret; 148862306a36Sopenharmony_ci} 148962306a36Sopenharmony_ci 149062306a36Sopenharmony_cistatic void trinity_apply_state_adjust_rules(struct radeon_device *rdev, 149162306a36Sopenharmony_ci struct radeon_ps *new_rps, 149262306a36Sopenharmony_ci struct radeon_ps *old_rps) 149362306a36Sopenharmony_ci{ 149462306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(new_rps); 149562306a36Sopenharmony_ci struct trinity_ps *current_ps = trinity_get_ps(old_rps); 149662306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 149762306a36Sopenharmony_ci u32 min_voltage = 0; /* ??? */ 149862306a36Sopenharmony_ci u32 min_sclk = pi->sys_info.min_sclk; /* XXX check against disp reqs */ 149962306a36Sopenharmony_ci u32 sclk_in_sr = pi->sys_info.min_sclk; /* ??? */ 150062306a36Sopenharmony_ci u32 i; 150162306a36Sopenharmony_ci u16 min_vce_voltage; 150262306a36Sopenharmony_ci bool force_high; 150362306a36Sopenharmony_ci u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 150462306a36Sopenharmony_ci 150562306a36Sopenharmony_ci if (new_rps->class & ATOM_PPLIB_CLASSIFICATION_THERMAL) 150662306a36Sopenharmony_ci return trinity_patch_thermal_state(rdev, ps, current_ps); 150762306a36Sopenharmony_ci 150862306a36Sopenharmony_ci trinity_adjust_uvd_state(rdev, new_rps); 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_ci if (new_rps->vce_active) { 151162306a36Sopenharmony_ci new_rps->evclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].evclk; 151262306a36Sopenharmony_ci new_rps->ecclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].ecclk; 151362306a36Sopenharmony_ci } else { 151462306a36Sopenharmony_ci new_rps->evclk = 0; 151562306a36Sopenharmony_ci new_rps->ecclk = 0; 151662306a36Sopenharmony_ci } 151762306a36Sopenharmony_ci 151862306a36Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 151962306a36Sopenharmony_ci if (ps->levels[i].vddc_index < min_voltage) 152062306a36Sopenharmony_ci ps->levels[i].vddc_index = min_voltage; 152162306a36Sopenharmony_ci 152262306a36Sopenharmony_ci if (ps->levels[i].sclk < min_sclk) 152362306a36Sopenharmony_ci ps->levels[i].sclk = 152462306a36Sopenharmony_ci trinity_get_valid_engine_clock(rdev, min_sclk); 152562306a36Sopenharmony_ci 152662306a36Sopenharmony_ci /* patch in vce limits */ 152762306a36Sopenharmony_ci if (new_rps->vce_active) { 152862306a36Sopenharmony_ci /* sclk */ 152962306a36Sopenharmony_ci if (ps->levels[i].sclk < rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk) 153062306a36Sopenharmony_ci ps->levels[i].sclk = rdev->pm.dpm.vce_states[rdev->pm.dpm.vce_level].sclk; 153162306a36Sopenharmony_ci /* vddc */ 153262306a36Sopenharmony_ci trinity_get_vce_clock_voltage(rdev, new_rps->evclk, new_rps->ecclk, &min_vce_voltage); 153362306a36Sopenharmony_ci if (ps->levels[i].vddc_index < min_vce_voltage) 153462306a36Sopenharmony_ci ps->levels[i].vddc_index = min_vce_voltage; 153562306a36Sopenharmony_ci } 153662306a36Sopenharmony_ci 153762306a36Sopenharmony_ci ps->levels[i].ds_divider_index = 153862306a36Sopenharmony_ci sumo_get_sleep_divider_id_from_clock(rdev, ps->levels[i].sclk, sclk_in_sr); 153962306a36Sopenharmony_ci 154062306a36Sopenharmony_ci ps->levels[i].ss_divider_index = ps->levels[i].ds_divider_index; 154162306a36Sopenharmony_ci 154262306a36Sopenharmony_ci ps->levels[i].allow_gnb_slow = 1; 154362306a36Sopenharmony_ci ps->levels[i].force_nbp_state = 0; 154462306a36Sopenharmony_ci ps->levels[i].display_wm = 154562306a36Sopenharmony_ci trinity_calculate_display_wm(rdev, ps, i); 154662306a36Sopenharmony_ci ps->levels[i].vce_wm = 154762306a36Sopenharmony_ci trinity_calculate_vce_wm(rdev, ps->levels[0].sclk); 154862306a36Sopenharmony_ci } 154962306a36Sopenharmony_ci 155062306a36Sopenharmony_ci if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 155162306a36Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) 155262306a36Sopenharmony_ci ps->bapm_flags |= TRINITY_POWERSTATE_FLAGS_BAPM_DISABLE; 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_ci if (pi->sys_info.nb_dpm_enable) { 155562306a36Sopenharmony_ci ps->Dpm0PgNbPsLo = 0x1; 155662306a36Sopenharmony_ci ps->Dpm0PgNbPsHi = 0x0; 155762306a36Sopenharmony_ci ps->DpmXNbPsLo = 0x2; 155862306a36Sopenharmony_ci ps->DpmXNbPsHi = 0x1; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci if ((new_rps->class & (ATOM_PPLIB_CLASSIFICATION_HDSTATE | ATOM_PPLIB_CLASSIFICATION_SDSTATE)) || 156162306a36Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_UI_MASK) == ATOM_PPLIB_CLASSIFICATION_UI_BATTERY)) { 156262306a36Sopenharmony_ci force_high = ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_HDSTATE) || 156362306a36Sopenharmony_ci ((new_rps->class & ATOM_PPLIB_CLASSIFICATION_SDSTATE) && 156462306a36Sopenharmony_ci (pi->sys_info.uma_channel_number == 1))); 156562306a36Sopenharmony_ci force_high = (num_active_displays >= 3) || force_high; 156662306a36Sopenharmony_ci ps->Dpm0PgNbPsLo = force_high ? 0x2 : 0x3; 156762306a36Sopenharmony_ci ps->Dpm0PgNbPsHi = 0x1; 156862306a36Sopenharmony_ci ps->DpmXNbPsLo = force_high ? 0x2 : 0x3; 156962306a36Sopenharmony_ci ps->DpmXNbPsHi = 0x2; 157062306a36Sopenharmony_ci ps->levels[ps->num_levels - 1].allow_gnb_slow = 0; 157162306a36Sopenharmony_ci } 157262306a36Sopenharmony_ci } 157362306a36Sopenharmony_ci} 157462306a36Sopenharmony_ci 157562306a36Sopenharmony_cistatic void trinity_cleanup_asic(struct radeon_device *rdev) 157662306a36Sopenharmony_ci{ 157762306a36Sopenharmony_ci sumo_take_smu_control(rdev, false); 157862306a36Sopenharmony_ci} 157962306a36Sopenharmony_ci 158062306a36Sopenharmony_ci#if 0 158162306a36Sopenharmony_cistatic void trinity_pre_display_configuration_change(struct radeon_device *rdev) 158262306a36Sopenharmony_ci{ 158362306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_ci if (pi->voltage_drop_in_dce) 158662306a36Sopenharmony_ci trinity_dce_enable_voltage_adjustment(rdev, false); 158762306a36Sopenharmony_ci} 158862306a36Sopenharmony_ci#endif 158962306a36Sopenharmony_ci 159062306a36Sopenharmony_cistatic void trinity_add_dccac_value(struct radeon_device *rdev) 159162306a36Sopenharmony_ci{ 159262306a36Sopenharmony_ci u32 gpu_cac_avrg_cntl_window_size; 159362306a36Sopenharmony_ci u32 num_active_displays = rdev->pm.dpm.new_active_crtc_count; 159462306a36Sopenharmony_ci u64 disp_clk = rdev->clock.default_dispclk / 100; 159562306a36Sopenharmony_ci u32 dc_cac_value; 159662306a36Sopenharmony_ci 159762306a36Sopenharmony_ci gpu_cac_avrg_cntl_window_size = 159862306a36Sopenharmony_ci (RREG32_SMC(GPU_CAC_AVRG_CNTL) & WINDOW_SIZE_MASK) >> WINDOW_SIZE_SHIFT; 159962306a36Sopenharmony_ci 160062306a36Sopenharmony_ci dc_cac_value = (u32)((14213 * disp_clk * disp_clk * (u64)num_active_displays) >> 160162306a36Sopenharmony_ci (32 - gpu_cac_avrg_cntl_window_size)); 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci WREG32_SMC(DC_CAC_VALUE, dc_cac_value); 160462306a36Sopenharmony_ci} 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_civoid trinity_dpm_display_configuration_changed(struct radeon_device *rdev) 160762306a36Sopenharmony_ci{ 160862306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 160962306a36Sopenharmony_ci 161062306a36Sopenharmony_ci if (pi->voltage_drop_in_dce) 161162306a36Sopenharmony_ci trinity_dce_enable_voltage_adjustment(rdev, true); 161262306a36Sopenharmony_ci trinity_add_dccac_value(rdev); 161362306a36Sopenharmony_ci} 161462306a36Sopenharmony_ci 161562306a36Sopenharmony_ciunion power_info { 161662306a36Sopenharmony_ci struct _ATOM_POWERPLAY_INFO info; 161762306a36Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V2 info_2; 161862306a36Sopenharmony_ci struct _ATOM_POWERPLAY_INFO_V3 info_3; 161962306a36Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE pplib; 162062306a36Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE2 pplib2; 162162306a36Sopenharmony_ci struct _ATOM_PPLIB_POWERPLAYTABLE3 pplib3; 162262306a36Sopenharmony_ci}; 162362306a36Sopenharmony_ci 162462306a36Sopenharmony_ciunion pplib_clock_info { 162562306a36Sopenharmony_ci struct _ATOM_PPLIB_R600_CLOCK_INFO r600; 162662306a36Sopenharmony_ci struct _ATOM_PPLIB_RS780_CLOCK_INFO rs780; 162762306a36Sopenharmony_ci struct _ATOM_PPLIB_EVERGREEN_CLOCK_INFO evergreen; 162862306a36Sopenharmony_ci struct _ATOM_PPLIB_SUMO_CLOCK_INFO sumo; 162962306a36Sopenharmony_ci}; 163062306a36Sopenharmony_ci 163162306a36Sopenharmony_ciunion pplib_power_state { 163262306a36Sopenharmony_ci struct _ATOM_PPLIB_STATE v1; 163362306a36Sopenharmony_ci struct _ATOM_PPLIB_STATE_V2 v2; 163462306a36Sopenharmony_ci}; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_cistatic void trinity_parse_pplib_non_clock_info(struct radeon_device *rdev, 163762306a36Sopenharmony_ci struct radeon_ps *rps, 163862306a36Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info, 163962306a36Sopenharmony_ci u8 table_rev) 164062306a36Sopenharmony_ci{ 164162306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 164262306a36Sopenharmony_ci 164362306a36Sopenharmony_ci rps->caps = le32_to_cpu(non_clock_info->ulCapsAndSettings); 164462306a36Sopenharmony_ci rps->class = le16_to_cpu(non_clock_info->usClassification); 164562306a36Sopenharmony_ci rps->class2 = le16_to_cpu(non_clock_info->usClassification2); 164662306a36Sopenharmony_ci 164762306a36Sopenharmony_ci if (ATOM_PPLIB_NONCLOCKINFO_VER1 < table_rev) { 164862306a36Sopenharmony_ci rps->vclk = le32_to_cpu(non_clock_info->ulVCLK); 164962306a36Sopenharmony_ci rps->dclk = le32_to_cpu(non_clock_info->ulDCLK); 165062306a36Sopenharmony_ci } else { 165162306a36Sopenharmony_ci rps->vclk = 0; 165262306a36Sopenharmony_ci rps->dclk = 0; 165362306a36Sopenharmony_ci } 165462306a36Sopenharmony_ci 165562306a36Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_BOOT) { 165662306a36Sopenharmony_ci rdev->pm.dpm.boot_ps = rps; 165762306a36Sopenharmony_ci trinity_patch_boot_state(rdev, ps); 165862306a36Sopenharmony_ci } 165962306a36Sopenharmony_ci if (rps->class & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) 166062306a36Sopenharmony_ci rdev->pm.dpm.uvd_ps = rps; 166162306a36Sopenharmony_ci} 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_cistatic void trinity_parse_pplib_clock_info(struct radeon_device *rdev, 166462306a36Sopenharmony_ci struct radeon_ps *rps, int index, 166562306a36Sopenharmony_ci union pplib_clock_info *clock_info) 166662306a36Sopenharmony_ci{ 166762306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 166862306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 166962306a36Sopenharmony_ci struct trinity_pl *pl = &ps->levels[index]; 167062306a36Sopenharmony_ci u32 sclk; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 167362306a36Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 167462306a36Sopenharmony_ci pl->sclk = sclk; 167562306a36Sopenharmony_ci pl->vddc_index = clock_info->sumo.vddcIndex; 167662306a36Sopenharmony_ci 167762306a36Sopenharmony_ci ps->num_levels = index + 1; 167862306a36Sopenharmony_ci 167962306a36Sopenharmony_ci if (pi->enable_sclk_ds) { 168062306a36Sopenharmony_ci pl->ds_divider_index = 5; 168162306a36Sopenharmony_ci pl->ss_divider_index = 5; 168262306a36Sopenharmony_ci } 168362306a36Sopenharmony_ci} 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_cistatic int trinity_parse_power_table(struct radeon_device *rdev) 168662306a36Sopenharmony_ci{ 168762306a36Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 168862306a36Sopenharmony_ci struct _ATOM_PPLIB_NONCLOCK_INFO *non_clock_info; 168962306a36Sopenharmony_ci union pplib_power_state *power_state; 169062306a36Sopenharmony_ci int i, j, k, non_clock_array_index, clock_array_index; 169162306a36Sopenharmony_ci union pplib_clock_info *clock_info; 169262306a36Sopenharmony_ci struct _StateArray *state_array; 169362306a36Sopenharmony_ci struct _ClockInfoArray *clock_info_array; 169462306a36Sopenharmony_ci struct _NonClockInfoArray *non_clock_info_array; 169562306a36Sopenharmony_ci union power_info *power_info; 169662306a36Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); 169762306a36Sopenharmony_ci u16 data_offset; 169862306a36Sopenharmony_ci u8 frev, crev; 169962306a36Sopenharmony_ci u8 *power_state_offset; 170062306a36Sopenharmony_ci struct sumo_ps *ps; 170162306a36Sopenharmony_ci 170262306a36Sopenharmony_ci if (!atom_parse_data_header(mode_info->atom_context, index, NULL, 170362306a36Sopenharmony_ci &frev, &crev, &data_offset)) 170462306a36Sopenharmony_ci return -EINVAL; 170562306a36Sopenharmony_ci power_info = (union power_info *)(mode_info->atom_context->bios + data_offset); 170662306a36Sopenharmony_ci 170762306a36Sopenharmony_ci state_array = (struct _StateArray *) 170862306a36Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 170962306a36Sopenharmony_ci le16_to_cpu(power_info->pplib.usStateArrayOffset)); 171062306a36Sopenharmony_ci clock_info_array = (struct _ClockInfoArray *) 171162306a36Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 171262306a36Sopenharmony_ci le16_to_cpu(power_info->pplib.usClockInfoArrayOffset)); 171362306a36Sopenharmony_ci non_clock_info_array = (struct _NonClockInfoArray *) 171462306a36Sopenharmony_ci (mode_info->atom_context->bios + data_offset + 171562306a36Sopenharmony_ci le16_to_cpu(power_info->pplib.usNonClockInfoArrayOffset)); 171662306a36Sopenharmony_ci 171762306a36Sopenharmony_ci rdev->pm.dpm.ps = kcalloc(state_array->ucNumEntries, 171862306a36Sopenharmony_ci sizeof(struct radeon_ps), 171962306a36Sopenharmony_ci GFP_KERNEL); 172062306a36Sopenharmony_ci if (!rdev->pm.dpm.ps) 172162306a36Sopenharmony_ci return -ENOMEM; 172262306a36Sopenharmony_ci power_state_offset = (u8 *)state_array->states; 172362306a36Sopenharmony_ci for (i = 0; i < state_array->ucNumEntries; i++) { 172462306a36Sopenharmony_ci u8 *idx; 172562306a36Sopenharmony_ci power_state = (union pplib_power_state *)power_state_offset; 172662306a36Sopenharmony_ci non_clock_array_index = power_state->v2.nonClockInfoIndex; 172762306a36Sopenharmony_ci non_clock_info = (struct _ATOM_PPLIB_NONCLOCK_INFO *) 172862306a36Sopenharmony_ci &non_clock_info_array->nonClockInfo[non_clock_array_index]; 172962306a36Sopenharmony_ci if (!rdev->pm.power_state[i].clock_info) { 173062306a36Sopenharmony_ci kfree(rdev->pm.dpm.ps); 173162306a36Sopenharmony_ci return -EINVAL; 173262306a36Sopenharmony_ci } 173362306a36Sopenharmony_ci ps = kzalloc(sizeof(struct sumo_ps), GFP_KERNEL); 173462306a36Sopenharmony_ci if (ps == NULL) { 173562306a36Sopenharmony_ci kfree(rdev->pm.dpm.ps); 173662306a36Sopenharmony_ci return -ENOMEM; 173762306a36Sopenharmony_ci } 173862306a36Sopenharmony_ci rdev->pm.dpm.ps[i].ps_priv = ps; 173962306a36Sopenharmony_ci k = 0; 174062306a36Sopenharmony_ci idx = (u8 *)&power_state->v2.clockInfoIndex[0]; 174162306a36Sopenharmony_ci for (j = 0; j < power_state->v2.ucNumDPMLevels; j++) { 174262306a36Sopenharmony_ci clock_array_index = idx[j]; 174362306a36Sopenharmony_ci if (clock_array_index >= clock_info_array->ucNumEntries) 174462306a36Sopenharmony_ci continue; 174562306a36Sopenharmony_ci if (k >= SUMO_MAX_HARDWARE_POWERLEVELS) 174662306a36Sopenharmony_ci break; 174762306a36Sopenharmony_ci clock_info = (union pplib_clock_info *) 174862306a36Sopenharmony_ci ((u8 *)&clock_info_array->clockInfo[0] + 174962306a36Sopenharmony_ci (clock_array_index * clock_info_array->ucEntrySize)); 175062306a36Sopenharmony_ci trinity_parse_pplib_clock_info(rdev, 175162306a36Sopenharmony_ci &rdev->pm.dpm.ps[i], k, 175262306a36Sopenharmony_ci clock_info); 175362306a36Sopenharmony_ci k++; 175462306a36Sopenharmony_ci } 175562306a36Sopenharmony_ci trinity_parse_pplib_non_clock_info(rdev, &rdev->pm.dpm.ps[i], 175662306a36Sopenharmony_ci non_clock_info, 175762306a36Sopenharmony_ci non_clock_info_array->ucEntrySize); 175862306a36Sopenharmony_ci power_state_offset += 2 + power_state->v2.ucNumDPMLevels; 175962306a36Sopenharmony_ci } 176062306a36Sopenharmony_ci rdev->pm.dpm.num_ps = state_array->ucNumEntries; 176162306a36Sopenharmony_ci 176262306a36Sopenharmony_ci /* fill in the vce power states */ 176362306a36Sopenharmony_ci for (i = 0; i < RADEON_MAX_VCE_LEVELS; i++) { 176462306a36Sopenharmony_ci u32 sclk; 176562306a36Sopenharmony_ci clock_array_index = rdev->pm.dpm.vce_states[i].clk_idx; 176662306a36Sopenharmony_ci clock_info = (union pplib_clock_info *) 176762306a36Sopenharmony_ci &clock_info_array->clockInfo[clock_array_index * clock_info_array->ucEntrySize]; 176862306a36Sopenharmony_ci sclk = le16_to_cpu(clock_info->sumo.usEngineClockLow); 176962306a36Sopenharmony_ci sclk |= clock_info->sumo.ucEngineClockHigh << 16; 177062306a36Sopenharmony_ci rdev->pm.dpm.vce_states[i].sclk = sclk; 177162306a36Sopenharmony_ci rdev->pm.dpm.vce_states[i].mclk = 0; 177262306a36Sopenharmony_ci } 177362306a36Sopenharmony_ci 177462306a36Sopenharmony_ci return 0; 177562306a36Sopenharmony_ci} 177662306a36Sopenharmony_ci 177762306a36Sopenharmony_ciunion igp_info { 177862306a36Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO info; 177962306a36Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V2 info_2; 178062306a36Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V5 info_5; 178162306a36Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V6 info_6; 178262306a36Sopenharmony_ci struct _ATOM_INTEGRATED_SYSTEM_INFO_V1_7 info_7; 178362306a36Sopenharmony_ci}; 178462306a36Sopenharmony_ci 178562306a36Sopenharmony_cistatic u32 trinity_convert_did_to_freq(struct radeon_device *rdev, u8 did) 178662306a36Sopenharmony_ci{ 178762306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 178862306a36Sopenharmony_ci u32 divider; 178962306a36Sopenharmony_ci 179062306a36Sopenharmony_ci if (did >= 8 && did <= 0x3f) 179162306a36Sopenharmony_ci divider = did * 25; 179262306a36Sopenharmony_ci else if (did > 0x3f && did <= 0x5f) 179362306a36Sopenharmony_ci divider = (did - 64) * 50 + 1600; 179462306a36Sopenharmony_ci else if (did > 0x5f && did <= 0x7e) 179562306a36Sopenharmony_ci divider = (did - 96) * 100 + 3200; 179662306a36Sopenharmony_ci else if (did == 0x7f) 179762306a36Sopenharmony_ci divider = 128 * 100; 179862306a36Sopenharmony_ci else 179962306a36Sopenharmony_ci return 10000; 180062306a36Sopenharmony_ci 180162306a36Sopenharmony_ci return ((pi->sys_info.dentist_vco_freq * 100) + (divider - 1)) / divider; 180262306a36Sopenharmony_ci} 180362306a36Sopenharmony_ci 180462306a36Sopenharmony_cistatic int trinity_parse_sys_info_table(struct radeon_device *rdev) 180562306a36Sopenharmony_ci{ 180662306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 180762306a36Sopenharmony_ci struct radeon_mode_info *mode_info = &rdev->mode_info; 180862306a36Sopenharmony_ci int index = GetIndexIntoMasterTable(DATA, IntegratedSystemInfo); 180962306a36Sopenharmony_ci union igp_info *igp_info; 181062306a36Sopenharmony_ci u8 frev, crev; 181162306a36Sopenharmony_ci u16 data_offset; 181262306a36Sopenharmony_ci int i; 181362306a36Sopenharmony_ci 181462306a36Sopenharmony_ci if (atom_parse_data_header(mode_info->atom_context, index, NULL, 181562306a36Sopenharmony_ci &frev, &crev, &data_offset)) { 181662306a36Sopenharmony_ci igp_info = (union igp_info *)(mode_info->atom_context->bios + 181762306a36Sopenharmony_ci data_offset); 181862306a36Sopenharmony_ci 181962306a36Sopenharmony_ci if (crev != 7) { 182062306a36Sopenharmony_ci DRM_ERROR("Unsupported IGP table: %d %d\n", frev, crev); 182162306a36Sopenharmony_ci return -EINVAL; 182262306a36Sopenharmony_ci } 182362306a36Sopenharmony_ci pi->sys_info.bootup_sclk = le32_to_cpu(igp_info->info_7.ulBootUpEngineClock); 182462306a36Sopenharmony_ci pi->sys_info.min_sclk = le32_to_cpu(igp_info->info_7.ulMinEngineClock); 182562306a36Sopenharmony_ci pi->sys_info.bootup_uma_clk = le32_to_cpu(igp_info->info_7.ulBootUpUMAClock); 182662306a36Sopenharmony_ci pi->sys_info.dentist_vco_freq = le32_to_cpu(igp_info->info_7.ulDentistVCOFreq); 182762306a36Sopenharmony_ci pi->sys_info.bootup_nb_voltage_index = 182862306a36Sopenharmony_ci le16_to_cpu(igp_info->info_7.usBootUpNBVoltage); 182962306a36Sopenharmony_ci if (igp_info->info_7.ucHtcTmpLmt == 0) 183062306a36Sopenharmony_ci pi->sys_info.htc_tmp_lmt = 203; 183162306a36Sopenharmony_ci else 183262306a36Sopenharmony_ci pi->sys_info.htc_tmp_lmt = igp_info->info_7.ucHtcTmpLmt; 183362306a36Sopenharmony_ci if (igp_info->info_7.ucHtcHystLmt == 0) 183462306a36Sopenharmony_ci pi->sys_info.htc_hyst_lmt = 5; 183562306a36Sopenharmony_ci else 183662306a36Sopenharmony_ci pi->sys_info.htc_hyst_lmt = igp_info->info_7.ucHtcHystLmt; 183762306a36Sopenharmony_ci if (pi->sys_info.htc_tmp_lmt <= pi->sys_info.htc_hyst_lmt) { 183862306a36Sopenharmony_ci DRM_ERROR("The htcTmpLmt should be larger than htcHystLmt.\n"); 183962306a36Sopenharmony_ci } 184062306a36Sopenharmony_ci 184162306a36Sopenharmony_ci if (pi->enable_nbps_policy) 184262306a36Sopenharmony_ci pi->sys_info.nb_dpm_enable = igp_info->info_7.ucNBDPMEnable; 184362306a36Sopenharmony_ci else 184462306a36Sopenharmony_ci pi->sys_info.nb_dpm_enable = 0; 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci for (i = 0; i < TRINITY_NUM_NBPSTATES; i++) { 184762306a36Sopenharmony_ci pi->sys_info.nbp_mclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateMemclkFreq[i]); 184862306a36Sopenharmony_ci pi->sys_info.nbp_nclk[i] = le32_to_cpu(igp_info->info_7.ulNbpStateNClkFreq[i]); 184962306a36Sopenharmony_ci } 185062306a36Sopenharmony_ci 185162306a36Sopenharmony_ci pi->sys_info.nbp_voltage_index[0] = le16_to_cpu(igp_info->info_7.usNBP0Voltage); 185262306a36Sopenharmony_ci pi->sys_info.nbp_voltage_index[1] = le16_to_cpu(igp_info->info_7.usNBP1Voltage); 185362306a36Sopenharmony_ci pi->sys_info.nbp_voltage_index[2] = le16_to_cpu(igp_info->info_7.usNBP2Voltage); 185462306a36Sopenharmony_ci pi->sys_info.nbp_voltage_index[3] = le16_to_cpu(igp_info->info_7.usNBP3Voltage); 185562306a36Sopenharmony_ci 185662306a36Sopenharmony_ci if (!pi->sys_info.nb_dpm_enable) { 185762306a36Sopenharmony_ci for (i = 1; i < TRINITY_NUM_NBPSTATES; i++) { 185862306a36Sopenharmony_ci pi->sys_info.nbp_mclk[i] = pi->sys_info.nbp_mclk[0]; 185962306a36Sopenharmony_ci pi->sys_info.nbp_nclk[i] = pi->sys_info.nbp_nclk[0]; 186062306a36Sopenharmony_ci pi->sys_info.nbp_voltage_index[i] = pi->sys_info.nbp_voltage_index[0]; 186162306a36Sopenharmony_ci } 186262306a36Sopenharmony_ci } 186362306a36Sopenharmony_ci 186462306a36Sopenharmony_ci pi->sys_info.uma_channel_number = igp_info->info_7.ucUMAChannelNumber; 186562306a36Sopenharmony_ci 186662306a36Sopenharmony_ci sumo_construct_sclk_voltage_mapping_table(rdev, 186762306a36Sopenharmony_ci &pi->sys_info.sclk_voltage_mapping_table, 186862306a36Sopenharmony_ci igp_info->info_7.sAvail_SCLK); 186962306a36Sopenharmony_ci sumo_construct_vid_mapping_table(rdev, &pi->sys_info.vid_mapping_table, 187062306a36Sopenharmony_ci igp_info->info_7.sAvail_SCLK); 187162306a36Sopenharmony_ci 187262306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[0].vclk_did = 187362306a36Sopenharmony_ci igp_info->info_7.ucDPMState0VclkFid; 187462306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[1].vclk_did = 187562306a36Sopenharmony_ci igp_info->info_7.ucDPMState1VclkFid; 187662306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[2].vclk_did = 187762306a36Sopenharmony_ci igp_info->info_7.ucDPMState2VclkFid; 187862306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[3].vclk_did = 187962306a36Sopenharmony_ci igp_info->info_7.ucDPMState3VclkFid; 188062306a36Sopenharmony_ci 188162306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[0].dclk_did = 188262306a36Sopenharmony_ci igp_info->info_7.ucDPMState0DclkFid; 188362306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[1].dclk_did = 188462306a36Sopenharmony_ci igp_info->info_7.ucDPMState1DclkFid; 188562306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[2].dclk_did = 188662306a36Sopenharmony_ci igp_info->info_7.ucDPMState2DclkFid; 188762306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[3].dclk_did = 188862306a36Sopenharmony_ci igp_info->info_7.ucDPMState3DclkFid; 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci for (i = 0; i < 4; i++) { 189162306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].vclk = 189262306a36Sopenharmony_ci trinity_convert_did_to_freq(rdev, 189362306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].vclk_did); 189462306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].dclk = 189562306a36Sopenharmony_ci trinity_convert_did_to_freq(rdev, 189662306a36Sopenharmony_ci pi->sys_info.uvd_clock_table_entries[i].dclk_did); 189762306a36Sopenharmony_ci } 189862306a36Sopenharmony_ci 189962306a36Sopenharmony_ci 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci } 190262306a36Sopenharmony_ci return 0; 190362306a36Sopenharmony_ci} 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ciint trinity_dpm_init(struct radeon_device *rdev) 190662306a36Sopenharmony_ci{ 190762306a36Sopenharmony_ci struct trinity_power_info *pi; 190862306a36Sopenharmony_ci int ret, i; 190962306a36Sopenharmony_ci 191062306a36Sopenharmony_ci pi = kzalloc(sizeof(struct trinity_power_info), GFP_KERNEL); 191162306a36Sopenharmony_ci if (pi == NULL) 191262306a36Sopenharmony_ci return -ENOMEM; 191362306a36Sopenharmony_ci rdev->pm.dpm.priv = pi; 191462306a36Sopenharmony_ci 191562306a36Sopenharmony_ci for (i = 0; i < SUMO_MAX_HARDWARE_POWERLEVELS; i++) 191662306a36Sopenharmony_ci pi->at[i] = TRINITY_AT_DFLT; 191762306a36Sopenharmony_ci 191862306a36Sopenharmony_ci if (radeon_bapm == -1) { 191962306a36Sopenharmony_ci /* There are stability issues reported on with 192062306a36Sopenharmony_ci * bapm enabled when switching between AC and battery 192162306a36Sopenharmony_ci * power. At the same time, some MSI boards hang 192262306a36Sopenharmony_ci * if it's not enabled and dpm is enabled. Just enable 192362306a36Sopenharmony_ci * it for MSI boards right now. 192462306a36Sopenharmony_ci */ 192562306a36Sopenharmony_ci if (rdev->pdev->subsystem_vendor == 0x1462) 192662306a36Sopenharmony_ci pi->enable_bapm = true; 192762306a36Sopenharmony_ci else 192862306a36Sopenharmony_ci pi->enable_bapm = false; 192962306a36Sopenharmony_ci } else if (radeon_bapm == 0) { 193062306a36Sopenharmony_ci pi->enable_bapm = false; 193162306a36Sopenharmony_ci } else { 193262306a36Sopenharmony_ci pi->enable_bapm = true; 193362306a36Sopenharmony_ci } 193462306a36Sopenharmony_ci pi->enable_nbps_policy = true; 193562306a36Sopenharmony_ci pi->enable_sclk_ds = true; 193662306a36Sopenharmony_ci pi->enable_gfx_power_gating = true; 193762306a36Sopenharmony_ci pi->enable_gfx_clock_gating = true; 193862306a36Sopenharmony_ci pi->enable_mg_clock_gating = false; 193962306a36Sopenharmony_ci pi->enable_gfx_dynamic_mgpg = false; 194062306a36Sopenharmony_ci pi->override_dynamic_mgpg = false; 194162306a36Sopenharmony_ci pi->enable_auto_thermal_throttling = true; 194262306a36Sopenharmony_ci pi->voltage_drop_in_dce = false; /* need to restructure dpm/modeset interaction */ 194362306a36Sopenharmony_ci pi->uvd_dpm = true; /* ??? */ 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci ret = trinity_parse_sys_info_table(rdev); 194662306a36Sopenharmony_ci if (ret) 194762306a36Sopenharmony_ci return ret; 194862306a36Sopenharmony_ci 194962306a36Sopenharmony_ci trinity_construct_boot_state(rdev); 195062306a36Sopenharmony_ci 195162306a36Sopenharmony_ci ret = r600_get_platform_caps(rdev); 195262306a36Sopenharmony_ci if (ret) 195362306a36Sopenharmony_ci return ret; 195462306a36Sopenharmony_ci 195562306a36Sopenharmony_ci ret = r600_parse_extended_power_table(rdev); 195662306a36Sopenharmony_ci if (ret) 195762306a36Sopenharmony_ci return ret; 195862306a36Sopenharmony_ci 195962306a36Sopenharmony_ci ret = trinity_parse_power_table(rdev); 196062306a36Sopenharmony_ci if (ret) 196162306a36Sopenharmony_ci return ret; 196262306a36Sopenharmony_ci 196362306a36Sopenharmony_ci pi->thermal_auto_throttling = pi->sys_info.htc_tmp_lmt; 196462306a36Sopenharmony_ci pi->enable_dpm = true; 196562306a36Sopenharmony_ci 196662306a36Sopenharmony_ci return 0; 196762306a36Sopenharmony_ci} 196862306a36Sopenharmony_ci 196962306a36Sopenharmony_civoid trinity_dpm_print_power_state(struct radeon_device *rdev, 197062306a36Sopenharmony_ci struct radeon_ps *rps) 197162306a36Sopenharmony_ci{ 197262306a36Sopenharmony_ci int i; 197362306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 197462306a36Sopenharmony_ci 197562306a36Sopenharmony_ci r600_dpm_print_class_info(rps->class, rps->class2); 197662306a36Sopenharmony_ci r600_dpm_print_cap_info(rps->caps); 197762306a36Sopenharmony_ci printk("\tuvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 197862306a36Sopenharmony_ci for (i = 0; i < ps->num_levels; i++) { 197962306a36Sopenharmony_ci struct trinity_pl *pl = &ps->levels[i]; 198062306a36Sopenharmony_ci printk("\t\tpower level %d sclk: %u vddc: %u\n", 198162306a36Sopenharmony_ci i, pl->sclk, 198262306a36Sopenharmony_ci trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 198362306a36Sopenharmony_ci } 198462306a36Sopenharmony_ci r600_dpm_print_ps_status(rdev, rps); 198562306a36Sopenharmony_ci} 198662306a36Sopenharmony_ci 198762306a36Sopenharmony_civoid trinity_dpm_debugfs_print_current_performance_level(struct radeon_device *rdev, 198862306a36Sopenharmony_ci struct seq_file *m) 198962306a36Sopenharmony_ci{ 199062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 199162306a36Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 199262306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 199362306a36Sopenharmony_ci struct trinity_pl *pl; 199462306a36Sopenharmony_ci u32 current_index = 199562306a36Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >> 199662306a36Sopenharmony_ci CURRENT_STATE_SHIFT; 199762306a36Sopenharmony_ci 199862306a36Sopenharmony_ci if (current_index >= ps->num_levels) { 199962306a36Sopenharmony_ci seq_printf(m, "invalid dpm profile %d\n", current_index); 200062306a36Sopenharmony_ci } else { 200162306a36Sopenharmony_ci pl = &ps->levels[current_index]; 200262306a36Sopenharmony_ci seq_printf(m, "uvd vclk: %d dclk: %d\n", rps->vclk, rps->dclk); 200362306a36Sopenharmony_ci seq_printf(m, "power level %d sclk: %u vddc: %u\n", 200462306a36Sopenharmony_ci current_index, pl->sclk, 200562306a36Sopenharmony_ci trinity_convert_voltage_index_to_value(rdev, pl->vddc_index)); 200662306a36Sopenharmony_ci } 200762306a36Sopenharmony_ci} 200862306a36Sopenharmony_ci 200962306a36Sopenharmony_ciu32 trinity_dpm_get_current_sclk(struct radeon_device *rdev) 201062306a36Sopenharmony_ci{ 201162306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 201262306a36Sopenharmony_ci struct radeon_ps *rps = &pi->current_rps; 201362306a36Sopenharmony_ci struct trinity_ps *ps = trinity_get_ps(rps); 201462306a36Sopenharmony_ci struct trinity_pl *pl; 201562306a36Sopenharmony_ci u32 current_index = 201662306a36Sopenharmony_ci (RREG32(TARGET_AND_CURRENT_PROFILE_INDEX) & CURRENT_STATE_MASK) >> 201762306a36Sopenharmony_ci CURRENT_STATE_SHIFT; 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_ci if (current_index >= ps->num_levels) { 202062306a36Sopenharmony_ci return 0; 202162306a36Sopenharmony_ci } else { 202262306a36Sopenharmony_ci pl = &ps->levels[current_index]; 202362306a36Sopenharmony_ci return pl->sclk; 202462306a36Sopenharmony_ci } 202562306a36Sopenharmony_ci} 202662306a36Sopenharmony_ci 202762306a36Sopenharmony_ciu32 trinity_dpm_get_current_mclk(struct radeon_device *rdev) 202862306a36Sopenharmony_ci{ 202962306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 203062306a36Sopenharmony_ci 203162306a36Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 203262306a36Sopenharmony_ci} 203362306a36Sopenharmony_ci 203462306a36Sopenharmony_civoid trinity_dpm_fini(struct radeon_device *rdev) 203562306a36Sopenharmony_ci{ 203662306a36Sopenharmony_ci int i; 203762306a36Sopenharmony_ci 203862306a36Sopenharmony_ci trinity_cleanup_asic(rdev); /* ??? */ 203962306a36Sopenharmony_ci 204062306a36Sopenharmony_ci for (i = 0; i < rdev->pm.dpm.num_ps; i++) { 204162306a36Sopenharmony_ci kfree(rdev->pm.dpm.ps[i].ps_priv); 204262306a36Sopenharmony_ci } 204362306a36Sopenharmony_ci kfree(rdev->pm.dpm.ps); 204462306a36Sopenharmony_ci kfree(rdev->pm.dpm.priv); 204562306a36Sopenharmony_ci r600_free_extended_power_table(rdev); 204662306a36Sopenharmony_ci} 204762306a36Sopenharmony_ci 204862306a36Sopenharmony_ciu32 trinity_dpm_get_sclk(struct radeon_device *rdev, bool low) 204962306a36Sopenharmony_ci{ 205062306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 205162306a36Sopenharmony_ci struct trinity_ps *requested_state = trinity_get_ps(&pi->requested_rps); 205262306a36Sopenharmony_ci 205362306a36Sopenharmony_ci if (low) 205462306a36Sopenharmony_ci return requested_state->levels[0].sclk; 205562306a36Sopenharmony_ci else 205662306a36Sopenharmony_ci return requested_state->levels[requested_state->num_levels - 1].sclk; 205762306a36Sopenharmony_ci} 205862306a36Sopenharmony_ci 205962306a36Sopenharmony_ciu32 trinity_dpm_get_mclk(struct radeon_device *rdev, bool low) 206062306a36Sopenharmony_ci{ 206162306a36Sopenharmony_ci struct trinity_power_info *pi = trinity_get_pi(rdev); 206262306a36Sopenharmony_ci 206362306a36Sopenharmony_ci return pi->sys_info.bootup_uma_clk; 206462306a36Sopenharmony_ci} 2065