Quellcodebibliothek Statistik Leitseite products/Sources/formale Sprachen/C/Linux/drivers/gpu/drm/radeon/   (Open Source Betriebssystem Version 6.17.9©)  Datei vom 24.10.2025 mit Größe 161 kB image not shown  

Quelle  evergreen.c   Sprache: C

 
/*
 * Copyright 2010 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/pci.h>
#include <linux/slab.h>

#include <drm/drm_edid.h>
#include <drm/drm_vblank.h>
#include <drm/radeon_drm.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>

#include "atom.h"
#include "avivod.h"
#include "cik.h"
#include "ni.h"
#include "rv770.h"
#include "evergreen.h"
#include "evergreen_blit_shaders.h"
#include "evergreen_reg.h"
#include "evergreend.h"
#include "radeon.h"
#include "radeon_asic.h"
#include "radeon_audio.h"
#include "radeon_ucode.h"
#include "si.h"

#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))

/*
 * Indirect registers accessor
 */

u32 eg_cg_rreg(struct radeon_device *rdev, u32 reg)
{
 unsigned long flags;
 u32 r;

 spin_lock_irqsave(&rdev->cg_idx_lock, flags);
 WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
 r = RREG32(EVERGREEN_CG_IND_DATA);
 spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
 return r;
}

void eg_cg_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->cg_idx_lock, flags);
 WREG32(EVERGREEN_CG_IND_ADDR, ((reg) & 0xffff));
 WREG32(EVERGREEN_CG_IND_DATA, (v));
 spin_unlock_irqrestore(&rdev->cg_idx_lock, flags);
}

u32 eg_pif_phy0_rreg(struct radeon_device *rdev, u32 reg)
{
 unsigned long flags;
 u32 r;

 spin_lock_irqsave(&rdev->pif_idx_lock, flags);
 WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
 r = RREG32(EVERGREEN_PIF_PHY0_DATA);
 spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
 return r;
}

void eg_pif_phy0_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->pif_idx_lock, flags);
 WREG32(EVERGREEN_PIF_PHY0_INDEX, ((reg) & 0xffff));
 WREG32(EVERGREEN_PIF_PHY0_DATA, (v));
 spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
}

u32 eg_pif_phy1_rreg(struct radeon_device *rdev, u32 reg)
{
 unsigned long flags;
 u32 r;

 spin_lock_irqsave(&rdev->pif_idx_lock, flags);
 WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
 r = RREG32(EVERGREEN_PIF_PHY1_DATA);
 spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
 return r;
}

void eg_pif_phy1_wreg(struct radeon_device *rdev, u32 reg, u32 v)
{
 unsigned long flags;

 spin_lock_irqsave(&rdev->pif_idx_lock, flags);
 WREG32(EVERGREEN_PIF_PHY1_INDEX, ((reg) & 0xffff));
 WREG32(EVERGREEN_PIF_PHY1_DATA, (v));
 spin_unlock_irqrestore(&rdev->pif_idx_lock, flags);
}

static const u32 crtc_offsets[6] =
{
 EVERGREEN_CRTC0_REGISTER_OFFSET,
 EVERGREEN_CRTC1_REGISTER_OFFSET,
 EVERGREEN_CRTC2_REGISTER_OFFSET,
 EVERGREEN_CRTC3_REGISTER_OFFSET,
 EVERGREEN_CRTC4_REGISTER_OFFSET,
 EVERGREEN_CRTC5_REGISTER_OFFSET
};

#include "clearstate_evergreen.h"

static const u32 sumo_rlc_save_restore_register_list[] =
{
 0x98fc,
 0x9830,
 0x9834,
 0x9838,
 0x9870,
 0x9874,
 0x8a14,
 0x8b24,
 0x8bcc,
 0x8b10,
 0x8d00,
 0x8d04,
 0x8c00,
 0x8c04,
 0x8c08,
 0x8c0c,
 0x8d8c,
 0x8c20,
 0x8c24,
 0x8c28,
 0x8c18,
 0x8c1c,
 0x8cf0,
 0x8e2c,
 0x8e38,
 0x8c30,
 0x9508,
 0x9688,
 0x9608,
 0x960c,
 0x9610,
 0x9614,
 0x88c4,
 0x88d4,
 0xa008,
 0x900c,
 0x9100,
 0x913c,
 0x98f8,
 0x98f4,
 0x9b7c,
 0x3f8c,
 0x8950,
 0x8954,
 0x8a18,
 0x8b28,
 0x9144,
 0x9148,
 0x914c,
 0x3f90,
 0x3f94,
 0x915c,
 0x9160,
 0x9178,
 0x917c,
 0x9180,
 0x918c,
 0x9190,
 0x9194,
 0x9198,
 0x919c,
 0x91a8,
 0x91ac,
 0x91b0,
 0x91b4,
 0x91b8,
 0x91c4,
 0x91c8,
 0x91cc,
 0x91d0,
 0x91d4,
 0x91e0,
 0x91e4,
 0x91ec,
 0x91f0,
 0x91f4,
 0x9200,
 0x9204,
 0x929c,
 0x9150,
 0x802c,
};

static void evergreen_gpu_init(struct radeon_device *rdev);
void evergreen_fini(struct radeon_device *rdev);
void evergreen_pcie_gen2_enable(struct radeon_device *rdev);
void evergreen_program_aspm(struct radeon_device *rdev);

static const u32 evergreen_golden_registers[] =
{
 0x3f90, 0xffff0000, 0xff000000,
 0x9148, 0xffff0000, 0xff000000,
 0x3f94, 0xffff0000, 0xff000000,
 0x914c, 0xffff0000, 0xff000000,
 0x9b7c, 0xffffffff, 0x00000000,
 0x8a14, 0xffffffff, 0x00000007,
 0x8b10, 0xffffffff, 0x00000000,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0xffffffff, 0x000000c2,
 0x88d4, 0xffffffff, 0x00000010,
 0x8974, 0xffffffff, 0x00000000,
 0xc78, 0x00000080, 0x00000080,
 0x5eb4, 0xffffffff, 0x00000002,
 0x5e78, 0xffffffff, 0x001000f0,
 0x6104, 0x01000300, 0x00000000,
 0x5bc0, 0x00300000, 0x00000000,
 0x7030, 0xffffffff, 0x00000011,
 0x7c30, 0xffffffff, 0x00000011,
 0x10830, 0xffffffff, 0x00000011,
 0x11430, 0xffffffff, 0x00000011,
 0x12030, 0xffffffff, 0x00000011,
 0x12c30, 0xffffffff, 0x00000011,
 0xd02c, 0xffffffff, 0x08421000,
 0x240c, 0xffffffff, 0x00000380,
 0x8b24, 0xffffffff, 0x00ff0fff,
 0x28a4c, 0x06000000, 0x06000000,
 0x10c, 0x00000001, 0x00000001,
 0x8d00, 0xffffffff, 0x100e4848,
 0x8d04, 0xffffffff, 0x00164745,
 0x8c00, 0xffffffff, 0xe4000003,
 0x8c04, 0xffffffff, 0x40600060,
 0x8c08, 0xffffffff, 0x001c001c,
 0x8cf0, 0xffffffff, 0x08e00620,
 0x8c20, 0xffffffff, 0x00800080,
 0x8c24, 0xffffffff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0xffffffff, 0x00001010,
 0x28350, 0xffffffff, 0x00000000,
 0xa008, 0xffffffff, 0x00010000,
 0x5c4, 0xffffffff, 0x00000001,
 0x9508, 0xffffffff, 0x00000002,
 0x913c, 0x0000000f, 0x0000000a
};

static const u32 evergreen_golden_registers2[] =
{
 0x2f4c, 0xffffffff, 0x00000000,
 0x54f4, 0xffffffff, 0x00000000,
 0x54f0, 0xffffffff, 0x00000000,
 0x5498, 0xffffffff, 0x00000000,
 0x549c, 0xffffffff, 0x00000000,
 0x5494, 0xffffffff, 0x00000000,
 0x53cc, 0xffffffff, 0x00000000,
 0x53c8, 0xffffffff, 0x00000000,
 0x53c4, 0xffffffff, 0x00000000,
 0x53c0, 0xffffffff, 0x00000000,
 0x53bc, 0xffffffff, 0x00000000,
 0x53b8, 0xffffffff, 0x00000000,
 0x53b4, 0xffffffff, 0x00000000,
 0x53b0, 0xffffffff, 0x00000000
};

static const u32 cypress_mgcg_init[] =
{
 0x802c, 0xffffffff, 0xc0000000,
 0x5448, 0xffffffff, 0x00000100,
 0x55e4, 0xffffffff, 0x00000100,
 0x160c, 0xffffffff, 0x00000100,
 0x5644, 0xffffffff, 0x00000100,
 0xc164, 0xffffffff, 0x00000100,
 0x8a18, 0xffffffff, 0x00000100,
 0x897c, 0xffffffff, 0x06000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x9a60, 0xffffffff, 0x00000100,
 0x9868, 0xffffffff, 0x00000100,
 0x8d58, 0xffffffff, 0x00000100,
 0x9510, 0xffffffff, 0x00000100,
 0x949c, 0xffffffff, 0x00000100,
 0x9654, 0xffffffff, 0x00000100,
 0x9030, 0xffffffff, 0x00000100,
 0x9034, 0xffffffff, 0x00000100,
 0x9038, 0xffffffff, 0x00000100,
 0x903c, 0xffffffff, 0x00000100,
 0x9040, 0xffffffff, 0x00000100,
 0xa200, 0xffffffff, 0x00000100,
 0xa204, 0xffffffff, 0x00000100,
 0xa208, 0xffffffff, 0x00000100,
 0xa20c, 0xffffffff, 0x00000100,
 0x971c, 0xffffffff, 0x00000100,
 0x977c, 0xffffffff, 0x00000100,
 0x3f80, 0xffffffff, 0x00000100,
 0xa210, 0xffffffff, 0x00000100,
 0xa214, 0xffffffff, 0x00000100,
 0x4d8, 0xffffffff, 0x00000100,
 0x9784, 0xffffffff, 0x00000100,
 0x9698, 0xffffffff, 0x00000100,
 0x4d4, 0xffffffff, 0x00000200,
 0x30cc, 0xffffffff, 0x00000100,
 0xd0c0, 0xffffffff, 0xff000100,
 0x802c, 0xffffffff, 0x40000000,
 0x915c, 0xffffffff, 0x00010000,
 0x9160, 0xffffffff, 0x00030002,
 0x9178, 0xffffffff, 0x00070000,
 0x917c, 0xffffffff, 0x00030002,
 0x9180, 0xffffffff, 0x00050004,
 0x918c, 0xffffffff, 0x00010006,
 0x9190, 0xffffffff, 0x00090008,
 0x9194, 0xffffffff, 0x00070000,
 0x9198, 0xffffffff, 0x00030002,
 0x919c, 0xffffffff, 0x00050004,
 0x91a8, 0xffffffff, 0x00010006,
 0x91ac, 0xffffffff, 0x00090008,
 0x91b0, 0xffffffff, 0x00070000,
 0x91b4, 0xffffffff, 0x00030002,
 0x91b8, 0xffffffff, 0x00050004,
 0x91c4, 0xffffffff, 0x00010006,
 0x91c8, 0xffffffff, 0x00090008,
 0x91cc, 0xffffffff, 0x00070000,
 0x91d0, 0xffffffff, 0x00030002,
 0x91d4, 0xffffffff, 0x00050004,
 0x91e0, 0xffffffff, 0x00010006,
 0x91e4, 0xffffffff, 0x00090008,
 0x91e8, 0xffffffff, 0x00000000,
 0x91ec, 0xffffffff, 0x00070000,
 0x91f0, 0xffffffff, 0x00030002,
 0x91f4, 0xffffffff, 0x00050004,
 0x9200, 0xffffffff, 0x00010006,
 0x9204, 0xffffffff, 0x00090008,
 0x9208, 0xffffffff, 0x00070000,
 0x920c, 0xffffffff, 0x00030002,
 0x9210, 0xffffffff, 0x00050004,
 0x921c, 0xffffffff, 0x00010006,
 0x9220, 0xffffffff, 0x00090008,
 0x9224, 0xffffffff, 0x00070000,
 0x9228, 0xffffffff, 0x00030002,
 0x922c, 0xffffffff, 0x00050004,
 0x9238, 0xffffffff, 0x00010006,
 0x923c, 0xffffffff, 0x00090008,
 0x9240, 0xffffffff, 0x00070000,
 0x9244, 0xffffffff, 0x00030002,
 0x9248, 0xffffffff, 0x00050004,
 0x9254, 0xffffffff, 0x00010006,
 0x9258, 0xffffffff, 0x00090008,
 0x925c, 0xffffffff, 0x00070000,
 0x9260, 0xffffffff, 0x00030002,
 0x9264, 0xffffffff, 0x00050004,
 0x9270, 0xffffffff, 0x00010006,
 0x9274, 0xffffffff, 0x00090008,
 0x9278, 0xffffffff, 0x00070000,
 0x927c, 0xffffffff, 0x00030002,
 0x9280, 0xffffffff, 0x00050004,
 0x928c, 0xffffffff, 0x00010006,
 0x9290, 0xffffffff, 0x00090008,
 0x9294, 0xffffffff, 0x00000000,
 0x929c, 0xffffffff, 0x00000001,
 0x802c, 0xffffffff, 0x40010000,
 0x915c, 0xffffffff, 0x00010000,
 0x9160, 0xffffffff, 0x00030002,
 0x9178, 0xffffffff, 0x00070000,
 0x917c, 0xffffffff, 0x00030002,
 0x9180, 0xffffffff, 0x00050004,
 0x918c, 0xffffffff, 0x00010006,
 0x9190, 0xffffffff, 0x00090008,
 0x9194, 0xffffffff, 0x00070000,
 0x9198, 0xffffffff, 0x00030002,
 0x919c, 0xffffffff, 0x00050004,
 0x91a8, 0xffffffff, 0x00010006,
 0x91ac, 0xffffffff, 0x00090008,
 0x91b0, 0xffffffff, 0x00070000,
 0x91b4, 0xffffffff, 0x00030002,
 0x91b8, 0xffffffff, 0x00050004,
 0x91c4, 0xffffffff, 0x00010006,
 0x91c8, 0xffffffff, 0x00090008,
 0x91cc, 0xffffffff, 0x00070000,
 0x91d0, 0xffffffff, 0x00030002,
 0x91d4, 0xffffffff, 0x00050004,
 0x91e0, 0xffffffff, 0x00010006,
 0x91e4, 0xffffffff, 0x00090008,
 0x91e8, 0xffffffff, 0x00000000,
 0x91ec, 0xffffffff, 0x00070000,
 0x91f0, 0xffffffff, 0x00030002,
 0x91f4, 0xffffffff, 0x00050004,
 0x9200, 0xffffffff, 0x00010006,
 0x9204, 0xffffffff, 0x00090008,
 0x9208, 0xffffffff, 0x00070000,
 0x920c, 0xffffffff, 0x00030002,
 0x9210, 0xffffffff, 0x00050004,
 0x921c, 0xffffffff, 0x00010006,
 0x9220, 0xffffffff, 0x00090008,
 0x9224, 0xffffffff, 0x00070000,
 0x9228, 0xffffffff, 0x00030002,
 0x922c, 0xffffffff, 0x00050004,
 0x9238, 0xffffffff, 0x00010006,
 0x923c, 0xffffffff, 0x00090008,
 0x9240, 0xffffffff, 0x00070000,
 0x9244, 0xffffffff, 0x00030002,
 0x9248, 0xffffffff, 0x00050004,
 0x9254, 0xffffffff, 0x00010006,
 0x9258, 0xffffffff, 0x00090008,
 0x925c, 0xffffffff, 0x00070000,
 0x9260, 0xffffffff, 0x00030002,
 0x9264, 0xffffffff, 0x00050004,
 0x9270, 0xffffffff, 0x00010006,
 0x9274, 0xffffffff, 0x00090008,
 0x9278, 0xffffffff, 0x00070000,
 0x927c, 0xffffffff, 0x00030002,
 0x9280, 0xffffffff, 0x00050004,
 0x928c, 0xffffffff, 0x00010006,
 0x9290, 0xffffffff, 0x00090008,
 0x9294, 0xffffffff, 0x00000000,
 0x929c, 0xffffffff, 0x00000001,
 0x802c, 0xffffffff, 0xc0000000
};

static const u32 redwood_mgcg_init[] =
{
 0x802c, 0xffffffff, 0xc0000000,
 0x5448, 0xffffffff, 0x00000100,
 0x55e4, 0xffffffff, 0x00000100,
 0x160c, 0xffffffff, 0x00000100,
 0x5644, 0xffffffff, 0x00000100,
 0xc164, 0xffffffff, 0x00000100,
 0x8a18, 0xffffffff, 0x00000100,
 0x897c, 0xffffffff, 0x06000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x9a60, 0xffffffff, 0x00000100,
 0x9868, 0xffffffff, 0x00000100,
 0x8d58, 0xffffffff, 0x00000100,
 0x9510, 0xffffffff, 0x00000100,
 0x949c, 0xffffffff, 0x00000100,
 0x9654, 0xffffffff, 0x00000100,
 0x9030, 0xffffffff, 0x00000100,
 0x9034, 0xffffffff, 0x00000100,
 0x9038, 0xffffffff, 0x00000100,
 0x903c, 0xffffffff, 0x00000100,
 0x9040, 0xffffffff, 0x00000100,
 0xa200, 0xffffffff, 0x00000100,
 0xa204, 0xffffffff, 0x00000100,
 0xa208, 0xffffffff, 0x00000100,
 0xa20c, 0xffffffff, 0x00000100,
 0x971c, 0xffffffff, 0x00000100,
 0x977c, 0xffffffff, 0x00000100,
 0x3f80, 0xffffffff, 0x00000100,
 0xa210, 0xffffffff, 0x00000100,
 0xa214, 0xffffffff, 0x00000100,
 0x4d8, 0xffffffff, 0x00000100,
 0x9784, 0xffffffff, 0x00000100,
 0x9698, 0xffffffff, 0x00000100,
 0x4d4, 0xffffffff, 0x00000200,
 0x30cc, 0xffffffff, 0x00000100,
 0xd0c0, 0xffffffff, 0xff000100,
 0x802c, 0xffffffff, 0x40000000,
 0x915c, 0xffffffff, 0x00010000,
 0x9160, 0xffffffff, 0x00030002,
 0x9178, 0xffffffff, 0x00070000,
 0x917c, 0xffffffff, 0x00030002,
 0x9180, 0xffffffff, 0x00050004,
 0x918c, 0xffffffff, 0x00010006,
 0x9190, 0xffffffff, 0x00090008,
 0x9194, 0xffffffff, 0x00070000,
 0x9198, 0xffffffff, 0x00030002,
 0x919c, 0xffffffff, 0x00050004,
 0x91a8, 0xffffffff, 0x00010006,
 0x91ac, 0xffffffff, 0x00090008,
 0x91b0, 0xffffffff, 0x00070000,
 0x91b4, 0xffffffff, 0x00030002,
 0x91b8, 0xffffffff, 0x00050004,
 0x91c4, 0xffffffff, 0x00010006,
 0x91c8, 0xffffffff, 0x00090008,
 0x91cc, 0xffffffff, 0x00070000,
 0x91d0, 0xffffffff, 0x00030002,
 0x91d4, 0xffffffff, 0x00050004,
 0x91e0, 0xffffffff, 0x00010006,
 0x91e4, 0xffffffff, 0x00090008,
 0x91e8, 0xffffffff, 0x00000000,
 0x91ec, 0xffffffff, 0x00070000,
 0x91f0, 0xffffffff, 0x00030002,
 0x91f4, 0xffffffff, 0x00050004,
 0x9200, 0xffffffff, 0x00010006,
 0x9204, 0xffffffff, 0x00090008,
 0x9294, 0xffffffff, 0x00000000,
 0x929c, 0xffffffff, 0x00000001,
 0x802c, 0xffffffff, 0xc0000000
};

static const u32 cedar_golden_registers[] =
{
 0x3f90, 0xffff0000, 0xff000000,
 0x9148, 0xffff0000, 0xff000000,
 0x3f94, 0xffff0000, 0xff000000,
 0x914c, 0xffff0000, 0xff000000,
 0x9b7c, 0xffffffff, 0x00000000,
 0x8a14, 0xffffffff, 0x00000007,
 0x8b10, 0xffffffff, 0x00000000,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0xffffffff, 0x000000c2,
 0x88d4, 0xffffffff, 0x00000000,
 0x8974, 0xffffffff, 0x00000000,
 0xc78, 0x00000080, 0x00000080,
 0x5eb4, 0xffffffff, 0x00000002,
 0x5e78, 0xffffffff, 0x001000f0,
 0x6104, 0x01000300, 0x00000000,
 0x5bc0, 0x00300000, 0x00000000,
 0x7030, 0xffffffff, 0x00000011,
 0x7c30, 0xffffffff, 0x00000011,
 0x10830, 0xffffffff, 0x00000011,
 0x11430, 0xffffffff, 0x00000011,
 0xd02c, 0xffffffff, 0x08421000,
 0x240c, 0xffffffff, 0x00000380,
 0x8b24, 0xffffffff, 0x00ff0fff,
 0x28a4c, 0x06000000, 0x06000000,
 0x10c, 0x00000001, 0x00000001,
 0x8d00, 0xffffffff, 0x100e4848,
 0x8d04, 0xffffffff, 0x00164745,
 0x8c00, 0xffffffff, 0xe4000003,
 0x8c04, 0xffffffff, 0x40600060,
 0x8c08, 0xffffffff, 0x001c001c,
 0x8cf0, 0xffffffff, 0x08e00410,
 0x8c20, 0xffffffff, 0x00800080,
 0x8c24, 0xffffffff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0xffffffff, 0x00001010,
 0x28350, 0xffffffff, 0x00000000,
 0xa008, 0xffffffff, 0x00010000,
 0x5c4, 0xffffffff, 0x00000001,
 0x9508, 0xffffffff, 0x00000002
};

static const u32 cedar_mgcg_init[] =
{
 0x802c, 0xffffffff, 0xc0000000,
 0x5448, 0xffffffff, 0x00000100,
 0x55e4, 0xffffffff, 0x00000100,
 0x160c, 0xffffffff, 0x00000100,
 0x5644, 0xffffffff, 0x00000100,
 0xc164, 0xffffffff, 0x00000100,
 0x8a18, 0xffffffff, 0x00000100,
 0x897c, 0xffffffff, 0x06000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x9a60, 0xffffffff, 0x00000100,
 0x9868, 0xffffffff, 0x00000100,
 0x8d58, 0xffffffff, 0x00000100,
 0x9510, 0xffffffff, 0x00000100,
 0x949c, 0xffffffff, 0x00000100,
 0x9654, 0xffffffff, 0x00000100,
 0x9030, 0xffffffff, 0x00000100,
 0x9034, 0xffffffff, 0x00000100,
 0x9038, 0xffffffff, 0x00000100,
 0x903c, 0xffffffff, 0x00000100,
 0x9040, 0xffffffff, 0x00000100,
 0xa200, 0xffffffff, 0x00000100,
 0xa204, 0xffffffff, 0x00000100,
 0xa208, 0xffffffff, 0x00000100,
 0xa20c, 0xffffffff, 0x00000100,
 0x971c, 0xffffffff, 0x00000100,
 0x977c, 0xffffffff, 0x00000100,
 0x3f80, 0xffffffff, 0x00000100,
 0xa210, 0xffffffff, 0x00000100,
 0xa214, 0xffffffff, 0x00000100,
 0x4d8, 0xffffffff, 0x00000100,
 0x9784, 0xffffffff, 0x00000100,
 0x9698, 0xffffffff, 0x00000100,
 0x4d4, 0xffffffff, 0x00000200,
 0x30cc, 0xffffffff, 0x00000100,
 0xd0c0, 0xffffffff, 0xff000100,
 0x802c, 0xffffffff, 0x40000000,
 0x915c, 0xffffffff, 0x00010000,
 0x9178, 0xffffffff, 0x00050000,
 0x917c, 0xffffffff, 0x00030002,
 0x918c, 0xffffffff, 0x00010004,
 0x9190, 0xffffffff, 0x00070006,
 0x9194, 0xffffffff, 0x00050000,
 0x9198, 0xffffffff, 0x00030002,
 0x91a8, 0xffffffff, 0x00010004,
 0x91ac, 0xffffffff, 0x00070006,
 0x91e8, 0xffffffff, 0x00000000,
 0x9294, 0xffffffff, 0x00000000,
 0x929c, 0xffffffff, 0x00000001,
 0x802c, 0xffffffff, 0xc0000000
};

static const u32 juniper_mgcg_init[] =
{
 0x802c, 0xffffffff, 0xc0000000,
 0x5448, 0xffffffff, 0x00000100,
 0x55e4, 0xffffffff, 0x00000100,
 0x160c, 0xffffffff, 0x00000100,
 0x5644, 0xffffffff, 0x00000100,
 0xc164, 0xffffffff, 0x00000100,
 0x8a18, 0xffffffff, 0x00000100,
 0x897c, 0xffffffff, 0x06000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x9a60, 0xffffffff, 0x00000100,
 0x9868, 0xffffffff, 0x00000100,
 0x8d58, 0xffffffff, 0x00000100,
 0x9510, 0xffffffff, 0x00000100,
 0x949c, 0xffffffff, 0x00000100,
 0x9654, 0xffffffff, 0x00000100,
 0x9030, 0xffffffff, 0x00000100,
 0x9034, 0xffffffff, 0x00000100,
 0x9038, 0xffffffff, 0x00000100,
 0x903c, 0xffffffff, 0x00000100,
 0x9040, 0xffffffff, 0x00000100,
 0xa200, 0xffffffff, 0x00000100,
 0xa204, 0xffffffff, 0x00000100,
 0xa208, 0xffffffff, 0x00000100,
 0xa20c, 0xffffffff, 0x00000100,
 0x971c, 0xffffffff, 0x00000100,
 0xd0c0, 0xffffffff, 0xff000100,
 0x802c, 0xffffffff, 0x40000000,
 0x915c, 0xffffffff, 0x00010000,
 0x9160, 0xffffffff, 0x00030002,
 0x9178, 0xffffffff, 0x00070000,
 0x917c, 0xffffffff, 0x00030002,
 0x9180, 0xffffffff, 0x00050004,
 0x918c, 0xffffffff, 0x00010006,
 0x9190, 0xffffffff, 0x00090008,
 0x9194, 0xffffffff, 0x00070000,
 0x9198, 0xffffffff, 0x00030002,
 0x919c, 0xffffffff, 0x00050004,
 0x91a8, 0xffffffff, 0x00010006,
 0x91ac, 0xffffffff, 0x00090008,
 0x91b0, 0xffffffff, 0x00070000,
 0x91b4, 0xffffffff, 0x00030002,
 0x91b8, 0xffffffff, 0x00050004,
 0x91c4, 0xffffffff, 0x00010006,
 0x91c8, 0xffffffff, 0x00090008,
 0x91cc, 0xffffffff, 0x00070000,
 0x91d0, 0xffffffff, 0x00030002,
 0x91d4, 0xffffffff, 0x00050004,
 0x91e0, 0xffffffff, 0x00010006,
 0x91e4, 0xffffffff, 0x00090008,
 0x91e8, 0xffffffff, 0x00000000,
 0x91ec, 0xffffffff, 0x00070000,
 0x91f0, 0xffffffff, 0x00030002,
 0x91f4, 0xffffffff, 0x00050004,
 0x9200, 0xffffffff, 0x00010006,
 0x9204, 0xffffffff, 0x00090008,
 0x9208, 0xffffffff, 0x00070000,
 0x920c, 0xffffffff, 0x00030002,
 0x9210, 0xffffffff, 0x00050004,
 0x921c, 0xffffffff, 0x00010006,
 0x9220, 0xffffffff, 0x00090008,
 0x9224, 0xffffffff, 0x00070000,
 0x9228, 0xffffffff, 0x00030002,
 0x922c, 0xffffffff, 0x00050004,
 0x9238, 0xffffffff, 0x00010006,
 0x923c, 0xffffffff, 0x00090008,
 0x9240, 0xffffffff, 0x00070000,
 0x9244, 0xffffffff, 0x00030002,
 0x9248, 0xffffffff, 0x00050004,
 0x9254, 0xffffffff, 0x00010006,
 0x9258, 0xffffffff, 0x00090008,
 0x925c, 0xffffffff, 0x00070000,
 0x9260, 0xffffffff, 0x00030002,
 0x9264, 0xffffffff, 0x00050004,
 0x9270, 0xffffffff, 0x00010006,
 0x9274, 0xffffffff, 0x00090008,
 0x9278, 0xffffffff, 0x00070000,
 0x927c, 0xffffffff, 0x00030002,
 0x9280, 0xffffffff, 0x00050004,
 0x928c, 0xffffffff, 0x00010006,
 0x9290, 0xffffffff, 0x00090008,
 0x9294, 0xffffffff, 0x00000000,
 0x929c, 0xffffffff, 0x00000001,
 0x802c, 0xffffffff, 0xc0000000,
 0x977c, 0xffffffff, 0x00000100,
 0x3f80, 0xffffffff, 0x00000100,
 0xa210, 0xffffffff, 0x00000100,
 0xa214, 0xffffffff, 0x00000100,
 0x4d8, 0xffffffff, 0x00000100,
 0x9784, 0xffffffff, 0x00000100,
 0x9698, 0xffffffff, 0x00000100,
 0x4d4, 0xffffffff, 0x00000200,
 0x30cc, 0xffffffff, 0x00000100,
 0x802c, 0xffffffff, 0xc0000000
};

static const u32 supersumo_golden_registers[] =
{
 0x5eb4, 0xffffffff, 0x00000002,
 0x5c4, 0xffffffff, 0x00000001,
 0x7030, 0xffffffff, 0x00000011,
 0x7c30, 0xffffffff, 0x00000011,
 0x6104, 0x01000300, 0x00000000,
 0x5bc0, 0x00300000, 0x00000000,
 0x8c04, 0xffffffff, 0x40600060,
 0x8c08, 0xffffffff, 0x001c001c,
 0x8c20, 0xffffffff, 0x00800080,
 0x8c24, 0xffffffff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0xffffffff, 0x00001010,
 0x918c, 0xffffffff, 0x00010006,
 0x91a8, 0xffffffff, 0x00010006,
 0x91c4, 0xffffffff, 0x00010006,
 0x91e0, 0xffffffff, 0x00010006,
 0x9200, 0xffffffff, 0x00010006,
 0x9150, 0xffffffff, 0x6e944040,
 0x917c, 0xffffffff, 0x00030002,
 0x9180, 0xffffffff, 0x00050004,
 0x9198, 0xffffffff, 0x00030002,
 0x919c, 0xffffffff, 0x00050004,
 0x91b4, 0xffffffff, 0x00030002,
 0x91b8, 0xffffffff, 0x00050004,
 0x91d0, 0xffffffff, 0x00030002,
 0x91d4, 0xffffffff, 0x00050004,
 0x91f0, 0xffffffff, 0x00030002,
 0x91f4, 0xffffffff, 0x00050004,
 0x915c, 0xffffffff, 0x00010000,
 0x9160, 0xffffffff, 0x00030002,
 0x3f90, 0xffff0000, 0xff000000,
 0x9178, 0xffffffff, 0x00070000,
 0x9194, 0xffffffff, 0x00070000,
 0x91b0, 0xffffffff, 0x00070000,
 0x91cc, 0xffffffff, 0x00070000,
 0x91ec, 0xffffffff, 0x00070000,
 0x9148, 0xffff0000, 0xff000000,
 0x9190, 0xffffffff, 0x00090008,
 0x91ac, 0xffffffff, 0x00090008,
 0x91c8, 0xffffffff, 0x00090008,
 0x91e4, 0xffffffff, 0x00090008,
 0x9204, 0xffffffff, 0x00090008,
 0x3f94, 0xffff0000, 0xff000000,
 0x914c, 0xffff0000, 0xff000000,
 0x929c, 0xffffffff, 0x00000001,
 0x8a18, 0xffffffff, 0x00000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x5644, 0xffffffff, 0x00000100,
 0x9b7c, 0xffffffff, 0x00000000,
 0x8030, 0xffffffff, 0x0000100a,
 0x8a14, 0xffffffff, 0x00000007,
 0x8b24, 0xffffffff, 0x00ff0fff,
 0x8b10, 0xffffffff, 0x00000000,
 0x28a4c, 0x06000000, 0x06000000,
 0x4d8, 0xffffffff, 0x00000100,
 0x913c, 0xffff000f, 0x0100000a,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0xffffffff, 0x000000c2,
 0x88d4, 0xffffffff, 0x00000010,
 0x8974, 0xffffffff, 0x00000000,
 0xc78, 0x00000080, 0x00000080,
 0x5e78, 0xffffffff, 0x001000f0,
 0xd02c, 0xffffffff, 0x08421000,
 0xa008, 0xffffffff, 0x00010000,
 0x8d00, 0xffffffff, 0x100e4848,
 0x8d04, 0xffffffff, 0x00164745,
 0x8c00, 0xffffffff, 0xe4000003,
 0x8cf0, 0x1fffffff, 0x08e00620,
 0x28350, 0xffffffff, 0x00000000,
 0x9508, 0xffffffff, 0x00000002
};

static const u32 sumo_golden_registers[] =
{
 0x900c, 0x00ffffff, 0x0017071f,
 0x8c18, 0xffffffff, 0x10101060,
 0x8c1c, 0xffffffff, 0x00001010,
 0x8c30, 0x0000000f, 0x00000005,
 0x9688, 0x0000000f, 0x00000007
};

static const u32 wrestler_golden_registers[] =
{
 0x5eb4, 0xffffffff, 0x00000002,
 0x5c4, 0xffffffff, 0x00000001,
 0x7030, 0xffffffff, 0x00000011,
 0x7c30, 0xffffffff, 0x00000011,
 0x6104, 0x01000300, 0x00000000,
 0x5bc0, 0x00300000, 0x00000000,
 0x918c, 0xffffffff, 0x00010006,
 0x91a8, 0xffffffff, 0x00010006,
 0x9150, 0xffffffff, 0x6e944040,
 0x917c, 0xffffffff, 0x00030002,
 0x9198, 0xffffffff, 0x00030002,
 0x915c, 0xffffffff, 0x00010000,
 0x3f90, 0xffff0000, 0xff000000,
 0x9178, 0xffffffff, 0x00070000,
 0x9194, 0xffffffff, 0x00070000,
 0x9148, 0xffff0000, 0xff000000,
 0x9190, 0xffffffff, 0x00090008,
 0x91ac, 0xffffffff, 0x00090008,
 0x3f94, 0xffff0000, 0xff000000,
 0x914c, 0xffff0000, 0xff000000,
 0x929c, 0xffffffff, 0x00000001,
 0x8a18, 0xffffffff, 0x00000100,
 0x8b28, 0xffffffff, 0x00000100,
 0x9144, 0xffffffff, 0x00000100,
 0x9b7c, 0xffffffff, 0x00000000,
 0x8030, 0xffffffff, 0x0000100a,
 0x8a14, 0xffffffff, 0x00000001,
 0x8b24, 0xffffffff, 0x00ff0fff,
 0x8b10, 0xffffffff, 0x00000000,
 0x28a4c, 0x06000000, 0x06000000,
 0x4d8, 0xffffffff, 0x00000100,
 0x913c, 0xffff000f, 0x0100000a,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0xffffffff, 0x000000c2,
 0x88d4, 0xffffffff, 0x00000010,
 0x8974, 0xffffffff, 0x00000000,
 0xc78, 0x00000080, 0x00000080,
 0x5e78, 0xffffffff, 0x001000f0,
 0xd02c, 0xffffffff, 0x08421000,
 0xa008, 0xffffffff, 0x00010000,
 0x8d00, 0xffffffff, 0x100e4848,
 0x8d04, 0xffffffff, 0x00164745,
 0x8c00, 0xffffffff, 0xe4000003,
 0x8cf0, 0x1fffffff, 0x08e00410,
 0x28350, 0xffffffff, 0x00000000,
 0x9508, 0xffffffff, 0x00000002,
 0x900c, 0xffffffff, 0x0017071f,
 0x8c18, 0xffffffff, 0x10101060,
 0x8c1c, 0xffffffff, 0x00001010
};

static const u32 barts_golden_registers[] =
{
 0x5eb4, 0xffffffff, 0x00000002,
 0x5e78, 0x8f311ff1, 0x001000f0,
 0x3f90, 0xffff0000, 0xff000000,
 0x9148, 0xffff0000, 0xff000000,
 0x3f94, 0xffff0000, 0xff000000,
 0x914c, 0xffff0000, 0xff000000,
 0xc78, 0x00000080, 0x00000080,
 0xbd4, 0x70073777, 0x00010001,
 0xd02c, 0xbfffff1f, 0x08421000,
 0xd0b8, 0x03773777, 0x02011003,
 0x5bc0, 0x00200000, 0x50100000,
 0x98f8, 0x33773777, 0x02011003,
 0x98fc, 0xffffffff, 0x76543210,
 0x7030, 0x31000311, 0x00000011,
 0x2f48, 0x00000007, 0x02011003,
 0x6b28, 0x00000010, 0x00000012,
 0x7728, 0x00000010, 0x00000012,
 0x10328, 0x00000010, 0x00000012,
 0x10f28, 0x00000010, 0x00000012,
 0x11b28, 0x00000010, 0x00000012,
 0x12728, 0x00000010, 0x00000012,
 0x240c, 0x000007ff, 0x00000380,
 0x8a14, 0xf000001f, 0x00000007,
 0x8b24, 0x3fff3fff, 0x00ff0fff,
 0x8b10, 0x0000ff0f, 0x00000000,
 0x28a4c, 0x07ffffff, 0x06000000,
 0x10c, 0x00000001, 0x00010003,
 0xa02c, 0xffffffff, 0x0000009b,
 0x913c, 0x0000000f, 0x0100000a,
 0x8d00, 0xffff7f7f, 0x100e4848,
 0x8d04, 0x00ffffff, 0x00164745,
 0x8c00, 0xfffc0003, 0xe4000003,
 0x8c04, 0xf8ff00ff, 0x40600060,
 0x8c08, 0x00ff00ff, 0x001c001c,
 0x8cf0, 0x1fff1fff, 0x08e00620,
 0x8c20, 0x0fff0fff, 0x00800080,
 0x8c24, 0x0fff0fff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0x0000ffff, 0x00001010,
 0x28350, 0x00000f01, 0x00000000,
 0x9508, 0x3700001f, 0x00000002,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0x001f3ae3, 0x000000c2,
 0x88d4, 0x0000001f, 0x00000010,
 0x8974, 0xffffffff, 0x00000000
};

static const u32 turks_golden_registers[] =
{
 0x5eb4, 0xffffffff, 0x00000002,
 0x5e78, 0x8f311ff1, 0x001000f0,
 0x8c8, 0x00003000, 0x00001070,
 0x8cc, 0x000fffff, 0x00040035,
 0x3f90, 0xffff0000, 0xfff00000,
 0x9148, 0xffff0000, 0xfff00000,
 0x3f94, 0xffff0000, 0xfff00000,
 0x914c, 0xffff0000, 0xfff00000,
 0xc78, 0x00000080, 0x00000080,
 0xbd4, 0x00073007, 0x00010002,
 0xd02c, 0xbfffff1f, 0x08421000,
 0xd0b8, 0x03773777, 0x02010002,
 0x5bc0, 0x00200000, 0x50100000,
 0x98f8, 0x33773777, 0x00010002,
 0x98fc, 0xffffffff, 0x33221100,
 0x7030, 0x31000311, 0x00000011,
 0x2f48, 0x33773777, 0x00010002,
 0x6b28, 0x00000010, 0x00000012,
 0x7728, 0x00000010, 0x00000012,
 0x10328, 0x00000010, 0x00000012,
 0x10f28, 0x00000010, 0x00000012,
 0x11b28, 0x00000010, 0x00000012,
 0x12728, 0x00000010, 0x00000012,
 0x240c, 0x000007ff, 0x00000380,
 0x8a14, 0xf000001f, 0x00000007,
 0x8b24, 0x3fff3fff, 0x00ff0fff,
 0x8b10, 0x0000ff0f, 0x00000000,
 0x28a4c, 0x07ffffff, 0x06000000,
 0x10c, 0x00000001, 0x00010003,
 0xa02c, 0xffffffff, 0x0000009b,
 0x913c, 0x0000000f, 0x0100000a,
 0x8d00, 0xffff7f7f, 0x100e4848,
 0x8d04, 0x00ffffff, 0x00164745,
 0x8c00, 0xfffc0003, 0xe4000003,
 0x8c04, 0xf8ff00ff, 0x40600060,
 0x8c08, 0x00ff00ff, 0x001c001c,
 0x8cf0, 0x1fff1fff, 0x08e00410,
 0x8c20, 0x0fff0fff, 0x00800080,
 0x8c24, 0x0fff0fff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0x0000ffff, 0x00001010,
 0x28350, 0x00000f01, 0x00000000,
 0x9508, 0x3700001f, 0x00000002,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0x001f3ae3, 0x000000c2,
 0x88d4, 0x0000001f, 0x00000010,
 0x8974, 0xffffffff, 0x00000000
};

static const u32 caicos_golden_registers[] =
{
 0x5eb4, 0xffffffff, 0x00000002,
 0x5e78, 0x8f311ff1, 0x001000f0,
 0x8c8, 0x00003420, 0x00001450,
 0x8cc, 0x000fffff, 0x00040035,
 0x3f90, 0xffff0000, 0xfffc0000,
 0x9148, 0xffff0000, 0xfffc0000,
 0x3f94, 0xffff0000, 0xfffc0000,
 0x914c, 0xffff0000, 0xfffc0000,
 0xc78, 0x00000080, 0x00000080,
 0xbd4, 0x00073007, 0x00010001,
 0xd02c, 0xbfffff1f, 0x08421000,
 0xd0b8, 0x03773777, 0x02010001,
 0x5bc0, 0x00200000, 0x50100000,
 0x98f8, 0x33773777, 0x02010001,
 0x98fc, 0xffffffff, 0x33221100,
 0x7030, 0x31000311, 0x00000011,
 0x2f48, 0x33773777, 0x02010001,
 0x6b28, 0x00000010, 0x00000012,
 0x7728, 0x00000010, 0x00000012,
 0x10328, 0x00000010, 0x00000012,
 0x10f28, 0x00000010, 0x00000012,
 0x11b28, 0x00000010, 0x00000012,
 0x12728, 0x00000010, 0x00000012,
 0x240c, 0x000007ff, 0x00000380,
 0x8a14, 0xf000001f, 0x00000001,
 0x8b24, 0x3fff3fff, 0x00ff0fff,
 0x8b10, 0x0000ff0f, 0x00000000,
 0x28a4c, 0x07ffffff, 0x06000000,
 0x10c, 0x00000001, 0x00010003,
 0xa02c, 0xffffffff, 0x0000009b,
 0x913c, 0x0000000f, 0x0100000a,
 0x8d00, 0xffff7f7f, 0x100e4848,
 0x8d04, 0x00ffffff, 0x00164745,
 0x8c00, 0xfffc0003, 0xe4000003,
 0x8c04, 0xf8ff00ff, 0x40600060,
 0x8c08, 0x00ff00ff, 0x001c001c,
 0x8cf0, 0x1fff1fff, 0x08e00410,
 0x8c20, 0x0fff0fff, 0x00800080,
 0x8c24, 0x0fff0fff, 0x00800080,
 0x8c18, 0xffffffff, 0x20202078,
 0x8c1c, 0x0000ffff, 0x00001010,
 0x28350, 0x00000f01, 0x00000000,
 0x9508, 0x3700001f, 0x00000002,
 0x960c, 0xffffffff, 0x54763210,
 0x88c4, 0x001f3ae3, 0x000000c2,
 0x88d4, 0x0000001f, 0x00000010,
 0x8974, 0xffffffff, 0x00000000
};

static void evergreen_init_golden_registers(struct radeon_device *rdev)
{
 switch (rdev->family) {
 case CHIP_CYPRESS:
 case CHIP_HEMLOCK:
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers,
       (const u32)ARRAY_SIZE(evergreen_golden_registers));
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers2,
       (const u32)ARRAY_SIZE(evergreen_golden_registers2));
  radeon_program_register_sequence(rdev,
       cypress_mgcg_init,
       (const u32)ARRAY_SIZE(cypress_mgcg_init));
  break;
 case CHIP_JUNIPER:
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers,
       (const u32)ARRAY_SIZE(evergreen_golden_registers));
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers2,
       (const u32)ARRAY_SIZE(evergreen_golden_registers2));
  radeon_program_register_sequence(rdev,
       juniper_mgcg_init,
       (const u32)ARRAY_SIZE(juniper_mgcg_init));
  break;
 case CHIP_REDWOOD:
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers,
       (const u32)ARRAY_SIZE(evergreen_golden_registers));
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers2,
       (const u32)ARRAY_SIZE(evergreen_golden_registers2));
  radeon_program_register_sequence(rdev,
       redwood_mgcg_init,
       (const u32)ARRAY_SIZE(redwood_mgcg_init));
  break;
 case CHIP_CEDAR:
  radeon_program_register_sequence(rdev,
       cedar_golden_registers,
       (const u32)ARRAY_SIZE(cedar_golden_registers));
  radeon_program_register_sequence(rdev,
       evergreen_golden_registers2,
       (const u32)ARRAY_SIZE(evergreen_golden_registers2));
  radeon_program_register_sequence(rdev,
       cedar_mgcg_init,
       (const u32)ARRAY_SIZE(cedar_mgcg_init));
  break;
 case CHIP_PALM:
  radeon_program_register_sequence(rdev,
       wrestler_golden_registers,
       (const u32)ARRAY_SIZE(wrestler_golden_registers));
  break;
 case CHIP_SUMO:
  radeon_program_register_sequence(rdev,
       supersumo_golden_registers,
       (const u32)ARRAY_SIZE(supersumo_golden_registers));
  break;
 case CHIP_SUMO2:
  radeon_program_register_sequence(rdev,
       supersumo_golden_registers,
       (const u32)ARRAY_SIZE(supersumo_golden_registers));
  radeon_program_register_sequence(rdev,
       sumo_golden_registers,
       (const u32)ARRAY_SIZE(sumo_golden_registers));
  break;
 case CHIP_BARTS:
  radeon_program_register_sequence(rdev,
       barts_golden_registers,
       (const u32)ARRAY_SIZE(barts_golden_registers));
  break;
 case CHIP_TURKS:
  radeon_program_register_sequence(rdev,
       turks_golden_registers,
       (const u32)ARRAY_SIZE(turks_golden_registers));
  break;
 case CHIP_CAICOS:
  radeon_program_register_sequence(rdev,
       caicos_golden_registers,
       (const u32)ARRAY_SIZE(caicos_golden_registers));
  break;
 default:
  break;
 }
}

/**
 * evergreen_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 evergreen_get_allowed_info_register(struct radeon_device *rdev,
     u32 reg, u32 *val)
{
 switch (reg) {
 case GRBM_STATUS:
 case GRBM_STATUS_SE0:
 case GRBM_STATUS_SE1:
 case SRBM_STATUS:
 case SRBM_STATUS2:
 case DMA_STATUS_REG:
 case UVD_STATUS:
  *val = RREG32(reg);
  return 0;
 default:
  return -EINVAL;
 }
}

void evergreen_tiling_fields(unsigned tiling_flags, unsigned *bankw,
        unsigned *bankh, unsigned *mtaspect,
        unsigned *tile_split)
{
 *bankw = (tiling_flags >> RADEON_TILING_EG_BANKW_SHIFT) & RADEON_TILING_EG_BANKW_MASK;
 *bankh = (tiling_flags >> RADEON_TILING_EG_BANKH_SHIFT) & RADEON_TILING_EG_BANKH_MASK;
 *mtaspect = (tiling_flags >> RADEON_TILING_EG_MACRO_TILE_ASPECT_SHIFT) & RADEON_TILING_EG_MACRO_TILE_ASPECT_MASK;
 *tile_split = (tiling_flags >> RADEON_TILING_EG_TILE_SPLIT_SHIFT) & RADEON_TILING_EG_TILE_SPLIT_MASK;
 switch (*bankw) {
 default:
 case 1: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_1; break;
 case 2: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_2; break;
 case 4: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_4; break;
 case 8: *bankw = EVERGREEN_ADDR_SURF_BANK_WIDTH_8; break;
 }
 switch (*bankh) {
 default:
 case 1: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_1; break;
 case 2: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_2; break;
 case 4: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_4; break;
 case 8: *bankh = EVERGREEN_ADDR_SURF_BANK_HEIGHT_8; break;
 }
 switch (*mtaspect) {
 default:
 case 1: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_1; break;
 case 2: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_2; break;
 case 4: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_4; break;
 case 8: *mtaspect = EVERGREEN_ADDR_SURF_MACRO_TILE_ASPECT_8; break;
 }
}

static int sumo_set_uvd_clock(struct radeon_device *rdev, u32 clock,
         u32 cntl_reg, u32 status_reg)
{
 int r, i;
 struct atom_clock_dividers dividers;

 r = radeon_atom_get_clock_dividers(rdev, COMPUTE_ENGINE_PLL_PARAM,
        clock, false, ÷rs);
 if (r)
  return r;

 WREG32_P(cntl_reg, dividers.post_div, ~(DCLK_DIR_CNTL_EN|DCLK_DIVIDER_MASK));

 for (i = 0; i < 100; i++) {
  if (RREG32(status_reg) & DCLK_STATUS)
   break;
  mdelay(10);
 }
 if (i == 100)
  return -ETIMEDOUT;

 return 0;
}

int sumo_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
 int r = 0;
 u32 cg_scratch = RREG32(CG_SCRATCH1);

 r = sumo_set_uvd_clock(rdev, vclk, CG_VCLK_CNTL, CG_VCLK_STATUS);
 if (r)
  goto done;
 cg_scratch &= 0xffff0000;
 cg_scratch |= vclk / 100; /* Mhz */

 r = sumo_set_uvd_clock(rdev, dclk, CG_DCLK_CNTL, CG_DCLK_STATUS);
 if (r)
  goto done;
 cg_scratch &= 0x0000ffff;
 cg_scratch |= (dclk / 100) << 16; /* Mhz */

done:
 WREG32(CG_SCRATCH1, cg_scratch);

 return r;
}

int evergreen_set_uvd_clocks(struct radeon_device *rdev, u32 vclk, u32 dclk)
{
 /* start off with something large */
 unsigned fb_div = 0, vclk_div = 0, dclk_div = 0;
 int r;

 /* bypass vclk and dclk with bclk */
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
  VCLK_SRC_SEL(1) | DCLK_SRC_SEL(1),
  ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));

 /* put PLL in bypass mode */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_BYPASS_EN_MASK, ~UPLL_BYPASS_EN_MASK);

 if (!vclk || !dclk) {
  /* keep the Bypass mode, put PLL to sleep */
  WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
  return 0;
 }

 r = radeon_uvd_calc_upll_dividers(rdev, vclk, dclk, 125000, 250000,
       16384, 0x03FFFFFF, 0, 128, 5,
       &fb_div, &vclk_div, &dclk_div);
 if (r)
  return r;

 /* set VCO_MODE to 1 */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_VCO_MODE_MASK, ~UPLL_VCO_MODE_MASK);

 /* toggle UPLL_SLEEP to 1 then back to 0 */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_SLEEP_MASK, ~UPLL_SLEEP_MASK);
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_SLEEP_MASK);

 /* deassert UPLL_RESET */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);

 mdelay(1);

 r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
 if (r)
  return r;

 /* assert UPLL_RESET again */
 WREG32_P(CG_UPLL_FUNC_CNTL, UPLL_RESET_MASK, ~UPLL_RESET_MASK);

 /* disable spread spectrum. */
 WREG32_P(CG_UPLL_SPREAD_SPECTRUM, 0, ~SSEN_MASK);

 /* set feedback divider */
 WREG32_P(CG_UPLL_FUNC_CNTL_3, UPLL_FB_DIV(fb_div), ~UPLL_FB_DIV_MASK);

 /* set ref divider to 0 */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_REF_DIV_MASK);

 if (fb_div < 307200)
  WREG32_P(CG_UPLL_FUNC_CNTL_4, 0, ~UPLL_SPARE_ISPARE9);
 else
  WREG32_P(CG_UPLL_FUNC_CNTL_4, UPLL_SPARE_ISPARE9, ~UPLL_SPARE_ISPARE9);

 /* set PDIV_A and PDIV_B */
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
  UPLL_PDIV_A(vclk_div) | UPLL_PDIV_B(dclk_div),
  ~(UPLL_PDIV_A_MASK | UPLL_PDIV_B_MASK));

 /* give the PLL some time to settle */
 mdelay(15);

 /* deassert PLL_RESET */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_RESET_MASK);

 mdelay(15);

 /* switch from bypass mode to normal mode */
 WREG32_P(CG_UPLL_FUNC_CNTL, 0, ~UPLL_BYPASS_EN_MASK);

 r = radeon_uvd_send_upll_ctlreq(rdev, CG_UPLL_FUNC_CNTL);
 if (r)
  return r;

 /* switch VCLK and DCLK selection */
 WREG32_P(CG_UPLL_FUNC_CNTL_2,
  VCLK_SRC_SEL(2) | DCLK_SRC_SEL(2),
  ~(VCLK_SRC_SEL_MASK | DCLK_SRC_SEL_MASK));

 mdelay(100);

 return 0;
}

void evergreen_fix_pci_max_read_req_size(struct radeon_device *rdev)
{
 int readrq;
 u16 v;

 readrq = pcie_get_readrq(rdev->pdev);
 v = ffs(readrq) - 8;
 /* if bios or OS sets MAX_READ_REQUEST_SIZE to an invalid value, fix it
 * to avoid hangs or perfomance issues
 */

 if ((v == 0) || (v == 6) || (v == 7))
  pcie_set_readrq(rdev->pdev, 512);
}

void dce4_program_fmt(struct drm_encoder *encoder)
{
 struct drm_device *dev = encoder->dev;
 struct radeon_device *rdev = dev->dev_private;
 struct radeon_encoder *radeon_encoder = to_radeon_encoder(encoder);
 struct radeon_crtc *radeon_crtc = to_radeon_crtc(encoder->crtc);
 struct drm_connector *connector = radeon_get_connector_for_encoder(encoder);
 int bpc = 0;
 u32 tmp = 0;
 enum radeon_connector_dither dither = RADEON_FMT_DITHER_DISABLE;

 if (connector) {
  struct radeon_connector *radeon_connector = to_radeon_connector(connector);
  bpc = radeon_get_monitor_bpc(connector);
  dither = radeon_connector->dither;
 }

 /* LVDS/eDP FMT is set up by atom */
 if (radeon_encoder->devices & ATOM_DEVICE_LCD_SUPPORT)
  return;

 /* not needed for analog */
 if ((radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1) ||
     (radeon_encoder->encoder_id == ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2))
  return;

 if (bpc == 0)
  return;

 switch (bpc) {
 case 6:
  if (dither == RADEON_FMT_DITHER_ENABLE)
   /* XXX sort out optimal dither settings */
   tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
    FMT_SPATIAL_DITHER_EN);
  else
   tmp |= FMT_TRUNCATE_EN;
  break;
 case 8:
  if (dither == RADEON_FMT_DITHER_ENABLE)
   /* XXX sort out optimal dither settings */
   tmp |= (FMT_FRAME_RANDOM_ENABLE | FMT_HIGHPASS_RANDOM_ENABLE |
    FMT_RGB_RANDOM_ENABLE |
    FMT_SPATIAL_DITHER_EN | FMT_SPATIAL_DITHER_DEPTH);
  else
   tmp |= (FMT_TRUNCATE_EN | FMT_TRUNCATE_DEPTH);
  break;
 case 10:
 default:
  /* not needed */
  break;
 }

 WREG32(FMT_BIT_DEPTH_CONTROL + radeon_crtc->crtc_offset, tmp);
}

static bool dce4_is_in_vblank(struct radeon_device *rdev, int crtc)
{
 if (RREG32(EVERGREEN_CRTC_STATUS + crtc_offsets[crtc]) & EVERGREEN_CRTC_V_BLANK)
  return true;
 else
  return false;
}

static bool dce4_is_counter_moving(struct radeon_device *rdev, int crtc)
{
 u32 pos1, pos2;

 pos1 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);
 pos2 = RREG32(EVERGREEN_CRTC_STATUS_POSITION + crtc_offsets[crtc]);

 if (pos1 != pos2)
  return true;
 else
  return false;
}

/**
 * dce4_wait_for_vblank - vblank wait asic callback.
 *
 * @rdev: radeon_device pointer
 * @crtc: crtc to wait for vblank on
 *
 * Wait for vblank on the requested crtc (evergreen+).
 */

void dce4_wait_for_vblank(struct radeon_device *rdev, int crtc)
{
 unsigned i = 0;

 if (crtc >= rdev->num_crtc)
  return;

 if (!(RREG32(EVERGREEN_CRTC_CONTROL + crtc_offsets[crtc]) & EVERGREEN_CRTC_MASTER_EN))
  return;

 /* depending on when we hit vblank, we may be close to active; if so,
 * wait for another frame.
 */

 while (dce4_is_in_vblank(rdev, crtc)) {
  if (i++ % 100 == 0) {
   if (!dce4_is_counter_moving(rdev, crtc))
    break;
  }
 }

 while (!dce4_is_in_vblank(rdev, crtc)) {
  if (i++ % 100 == 0) {
   if (!dce4_is_counter_moving(rdev, crtc))
    break;
  }
 }
}

/**
 * evergreen_page_flip - pageflip callback.
 *
 * @rdev: radeon_device pointer
 * @crtc_id: crtc to cleanup pageflip on
 * @crtc_base: new address of the crtc (GPU MC address)
 * @async: asynchronous flip
 *
 * Triggers the actual pageflip by updating the primary
 * surface base address (evergreen+).
 */

void evergreen_page_flip(struct radeon_device *rdev, int crtc_id, u64 crtc_base,
    bool async)
{
 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];
 struct drm_framebuffer *fb = radeon_crtc->base.primary->fb;

 /* flip at hsync for async, default is vsync */
 WREG32(EVERGREEN_GRPH_FLIP_CONTROL + radeon_crtc->crtc_offset,
        async ? EVERGREEN_GRPH_SURFACE_UPDATE_H_RETRACE_EN : 0);
 /* update pitch */
 WREG32(EVERGREEN_GRPH_PITCH + radeon_crtc->crtc_offset,
        fb->pitches[0] / fb->format->cpp[0]);
 /* update the scanout addresses */
 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS_HIGH + radeon_crtc->crtc_offset,
        upper_32_bits(crtc_base));
 WREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset,
        (u32)crtc_base);
 /* post the write */
 RREG32(EVERGREEN_GRPH_PRIMARY_SURFACE_ADDRESS + radeon_crtc->crtc_offset);
}

/**
 * evergreen_page_flip_pending - check if page flip is still pending
 *
 * @rdev: radeon_device pointer
 * @crtc_id: crtc to check
 *
 * Returns the current update pending status.
 */

bool evergreen_page_flip_pending(struct radeon_device *rdev, int crtc_id)
{
 struct radeon_crtc *radeon_crtc = rdev->mode_info.crtcs[crtc_id];

 /* Return current update_pending status: */
 return !!(RREG32(EVERGREEN_GRPH_UPDATE + radeon_crtc->crtc_offset) &
  EVERGREEN_GRPH_SURFACE_UPDATE_PENDING);
}

/* get temperature in millidegrees */
int evergreen_get_temp(struct radeon_device *rdev)
{
 u32 temp, toffset;
 int actual_temp = 0;

 if (rdev->family == CHIP_JUNIPER) {
  toffset = (RREG32(CG_THERMAL_CTRL) & TOFFSET_MASK) >>
   TOFFSET_SHIFT;
  temp = (RREG32(CG_TS0_STATUS) & TS0_ADC_DOUT_MASK) >>
   TS0_ADC_DOUT_SHIFT;

  if (toffset & 0x100)
   actual_temp = temp / 2 - (0x200 - toffset);
  else
   actual_temp = temp / 2 + toffset;

  actual_temp = actual_temp * 1000;

 } else {
  temp = (RREG32(CG_MULT_THERMAL_STATUS) & ASIC_T_MASK) >>
   ASIC_T_SHIFT;

  if (temp & 0x400)
   actual_temp = -256;
  else if (temp & 0x200)
   actual_temp = 255;
  else if (temp & 0x100) {
   actual_temp = temp & 0x1ff;
   actual_temp |= ~0x1ff;
  } else
   actual_temp = temp & 0xff;

  actual_temp = (actual_temp * 1000) / 2;
 }

 return actual_temp;
}

int sumo_get_temp(struct radeon_device *rdev)
{
 u32 temp = RREG32(CG_THERMAL_STATUS) & 0xff;
 int actual_temp = temp - 49;

 return actual_temp * 1000;
}

/**
 * sumo_pm_init_profile - Initialize power profiles callback.
 *
 * @rdev: radeon_device pointer
 *
 * Initialize the power states used in profile mode
 * (sumo, trinity, SI).
 * Used for profile mode only.
 */

void sumo_pm_init_profile(struct radeon_device *rdev)
{
 int idx;

 /* default */
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 0;

 /* low,mid sh/mh */
 if (rdev->flags & RADEON_IS_MOBILITY)
  idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
 else
  idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);

 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;

 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;

 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 0;

 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 0;

 /* high sh/mh */
 idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx =
  rdev->pm.power_state[idx].num_clock_modes - 1;

 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx =
  rdev->pm.power_state[idx].num_clock_modes - 1;
}

/**
 * btc_pm_init_profile - Initialize power profiles callback.
 *
 * @rdev: radeon_device pointer
 *
 * Initialize the power states used in profile mode
 * (BTC, cayman).
 * Used for profile mode only.
 */

void btc_pm_init_profile(struct radeon_device *rdev)
{
 int idx;

 /* default */
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_ps_idx = rdev->pm.default_power_state_index;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_ps_idx = rdev->pm.default_power_state_index;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_DEFAULT_IDX].dpms_on_cm_idx = 2;
 /* starting with BTC, there is one state that is used for both
 * MH and SH.  Difference is that we always use the high clock index for
 * mclk.
 */

 if (rdev->flags & RADEON_IS_MOBILITY)
  idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_BATTERY, 0);
 else
  idx = radeon_pm_get_type_index(rdev, POWER_STATE_TYPE_PERFORMANCE, 0);
 /* low sh */
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_LOW_SH_IDX].dpms_on_cm_idx = 0;
 /* mid sh */
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_MID_SH_IDX].dpms_on_cm_idx = 1;
 /* high sh */
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_HIGH_SH_IDX].dpms_on_cm_idx = 2;
 /* low mh */
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_LOW_MH_IDX].dpms_on_cm_idx = 0;
 /* mid mh */
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_MID_MH_IDX].dpms_on_cm_idx = 1;
 /* high mh */
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_ps_idx = idx;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_off_cm_idx = 0;
 rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx = 2;
}

/**
 * evergreen_pm_misc - set additional pm hw parameters callback.
 *
 * @rdev: radeon_device pointer
 *
 * Set non-clock parameters associated with a power state
 * (voltage, etc.) (evergreen+).
 */

void evergreen_pm_misc(struct radeon_device *rdev)
{
 int req_ps_idx = rdev->pm.requested_power_state_index;
 int req_cm_idx = rdev->pm.requested_clock_mode_index;
 struct radeon_power_state *ps = &rdev->pm.power_state[req_ps_idx];
 struct radeon_voltage *voltage = &ps->clock_info[req_cm_idx].voltage;

 if (voltage->type == VOLTAGE_SW) {
  /* 0xff0x are flags rather then an actual voltage */
  if ((voltage->voltage & 0xff00) == 0xff00)
   return;
  if (voltage->voltage && (voltage->voltage != rdev->pm.current_vddc)) {
   radeon_atom_set_voltage(rdev, voltage->voltage, SET_VOLTAGE_TYPE_ASIC_VDDC);
   rdev->pm.current_vddc = voltage->voltage;
   DRM_DEBUG("Setting: vddc: %d\n", voltage->voltage);
  }

  /* starting with BTC, there is one state that is used for both
 * MH and SH.  Difference is that we always use the high clock index for
 * mclk and vddci.
 */

  if ((rdev->pm.pm_method == PM_METHOD_PROFILE) &&
      (rdev->family >= CHIP_BARTS) &&
      rdev->pm.active_crtc_count &&
      ((rdev->pm.profile_index == PM_PROFILE_MID_MH_IDX) ||
       (rdev->pm.profile_index == PM_PROFILE_LOW_MH_IDX)))
   voltage = &rdev->pm.power_state[req_ps_idx].
    clock_info[rdev->pm.profiles[PM_PROFILE_HIGH_MH_IDX].dpms_on_cm_idx].voltage;

  /* 0xff0x are flags rather then an actual voltage */
  if ((voltage->vddci & 0xff00) == 0xff00)
   return;
  if (voltage->vddci && (voltage->vddci != rdev->pm.current_vddci)) {
   radeon_atom_set_voltage(rdev, voltage->vddci, SET_VOLTAGE_TYPE_ASIC_VDDCI);
   rdev->pm.current_vddci = voltage->vddci;
   DRM_DEBUG("Setting: vddci: %d\n", voltage->vddci);
  }
 }
}

/**
 * evergreen_pm_prepare - pre-power state change callback.
 *
 * @rdev: radeon_device pointer
 *
 * Prepare for a power state change (evergreen+).
 */

void evergreen_pm_prepare(struct radeon_device *rdev)
{
 struct drm_device *ddev = rdev_to_drm(rdev);
 struct drm_crtc *crtc;
 struct radeon_crtc *radeon_crtc;
 u32 tmp;

 /* disable any active CRTCs */
 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
  radeon_crtc = to_radeon_crtc(crtc);
  if (radeon_crtc->enabled) {
   tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
   tmp |= EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
   WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
  }
 }
}

/**
 * evergreen_pm_finish - post-power state change callback.
 *
 * @rdev: radeon_device pointer
 *
 * Clean up after a power state change (evergreen+).
 */

void evergreen_pm_finish(struct radeon_device *rdev)
{
 struct drm_device *ddev = rdev_to_drm(rdev);
 struct drm_crtc *crtc;
 struct radeon_crtc *radeon_crtc;
 u32 tmp;

 /* enable any active CRTCs */
 list_for_each_entry(crtc, &ddev->mode_config.crtc_list, head) {
  radeon_crtc = to_radeon_crtc(crtc);
  if (radeon_crtc->enabled) {
   tmp = RREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset);
   tmp &= ~EVERGREEN_CRTC_DISP_READ_REQUEST_DISABLE;
   WREG32(EVERGREEN_CRTC_CONTROL + radeon_crtc->crtc_offset, tmp);
  }
 }
}

/**
 * evergreen_hpd_sense - hpd sense callback.
 *
 * @rdev: radeon_device pointer
 * @hpd: hpd (hotplug detect) pin
 *
 * Checks if a digital monitor is connected (evergreen+).
 * Returns true if connected, false if not connected.
 */

bool evergreen_hpd_sense(struct radeon_device *rdev, enum radeon_hpd_id hpd)
{
 if (hpd == RADEON_HPD_NONE)
  return false;

 return !!(RREG32(DC_HPDx_INT_STATUS_REG(hpd)) & DC_HPDx_SENSE);
}

/**
 * evergreen_hpd_set_polarity - hpd set polarity callback.
 *
 * @rdev: radeon_device pointer
 * @hpd: hpd (hotplug detect) pin
 *
 * Set the polarity of the hpd pin (evergreen+).
 */

void evergreen_hpd_set_polarity(struct radeon_device *rdev,
    enum radeon_hpd_id hpd)
{
 bool connected = evergreen_hpd_sense(rdev, hpd);

 if (hpd == RADEON_HPD_NONE)
  return;

 if (connected)
  WREG32_AND(DC_HPDx_INT_CONTROL(hpd), ~DC_HPDx_INT_POLARITY);
 else
  WREG32_OR(DC_HPDx_INT_CONTROL(hpd), DC_HPDx_INT_POLARITY);
}

/**
 * evergreen_hpd_init - hpd setup callback.
 *
 * @rdev: radeon_device pointer
 *
 * Setup the hpd pins used by the card (evergreen+).
 * Enable the pin, set the polarity, and enable the hpd interrupts.
 */

void evergreen_hpd_init(struct radeon_device *rdev)
{
 struct drm_device *dev = rdev_to_drm(rdev);
 struct drm_connector *connector;
 unsigned enabled = 0;
 u32 tmp = DC_HPDx_CONNECTION_TIMER(0x9c4) |
  DC_HPDx_RX_INT_TIMER(0xfa) | DC_HPDx_EN;

 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  enum radeon_hpd_id hpd =
   to_radeon_connector(connector)->hpd.hpd;

  if (connector->connector_type == DRM_MODE_CONNECTOR_eDP ||
      connector->connector_type == DRM_MODE_CONNECTOR_LVDS) {
   /* don't try to enable hpd on eDP or LVDS avoid breaking the
 * aux dp channel on imac and help (but not completely fix)
 * https://bugzilla.redhat.com/show_bug.cgi?id=726143
 * also avoid interrupt storms during dpms.
 */

   continue;
  }

  if (hpd == RADEON_HPD_NONE)
   continue;

  WREG32(DC_HPDx_CONTROL(hpd), tmp);
  enabled |= 1 << hpd;

  radeon_hpd_set_polarity(rdev, hpd);
 }
 radeon_irq_kms_enable_hpd(rdev, enabled);
}

/**
 * evergreen_hpd_fini - hpd tear down callback.
 *
 * @rdev: radeon_device pointer
 *
 * Tear down the hpd pins used by the card (evergreen+).
 * Disable the hpd interrupts.
 */

void evergreen_hpd_fini(struct radeon_device *rdev)
{
 struct drm_device *dev = rdev_to_drm(rdev);
 struct drm_connector *connector;
 unsigned disabled = 0;

 list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
  enum radeon_hpd_id hpd =
   to_radeon_connector(connector)->hpd.hpd;

  if (hpd == RADEON_HPD_NONE)
   continue;

  WREG32(DC_HPDx_CONTROL(hpd), 0);
  disabled |= 1 << hpd;
 }
 radeon_irq_kms_disable_hpd(rdev, disabled);
}

/* watermark setup */

static u32 evergreen_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 2:0:
 * first display controller
 *  0 - first half of lb (3840 * 2)
 *  1 - first 3/4 of lb (5760 * 2)
 *  2 - whole lb (7680 * 2), other crtc must be disabled
 *  3 - first 1/4 of lb (1920 * 2)
 * second display controller
 *  4 - second half of lb (3840 * 2)
 *  5 - second 3/4 of lb (5760 * 2)
 *  6 - whole lb (7680 * 2), other crtc must be disabled
 *  7 - last 1/4 of lb (1920 * 2)
 */

 /* 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;
 }

 /* second controller of the pair uses second half of the lb */
 if (radeon_crtc->crtc_id % 2)
  tmp += 4;
 WREG32(DC_LB_MEMORY_SPLIT + radeon_crtc->crtc_offset, tmp);

 if (ASIC_IS_DCE41(rdev) || ASIC_IS_DCE5(rdev)) {
  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:
  case 4:
  default:
   if (ASIC_IS_DCE5(rdev))
    return 4096 * 2;
   else
    return 3840 * 2;
  case 1:
  case 5:
   if (ASIC_IS_DCE5(rdev))
    return 6144 * 2;
   else
    return 5760 * 2;
  case 2:
  case 6:
   if (ASIC_IS_DCE5(rdev))
    return 8192 * 2;
   else
    return 7680 * 2;
  case 3:
  case 7:
   if (ASIC_IS_DCE5(rdev))
    return 2048 * 2;
   else
    return 1920 * 2;
  }
 }

 /* controller not enabled, so no lb used */
 return 0;
}

u32 evergreen_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;
 }
}

struct evergreen_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 evergreen_dram_bandwidth(struct evergreen_wm_params *wm)
{
 /* Calculate DRAM Bandwidth and the part allocated to display. */
 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 evergreen_dram_bandwidth_for_display(struct evergreen_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 evergreen_data_return_bandwidth(struct evergreen_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 evergreen_dmif_request_bandwidth(struct evergreen_wm_params *wm)
{
 /* Calculate the DMIF Request Bandwidth */
 fixed20_12 disp_clk_request_efficiency; /* 0.8 */
 fixed20_12 disp_clk, bandwidth;
 fixed20_12 a;

 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(10);
 disp_clk_request_efficiency.full = dfixed_const(8);
 disp_clk_request_efficiency.full = dfixed_div(disp_clk_request_efficiency, a);
 a.full = dfixed_const(32);
 bandwidth.full = dfixed_mul(a, disp_clk);
 bandwidth.full = dfixed_mul(bandwidth, disp_clk_request_efficiency);

 return dfixed_trunc(bandwidth);
}

static u32 evergreen_available_bandwidth(struct evergreen_wm_params *wm)
{
 /* Calculate the Available bandwidth. Display can use this temporarily but not in average. */
 u32 dram_bandwidth = evergreen_dram_bandwidth(wm);
 u32 data_return_bandwidth = evergreen_data_return_bandwidth(wm);
 u32 dmif_req_bandwidth = evergreen_dmif_request_bandwidth(wm);

 return min(dram_bandwidth, min(data_return_bandwidth, dmif_req_bandwidth));
}

static u32 evergreen_average_bandwidth(struct evergreen_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 evergreen_latency_watermark(struct evergreen_wm_params *wm)
{
 /* First calcualte the latency in ns */
 u32 mc_latency = 2000; /* 2000 ns. */
 u32 available_bandwidth = evergreen_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;
 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);

 lb_fill_bw = min(dfixed_trunc(a), 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 evergreen_average_bandwidth_vs_dram_bandwidth_for_display(struct evergreen_wm_params *wm)
{
 if (evergreen_average_bandwidth(wm) <=
     (evergreen_dram_bandwidth_for_display(wm) / wm->num_heads))
  return true;
 else
  return false;
};

static bool evergreen_average_bandwidth_vs_available_bandwidth(struct evergreen_wm_params *wm)
{
 if (evergreen_average_bandwidth(wm) <=
     (evergreen_available_bandwidth(wm) / wm->num_heads))
  return true;
 else
  return false;
};

static bool evergreen_check_latency_hiding(struct evergreen_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 (evergreen_latency_watermark(wm) <= latency_hiding)
  return true;
 else
  return false;
}

static void evergreen_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 evergreen_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 pipe_offset = radeon_crtc->crtc_id * 16;
 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;
  dram_channels = evergreen_get_number_of_dram_channels(rdev);

  /* watermark for high clocks */
--> --------------------

--> maximum size reached

--> --------------------

Messung V0.5
C=94 H=94 G=93

¤ Dauer der Verarbeitung: 0.16 Sekunden  ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

Beweissystem der NASA

Beweissystem Isabelle

NIST Cobol Testsuite

Cephes Mathematical Library

Wiener Entwicklungsmethode

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.