blob: 1907c950d76f05ef32811685baaee9f7d4db83b9 [file] [log] [blame]
/*
* Copyright 2011 Advanced Micro Devices, Inc.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
* OTHER DEALINGS IN THE SOFTWARE.
*
* Authors: Alex Deucher
*/
#include <linux/firmware.h>
#include <linux/slab.h>
#include <linux/module.h>
#include <drm/drmP.h>
#include "radeon.h"
#include "radeon_asic.h"
#include "radeon_audio.h"
#include <drm/radeon_drm.h>
#include "sid.h"
#include "atom.h"
#include "si_blit_shaders.h"
#include "clearstate_si.h"
#include "radeon_ucode.h"
MODULE_FIRMWARE("radeon/TAHITI_pfp.bin");
MODULE_FIRMWARE("radeon/TAHITI_me.bin");
MODULE_FIRMWARE("radeon/TAHITI_ce.bin");
MODULE_FIRMWARE("radeon/TAHITI_mc.bin");
MODULE_FIRMWARE("radeon/TAHITI_mc2.bin");
MODULE_FIRMWARE("radeon/TAHITI_rlc.bin");
MODULE_FIRMWARE("radeon/TAHITI_smc.bin");
MODULE_FIRMWARE("radeon/tahiti_pfp.bin");
MODULE_FIRMWARE("radeon/tahiti_me.bin");
MODULE_FIRMWARE("radeon/tahiti_ce.bin");
MODULE_FIRMWARE("radeon/tahiti_mc.bin");
MODULE_FIRMWARE("radeon/tahiti_rlc.bin");
MODULE_FIRMWARE("radeon/tahiti_smc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_pfp.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_me.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_ce.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_mc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_mc2.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_rlc.bin");
MODULE_FIRMWARE("radeon/PITCAIRN_smc.bin");
MODULE_FIRMWARE("radeon/pitcairn_pfp.bin");
MODULE_FIRMWARE("radeon/pitcairn_me.bin");
MODULE_FIRMWARE("radeon/pitcairn_ce.bin");
MODULE_FIRMWARE("radeon/pitcairn_mc.bin");
MODULE_FIRMWARE("radeon/pitcairn_rlc.bin");
MODULE_FIRMWARE("radeon/pitcairn_smc.bin");
MODULE_FIRMWARE("radeon/pitcairn_k_smc.bin");
MODULE_FIRMWARE("radeon/VERDE_pfp.bin");
MODULE_FIRMWARE("radeon/VERDE_me.bin");
MODULE_FIRMWARE("radeon/VERDE_ce.bin");
MODULE_FIRMWARE("radeon/VERDE_mc.bin");
MODULE_FIRMWARE("radeon/VERDE_mc2.bin");
MODULE_FIRMWARE("radeon/VERDE_rlc.bin");
MODULE_FIRMWARE("radeon/VERDE_smc.bin");
MODULE_FIRMWARE("radeon/verde_pfp.bin");
MODULE_FIRMWARE("radeon/verde_me.bin");
MODULE_FIRMWARE("radeon/verde_ce.bin");
MODULE_FIRMWARE("radeon/verde_mc.bin");
MODULE_FIRMWARE("radeon/verde_rlc.bin");
MODULE_FIRMWARE("radeon/verde_smc.bin");
MODULE_FIRMWARE("radeon/verde_k_smc.bin");
MODULE_FIRMWARE("radeon/OLAND_pfp.bin");
MODULE_FIRMWARE("radeon/OLAND_me.bin");
MODULE_FIRMWARE("radeon/OLAND_ce.bin");
MODULE_FIRMWARE("radeon/OLAND_mc.bin");
MODULE_FIRMWARE("radeon/OLAND_mc2.bin");
MODULE_FIRMWARE("radeon/OLAND_rlc.bin");
MODULE_FIRMWARE("radeon/OLAND_smc.bin");
MODULE_FIRMWARE("radeon/oland_pfp.bin");
MODULE_FIRMWARE("radeon/oland_me.bin");
MODULE_FIRMWARE("radeon/oland_ce.bin");
MODULE_FIRMWARE("radeon/oland_mc.bin");
MODULE_FIRMWARE("radeon/oland_rlc.bin");
MODULE_FIRMWARE("radeon/oland_smc.bin");
MODULE_FIRMWARE("radeon/oland_k_smc.bin");
MODULE_FIRMWARE("radeon/HAINAN_pfp.bin");
MODULE_FIRMWARE("radeon/HAINAN_me.bin");
MODULE_FIRMWARE("radeon/HAINAN_ce.bin");
MODULE_FIRMWARE("radeon/HAINAN_mc.bin");
MODULE_FIRMWARE("radeon/HAINAN_mc2.bin");
MODULE_FIRMWARE("radeon/HAINAN_rlc.bin");
MODULE_FIRMWARE("radeon/HAINAN_smc.bin");
MODULE_FIRMWARE("radeon/hainan_pfp.bin");
MODULE_FIRMWARE("radeon/hainan_me.bin");
MODULE_FIRMWARE("radeon/hainan_ce.bin");
MODULE_FIRMWARE("radeon/hainan_mc.bin");
MODULE_FIRMWARE("radeon/hainan_rlc.bin");
MODULE_FIRMWARE("radeon/hainan_smc.bin");
MODULE_FIRMWARE("radeon/hainan_k_smc.bin");
MODULE_FIRMWARE("radeon/banks_k_2_smc.bin");
MODULE_FIRMWARE("radeon/si58_mc.bin");
static u32 si_get_cu_active_bitmap(struct radeon_device *rdev, u32 se, u32 sh);
static void si_pcie_gen3_enable(struct radeon_device *rdev);
static void si_program_aspm(struct radeon_device *rdev);
extern void sumo_rlc_fini(struct radeon_device *rdev);
extern int sumo_rlc_init(struct radeon_device *rdev);
extern int r600_ih_ring_alloc(struct radeon_device *rdev);
extern void r600_ih_ring_fini(struct radeon_device *rdev);
extern void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev);
extern void evergreen_mc_stop(struct radeon_device *rdev, struct evergreen_mc_save *save);
extern void evergreen_mc_resume(struct radeon_device *rdev, struct evergreen_mc_save *save);
extern u32 evergreen_get_number_of_dram_channels(struct radeon_device *rdev);
extern void evergreen_print_gpu_status_regs(struct radeon_device *rdev);
extern bool evergreen_is_display_hung(struct radeon_device *rdev);
static void si_enable_gui_idle_interrupt(struct radeon_device *rdev,
bool enable);
static void si_init_pg(struct radeon_device *rdev);
static void si_init_cg(struct radeon_device *rdev);
static void si_fini_pg(struct radeon_device *rdev);
static void si_fini_cg(struct radeon_device *rdev);
static void si_rlc_stop(struct radeon_device *rdev);
static const u32 crtc_offsets[] =
{
EVERGREEN_CRTC0_REGISTER_OFFSET,
EVERGREEN_CRTC1_REGISTER_OFFSET,
EVERGREEN_CRTC2_REGISTER_OFFSET,
EVERGREEN_CRTC3_REGISTER_OFFSET,
EVERGREEN_CRTC4_REGISTER_OFFSET,
EVERGREEN_CRTC5_REGISTER_OFFSET
};
static const u32 si_disp_int_status[] =
{
DISP_INTERRUPT_STATUS,
DISP_INTERRUPT_STATUS_CONTINUE,
DISP_INTERRUPT_STATUS_CONTINUE2,
DISP_INTERRUPT_STATUS_CONTINUE3,
DISP_INTERRUPT_STATUS_CONTINUE4,
DISP_INTERRUPT_STATUS_CONTINUE5
};
#define DC_HPDx_CONTROL(x) (DC_HPD1_CONTROL + (x * 0xc))
#define DC_HPDx_INT_CONTROL(x) (DC_HPD1_INT_CONTROL + (x * 0xc))
#define DC_HPDx_INT_STATUS_REG(x) (DC_HPD1_INT_STATUS + (x * 0xc))
static const u32 verde_rlc_save_restore_register_list[] =
{
(0x8000 << 16) | (0x98f4 >> 2),
0x00000000,
(0x8040 << 16) | (0x98f4 >> 2),
0x00000000,
(0x8000 << 16) | (0xe80 >> 2),
0x00000000,
(0x8040 << 16) | (0xe80 >> 2),
0x00000000,
(0x8000 << 16) | (0x89bc >> 2),
0x00000000,
(0x8040 << 16) | (0x89bc >> 2),
0x00000000,
(0x8000 << 16) | (0x8c1c >> 2),
0x00000000,
(0x8040 << 16) | (0x8c1c >> 2),
0x00000000,
(0x9c00 << 16) | (0x98f0 >> 2),
0x00000000,
(0x9c00 << 16) | (0xe7c >> 2),
0x00000000,
(0x8000 << 16) | (0x9148 >> 2),
0x00000000,
(0x8040 << 16) | (0x9148 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9150 >> 2),
0x00000000,
(0x9c00 << 16) | (0x897c >> 2),
0x00000000,
(0x9c00 << 16) | (0x8d8c >> 2),
0x00000000,
(0x9c00 << 16) | (0xac54 >> 2),
0X00000000,
0x3,
(0x9c00 << 16) | (0x98f8 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9910 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9914 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9918 >> 2),
0x00000000,
(0x9c00 << 16) | (0x991c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9920 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9924 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9928 >> 2),
0x00000000,
(0x9c00 << 16) | (0x992c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9930 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9934 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9938 >> 2),
0x00000000,
(0x9c00 << 16) | (0x993c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9940 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9944 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9948 >> 2),
0x00000000,
(0x9c00 << 16) | (0x994c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9950 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9954 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9958 >> 2),
0x00000000,
(0x9c00 << 16) | (0x995c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9960 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9964 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9968 >> 2),
0x00000000,
(0x9c00 << 16) | (0x996c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9970 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9974 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9978 >> 2),
0x00000000,
(0x9c00 << 16) | (0x997c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9980 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9984 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9988 >> 2),
0x00000000,
(0x9c00 << 16) | (0x998c >> 2),
0x00000000,
(0x9c00 << 16) | (0x8c00 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8c14 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8c04 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8c08 >> 2),
0x00000000,
(0x8000 << 16) | (0x9b7c >> 2),
0x00000000,
(0x8040 << 16) | (0x9b7c >> 2),
0x00000000,
(0x8000 << 16) | (0xe84 >> 2),
0x00000000,
(0x8040 << 16) | (0xe84 >> 2),
0x00000000,
(0x8000 << 16) | (0x89c0 >> 2),
0x00000000,
(0x8040 << 16) | (0x89c0 >> 2),
0x00000000,
(0x8000 << 16) | (0x914c >> 2),
0x00000000,
(0x8040 << 16) | (0x914c >> 2),
0x00000000,
(0x8000 << 16) | (0x8c20 >> 2),
0x00000000,
(0x8040 << 16) | (0x8c20 >> 2),
0x00000000,
(0x8000 << 16) | (0x9354 >> 2),
0x00000000,
(0x8040 << 16) | (0x9354 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9060 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9364 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9100 >> 2),
0x00000000,
(0x9c00 << 16) | (0x913c >> 2),
0x00000000,
(0x8000 << 16) | (0x90e0 >> 2),
0x00000000,
(0x8000 << 16) | (0x90e4 >> 2),
0x00000000,
(0x8000 << 16) | (0x90e8 >> 2),
0x00000000,
(0x8040 << 16) | (0x90e0 >> 2),
0x00000000,
(0x8040 << 16) | (0x90e4 >> 2),
0x00000000,
(0x8040 << 16) | (0x90e8 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8bcc >> 2),
0x00000000,
(0x9c00 << 16) | (0x8b24 >> 2),
0x00000000,
(0x9c00 << 16) | (0x88c4 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8e50 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8c0c >> 2),
0x00000000,
(0x9c00 << 16) | (0x8e58 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8e5c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9508 >> 2),
0x00000000,
(0x9c00 << 16) | (0x950c >> 2),
0x00000000,
(0x9c00 << 16) | (0x9494 >> 2),
0x00000000,
(0x9c00 << 16) | (0xac0c >> 2),
0x00000000,
(0x9c00 << 16) | (0xac10 >> 2),
0x00000000,
(0x9c00 << 16) | (0xac14 >> 2),
0x00000000,
(0x9c00 << 16) | (0xae00 >> 2),
0x00000000,
(0x9c00 << 16) | (0xac08 >> 2),
0x00000000,
(0x9c00 << 16) | (0x88d4 >> 2),
0x00000000,
(0x9c00 << 16) | (0x88c8 >> 2),
0x00000000,
(0x9c00 << 16) | (0x88cc >> 2),
0x00000000,
(0x9c00 << 16) | (0x89b0 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8b10 >> 2),
0x00000000,
(0x9c00 << 16) | (0x8a14 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9830 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9834 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9838 >> 2),
0x00000000,
(0x9c00 << 16) | (0x9a10 >> 2),
0x00000000,
(0x8000 << 16) | (0x9870 >> 2),
0x00000000,
(0x8000 << 16) | (0x9874 >> 2),
0x00000000,
(0x8001 << 16) | (0x9870 >> 2),
0x00000000,
(0x8001 << 16) | (0x9874 >> 2),
0x00000000,
(0x8040 << 16) | (0x9870 >> 2),
0x00000000,
(0x8040 << 16) | (0x9874 >> 2),
0x00000000,
(0x8041 << 16) | (0x9870 >> 2),
0x00000000,
(0x8041 << 16) | (0x9874 >> 2),
0x00000000,
0x00000000
};
static const u32 tahiti_golden_rlc_registers[] =
{
0xc424, 0xffffffff, 0x00601005,
0xc47c, 0xffffffff, 0x10104040,
0xc488, 0xffffffff, 0x0100000a,
0xc314, 0xffffffff, 0x00000800,
0xc30c, 0xffffffff, 0x800000f4,
0xf4a8, 0xffffffff, 0x00000000
};
static const u32 tahiti_golden_registers[] =
{
0x9a10, 0x00010000, 0x00018208,
0x9830, 0xffffffff, 0x00000000,
0x9834, 0xf00fffff, 0x00000400,
0x9838, 0x0002021c, 0x00020200,
0xc78, 0x00000080, 0x00000000,
0xd030, 0x000300c0, 0x00800040,
0xd830, 0x000300c0, 0x00800040,
0x5bb0, 0x000000f0, 0x00000070,
0x5bc0, 0x00200000, 0x50100000,
0x7030, 0x31000311, 0x00000011,
0x277c, 0x00000003, 0x000007ff,
0x240c, 0x000007ff, 0x00000000,
0x8a14, 0xf000001f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x8b10, 0x0000ff0f, 0x00000000,
0x28a4c, 0x07ffffff, 0x4e000000,
0x28350, 0x3f3f3fff, 0x2a00126a,
0x30, 0x000000ff, 0x0040,
0x34, 0x00000040, 0x00004040,
0x9100, 0x07ffffff, 0x03000000,
0x8e88, 0x01ff1f3f, 0x00000000,
0x8e84, 0x01ff1f3f, 0x00000000,
0x9060, 0x0000007f, 0x00000020,
0x9508, 0x00010000, 0x00010000,
0xac14, 0x00000200, 0x000002fb,
0xac10, 0xffffffff, 0x0000543b,
0xac0c, 0xffffffff, 0xa9210876,
0x88d0, 0xffffffff, 0x000fff40,
0x88d4, 0x0000001f, 0x00000010,
0x1410, 0x20000000, 0x20fffed8,
0x15c0, 0x000c0fc0, 0x000c0400
};
static const u32 tahiti_golden_registers2[] =
{
0xc64, 0x00000001, 0x00000001
};
static const u32 pitcairn_golden_rlc_registers[] =
{
0xc424, 0xffffffff, 0x00601004,
0xc47c, 0xffffffff, 0x10102020,
0xc488, 0xffffffff, 0x01000020,
0xc314, 0xffffffff, 0x00000800,
0xc30c, 0xffffffff, 0x800000a4
};
static const u32 pitcairn_golden_registers[] =
{
0x9a10, 0x00010000, 0x00018208,
0x9830, 0xffffffff, 0x00000000,
0x9834, 0xf00fffff, 0x00000400,
0x9838, 0x0002021c, 0x00020200,
0xc78, 0x00000080, 0x00000000,
0xd030, 0x000300c0, 0x00800040,
0xd830, 0x000300c0, 0x00800040,
0x5bb0, 0x000000f0, 0x00000070,
0x5bc0, 0x00200000, 0x50100000,
0x7030, 0x31000311, 0x00000011,
0x2ae4, 0x00073ffe, 0x000022a2,
0x240c, 0x000007ff, 0x00000000,
0x8a14, 0xf000001f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x8b10, 0x0000ff0f, 0x00000000,
0x28a4c, 0x07ffffff, 0x4e000000,
0x28350, 0x3f3f3fff, 0x2a00126a,
0x30, 0x000000ff, 0x0040,
0x34, 0x00000040, 0x00004040,
0x9100, 0x07ffffff, 0x03000000,
0x9060, 0x0000007f, 0x00000020,
0x9508, 0x00010000, 0x00010000,
0xac14, 0x000003ff, 0x000000f7,
0xac10, 0xffffffff, 0x00000000,
0xac0c, 0xffffffff, 0x32761054,
0x88d4, 0x0000001f, 0x00000010,
0x15c0, 0x000c0fc0, 0x000c0400
};
static const u32 verde_golden_rlc_registers[] =
{
0xc424, 0xffffffff, 0x033f1005,
0xc47c, 0xffffffff, 0x10808020,
0xc488, 0xffffffff, 0x00800008,
0xc314, 0xffffffff, 0x00001000,
0xc30c, 0xffffffff, 0x80010014
};
static const u32 verde_golden_registers[] =
{
0x9a10, 0x00010000, 0x00018208,
0x9830, 0xffffffff, 0x00000000,
0x9834, 0xf00fffff, 0x00000400,
0x9838, 0x0002021c, 0x00020200,
0xc78, 0x00000080, 0x00000000,
0xd030, 0x000300c0, 0x00800040,
0xd030, 0x000300c0, 0x00800040,
0xd830, 0x000300c0, 0x00800040,
0xd830, 0x000300c0, 0x00800040,
0x5bb0, 0x000000f0, 0x00000070,
0x5bc0, 0x00200000, 0x50100000,
0x7030, 0x31000311, 0x00000011,
0x2ae4, 0x00073ffe, 0x000022a2,
0x2ae4, 0x00073ffe, 0x000022a2,
0x2ae4, 0x00073ffe, 0x000022a2,
0x240c, 0x000007ff, 0x00000000,
0x240c, 0x000007ff, 0x00000000,
0x240c, 0x000007ff, 0x00000000,
0x8a14, 0xf000001f, 0x00000007,
0x8a14, 0xf000001f, 0x00000007,
0x8a14, 0xf000001f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x8b10, 0x0000ff0f, 0x00000000,
0x28a4c, 0x07ffffff, 0x4e000000,
0x28350, 0x3f3f3fff, 0x0000124a,
0x28350, 0x3f3f3fff, 0x0000124a,
0x28350, 0x3f3f3fff, 0x0000124a,
0x30, 0x000000ff, 0x0040,
0x34, 0x00000040, 0x00004040,
0x9100, 0x07ffffff, 0x03000000,
0x9100, 0x07ffffff, 0x03000000,
0x8e88, 0x01ff1f3f, 0x00000000,
0x8e88, 0x01ff1f3f, 0x00000000,
0x8e88, 0x01ff1f3f, 0x00000000,
0x8e84, 0x01ff1f3f, 0x00000000,
0x8e84, 0x01ff1f3f, 0x00000000,
0x8e84, 0x01ff1f3f, 0x00000000,
0x9060, 0x0000007f, 0x00000020,
0x9508, 0x00010000, 0x00010000,
0xac14, 0x000003ff, 0x00000003,
0xac14, 0x000003ff, 0x00000003,
0xac14, 0x000003ff, 0x00000003,
0xac10, 0xffffffff, 0x00000000,
0xac10, 0xffffffff, 0x00000000,
0xac10, 0xffffffff, 0x00000000,
0xac0c, 0xffffffff, 0x00001032,
0xac0c, 0xffffffff, 0x00001032,
0xac0c, 0xffffffff, 0x00001032,
0x88d4, 0x0000001f, 0x00000010,
0x88d4, 0x0000001f, 0x00000010,
0x88d4, 0x0000001f, 0x00000010,
0x15c0, 0x000c0fc0, 0x000c0400
};
static const u32 oland_golden_rlc_registers[] =
{
0xc424, 0xffffffff, 0x00601005,
0xc47c, 0xffffffff, 0x10104040,
0xc488, 0xffffffff, 0x0100000a,
0xc314, 0xffffffff, 0x00000800,
0xc30c, 0xffffffff, 0x800000f4
};
static const u32 oland_golden_registers[] =
{
0x9a10, 0x00010000, 0x00018208,
0x9830, 0xffffffff, 0x00000000,
0x9834, 0xf00fffff, 0x00000400,
0x9838, 0x0002021c, 0x00020200,
0xc78, 0x00000080, 0x00000000,
0xd030, 0x000300c0, 0x00800040,
0xd830, 0x000300c0, 0x00800040,
0x5bb0, 0x000000f0, 0x00000070,
0x5bc0, 0x00200000, 0x50100000,
0x7030, 0x31000311, 0x00000011,
0x2ae4, 0x00073ffe, 0x000022a2,
0x240c, 0x000007ff, 0x00000000,
0x8a14, 0xf000001f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x8b10, 0x0000ff0f, 0x00000000,
0x28a4c, 0x07ffffff, 0x4e000000,
0x28350, 0x3f3f3fff, 0x00000082,
0x30, 0x000000ff, 0x0040,
0x34, 0x00000040, 0x00004040,
0x9100, 0x07ffffff, 0x03000000,
0x9060, 0x0000007f, 0x00000020,
0x9508, 0x00010000, 0x00010000,
0xac14, 0x000003ff, 0x000000f3,
0xac10, 0xffffffff, 0x00000000,
0xac0c, 0xffffffff, 0x00003210,
0x88d4, 0x0000001f, 0x00000010,
0x15c0, 0x000c0fc0, 0x000c0400
};
static const u32 hainan_golden_registers[] =
{
0x9a10, 0x00010000, 0x00018208,
0x9830, 0xffffffff, 0x00000000,
0x9834, 0xf00fffff, 0x00000400,
0x9838, 0x0002021c, 0x00020200,
0xd0c0, 0xff000fff, 0x00000100,
0xd030, 0x000300c0, 0x00800040,
0xd8c0, 0xff000fff, 0x00000100,
0xd830, 0x000300c0, 0x00800040,
0x2ae4, 0x00073ffe, 0x000022a2,
0x240c, 0x000007ff, 0x00000000,
0x8a14, 0xf000001f, 0x00000007,
0x8b24, 0xffffffff, 0x00ffffff,
0x8b10, 0x0000ff0f, 0x00000000,
0x28a4c, 0x07ffffff, 0x4e000000,
0x28350, 0x3f3f3fff, 0x00000000,
0x30, 0x000000ff, 0x0040,
0x34, 0x00000040, 0x00004040,
0x9100, 0x03e00000, 0x03600000,
0x9060, 0x0000007f, 0x00000020,
0x9508, 0x00010000, 0x00010000,
0xac14, 0x000003ff, 0x000000f1,
0xac10, 0xffffffff, 0x00000000,
0xac0c, 0xffffffff, 0x00003210,
0x88d4, 0x0000001f, 0x00000010,
0x15c0, 0x000c0fc0, 0x000c0400
};
static const u32 hainan_golden_registers2[] =
{
0x98f8, 0xffffffff, 0x02010001
};
static const u32 tahiti_mgcg_cgcg_init[] =
{
0xc400, 0xffffffff, 0xfffffffc,
0x802c, 0xffffffff, 0xe0000000,
0x9a60, 0xffffffff, 0x00000100,
0x92a4, 0xffffffff, 0x00000100,
0xc164, 0xffffffff, 0x00000100,
0x9774, 0xffffffff, 0x00000100,
0x8984, 0xffffffff, 0x06000100,
0x8a18, 0xffffffff, 0x00000100,
0x92a0, 0xffffffff, 0x00000100,
0xc380, 0xffffffff, 0x00000100,
0x8b28, 0xffffffff, 0x00000100,
0x9144, 0xffffffff, 0x00000100,
0x8d88, 0xffffffff, 0x00000100,
0x8d8c, 0xffffffff, 0x00000100,
0x9030, 0xffffffff, 0x00000100,
0x9034, 0xffffffff, 0x00000100,
0x9038, 0xffffffff, 0x00000100,
0x903c, 0xffffffff, 0x00000100,
0xad80, 0xffffffff, 0x00000100,
0xac54, 0xffffffff, 0x00000100,
0x897c, 0xffffffff, 0x06000100,
0x9868, 0xffffffff, 0x00000100,
0x9510, 0xffffffff, 0x00000100,
0xaf04, 0xffffffff, 0x00000100,
0xae04, 0xffffffff, 0x00000100,
0x949c, 0xffffffff, 0x00000100,
0x802c, 0xffffffff, 0xe0000000,
0x9160, 0xffffffff, 0x00010000,
0x9164, 0xffffffff, 0x00030002,
0x9168, 0xffffffff, 0x00040007,
0x916c, 0xffffffff, 0x00060005,
0x9170, 0xffffffff, 0x00090008,
0x9174, 0xffffffff, 0x00020001,
0x9178, 0xffffffff, 0x00040003,
0x917c, 0xffffffff, 0x00000007,
0x9180, 0xffffffff, 0x00060005,
0x9184, 0xffffffff, 0x00090008,
0x9188, 0xffffffff, 0x00030002,
0x918c, 0xffffffff, 0x00050004,
0x9190, 0xffffffff, 0x00000008,
0x9194, 0xffffffff, 0x00070006,
0x9198, 0xffffffff, 0x000a0009,
0x919c, 0xffffffff, 0x00040003,
0x91a0, 0xffffffff, 0x00060005,
0x91a4, 0xffffffff, 0x00000009,
0x91a8, 0xffffffff, 0x00080007,
0x91ac, 0xffffffff, 0x000b000a,
0x91b0, 0xffffffff, 0x00050004,
0x91b4, 0xffffffff, 0x00070006,
0x91b8, 0xffffffff, 0x0008000b,
0x91bc, 0xffffffff, 0x000a0009,
0x91c0, 0xffffffff, 0x000d000c,
0x91c4, 0xffffffff, 0x00060005,
0x91c8, 0xffffffff, 0x00080007,
0x91cc, 0xffffffff, 0x0000000b,
0x91d0, 0xffffffff, 0x000a0009,
0x91d4, 0xffffffff, 0x000d000c,
0x91d8, 0xffffffff, 0x00070006,
0x91dc, 0xffffffff, 0x00090008,
0x91e0, 0xffffffff, 0x0000000c,
0x91e4, 0xffffffff, 0x000b000a,
0x91e8, 0xffffffff, 0x000e000d,
0x91ec, 0xffffffff, 0x00080007,
0x91f0, 0xffffffff, 0x000a0009,
0x91f4, 0xffffffff, 0x0000000d,
0x91f8, 0xffffffff, 0x000c000b,
0x91fc, 0xffffffff, 0x000f000e,
0x9200, 0xffffffff, 0x00090008,
0x9204, 0xffffffff, 0x000b000a,
0x9208, 0xffffffff, 0x000c000f,
0x920c, 0xffffffff, 0x000e000d,
0x9210, 0xffffffff, 0x00110010,
0x9214, 0xffffffff, 0x000a0009,
0x9218, 0xffffffff, 0x000c000b,
0x921c, 0xffffffff, 0x0000000f,
0x9220, 0xffffffff, 0x000e000d,
0x9224, 0xffffffff, 0x00110010,
0x9228, 0xffffffff, 0x000b000a,
0x922c, 0xffffffff, 0x000d000c,
0x9230, 0xffffffff, 0x00000010,
0x9234, 0xffffffff, 0x000f000e,
0x9238, 0xffffffff, 0x00120011,
0x923c, 0xffffffff, 0x000c000b,
0x9240, 0xffffffff, 0x000e000d,
0x9244, 0xffffffff, 0x00000011,
0x9248, 0xffffffff, 0x0010000f,
0x924c, 0xffffffff, 0x00130012,
0x9250, 0xffffffff, 0x000d000c,
0x9254, 0xffffffff, 0x000f000e,
0x9258, 0xffffffff, 0x00100013,
0x925c, 0xffffffff, 0x00120011,
0x9260, 0xffffffff, 0x00150014,
0x9264, 0xffffffff, 0x000e000d,
0x9268, 0xffffffff, 0x0010000f,
0x926c, 0xffffffff, 0x00000013,
0x9270, 0xffffffff, 0x00120011,
0x9274, 0xffffffff, 0x00150014,
0x9278, 0xffffffff, 0x000f000e,
0x927c, 0xffffffff, 0x00110010,
0x9280, 0xffffffff, 0x00000014,
0x9284, 0xffffffff, 0x00130012,
0x9288, 0xffffffff, 0x00160015,
0x928c, 0xffffffff, 0x0010000f,
0x9290, 0xffffffff, 0x00120011,
0x9294, 0xffffffff, 0x00000015,
0x9298, 0xffffffff, 0x00140013,
0x929c, 0xffffffff, 0x00170016,
0x9150, 0xffffffff, 0x96940200,
0x8708, 0xffffffff, 0x00900100,
0xc478, 0xffffffff, 0x00000080,
0xc404, 0xffffffff, 0x0020003f,
0x30, 0xffffffff, 0x0000001c,
0x34, 0x000f0000, 0x000f0000,
0x160c, 0xffffffff, 0x00000100,
0x1024, 0xffffffff, 0x00000100,
0x102c, 0x00000101, 0x00000000,
0x20a8, 0xffffffff, 0x00000104,
0x264c, 0x000c0000, 0x000c0000,
0x2648, 0x000c0000, 0x000c0000,
0x55e4, 0xff000fff, 0x00000100,
0x55e8, 0x00000001, 0x00000001,
0x2f50, 0x00000001, 0x00000001,
0x30cc, 0xc0000fff, 0x00000104,
0xc1e4, 0x00000001, 0x00000001,
0xd0c0, 0xfffffff0, 0x00000100,
0xd8c0, 0xfffffff0, 0x00000100
};
static const u32 pitcairn_mgcg_cgcg_init[] =
{
0xc400, 0xffffffff, 0xfffffffc,
0x802c, 0xffffffff, 0xe0000000,
0x9a60, 0xffffffff, 0x00000100,
0x92a4, 0xffffffff, 0x00000100,
0xc164, 0xffffffff, 0x00000100,
0x9774, 0xffffffff, 0x00000100,
0x8984, 0xffffffff, 0x06000100,
0x8a18, 0xffffffff, 0x00000100,
0x92a0, 0xffffffff, 0x00000100,
0xc380, 0xffffffff, 0x00000100,
0x8b28, 0xffffffff, 0x00000100,
0x9144, 0xffffffff, 0x00000100,
0x8d88, 0xffffffff, 0x00000100,
0x8d8c, 0xffffffff, 0x00000100,
0x9030, 0xffffffff, 0x00000100,
0x9034, 0xffffffff, 0x00000100,
0x9038, 0xffffffff, 0x00000100,
0x903c, 0xffffffff, 0x00000100,
0xad80, 0xffffffff, 0x00000100,
0xac54, 0xffffffff, 0x00000100,
0x897c, 0xffffffff, 0x06000100,
0x9868, 0xffffffff, 0x00000100,
0x9510, 0xffffffff, 0x00000100,
0xaf04, 0xffffffff, 0x00000100,
0xae04, 0xffffffff, 0x00000100,
0x949c, 0xffffffff, 0x00000100,
0x802c, 0xffffffff, 0xe0000000,
0x9160, 0xffffffff, 0x00010000,
0x9164, 0xffffffff, 0x00030002,
0x9168, 0xffffffff, 0x00040007,
0x916c, 0xffffffff, 0x00060005,
0x9170, 0xffffffff, 0x00090008,
0x9174, 0xffffffff, 0x00020001,
0x9178, 0xffffffff, 0x00040003,
0x917c, 0xffffffff, 0x00000007,
0x9180, 0xffffffff, 0x00060005,
0x9184, 0xffffffff, 0x00090008,
0x9188, 0xffffffff, 0x00030002,
0x918c, 0xffffffff, 0x00050004,
0x9190, 0xffffffff, 0x00000008,
0x9194, 0xffffffff, 0x00070006,
0x9198, 0xffffffff, 0x000a0009,
0x919c, 0xffffffff, 0x00040003,
0x91a0, 0xffffffff, 0x00060005,
0x91a4, 0xffffffff, 0x00000009,
0x91a8, 0xffffffff, 0x00080007,
0x91ac, 0xffffffff, 0x000b000a,
0x91b0, 0xffffffff, 0x00050004,
0x91b4, 0xffffffff, 0x00070006,
0x91b8, 0xffffffff, 0x0008000b,
0x91bc, 0xffffffff, 0x000a0009,
0x91c0, 0xffffffff, 0x000d000c,
0x9200, 0xffffffff, 0x00090008,
0x9204, 0xffffffff, 0x000b000a,
0x9208, 0xffffffff, 0x000c000f,
0x920c, 0xffffffff, 0x000e000d,
0x9210, 0xffffffff, 0x00110010,
0x9214, 0xffffffff, 0x000a0009,
0x9218, 0xffffffff, 0x000c000b,
0x921c, 0xffffffff, 0x0000000f,
0x9220, 0xffffffff, 0x000e000d,
0x9224, 0xffffffff, 0x00110010,
0x9228, 0xffffffff, 0x000b000a,
0x922c, 0xffffffff, 0x000d000c,
0x9230, 0xffffffff, 0x00000010,
0x9234, 0xffffffff, 0x000f000e,
0x9238, 0xffffffff, 0x00120011,
0x923c, 0xffffffff, 0x000c000b,
0x9240, 0xffffffff, 0x000e000d,
0x9244, 0xffffffff, 0x00000011,
0x9248, 0xffffffff, 0x0010000f,
0x924c, 0xffffffff, 0x00130012,
0x9250, 0xffffffff, 0x000d000c,
0x9254, 0xffffffff, 0x000f000e,
0x9258, 0xffffffff, 0x00100013,
0x925c, 0xffffffff, 0x00120011,
0x9260, 0xffffffff, 0x00150014,
0x9150, 0xffffffff, 0x96940200,
0x8708, 0xffffffff, 0x00900100,
0xc478, 0xffffffff, 0x00000080,
0xc404, 0xffffffff, 0x0020003f,
0x30, 0xffffffff, 0x0000001c,
0x34, 0x000f0000, 0x000f0000,
0x160c, 0xffffffff, 0x00000100,
0x1024, 0xffffffff, 0x00000100,
0x102c, 0x00000101, 0x00000000,
0x20a8, 0xffffffff, 0x00000104,
0x55e4, 0xff000fff, 0x00000100,
0x55e8, 0x00000001, 0x00000001,
0x2f50, 0x00000001, 0x00000001,
0x30cc, 0xc0000fff, 0x00000104,
0xc1e4, 0x00000001, 0x00000001,
0xd0c0, 0xfffffff0, 0x00000100,
0xd8c0, 0xfffffff0, 0x00000100
};
static const u32 verde_mgcg_cgcg_init[] =
{
0xc400, 0xffffffff, 0xfffffffc,
0x802c, 0xffffffff, 0xe0000000,
0x9a60, 0xffffffff, 0x00000100,
0x92a4, 0xffffffff, 0x00000100,
0xc164, 0xffffffff, 0x00000100,
0x9774, 0xffffffff, 0x00000100,
0x8984, 0xffffffff, 0x06000100,
0x8a18, 0xffffffff, 0x00000100,
0x92a0, 0xffffffff, 0x00000100,
0xc380, 0xffffffff, 0x00000100,
0x8b28, 0xffffffff, 0x00000100,
0x9144, 0xffffffff, 0x00000100,
0x8d88, 0xffffffff, 0x00000100,
0x8d8c, 0xffffffff, 0x00000100,
0x9030, 0xffffffff, 0x00000100,
0x9034, 0xffffffff, 0x00000100,
0x9038, 0xffffffff, 0x00000100,
0x903c, 0xffffffff, 0x00000100,
0xad80, 0xffffffff, 0x00000100,
0xac54, 0xffffffff, 0x00000100,
0x897c, 0xffffffff, 0x06000100,
0x9868, 0xffffffff, 0x00000100,
0x9510, 0xffffffff, 0x00000100,
0xaf04, 0xffffffff, 0x00000100,
0xae04, 0xffffffff, 0x00000100,
0x949c, 0xffffffff, 0x00000100,
0x802c, 0xffffffff, 0xe0000000,
0x9160, 0xffffffff, 0x00010000,
0x9164, 0xffffffff, 0x00030002,
0x9168, 0xffffffff, 0x00040007,
0x916c, 0xffffffff, 0x00060005,
0x9170, 0xffffffff, 0x00090008,
0x9174, 0xffffffff, 0x00020001,
0x9178, 0xffffffff, 0x00040003,
0x917c, 0xffffffff, 0x00000007,
0x9180, 0xffffffff, 0x00060005,
0x9184, 0xffffffff, 0x00090008,
0x9188, 0xffffffff, 0x00030002,
0x918c, 0xffffffff, 0x00050004,
0x9190, 0xffffffff, 0x00000008,
0x9194, 0xffffffff, 0x00070006,
0x9198, 0xffffffff, 0x000a0009,
0x919c, 0xffffffff, 0x00040003,
0x91a0, 0xffffffff, 0x00060005,
0x91a4, 0xffffffff, 0x00000009,
0x91a8, 0xffffffff, 0x00080007,
0x91ac, 0xffffffff, 0x000b000a,
0x91b0, 0xffffffff, 0x00050004,
0x91b4, 0xffffffff, 0x00070006,
0x91b8, 0xffffffff, 0x0008000b,
0x91bc, 0xffffffff, 0x000a0009,
0x91c0, 0xffffffff, 0x000d000c,
0x9200, 0xffffffff, 0x00090008,
0x9204, 0xffffffff, 0x000b000a,
0x9208, 0xffffffff, 0x000c000f,
0x920c, 0xffffffff, 0x000e000d,
0x9210, 0xffffffff, 0x00110010,
0x9214, 0xffffffff, 0x000a0009,
0x9218, 0xffffffff, 0x000c000b,
0x921c, 0xffffffff, 0x0000000f,
0x9220, 0xffffffff, 0x000e000d,
0x9224, 0xffffffff, 0x00110010,
0x9228, 0xffffffff, 0x000b000a,
0x922c, 0xffffffff, 0x000d000c,
0x9230, 0xffffffff, 0x00000010,
0x9234, 0xffffffff, 0x000f000e,
0x9238, 0xffffffff, 0x00120011,
0x923c, 0xffffffff, 0x000c000b,
0x9240, 0xffffffff, 0x000e000d,
0x9244, 0xffffffff, 0x00000011,
0x9248, 0xffffffff, 0x0010000f,
0x924c, 0xffffffff, 0x00130012,
0x9250, 0xffffffff, 0x000d000c,
0x9254, 0xffffffff, 0x000f000e,
0x9258, 0xffffffff, 0x00100013,
0x925c, 0xffffffff, 0x00120011,
0x9260, 0xffffffff, 0x00150014,
0x9150, 0xffffffff, 0x96940200,
0x8708, 0xffffffff, 0x00900100,
0xc478, 0xffffffff, 0x00000080,
0xc404, 0xffffffff, 0x0020003f,
0x30, 0xffffffff, 0x0000001c,
0x34, 0x000f0000, 0x000f0000,
0x160c, 0xffffffff, 0x00000100,
0x1024, 0xffffffff, 0x00000100,
0x102c, 0x00000101, 0x00000000,
0x20a8, 0xffffffff, 0x00000104,
0x264c, 0x000c0000, 0x000c0000,
0x2648, 0x000c0000, 0x000c0000,
0x55e4, 0xff000fff, 0x00000100,
0x55e8, 0x00000001, 0x00000001,
0x2f50, 0x00000001, 0x00000001,
0x30cc, 0xc0000fff, 0x00000104,
0xc1e4, 0x00000001, 0x00000001,
0xd0c0, 0xfffffff0, 0x00000100,
0xd8c0, 0xfffffff0, 0x00000100
};
static const u32 oland_mgcg_cgcg_init[] =
{
0xc400, 0xffffffff, 0xfffffffc,
0x802c, 0xffffffff, 0xe0000000,
0x9a60, 0xffffffff, 0x00000100,
0x92a4, 0xffffffff, 0x00000100,
0xc164, 0xffffffff, 0x00000100,
0x9774, 0xffffffff, 0x00000100,
0x8984, 0xffffffff, 0x06000100,
0x8a18, 0xffffffff, 0x00000100,
0x92a0, 0xffffffff, 0x00000100,
0xc380, 0xffffffff, 0x00000100,
0x8b28, 0xffffffff, 0x00000100,
0x9144, 0xffffffff, 0x00000100,
0x8d88, 0xffffffff, 0x00000100,
0x8d8c, 0xffffffff, 0x00000100,
0x9030, 0xffffffff, 0x00000100,
0x9034, 0xffffffff, 0x00000100,
0x9038, 0xffffffff, 0x00000100,
0x903c, 0xffffffff, 0x00000100,
0xad80, 0xffffffff, 0x00000100,
0xac54, 0xffffffff, 0x00000100,
0x897c, 0xffffffff, 0x06000100,
0x9868, 0xffffffff, 0x00000100,
0x9510, 0xffffffff, 0x00000100,
0xaf04, 0xffffffff, 0x00000100,
0xae04, 0xffffffff, 0x00000100,
0x949c, 0xffffffff, 0x00000100,
0x802c, 0xffffffff, 0xe0000000,
0x9160, 0xffffffff, 0x00010000,
0x9164, 0xffffffff, 0x00030002,
0x9168, 0xffffffff, 0x00040007,
0x916c, 0xffffffff, 0x00060005,
0x9170, 0xffffffff, 0x00090008,
0x9174, 0xffffffff, 0x00020001,
0x9178, 0xffffffff, 0x00040003,
0x917c, 0xffffffff, 0x00000007,
0x9180, 0xffffffff, 0x00060005,
0x9184, 0xffffffff, 0x00090008,
0x9188, 0xffffffff, 0x00030002,
0x918c, 0xffffffff, 0x00050004,
0x9190, 0xffffffff, 0x00000008,
0x9194, 0xffffffff, 0x00070006,
0x9198, 0xffffffff, 0x000a0009,
0x919c, 0xffffffff, 0x00040003,
0x91a0, 0xffffffff, 0x00060005,
0x91a4, 0xffffffff, 0x00000009,
0x91a8, 0xffffffff, 0x00080007,
0x91ac, 0xffffffff, 0x000b000a,
0x91b0, 0xffffffff, 0x00050004,
0x91b4, 0xffffffff, 0x00070006,
0x91b8, 0xffffffff, 0x0008000b,
0x91bc, 0xffffffff, 0x000a0009,
0x91c0, 0xffffffff, 0x000d000c,
0x91c4, 0xffffffff, 0x00060005,
0x91c8, 0xffffffff, 0x00080007,
0x91cc, 0xffffffff, 0x0000000b,
0x91d0, 0xffffffff, 0x000a0009,
0x91d4, 0xffffffff, 0x000d000c,
0x9150, 0xffffffff, 0x96940200,
0x8708, 0xffffffff, 0x00900100,
0xc478, 0xffffffff, 0x00000080,
0xc404, 0xffffffff, 0x0020003f,
0x30, 0xffffffff, 0x0000001c,
0x34, 0x000f0000, 0x000f0000,
0x160c, 0xffffffff, 0x00000100,
0x1024, 0xffffffff, 0x00000100,
0x102c, 0x00000101, 0x00000000,
0x20a8, 0xffffffff, 0x00000104,
0x264c, 0x000c0000, 0x000c0000,
0x2648, 0x000c0000, 0x000c0000,
0x55e4, 0xff000fff, 0x00000100,
0x55e8, 0x00000001, 0x00000001,
0x2f50, 0x00000001, 0x00000001,
0x30cc, 0xc0000fff, 0x00000104,
0xc1e4, 0x00000001, 0x00000001,
0xd0c0, 0xfffffff0, 0x00000100,
0xd8c0, 0xfffffff0, 0x00000100
};
static const u32 hainan_mgcg_cgcg_init[] =
{
0xc400, 0xffffffff, 0xfffffffc,
0x802c, 0xffffffff, 0xe0000000,
0x9a60, 0xffffffff, 0x00000100,
0x92a4, 0xffffffff, 0x00000100,
0xc164, 0xffffffff, 0x00000100,
0x9774, 0xffffffff, 0x00000100,
0x8984, 0xffffffff, 0x06000100,
0x8a18, 0xffffffff, 0x00000100,
0x92a0, 0xffffffff, 0x00000100,
0xc380, 0xffffffff, 0x00000100,
0x8b28, 0xffffffff, 0x00000100,
0x9144, 0xffffffff, 0x00000100,
0x8d88, 0xffffffff, 0x00000100,
0x8d8c, 0xffffffff, 0x00000100,
0x9030, 0xffffffff, 0x00000100,
0x9034, 0xffffffff, 0x00000100,
0x9038, 0xffffffff, 0x00000100,
0x903c, 0xffffffff, 0x00000100,
0xad80, 0xffffffff, 0x00000100,
0xac54, 0xffffffff, 0x00000100,
0x897c, 0xffffffff, 0x06000100,
0x9868, 0xffffffff, 0x00000100,
0x9510, 0xffffffff, 0x00000100,
0xaf04, 0xffffffff, 0x00000100,
0xae04, 0xffffffff, 0x00000100,
0x949c, 0xffffffff, 0x00000100,
0x802c, 0xffffffff, 0xe0000000,
0x9160, 0xffffffff, 0x00010000,
0x9164, 0xffffffff, 0x00030002,
0x9168, 0xffffffff, 0x00040007,
0x916c, 0xffffffff, 0x00060005,
0x9170, 0xffffffff, 0x00090008,
0x9174, 0xffffffff, 0x00020001,
0x9178, 0xffffffff, 0x00040003,
0x917c, 0xffffffff, 0x00000007,
0x9180, 0xffffffff, 0x00060005,
0x9184, 0xffffffff, 0x00090008,
0x9188, 0xffffffff, 0x00030002,
0x918c, 0xffffffff, 0x00050004,
0x9190, 0xffffffff, 0x00000008,
0x9194, 0xffffffff, 0x00070006,
0x9198, 0xffffffff, 0x000a0009,
0x919c, 0xffffffff, 0x00040003,
0x91a0, 0xffffffff, 0x00060005,
0x91a4, 0xffffffff, 0x00000009,
0x91a8, 0xffffffff, 0x00080007,
0x91ac, 0xffffffff, 0x000b000a,
0x91b0, 0xffffffff, 0x00050004,
0x91b4, 0xffffffff, 0x00070006,
0x91b8, 0xffffffff, 0x0008000b,
0x91bc, 0xffffffff, 0x000a0009,
0x91c0, 0xffffffff, 0x000d000c,
0x91c4, 0xffffffff, 0x00060005,
0x91c8, 0xffffffff, 0x00080007,
0x91cc, 0xffffffff, 0x0000000b,
0x91d0, 0xffffffff, 0x000a0009,
0x91d4, 0xffffffff, 0x000d000c,
0x9150, 0xffffffff, 0x96940200,
0x8708, 0xffffffff, 0x00900100,
0xc478, 0xffffffff, 0x00000080,
0xc404, 0xffffffff, 0x0020003f,
0x30, 0xffffffff, 0x0000001c,
0x34, 0x000f0000, 0x000f0000,
0x160c, 0xffffffff, 0x00000100,
0x1024, 0xffffffff, 0x00000100,
0x20a8, 0xffffffff, 0x00000104,
0x264c, 0x000c0000, 0x000c0000,
0x2648, 0x000c0000, 0x000c0000,
0x2f50, 0x00000001, 0x00000001,
0x30cc, 0xc0000fff, 0x00000104,
0xc1e4, 0x00000001, 0x00000001,
0xd0c0, 0xfffffff0, 0x00000100,
0xd8c0, 0xfffffff0, 0x00000100
};
static u32 verde_pg_init[] =
{
0x353c, 0xffffffff, 0x40000,
0x3538, 0xffffffff, 0x200010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x7007,
0x3538, 0xffffffff, 0x300010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x400000,
0x3538, 0xffffffff, 0x100010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x120200,
0x3538, 0xffffffff, 0x500010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x1e1e16,
0x3538, 0xffffffff, 0x600010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x171f1e,
0x3538, 0xffffffff, 0x700010ff,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x353c, 0xffffffff, 0x0,
0x3538, 0xffffffff, 0x9ff,
0x3500, 0xffffffff, 0x0,
0x3504, 0xffffffff, 0x10000800,
0x3504, 0xffffffff, 0xf,
0x3504, 0xffffffff, 0xf,
0x3500, 0xffffffff, 0x4,
0x3504, 0xffffffff, 0x1000051e,
0x3504, 0xffffffff, 0xffff,
0x3504, 0xffffffff, 0xffff,
0x3500, 0xffffffff, 0x8,
0x3504, 0xffffffff, 0x80500,
0x3500, 0xffffffff, 0x12,
0x3504, 0xffffffff, 0x9050c,
0x3500, 0xffffffff, 0x1d,
0x3504, 0xffffffff, 0xb052c,
0x3500, 0xffffffff, 0x2a,
0x3504, 0xffffffff, 0x1053e,
0x3500, 0xffffffff, 0x2d,
0x3504, 0xffffffff, 0x10546,
0x3500, 0xffffffff, 0x30,
0x3504, 0xffffffff, 0xa054e,
0x3500, 0xffffffff, 0x3c,
0x3504, 0xffffffff, 0x1055f,
0x3500, 0xffffffff, 0x3f,
0x3504, 0xffffffff, 0x10567,
0x3500, 0xffffffff, 0x42,
0x3504, 0xffffffff, 0x1056f,
0x3500, 0xffffffff, 0x45,
0x3504, 0xffffffff, 0x10572,
0x3500, 0xffffffff, 0x48,
0x3504, 0xffffffff, 0x20575,
0x3500, 0xffffffff, 0x4c,
0x3504, 0xffffffff, 0x190801,
0x3500, 0xffffffff, 0x67,
0x3504, 0xffffffff, 0x1082a,
0x3500, 0xffffffff, 0x6a,
0x3504, 0xffffffff, 0x1b082d,
0x3500, 0xffffffff, 0x87,
0x3504, 0xffffffff, 0x310851,
0x3500, 0xffffffff, 0xba,
0x3504, 0xffffffff, 0x891,
0x3500, 0xffffffff, 0xbc,
0x3504, 0xffffffff, 0x893,
0x3500, 0xffffffff, 0xbe,
0x3504, 0xffffffff, 0x20895,
0x3500, 0xffffffff, 0xc2,
0x3504, 0xffffffff, 0x20899,
0x3500, 0xffffffff, 0xc6,
0x3504, 0xffffffff, 0x2089d,
0x3500, 0xffffffff, 0xca,
0x3504, 0xffffffff, 0x8a1,
0x3500, 0xffffffff, 0xcc,
0x3504, 0xffffffff, 0x8a3,
0x3500, 0xffffffff, 0xce,
0x3504, 0xffffffff, 0x308a5,
0x3500, 0xffffffff, 0xd3,
0x3504, 0xffffffff, 0x6d08cd,
0x3500, 0xffffffff, 0x142,
0x3504, 0xffffffff, 0x2000095a,
0x3504, 0xffffffff, 0x1,
0x3500, 0xffffffff, 0x144,
0x3504, 0xffffffff, 0x301f095b,
0x3500, 0xffffffff, 0x165,
0x3504, 0xffffffff, 0xc094d,
0x3500, 0xffffffff, 0x173,
0x3504, 0xffffffff, 0xf096d,
0x3500, 0xffffffff, 0x184,
0x3504, 0xffffffff, 0x15097f,
0x3500, 0xffffffff, 0x19b,
0x3504, 0xffffffff, 0xc0998,
0x3500, 0xffffffff, 0x1a9,
0x3504, 0xffffffff, 0x409a7,
0x3500, 0xffffffff, 0x1af,
0x3504, 0xffffffff, 0xcdc,
0x3500, 0xffffffff, 0x1b1,
0x3504, 0xffffffff, 0x800,
0x3508, 0xffffffff, 0x6c9b2000,
0x3510, 0xfc00, 0x2000,
0x3544, 0xffffffff, 0xfc0,
0x28d4, 0x00000100, 0x100
};
static void si_init_golden_registers(struct radeon_device *rdev)
{
switch (rdev->family) {
case CHIP_TAHITI:
radeon_program_register_sequence(rdev,
tahiti_golden_registers,
(const u32)ARRAY_SIZE(tahiti_golden_registers));
radeon_program_register_sequence(rdev,
tahiti_golden_rlc_registers,
(const u32)ARRAY_SIZE(tahiti_golden_rlc_registers));
radeon_program_register_sequence(rdev,
tahiti_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(tahiti_mgcg_cgcg_init));
radeon_program_register_sequence(rdev,
tahiti_golden_registers2,
(const u32)ARRAY_SIZE(tahiti_golden_registers2));
break;
case CHIP_PITCAIRN:
radeon_program_register_sequence(rdev,
pitcairn_golden_registers,
(const u32)ARRAY_SIZE(pitcairn_golden_registers));
radeon_program_register_sequence(rdev,
pitcairn_golden_rlc_registers,
(const u32)ARRAY_SIZE(pitcairn_golden_rlc_registers));
radeon_program_register_sequence(rdev,
pitcairn_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(pitcairn_mgcg_cgcg_init));
break;
case CHIP_VERDE:
radeon_program_register_sequence(rdev,
verde_golden_registers,
(const u32)ARRAY_SIZE(verde_golden_registers));
radeon_program_register_sequence(rdev,
verde_golden_rlc_registers,
(const u32)ARRAY_SIZE(verde_golden_rlc_registers));
radeon_program_register_sequence(rdev,
verde_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(verde_mgcg_cgcg_init));
radeon_program_register_sequence(rdev,
verde_pg_init,
(const u32)ARRAY_SIZE(verde_pg_init));
break;
case CHIP_OLAND:
radeon_program_register_sequence(rdev,
oland_golden_registers,
(const u32)ARRAY_SIZE(oland_golden_registers));
radeon_program_register_sequence(rdev,
oland_golden_rlc_registers,
(const u32)ARRAY_SIZE(oland_golden_rlc_registers));
radeon_program_register_sequence(rdev,
oland_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(oland_mgcg_cgcg_init));
break;
case CHIP_HAINAN:
radeon_program_register_sequence(rdev,
hainan_golden_registers,
(const u32)ARRAY_SIZE(hainan_golden_registers));
radeon_program_register_sequence(rdev,
hainan_golden_registers2,
(const u32)ARRAY_SIZE(hainan_golden_registers2));
radeon_program_register_sequence(rdev,
hainan_mgcg_cgcg_init,
(const u32)ARRAY_SIZE(hainan_mgcg_cgcg_init));
break;
default:
break;
}
}
/**
* si_get_allowed_info_register - fetch the register for the info ioctl
*
* @rdev: radeon_device pointer
* @reg: register offset in bytes
* @val: register value
*
* Returns 0 for success or -EINVAL for an invalid register
*
*/
int si_get_allowed_info_register(struct radeon_device *rdev,
u32 reg, u32 *val)
{
switch (reg) {
case GRBM_STATUS:
case GRBM_STATUS2:
case GRBM_STATUS_SE0:
case GRBM_STATUS_SE1:
case SRBM_STATUS:
case SRBM_STATUS2:
case (DMA_STATUS_REG + DMA0_REGISTER_OFFSET):
case (DMA_STATUS_REG + DMA1_REGISTER_OFFSET):
case UVD_STATUS:
*val = RREG32(reg);
return 0;
default:
return -EINVAL;
}
}
#define PCIE_BUS_CLK 10000
#define TCLK (PCIE_BUS_CLK / 10)
/**
* si_get_xclk - get the xclk
*
* @rdev: radeon_device pointer
*
* Returns the reference clock used by the gfx engine
* (SI).
*/
u32 si_get_xclk(struct radeon_device *rdev)
{
u32 reference_clock = rdev->clock.spll.reference_freq;
u32 tmp;
tmp = RREG32(CG_CLKPIN_CNTL_2);
if (tmp & MUX_TCLK_TO_XCLK)
return TCLK;
tmp = RREG32(CG_CLKPIN_CNTL);
if (tmp & XTALIN_DIVIDE)
return reference_clock / 4;
return reference_clock;
}
/* get temperature in millidegrees */
int si_get_temp(struct radeon_device *rdev)
{
u32 temp;
int actual_temp = 0;
temp = (RREG32(CG_MULT_THERMAL_STATUS) & CTF_TEMP_MASK) >>
CTF_TEMP_SHIFT;
if (temp & 0x200)
actual_temp = 255;
else
actual_temp = temp & 0x1ff;
actual_temp = (actual_temp * 1000);
return actual_temp;
}
#define TAHITI_IO_MC_REGS_SIZE 36
static const u32 tahiti_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
{0x0000006f, 0x03044000},
{0x00000070, 0x0480c018},
{0x00000071, 0x00000040},
{0x00000072, 0x01000000},
{0x00000074, 0x000000ff},
{0x00000075, 0x00143400},
{0x00000076, 0x08ec0800},
{0x00000077, 0x040000cc},
{0x00000079, 0x00000000},
{0x0000007a, 0x21000409},
{0x0000007c, 0x00000000},
{0x0000007d, 0xe8000000},
{0x0000007e, 0x044408a8},
{0x0000007f, 0x00000003},
{0x00000080, 0x00000000},
{0x00000081, 0x01000000},
{0x00000082, 0x02000000},
{0x00000083, 0x00000000},
{0x00000084, 0xe3f3e4f4},
{0x00000085, 0x00052024},
{0x00000087, 0x00000000},
{0x00000088, 0x66036603},
{0x00000089, 0x01000000},
{0x0000008b, 0x1c0a0000},
{0x0000008c, 0xff010000},
{0x0000008e, 0xffffefff},
{0x0000008f, 0xfff3efff},
{0x00000090, 0xfff3efbf},
{0x00000094, 0x00101101},
{0x00000095, 0x00000fff},
{0x00000096, 0x00116fff},
{0x00000097, 0x60010000},
{0x00000098, 0x10010000},
{0x00000099, 0x00006000},
{0x0000009a, 0x00001000},
{0x0000009f, 0x00a77400}
};
static const u32 pitcairn_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
{0x0000006f, 0x03044000},
{0x00000070, 0x0480c018},
{0x00000071, 0x00000040},
{0x00000072, 0x01000000},
{0x00000074, 0x000000ff},
{0x00000075, 0x00143400},
{0x00000076, 0x08ec0800},
{0x00000077, 0x040000cc},
{0x00000079, 0x00000000},
{0x0000007a, 0x21000409},
{0x0000007c, 0x00000000},
{0x0000007d, 0xe8000000},
{0x0000007e, 0x044408a8},
{0x0000007f, 0x00000003},
{0x00000080, 0x00000000},
{0x00000081, 0x01000000},
{0x00000082, 0x02000000},
{0x00000083, 0x00000000},
{0x00000084, 0xe3f3e4f4},
{0x00000085, 0x00052024},
{0x00000087, 0x00000000},
{0x00000088, 0x66036603},
{0x00000089, 0x01000000},
{0x0000008b, 0x1c0a0000},
{0x0000008c, 0xff010000},
{0x0000008e, 0xffffefff},
{0x0000008f, 0xfff3efff},
{0x00000090, 0xfff3efbf},
{0x00000094, 0x00101101},
{0x00000095, 0x00000fff},
{0x00000096, 0x00116fff},
{0x00000097, 0x60010000},
{0x00000098, 0x10010000},
{0x00000099, 0x00006000},
{0x0000009a, 0x00001000},
{0x0000009f, 0x00a47400}
};
static const u32 verde_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
{0x0000006f, 0x03044000},
{0x00000070, 0x0480c018},
{0x00000071, 0x00000040},
{0x00000072, 0x01000000},
{0x00000074, 0x000000ff},
{0x00000075, 0x00143400},
{0x00000076, 0x08ec0800},
{0x00000077, 0x040000cc},
{0x00000079, 0x00000000},
{0x0000007a, 0x21000409},
{0x0000007c, 0x00000000},
{0x0000007d, 0xe8000000},
{0x0000007e, 0x044408a8},
{0x0000007f, 0x00000003},
{0x00000080, 0x00000000},
{0x00000081, 0x01000000},
{0x00000082, 0x02000000},
{0x00000083, 0x00000000},
{0x00000084, 0xe3f3e4f4},
{0x00000085, 0x00052024},
{0x00000087, 0x00000000},
{0x00000088, 0x66036603},
{0x00000089, 0x01000000},
{0x0000008b, 0x1c0a0000},
{0x0000008c, 0xff010000},
{0x0000008e, 0xffffefff},
{0x0000008f, 0xfff3efff},
{0x00000090, 0xfff3efbf},
{0x00000094, 0x00101101},
{0x00000095, 0x00000fff},
{0x00000096, 0x00116fff},
{0x00000097, 0x60010000},
{0x00000098, 0x10010000},
{0x00000099, 0x00006000},
{0x0000009a, 0x00001000},
{0x0000009f, 0x00a37400}
};
static const u32 oland_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
{0x0000006f, 0x03044000},
{0x00000070, 0x0480c018},
{0x00000071, 0x00000040},
{0x00000072, 0x01000000},
{0x00000074, 0x000000ff},
{0x00000075, 0x00143400},
{0x00000076, 0x08ec0800},
{0x00000077, 0x040000cc},
{0x00000079, 0x00000000},
{0x0000007a, 0x21000409},
{0x0000007c, 0x00000000},
{0x0000007d, 0xe8000000},
{0x0000007e, 0x044408a8},
{0x0000007f, 0x00000003},
{0x00000080, 0x00000000},
{0x00000081, 0x01000000},
{0x00000082, 0x02000000},
{0x00000083, 0x00000000},
{0x00000084, 0xe3f3e4f4},
{0x00000085, 0x00052024},
{0x00000087, 0x00000000},
{0x00000088, 0x66036603},
{0x00000089, 0x01000000},
{0x0000008b, 0x1c0a0000},
{0x0000008c, 0xff010000},
{0x0000008e, 0xffffefff},
{0x0000008f, 0xfff3efff},
{0x00000090, 0xfff3efbf},
{0x00000094, 0x00101101},
{0x00000095, 0x00000fff},
{0x00000096, 0x00116fff},
{0x00000097, 0x60010000},
{0x00000098, 0x10010000},
{0x00000099, 0x00006000},
{0x0000009a, 0x00001000},
{0x0000009f, 0x00a17730}
};
static const u32 hainan_io_mc_regs[TAHITI_IO_MC_REGS_SIZE][2] = {
{0x0000006f, 0x03044000},
{0x00000070, 0x0480c018},
{0x00000071, 0x00000040},
{0x00000072, 0x01000000},
{0x00000074, 0x000000ff},
{0x00000075, 0x00143400},
{0x00000076, 0x08ec0800},
{0x00000077, 0x040000cc},
{0x00000079, 0x00000000},
{0x0000007a, 0x21000409},
{0x0000007c, 0x00000000},
{0x0000007d, 0xe8000000},
{0x0000007e, 0x044408a8},
{0x0000007f, 0x00000003},
{0x00000080, 0x00000000},
{0x00000081, 0x01000000},
{0x00000082, 0x02000000},
{0x00000083, 0x00000000},
{0x00000084, 0xe3f3e4f4},
{0x00000085, 0x00052024},
{0x00000087, 0x00000000},
{0x00000088, 0x66036603},
{0x00000089, 0x01000000},
{0x0000008b, 0x1c0a0000},
{0x0000008c, 0xff010000},
{0x0000008e, 0xffffefff},
{0x0000008f, 0xfff3efff},
{0x00000090, 0xfff3efbf},
{0x00000094, 0x00101101},
{0x00000095, 0x00000fff},
{0x00000096, 0x00116fff},
{0x00000097, 0x60010000},
{0x00000098, 0x10010000},
{0x00000099, 0x00006000},
{0x0000009a, 0x00001000},
{0x0000009f, 0x00a07730}
};
/* ucode loading */
int si_mc_load_microcode(struct radeon_device *rdev)
{
const __be32 *fw_data = NULL;
const __le32 *new_fw_data = NULL;
u32 running;
u32 *io_mc_regs = NULL;
const __le32 *new_io_mc_regs = NULL;
int i, regs_size, ucode_size;
if (!rdev->mc_fw)
return -EINVAL;
if (rdev->new_fw) {
const struct mc_firmware_header_v1_0 *hdr =
(const struct mc_firmware_header_v1_0 *)rdev->mc_fw->data;
radeon_ucode_print_mc_hdr(&hdr->header);
regs_size = le32_to_cpu(hdr->io_debug_size_bytes) / (4 * 2);
new_io_mc_regs = (const __le32 *)
(rdev->mc_fw->data + le32_to_cpu(hdr->io_debug_array_offset_bytes));
ucode_size = le32_to_cpu(hdr->header.ucode_size_bytes) / 4;
new_fw_data = (const __le32 *)
(rdev->mc_fw->data + le32_to_cpu(hdr->header.ucode_array_offset_bytes));
} else {
ucode_size = rdev->mc_fw->size / 4;
switch (rdev->family) {
case CHIP_TAHITI:
io_mc_regs = (u32 *)&tahiti_io_mc_regs;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_PITCAIRN:
io_mc_regs = (u32 *)&pitcairn_io_mc_regs;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_VERDE:
default:
io_mc_regs = (u32 *)&verde_io_mc_regs;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_OLAND:
io_mc_regs = (u32 *)&oland_io_mc_regs;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
case CHIP_HAINAN:
io_mc_regs = (u32 *)&hainan_io_mc_regs;
regs_size = TAHITI_IO_MC_REGS_SIZE;
break;
}
fw_data = (const __be32 *)rdev->mc_fw->data;
}
running = RREG32(MC_SEQ_SUP_CNTL) & RUN_MASK;
if (running == 0) {
/* reset the engine and set to writable */
WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
WREG32(MC_SEQ_SUP_CNTL, 0x00000010);
/* load mc io regs */
for (i = 0; i < regs_size; i++) {
if (rdev->new_fw) {
WREG32(MC_SEQ_IO_DEBUG_INDEX, le32_to_cpup(new_io_mc_regs++));
WREG32(MC_SEQ_IO_DEBUG_DATA, le32_to_cpup(new_io_mc_regs++));
} else {
WREG32(MC_SEQ_IO_DEBUG_INDEX, io_mc_regs[(i << 1)]);
WREG32(MC_SEQ_IO_DEBUG_DATA, io_mc_regs[(i << 1) + 1]);
}
}
/* load the MC ucode */
for (i = 0; i < ucode_size; i++) {
if (rdev->new_fw)
WREG32(MC_SEQ_SUP_PGM, le32_to_cpup(new_fw_data++));
else
WREG32(MC_SEQ_SUP_PGM, be32_to_cpup(fw_data++));
}
/* put the engine back into the active state */
WREG32(MC_SEQ_SUP_CNTL, 0x00000008);
WREG32(MC_SEQ_SUP_CNTL, 0x00000004);
WREG32(MC_SEQ_SUP_CNTL, 0x00000001);
/* wait for training to complete */
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D0)
break;
udelay(1);
}
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(MC_SEQ_TRAIN_WAKEUP_CNTL) & TRAIN_DONE_D1)
break;
udelay(1);
}
}
return 0;
}
static int si_init_microcode(struct radeon_device *rdev)
{
const char *chip_name;
const char *new_chip_name;
size_t pfp_req_size, me_req_size, ce_req_size, rlc_req_size, mc_req_size;
size_t smc_req_size, mc2_req_size;
char fw_name[30];
int err;
int new_fw = 0;
bool new_smc = false;
bool si58_fw = false;
bool banks2_fw = false;
DRM_DEBUG("\n");
switch (rdev->family) {
case CHIP_TAHITI:
chip_name = "TAHITI";
new_chip_name = "tahiti";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
mc2_req_size = TAHITI_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(TAHITI_SMC_UCODE_SIZE, 4);
break;
case CHIP_PITCAIRN:
chip_name = "PITCAIRN";
if ((rdev->pdev->revision == 0x81) &&
((rdev->pdev->device == 0x6810) ||
(rdev->pdev->device == 0x6811)))
new_smc = true;
new_chip_name = "pitcairn";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
mc2_req_size = PITCAIRN_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(PITCAIRN_SMC_UCODE_SIZE, 4);
break;
case CHIP_VERDE:
chip_name = "VERDE";
if (((rdev->pdev->device == 0x6820) &&
((rdev->pdev->revision == 0x81) ||
(rdev->pdev->revision == 0x83))) ||
((rdev->pdev->device == 0x6821) &&
((rdev->pdev->revision == 0x83) ||
(rdev->pdev->revision == 0x87))) ||
((rdev->pdev->revision == 0x87) &&
((rdev->pdev->device == 0x6823) ||
(rdev->pdev->device == 0x682b))))
new_smc = true;
new_chip_name = "verde";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = SI_MC_UCODE_SIZE * 4;
mc2_req_size = VERDE_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(VERDE_SMC_UCODE_SIZE, 4);
break;
case CHIP_OLAND:
chip_name = "OLAND";
if (((rdev->pdev->revision == 0x81) &&
((rdev->pdev->device == 0x6600) ||
(rdev->pdev->device == 0x6604) ||
(rdev->pdev->device == 0x6605) ||
(rdev->pdev->device == 0x6610))) ||
((rdev->pdev->revision == 0x83) &&
(rdev->pdev->device == 0x6610)))
new_smc = true;
new_chip_name = "oland";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(OLAND_SMC_UCODE_SIZE, 4);
break;
case CHIP_HAINAN:
chip_name = "HAINAN";
if (((rdev->pdev->revision == 0x81) &&
(rdev->pdev->device == 0x6660)) ||
((rdev->pdev->revision == 0x83) &&
((rdev->pdev->device == 0x6660) ||
(rdev->pdev->device == 0x6663) ||
(rdev->pdev->device == 0x6665) ||
(rdev->pdev->device == 0x6667))))
new_smc = true;
else if ((rdev->pdev->revision == 0xc3) &&
(rdev->pdev->device == 0x6665))
banks2_fw = true;
new_chip_name = "hainan";
pfp_req_size = SI_PFP_UCODE_SIZE * 4;
me_req_size = SI_PM4_UCODE_SIZE * 4;
ce_req_size = SI_CE_UCODE_SIZE * 4;
rlc_req_size = SI_RLC_UCODE_SIZE * 4;
mc_req_size = mc2_req_size = OLAND_MC_UCODE_SIZE * 4;
smc_req_size = ALIGN(HAINAN_SMC_UCODE_SIZE, 4);
break;
default: BUG();
}
/* this memory configuration requires special firmware */
if (((RREG32(MC_SEQ_MISC0) & 0xff000000) >> 24) == 0x58)
si58_fw = true;
DRM_INFO("Loading %s Microcode\n", new_chip_name);
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", new_chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name);
err = request_firmware(&rdev->pfp_fw, fw_name, rdev->dev);
if (err)
goto out;
if (rdev->pfp_fw->size != pfp_req_size) {
pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->pfp_fw->size, fw_name);
err = -EINVAL;
goto out;
}
} else {
err = radeon_ucode_validate(rdev->pfp_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", new_chip_name);
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name);
err = request_firmware(&rdev->me_fw, fw_name, rdev->dev);
if (err)
goto out;
if (rdev->me_fw->size != me_req_size) {
pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->me_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->me_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", new_chip_name);
err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_ce.bin", chip_name);
err = request_firmware(&rdev->ce_fw, fw_name, rdev->dev);
if (err)
goto out;
if (rdev->ce_fw->size != ce_req_size) {
pr_err("si_cp: Bogus length %zu in firmware \"%s\"\n",
rdev->ce_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->ce_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", new_chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_rlc.bin", chip_name);
err = request_firmware(&rdev->rlc_fw, fw_name, rdev->dev);
if (err)
goto out;
if (rdev->rlc_fw->size != rlc_req_size) {
pr_err("si_rlc: Bogus length %zu in firmware \"%s\"\n",
rdev->rlc_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->rlc_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
if (si58_fw)
snprintf(fw_name, sizeof(fw_name), "radeon/si58_mc.bin");
else
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", new_chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc2.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_mc.bin", chip_name);
err = request_firmware(&rdev->mc_fw, fw_name, rdev->dev);
if (err)
goto out;
}
if ((rdev->mc_fw->size != mc_req_size) &&
(rdev->mc_fw->size != mc2_req_size)) {
pr_err("si_mc: Bogus length %zu in firmware \"%s\"\n",
rdev->mc_fw->size, fw_name);
err = -EINVAL;
}
DRM_INFO("%s: %zu bytes\n", fw_name, rdev->mc_fw->size);
} else {
err = radeon_ucode_validate(rdev->mc_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
if (banks2_fw)
snprintf(fw_name, sizeof(fw_name), "radeon/banks_k_2_smc.bin");
else if (new_smc)
snprintf(fw_name, sizeof(fw_name), "radeon/%s_k_smc.bin", new_chip_name);
else
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", new_chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) {
snprintf(fw_name, sizeof(fw_name), "radeon/%s_smc.bin", chip_name);
err = request_firmware(&rdev->smc_fw, fw_name, rdev->dev);
if (err) {
pr_err("smc: error loading firmware \"%s\"\n", fw_name);
release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL;
err = 0;
} else if (rdev->smc_fw->size != smc_req_size) {
pr_err("si_smc: Bogus length %zu in firmware \"%s\"\n",
rdev->smc_fw->size, fw_name);
err = -EINVAL;
}
} else {
err = radeon_ucode_validate(rdev->smc_fw);
if (err) {
pr_err("si_cp: validation failed for firmware \"%s\"\n",
fw_name);
goto out;
} else {
new_fw++;
}
}
if (new_fw == 0) {
rdev->new_fw = false;
} else if (new_fw < 6) {
pr_err("si_fw: mixing new and old firmware!\n");
err = -EINVAL;
} else {
rdev->new_fw = true;
}
out:
if (err) {
if (err != -EINVAL)
pr_err("si_cp: Failed to load firmware \"%s\"\n",
fw_name);
release_firmware(rdev->pfp_fw);
rdev->pfp_fw = NULL;
release_firmware(rdev->me_fw);
rdev->me_fw = NULL;
release_firmware(rdev->ce_fw);
rdev->ce_fw = NULL;
release_firmware(rdev->rlc_fw);
rdev->rlc_fw = NULL;
release_firmware(rdev->mc_fw);
rdev->mc_fw = NULL;
release_firmware(rdev->smc_fw);
rdev->smc_fw = NULL;
}
return err;
}
/* watermark setup */
static u32 dce6_line_buffer_adjust(struct radeon_device *rdev,
struct radeon_crtc *radeon_crtc,
struct drm_display_mode *mode,
struct drm_display_mode *other_mode)
{
u32 tmp, buffer_alloc, i;
u32 pipe_offset = radeon_crtc->crtc_id * 0x20;
/*
* Line Buffer Setup
* There are 3 line buffers, each one shared by 2 display controllers.
* DC_LB_MEMORY_SPLIT controls how that line buffer is shared between
* the display controllers. The paritioning is done via one of four
* preset allocations specified in bits 21:20:
* 0 - half lb
* 2 - whole lb, other crtc must be disabled
*/
/* this can get tricky if we have two large displays on a paired group
* of crtcs. Ideally for multiple large displays we'd assign them to
* non-linked crtcs for maximum line buffer allocation.
*/
if (radeon_crtc->base.enabled && mode) {
if (other_mode) {
tmp = 0; /* 1/2 */
buffer_alloc = 1;
} else {
tmp = 2; /* whole */
buffer_alloc = 2;
}
} else {
tmp = 0;
buffer_alloc = 0;
}
WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset,
DC_LB_MEMORY_CONFIG(tmp));
WREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset,
DMIF_BUFFERS_ALLOCATED(buffer_alloc));
for (i = 0; i < rdev->usec_timeout; i++) {
if (RREG32(PIPE0_DMIF_BUFFER_CONTROL + pipe_offset) &
DMIF_BUFFERS_ALLOCATED_COMPLETED)
break;
udelay(1);
}
if (radeon_crtc->base.enabled && mode) {
switch (tmp) {
case 0:
default:
return 4096 * 2;
case 2:
return 8192 * 2;
}
}
/* controller not enabled, so no lb used */
return 0;
}
static u32 si_get_number_of_dram_channels(struct radeon_device *rdev)
{
u32 tmp = RREG32(MC_SHARED_CHMAP);
switch ((tmp & NOOFCHAN_MASK) >> NOOFCHAN_SHIFT) {
case 0:
default:
return 1;
case 1:
return 2;
case 2:
return 4;
case 3:
return 8;
case 4:
return 3;
case 5:
return 6;
case 6:
return 10;
case 7:
return 12;
case 8:
return 16;
}
}
struct dce6_wm_params {
u32 dram_channels; /* number of dram channels */
u32 yclk; /* bandwidth per dram data pin in kHz */
u32 sclk; /* engine clock in kHz */
u32 disp_clk; /* display clock in kHz */
u32 src_width; /* viewport width */
u32 active_time; /* active display time in ns */
u32 blank_time; /* blank time in ns */
bool interlaced; /* mode is interlaced */
fixed20_12 vsc; /* vertical scale ratio */
u32 num_heads; /* number of active crtcs */
u32 bytes_per_pixel; /* bytes per pixel display + overlay */
u32 lb_size; /* line buffer allocated to pipe */
u32 vtaps; /* vertical scaler taps */
};
static u32 dce6_dram_bandwidth(struct dce6_wm_params *wm)
{
/* Calculate raw DRAM Bandwidth */
fixed20_12 dram_efficiency; /* 0.7 */
fixed20_12 yclk, dram_channels, bandwidth;
fixed20_12 a;
a.full = dfixed_const(1000);
yclk.full = dfixed_const(wm->yclk);
yclk.full = dfixed_div(yclk, a);
dram_channels.full = dfixed_const(wm->dram_channels * 4);
a.full = dfixed_const(10);
dram_efficiency.full = dfixed_const(7);
dram_efficiency.full = dfixed_div(dram_efficiency, a);
bandwidth.full = dfixed_mul(dram_channels, yclk);
bandwidth.full = dfixed_mul(bandwidth, dram_efficiency);
return dfixed_trunc(bandwidth);
}
static u32 dce6_dram_bandwidth_for_display(struct dce6_wm_params *wm)
{
/* Calculate DRAM Bandwidth and the part allocated to display. */
fixed20_12 disp_dram_allocation; /* 0.3 to 0.7 */
fixed20_12 yclk, dram_channels, bandwidth;
fixed20_12 a;
a.full = dfixed_const(1000);
yclk.full = dfixed_const(wm->yclk);
yclk.full = dfixed_div(yclk, a);
dram_channels.full = dfixed_const(wm->dram_channels * 4);
a.full = dfixed_const(10);
disp_dram_allocation.full = dfixed_const(3); /* XXX worse case value 0.3 */
disp_dram_allocation.full = dfixed_div(disp_dram_allocation, a);
bandwidth.full = dfixed_mul(dram_channels, yclk);
bandwidth.full = dfixed_mul(bandwidth, disp_dram_allocation);
return dfixed_trunc(bandwidth);
}
static u32 dce6_data_return_bandwidth(struct dce6_wm_params *wm)
{
/* Calculate the display Data return Bandwidth */
fixed20_12 return_efficiency; /* 0.8 */
fixed20_12 sclk, bandwidth;
fixed20_12 a;
a.full = dfixed_const(1000);
sclk.full = dfixed_const(wm->sclk);
sclk.full = dfixed_div(sclk, a);
a.full = dfixed_const(10);
return_efficiency.full = dfixed_const(8);
return_efficiency.full = dfixed_div(return_efficiency, a);
a.full = dfixed_const(32);
bandwidth.full = dfixed_mul(a, sclk);
bandwidth.full = dfixed_mul(bandwidth, return_efficiency);
return dfixed_trunc(bandwidth);
}
static u32 dce6_get_dmif_bytes_per_request(struct dce6_wm_params *wm)
{
return 32;
}
static u32 dce6_dmif_request_bandwidth(struct dce6_wm_params *wm)
{
/* Calculate the DMIF Request Bandwidth */
fixed20_12 disp_clk_request_efficiency; /* 0.8 */
fixed20_12 disp_clk, sclk, bandwidth;
fixed20_12 a, b1, b2;
u32 min_bandwidth;
a.full = dfixed_const(1000);
disp_clk.full = dfixed_const(wm->disp_clk);
disp_clk.full = dfixed_div(disp_clk, a);
a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm) / 2);
b1.full = dfixed_mul(a, disp_clk);
a.full = dfixed_const(1000);
sclk.full = dfixed_const(wm->sclk);
sclk.full = dfixed_div(sclk, a);
a.full = dfixed_const(dce6_get_dmif_bytes_per_request(wm));
b2.full = dfixed_mul(a, sclk);
a.full = dfixed_const(10);
disp_clk_request_efficiency.full = dfixed_const(8);
disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a);
min_bandwidth = min(dfixed_trunc(b1), dfixed_trunc(b2));
a.full = dfixed_const(min_bandwidth);
bandwidth.full = dfixed_mul(a, disp_clk_request_efficiency);
return dfixed_trunc(bandwidth);
}
static u32 dce6_available_bandwidth(struct dce6_wm_params *wm)
{
/* Calculate the Available bandwidth. Display can use this temporarily but not in average. */
u32 dram_bandwidth = dce6_dram_bandwidth(wm);
u32 data_return_bandwidth = dce6_data_return_bandwidth(wm);
u32 dmif_req_bandwidth = dce6_dmif_request_bandwidth(wm);
return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth));
}
static u32 dce6_average_bandwidth(struct dce6_wm_params *wm)
{
/* Calculate the display mode Average Bandwidth
* DisplayMode should contain the source and destination dimensions,
* timing, etc.
*/
fixed20_12 bpp;
fixed20_12 line_time;
fixed20_12 src_width;
fixed20_12 bandwidth;
fixed20_12 a;
a.full = dfixed_const(1000);
line_time.full = dfixed_const(wm->active_time + wm->blank_time);
line_time.full = dfixed_div(line_time, a);
bpp.full = dfixed_const(wm->bytes_per_pixel);
src_width.full = dfixed_const(wm->src_width);
bandwidth.full = dfixed_mul(src_width, bpp);
bandwidth.full = dfixed_mul(bandwidth, wm->vsc);
bandwidth.full = dfixed_div(bandwidth, line_time);
return dfixed_trunc(bandwidth);
}
static u32 dce6_latency_watermark(struct dce6_wm_params *wm)
{
/* First calcualte the latency in ns */
u32 mc_latency = 2000; /* 2000 ns. */
u32 available_bandwidth = dce6_available_bandwidth(wm);
u32 worst_chunk_return_time = (512 * 8 * 1000) / available_bandwidth;
u32 cursor_line_pair_return_time = (128 * 4 * 1000) / available_bandwidth;
u32 dc_latency = 40000000 / wm->disp_clk; /* dc pipe latency */
u32 other_heads_data_return_time = ((wm->num_heads + 1) * worst_chunk_return_time) +
(wm->num_heads * cursor_line_pair_return_time);
u32 latency = mc_latency + other_heads_data_return_time + dc_latency;
u32 max_src_lines_per_dst_line, lb_fill_bw, line_fill_time;
u32 tmp, dmif_size = 12288;
fixed20_12 a, b, c;
if (wm->num_heads == 0)
return 0;
a.full = dfixed_const(2);
b.full = dfixed_const(1);
if ((wm->vsc.full > a.full) ||
((wm->vsc.full > b.full) && (wm->vtaps >= 3)) ||
(wm->vtaps >= 5) ||
((wm->vsc.full >= a.full) && wm->interlaced))
max_src_lines_per_dst_line = 4;
else
max_src_lines_per_dst_line = 2;
a.full = dfixed_const(available_bandwidth);
b.full = dfixed_const(wm->num_heads);
a.full = dfixed_div(a, b);
tmp = div_u64((u64) dmif_size * (u64) wm->disp_clk, mc_latency + 512);
tmp = min(dfixed_trunc(a), tmp);
lb_fill_bw = min(tmp, wm->disp_clk * wm->bytes_per_pixel / 1000);
a.full = dfixed_const(max_src_lines_per_dst_line * wm->src_width * wm->bytes_per_pixel);
b.full = dfixed_const(1000);
c.full = dfixed_const(lb_fill_bw);
b.full = dfixed_div(c, b);
a.full = dfixed_div(a, b);
line_fill_time = dfixed_trunc(a);
if (line_fill_time < wm->active_time)
return latency;
else
return latency + (line_fill_time - wm->active_time);
}
static bool dce6_average_bandwidth_vs_dram_bandwidth_for_display(struct dce6_wm_params *wm)
{
if (dce6_average_bandwidth(wm) <=
(dce6_dram_bandwidth_for_display(wm) / wm->num_heads))
return true;
else
return false;
};
static bool dce6_average_bandwidth_vs_available_bandwidth(struct dce6_wm_params *wm)
{
if (dce6_average_bandwidth(wm) <=
(dce6_available_bandwidth(wm) / wm->num_heads))
return true;
else
return false;
};
static bool dce6_check_latency_hiding(struct dce6_wm_params *wm)
{
u32 lb_partitions = wm->lb_size / wm->src_width;
u32 line_time = wm->active_time + wm->blank_time;
u32 latency_tolerant_lines;
u32 latency_hiding;
fixed20_12 a;
a.full = dfixed_const(1);
if (wm->vsc.full > a.full)
latency_tolerant_lines = 1;
else {
if (lb_partitions <= (wm->vtaps + 1))
latency_tolerant_lines = 1;
else
latency_tolerant_lines = 2;
}
latency_hiding = (latency_tolerant_lines * line_time + wm->blank_time);
if (dce6_latency_watermark(wm) <= latency_hiding)
return true;
else
return false;
}
static void dce6_program_watermarks(struct radeon_device *rdev,
struct radeon_crtc *radeon_crtc,
u32 lb_size, u32 num_heads)
{
struct drm_display_mode *mode = &radeon_crtc->base.mode;
struct dce6_wm_params wm_low, wm_high;
u32 dram_channels;
u32 active_time;
u32 line_time = 0;
u32 latency_watermark_a = 0, latency_watermark_b = 0;
u32 priority_a_mark = 0, priority_b_mark = 0;
u32 priority_a_cnt = PRIORITY_OFF;
u32 priority_b_cnt = PRIORITY_OFF;
u32 tmp, arb_control3;
fixed20_12 a, b, c;
if (radeon_crtc->base.enabled && num_heads && mode) {
active_time = (u32) div_u64((u64)mode->crtc_hdisplay * 1000000,
(u32)mode->clock);
line_time = (u32) div_u64((u64)mode->crtc_htotal * 1000000,
(u32)mode->clock);
line_time = min(line_time, (u32)65535);
priority_a_cnt = 0;
priority_b_cnt = 0;
if (rdev->family == CHIP_ARUBA)
dram_channels = evergreen_get_number_of_dram_channels(rdev);
else
dram_channels = si_get_number_of_dram_channels(rdev);
/* watermark for high clocks */
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
wm_high.yclk =
radeon_dpm_get_mclk(rdev, false) * 10;
wm_high.sclk =
radeon_dpm_get_sclk(rdev, false) * 10;
} else {
wm_high.yclk = rdev->pm.current_mclk * 10;
wm_high.sclk = rdev->pm.current_sclk * 10;
}
wm_high.disp_clk = mode->clock;
wm_high.src_width = mode->crtc_hdisplay;
wm_high.active_time = active_time;
wm_high.blank_time = line_time - wm_high.active_time;
wm_high.interlaced = false;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
wm_high.interlaced = true;
wm_high.vsc = radeon_crtc->vsc;
wm_high.vtaps = 1;
if (radeon_crtc->rmx_type != RMX_OFF)
wm_high.vtaps = 2;
wm_high.bytes_per_pixel = 4; /* XXX: get this from fb config */
wm_high.lb_size = lb_size;
wm_high.dram_channels = dram_channels;
wm_high.num_heads = num_heads;
/* watermark for low clocks */
if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) {
wm_low.yclk =
radeon_dpm_get_mclk(rdev, true) * 10;
wm_low.sclk =
radeon_dpm_get_sclk(rdev, true) * 10;
} else {
wm_low.yclk = rdev->pm.current_mclk * 10;
wm_low.sclk = rdev->pm.current_sclk * 10;
}
wm_low.disp_clk = mode->clock;
wm_low.src_width = mode->crtc_hdisplay;
wm_low.active_time = active_time;
wm_low.blank_time = line_time - wm_low.active_time;
wm_low.interlaced = false;
if (mode->flags & DRM_MODE_FLAG_INTERLACE)
wm_low.interlaced = true;
wm_low.vsc = radeon_crtc->vsc;
wm_low.vtaps = 1;
if (radeon_crtc->rmx_type != RMX_OFF)
wm_low.vtaps = 2;
wm_low.bytes_per_pixel = 4; /* XXX: get this from fb config */
wm_low.lb_size = lb_size;
wm_low.dram_channels = dram_channels;
wm_low.num_heads = num_heads;
/* set for high clocks */
latency_watermark_a = min(dce6_latency_watermark(&wm_high), (u32)65535);
/* set for low clocks */
latency_watermark_b = min(dce6_latency_watermark(&wm_low), (u32)65535);
/* possibly force display priority to high */
/* should really do this at mode validation time... */
if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_high) ||
!dce6_average_bandwidth_vs_available_bandwidth(&wm_high) ||
!dce6_check_latency_hiding(&wm_high) ||
(rdev->disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
priority_a_cnt |= PRIORITY_ALWAYS_ON;
priority_b_cnt |= PRIORITY_ALWAYS_ON;
}
if (!dce6_average_bandwidth_vs_dram_bandwidth_for_display(&wm_low) ||
!dce6_average_bandwidth_vs_available_bandwidth(&wm_low) ||
!dce6_check_latency_hiding(&wm_low) ||
(rdev->disp_priority == 2)) {
DRM_DEBUG_KMS("force priority to high\n");
priority_a_cnt |= PRIORITY_ALWAYS_ON;
priority_b_cnt |= PRIORITY_ALWAYS_ON;
}
a.full = dfixed_const(1000);
b.full = dfixed_const(mode->clock);
b.full = dfixed_div(b, a);
c.full = dfixed_const(latency_watermark_a);
c.full = dfixed_mul(c, b);
c.full = dfixed_mul(c, radeon_crtc->hsc);
c.full = dfixed_div(c, a);
a.full = dfixed_const(16);
c.full = dfixed_div(c, a);
priority_a_mark = dfixed_trunc(c);
priority_a_cnt |= priority_a_mark & PRIORITY_MARK_MASK;
a.full = dfixed_const(1000);
b.full = dfixed_const(mode->clock);
b.full = dfixed_div(b, a);
c.full = dfixed_const(latency_watermark_b);
c.full = dfixed_mul(c, b);
c.full = dfixed_mul(c, radeon_crtc->hsc);
c.full = dfixed_div(c, a);
a.full = dfixed_const(16);
c.full = dfixed_div(c, a);
priority_b_mark = dfixed_trunc(c);
priority_b_cnt |= priority_b_mark & PRIORITY_MARK_MASK;
/* Save number of lines the linebuffer leads before the scanout */
radeon_crtc->lb_vblank_lead_lines = DIV_ROUND_UP(lb_size, mode->crtc_hdisplay);
}
/* select wm A */
arb_control3 = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset);
tmp = arb_control3;
tmp &= ~LATENCY_WATERMARK_MASK(3);
tmp |= LATENCY_WATERMARK_MASK(1);
WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp);
WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset,
(LATENCY_LOW_WATERMARK(latency_watermark_a) |
LATENCY_HIGH_WATERMARK(line_time)));
/* select wm B */
tmp = RREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset);
tmp &= ~LATENCY_WATERMARK_MASK(3);
tmp |= LATENCY_WATERMARK_MASK(2);
WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, tmp);
WREG32(DPG_PIPE_LATENCY_CONTROL + radeon_crtc->crtc_offset,
(LATENCY_LOW_WATERMARK(latency_watermark_b) |
LATENCY_HIGH_WATERMARK(line_time)));
/* restore original selection */
WREG32(DPG_PIPE_ARBITRATION_CONTROL3 + radeon_crtc->crtc_offset, arb_control3);
/* write the priority marks */
WREG32(PRIORITY_A_CNT + radeon_crtc->crtc_offset, priority_a_cnt);
WREG32(PRIORITY_B_CNT + radeon_crtc->crtc_offset, priority_b_cnt);
/* save values for DPM */
radeon_crtc->line_time = line_time;
radeon_crtc->wm_high = latency_watermark_a;
radeon_crtc->wm_low = latency_watermark_b;
}
void dce6_bandwidth_update(struct radeon_device *rdev)
{
struct drm_display_mode *mode0 = NULL;
struct drm_display_mode *mode1 = NULL;
u32 num_heads = 0, lb_size;
int i;
if (!rdev->mode_info.mode_config_initialized)
return;
radeon_update_display_priority(rdev);
for (i = 0; i < rdev->num_crtc; i++) {
if (rdev->mode_info.crtcs[i]->base.enabled)
num_heads++;
}
for (i = 0; i < rdev->num_crtc; i += 2) {
mode0 = &rdev->mode_info.crtcs[i]->base.mode;
mode1 = &rdev->mode_info.crtcs[i+1]->base.mode;
lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i], mode0, mode1);
dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i], lb_size, num_heads);
lb_size = dce6_line_buffer_adjust(rdev, rdev->mode_info.crtcs[i+1], mode1, mode0);
dce6_program_watermarks(rdev, rdev->mode_info.crtcs[i+1], lb_size, num_heads);
}
}
/*
* Core functions
*/
static void si_tiling_mode_table_init(struct radeon_device *rdev)
{
u32 *tile = rdev->config.si.tile_mode_array;
const u32 num_tile_mode_states =
ARRAY_SIZE(rdev->config.si.tile_mode_array);
u32 reg_offset, split_equal_to_row_size;
switch (rdev->config.si.mem_row_size_in_kb) {
case 1:
split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_1KB;
break;
case 2:
default:
split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_2KB;
break;
case 4:
split_equal_to_row_size = ADDR_SURF_TILE_SPLIT_4KB;
break;
}
for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++)
tile[reg_offset] = 0;
switch(rdev->family) {
case CHIP_TAHITI:
case CHIP_PITCAIRN:
/* non-AA compressed depth or any compressed stencil */
tile[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* 2xAA/4xAA compressed depth only */
tile[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* 8xAA compressed depth only */
tile[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* 2xAA/4xAA compressed depth with stencil (for depth buffer) */
tile[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Maps w/ a dimension less than the 2D macro-tile dimensions (for mipmapped depth textures) */
tile[4] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Uncompressed 16bpp depth - and stencil buffer allocated with it */
tile[5] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(split_equal_to_row_size) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Uncompressed 32bpp depth - and stencil buffer allocated with it */
tile[6] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(split_equal_to_row_size) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
/* Uncompressed 8bpp stencil without depth (drivers typically do not use) */
tile[7] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DEPTH_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(split_equal_to_row_size) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* 1D and 1D Array Surfaces */
tile[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Displayable maps. */
tile[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Display 8bpp. */
tile[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Display 16bpp. */
tile[11] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
/* Display 32bpp. */
tile[12] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_DISPLAY_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1));
/* Thin. */
tile[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) |
MICRO_TILE_MODE(ADDR_SURF_THIN_MICRO_TILING) |
PIPE_CONFIG(ADDR_SURF_P8_32x32_8x16) |
TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) |
NUM_BANKS(ADDR_SURF_16_BANK) |
BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) |
BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) |
MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2));
</