diff options
author | Dave Airlie <airlied@redhat.com> | 2015-12-23 07:15:26 +0300 |
---|---|---|
committer | Dave Airlie <airlied@redhat.com> | 2015-12-23 07:15:26 +0300 |
commit | fd3e14ffbd9ec7593ba4dafc9452a91373a4df05 (patch) | |
tree | 2db6625f712787514208f794ac62d24f415771a4 /drivers | |
parent | 9116199536878bb2fdd63d6064633d6e3f2cba22 (diff) | |
parent | eafbbd9883d0121811a9388988b80476dc12b1bf (diff) | |
download | linux-fd3e14ffbd9ec7593ba4dafc9452a91373a4df05.tar.xz |
Merge branch 'drm-next-4.5' of git://people.freedesktop.org/~agd5f/linux into drm-next
[airlied: fixup build problems on arm - added errno.h include]
* 'drm-next-4.5' of git://people.freedesktop.org/~agd5f/linux: (152 commits)
amd/powerplay: fix copy paste typo in hardwaremanager.c
amd/powerplay: disable powerplay by default initially
amd/powerplay: don't enable ucode fan control if vbios has no fan table
drm/amd/powerplay: show gpu load when print gpu performance for Cz. (v2)
drm/amd/powerplay: check whether need to enable thermal control. (v2)
drm/amd/powerplay: add point check to avoid NULL point hang.
drm/amdgpu/powerplay: Program a calculated value as Deep Sleep clock.
drm/amd/powerplay: Don't return an error if fan table is missing
drm/powerplay/hwmgr: log errors in tonga_hwmgr_backend_init
drm/powerplay: add debugging output to processpptables.c
drm/powerplay: add debugging output to tonga_processpptables.c
amd/powerplay: Add structures required to report configuration change
amd/powerplay: Fix get dal power level
amd\powerplay Implement get dal power level
drm/amd/powerplay: display gpu load when print performance for tonga.
drm/amdgpu/powerplay: enable sysfs and debugfs interfaces late
drm/amd/powerplay: move shared function of vi to hwmgr. (v2)
drm/amd/powerplay: check whether enable dpm in powerplay.
drm/amd/powerplay: fix bug that dpm funcs in debugfs/sysfs missing.
drm/amd/powerplay: fix boolreturn.cocci warnings
...
Diffstat (limited to 'drivers')
164 files changed, 50705 insertions, 15886 deletions
diff --git a/drivers/gpu/drm/Kconfig b/drivers/gpu/drm/Kconfig index b02ac62f5863..59babd5a5396 100644 --- a/drivers/gpu/drm/Kconfig +++ b/drivers/gpu/drm/Kconfig @@ -160,6 +160,7 @@ config DRM_AMDGPU If M is selected, the module will be called amdgpu. source "drivers/gpu/drm/amd/amdgpu/Kconfig" +source "drivers/gpu/drm/amd/powerplay/Kconfig" source "drivers/gpu/drm/nouveau/Kconfig" diff --git a/drivers/gpu/drm/amd/amdgpu/Makefile b/drivers/gpu/drm/amd/amdgpu/Makefile index 04c270757030..66f729eaf00b 100644 --- a/drivers/gpu/drm/amd/amdgpu/Makefile +++ b/drivers/gpu/drm/amd/amdgpu/Makefile @@ -2,10 +2,13 @@ # Makefile for the drm device driver. This driver provides support for the # Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher. -ccflags-y := -Iinclude/drm -Idrivers/gpu/drm/amd/include/asic_reg \ - -Idrivers/gpu/drm/amd/include \ - -Idrivers/gpu/drm/amd/amdgpu \ - -Idrivers/gpu/drm/amd/scheduler +FULL_AMD_PATH=$(src)/.. + +ccflags-y := -Iinclude/drm -I$(FULL_AMD_PATH)/include/asic_reg \ + -I$(FULL_AMD_PATH)/include \ + -I$(FULL_AMD_PATH)/amdgpu \ + -I$(FULL_AMD_PATH)/scheduler \ + -I$(FULL_AMD_PATH)/powerplay/inc amdgpu-y := amdgpu_drv.o @@ -44,6 +47,7 @@ amdgpu-y += \ # add SMC block amdgpu-y += \ amdgpu_dpm.o \ + amdgpu_powerplay.o \ cz_smc.o cz_dpm.o \ tonga_smc.o tonga_dpm.o \ fiji_smc.o fiji_dpm.o \ @@ -94,6 +98,14 @@ amdgpu-$(CONFIG_VGA_SWITCHEROO) += amdgpu_atpx_handler.o amdgpu-$(CONFIG_ACPI) += amdgpu_acpi.o amdgpu-$(CONFIG_MMU_NOTIFIER) += amdgpu_mn.o +ifneq ($(CONFIG_DRM_AMD_POWERPLAY),) + +include $(FULL_AMD_PATH)/powerplay/Makefile + +amdgpu-y += $(AMD_POWERPLAY_FILES) + +endif + obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o CFLAGS_amdgpu_trace_points.o := -I$(src) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu.h b/drivers/gpu/drm/amd/amdgpu/amdgpu.h index 5a5f04d0902d..fca4ef78589c 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu.h +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu.h @@ -52,6 +52,7 @@ #include "amdgpu_irq.h" #include "amdgpu_ucode.h" #include "amdgpu_gds.h" +#include "amd_powerplay.h" #include "gpu_scheduler.h" @@ -85,6 +86,7 @@ extern int amdgpu_enable_scheduler; extern int amdgpu_sched_jobs; extern int amdgpu_sched_hw_submission; extern int amdgpu_enable_semaphores; +extern int amdgpu_powerplay; #define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000 #define AMDGPU_MAX_USEC_TIMEOUT 100000 /* 100 ms */ @@ -918,8 +920,8 @@ struct amdgpu_ring { #define AMDGPU_VM_FAULT_STOP_ALWAYS 2 struct amdgpu_vm_pt { - struct amdgpu_bo *bo; - uint64_t addr; + struct amdgpu_bo_list_entry entry; + uint64_t addr; }; struct amdgpu_vm_id { @@ -981,9 +983,10 @@ struct amdgpu_vm_manager { void amdgpu_vm_manager_fini(struct amdgpu_device *adev); int amdgpu_vm_init(struct amdgpu_device *adev, struct amdgpu_vm *vm); void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm); -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *head); +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry); +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates); int amdgpu_vm_grab_id(struct amdgpu_vm *vm, struct amdgpu_ring *ring, struct amdgpu_sync *sync); void amdgpu_vm_flush(struct amdgpu_ring *ring, @@ -1024,11 +1027,9 @@ int amdgpu_vm_free_job(struct amdgpu_job *job); * context related structures */ -#define AMDGPU_CTX_MAX_CS_PENDING 16 - struct amdgpu_ctx_ring { uint64_t sequence; - struct fence *fences[AMDGPU_CTX_MAX_CS_PENDING]; + struct fence **fences; struct amd_sched_entity entity; }; @@ -1037,6 +1038,7 @@ struct amdgpu_ctx { struct amdgpu_device *adev; unsigned reset_counter; spinlock_t ring_lock; + struct fence **fences; struct amdgpu_ctx_ring rings[AMDGPU_MAX_RINGS]; }; @@ -1047,7 +1049,7 @@ struct amdgpu_ctx_mgr { struct idr ctx_handles; }; -int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, +int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, struct amdgpu_ctx *ctx); void amdgpu_ctx_fini(struct amdgpu_ctx *ctx); @@ -1254,7 +1256,7 @@ struct amdgpu_cs_parser { unsigned nchunks; struct amdgpu_cs_chunk *chunks; /* relocations */ - struct amdgpu_bo_list_entry *vm_bos; + struct amdgpu_bo_list_entry vm_pd; struct list_head validated; struct fence *fence; @@ -1300,31 +1302,7 @@ struct amdgpu_wb { int amdgpu_wb_get(struct amdgpu_device *adev, u32 *wb); void amdgpu_wb_free(struct amdgpu_device *adev, u32 wb); -/** - * struct amdgpu_pm - power management datas - * It keeps track of various data needed to take powermanagement decision. - */ -enum amdgpu_pm_state_type { - /* not used for dpm */ - POWER_STATE_TYPE_DEFAULT, - POWER_STATE_TYPE_POWERSAVE, - /* user selectable states */ - POWER_STATE_TYPE_BATTERY, - POWER_STATE_TYPE_BALANCED, - POWER_STATE_TYPE_PERFORMANCE, - /* internal states */ - POWER_STATE_TYPE_INTERNAL_UVD, - POWER_STATE_TYPE_INTERNAL_UVD_SD, - POWER_STATE_TYPE_INTERNAL_UVD_HD, - POWER_STATE_TYPE_INTERNAL_UVD_HD2, - POWER_STATE_TYPE_INTERNAL_UVD_MVC, - POWER_STATE_TYPE_INTERNAL_BOOT, - POWER_STATE_TYPE_INTERNAL_THERMAL, - POWER_STATE_TYPE_INTERNAL_ACPI, - POWER_STATE_TYPE_INTERNAL_ULV, - POWER_STATE_TYPE_INTERNAL_3DPERF, -}; enum amdgpu_int_thermal_type { THERMAL_TYPE_NONE, @@ -1606,8 +1584,8 @@ struct amdgpu_dpm { /* vce requirements */ struct amdgpu_vce_state vce_states[AMDGPU_MAX_VCE_LEVELS]; enum amdgpu_vce_level vce_level; - enum amdgpu_pm_state_type state; - enum amdgpu_pm_state_type user_state; + enum amd_pm_state_type state; + enum amd_pm_state_type user_state; u32 platform_caps; u32 voltage_response_time; u32 backbias_response_time; @@ -1660,8 +1638,13 @@ struct amdgpu_pm { const struct firmware *fw; /* SMC firmware */ uint32_t fw_version; const struct amdgpu_dpm_funcs *funcs; + uint32_t pcie_gen_mask; + uint32_t pcie_mlw_mask; + struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */ }; +void amdgpu_get_pcie_info(struct amdgpu_device *adev); + /* * UVD */ @@ -1829,6 +1812,8 @@ struct amdgpu_cu_info { */ struct amdgpu_asic_funcs { bool (*read_disabled_bios)(struct amdgpu_device *adev); + bool (*read_bios_from_rom)(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes); int (*read_register)(struct amdgpu_device *adev, u32 se_num, u32 sh_num, u32 reg_offset, u32 *value); void (*set_vga_state)(struct amdgpu_device *adev, bool state); @@ -2059,6 +2044,10 @@ struct amdgpu_device { /* interrupts */ struct amdgpu_irq irq; + /* powerplay */ + struct amd_powerplay powerplay; + bool pp_enabled; + /* dpm */ struct amdgpu_pm pm; u32 cg_flags; @@ -2235,6 +2224,7 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_asic_set_vce_clocks(adev, ev, ec) (adev)->asic_funcs->set_vce_clocks((adev), (ev), (ec)) #define amdgpu_asic_get_gpu_clock_counter(adev) (adev)->asic_funcs->get_gpu_clock_counter((adev)) #define amdgpu_asic_read_disabled_bios(adev) (adev)->asic_funcs->read_disabled_bios((adev)) +#define amdgpu_asic_read_bios_from_rom(adev, b, l) (adev)->asic_funcs->read_bios_from_rom((adev), (b), (l)) #define amdgpu_asic_read_register(adev, se, sh, offset, v)((adev)->asic_funcs->read_register((adev), (se), (sh), (offset), (v))) #define amdgpu_asic_get_cu_info(adev, info) (adev)->asic_funcs->get_cu_info((adev), (info)) #define amdgpu_gart_flush_gpu_tlb(adev, vmid) (adev)->gart.gart_funcs->flush_gpu_tlb((adev), (vmid)) @@ -2276,24 +2266,78 @@ amdgpu_get_sdma_instance(struct amdgpu_ring *ring) #define amdgpu_display_resume_mc_access(adev, s) (adev)->mode_info.funcs->resume_mc_access((adev), (s)) #define amdgpu_emit_copy_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_copy_buffer((ib), (s), (d), (b)) #define amdgpu_emit_fill_buffer(adev, ib, s, d, b) (adev)->mman.buffer_funcs->emit_fill_buffer((ib), (s), (d), (b)) -#define amdgpu_dpm_get_temperature(adev) (adev)->pm.funcs->get_temperature((adev)) #define amdgpu_dpm_pre_set_power_state(adev) (adev)->pm.funcs->pre_set_power_state((adev)) #define amdgpu_dpm_set_power_state(adev) (adev)->pm.funcs->set_power_state((adev)) #define amdgpu_dpm_post_set_power_state(adev) (adev)->pm.funcs->post_set_power_state((adev)) #define amdgpu_dpm_display_configuration_changed(adev) (adev)->pm.funcs->display_configuration_changed((adev)) -#define amdgpu_dpm_get_sclk(adev, l) (adev)->pm.funcs->get_sclk((adev), (l)) -#define amdgpu_dpm_get_mclk(adev, l) (adev)->pm.funcs->get_mclk((adev), (l)) #define amdgpu_dpm_print_power_state(adev, ps) (adev)->pm.funcs->print_power_state((adev), (ps)) -#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) -#define amdgpu_dpm_force_performance_level(adev, l) (adev)->pm.funcs->force_performance_level((adev), (l)) #define amdgpu_dpm_vblank_too_short(adev) (adev)->pm.funcs->vblank_too_short((adev)) -#define amdgpu_dpm_powergate_uvd(adev, g) (adev)->pm.funcs->powergate_uvd((adev), (g)) -#define amdgpu_dpm_powergate_vce(adev, g) (adev)->pm.funcs->powergate_vce((adev), (g)) #define amdgpu_dpm_enable_bapm(adev, e) (adev)->pm.funcs->enable_bapm((adev), (e)) -#define amdgpu_dpm_set_fan_control_mode(adev, m) (adev)->pm.funcs->set_fan_control_mode((adev), (m)) -#define amdgpu_dpm_get_fan_control_mode(adev) (adev)->pm.funcs->get_fan_control_mode((adev)) -#define amdgpu_dpm_set_fan_speed_percent(adev, s) (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) -#define amdgpu_dpm_get_fan_speed_percent(adev, s) (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) + +#define amdgpu_dpm_get_temperature(adev) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_temperature((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_temperature((adev)) + +#define amdgpu_dpm_set_fan_control_mode(adev, m) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_control_mode((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->set_fan_control_mode((adev), (m)) + +#define amdgpu_dpm_get_fan_control_mode(adev) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_control_mode((adev)->powerplay.pp_handle) : \ + (adev)->pm.funcs->get_fan_control_mode((adev)) + +#define amdgpu_dpm_set_fan_speed_percent(adev, s) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->set_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->set_fan_speed_percent((adev), (s)) + +#define amdgpu_dpm_get_fan_speed_percent(adev, s) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_fan_speed_percent((adev)->powerplay.pp_handle, (s)) : \ + (adev)->pm.funcs->get_fan_speed_percent((adev), (s)) + +#define amdgpu_dpm_get_sclk(adev, l) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_sclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_sclk((adev), (l)) + +#define amdgpu_dpm_get_mclk(adev, l) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->get_mclk((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->get_mclk((adev), (l)) + + +#define amdgpu_dpm_force_performance_level(adev, l) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->force_performance_level((adev)->powerplay.pp_handle, (l)) : \ + (adev)->pm.funcs->force_performance_level((adev), (l)) + +#define amdgpu_dpm_powergate_uvd(adev, g) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_uvd((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_uvd((adev), (g)) + +#define amdgpu_dpm_powergate_vce(adev, g) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->powergate_vce((adev)->powerplay.pp_handle, (g)) : \ + (adev)->pm.funcs->powergate_vce((adev), (g)) + +#define amdgpu_dpm_debugfs_print_current_performance_level(adev, m) \ + (adev)->pp_enabled ? \ + (adev)->powerplay.pp_funcs->print_current_performance_level((adev)->powerplay.pp_handle, (m)) : \ + (adev)->pm.funcs->debugfs_print_current_performance_level((adev), (m)) + +#define amdgpu_dpm_get_current_power_state(adev) \ + (adev)->powerplay.pp_funcs->get_current_power_state((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_get_performance_level(adev) \ + (adev)->powerplay.pp_funcs->get_performance_level((adev)->powerplay.pp_handle) + +#define amdgpu_dpm_dispatch_task(adev, event_id, input, output) \ + (adev)->powerplay.pp_funcs->dispatch_tasks((adev)->powerplay.pp_handle, (event_id), (input), (output)) #define amdgpu_gds_switch(adev, r, v, d, w, a) (adev)->gds.funcs->patch_gds_switch((r), (v), (d), (w), (a)) diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c index a142d5ae148d..5cd7b736a9de 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.c @@ -29,66 +29,10 @@ #include <drm/drmP.h> #include <drm/drm_crtc_helper.h> #include "amdgpu.h" -#include "amdgpu_acpi.h" +#include "amd_acpi.h" #include "atom.h" -#define ACPI_AC_CLASS "ac_adapter" - extern void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev); - -struct atif_verify_interface { - u16 size; /* structure size in bytes (includes size field) */ - u16 version; /* version */ - u32 notification_mask; /* supported notifications mask */ - u32 function_bits; /* supported functions bit vector */ -} __packed; - -struct atif_system_params { - u16 size; /* structure size in bytes (includes size field) */ - u32 valid_mask; /* valid flags mask */ - u32 flags; /* flags */ - u8 command_code; /* notify command code */ -} __packed; - -struct atif_sbios_requests { - u16 size; /* structure size in bytes (includes size field) */ - u32 pending; /* pending sbios requests */ - u8 panel_exp_mode; /* panel expansion mode */ - u8 thermal_gfx; /* thermal state: target gfx controller */ - u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ - u8 forced_power_gfx; /* forced power state: target gfx controller */ - u8 forced_power_state; /* forced power state: state id */ - u8 system_power_src; /* system power source */ - u8 backlight_level; /* panel backlight level (0-255) */ -} __packed; - -#define ATIF_NOTIFY_MASK 0x3 -#define ATIF_NOTIFY_NONE 0 -#define ATIF_NOTIFY_81 1 -#define ATIF_NOTIFY_N 2 - -struct atcs_verify_interface { - u16 size; /* structure size in bytes (includes size field) */ - u16 version; /* version */ - u32 function_bits; /* supported functions bit vector */ -} __packed; - -#define ATCS_VALID_FLAGS_MASK 0x3 - -struct atcs_pref_req_input { - u16 size; /* structure size in bytes (includes size field) */ - u16 client_id; /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ - u16 valid_flags_mask; /* valid flags mask */ - u16 flags; /* flags */ - u8 req_type; /* request type */ - u8 perf_req; /* performance request */ -} __packed; - -struct atcs_pref_req_output { - u16 size; /* structure size in bytes (includes size field) */ - u8 ret_val; /* return value */ -} __packed; - /* Call the ATIF method */ /** diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c index 5a8fbadbd27b..3c895863fcf5 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_atpx_handler.c @@ -11,7 +11,7 @@ #include <linux/acpi.h> #include <linux/pci.h> -#include "amdgpu_acpi.h" +#include "amd_acpi.h" struct amdgpu_atpx_functions { bool px_params; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c index c44c0c6afd1b..80add22375ee 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_bios.c @@ -35,6 +35,13 @@ * BIOS. */ +#define AMD_VBIOS_SIGNATURE " 761295520" +#define AMD_VBIOS_SIGNATURE_OFFSET 0x30 +#define AMD_VBIOS_SIGNATURE_SIZE sizeof(AMD_VBIOS_SIGNATURE) +#define AMD_VBIOS_SIGNATURE_END (AMD_VBIOS_SIGNATURE_OFFSET + AMD_VBIOS_SIGNATURE_SIZE) +#define AMD_IS_VALID_VBIOS(p) ((p)[0] == 0x55 && (p)[1] == 0xAA) +#define AMD_VBIOS_LENGTH(p) ((p)[2] << 9) + /* If you boot an IGP board with a discrete card as the primary, * the IGP rom is not accessible via the rom bar as the IGP rom is * part of the system bios. On boot, the system bios puts a @@ -58,7 +65,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev) return false; } - if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) { iounmap(bios); return false; } @@ -74,7 +81,7 @@ static bool igp_read_bios_from_vram(struct amdgpu_device *adev) bool amdgpu_read_bios(struct amdgpu_device *adev) { - uint8_t __iomem *bios, val1, val2; + uint8_t __iomem *bios, val[2]; size_t size; adev->bios = NULL; @@ -84,10 +91,10 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) return false; } - val1 = readb(&bios[0]); - val2 = readb(&bios[1]); + val[0] = readb(&bios[0]); + val[1] = readb(&bios[1]); - if (size == 0 || val1 != 0x55 || val2 != 0xaa) { + if (size == 0 || !AMD_IS_VALID_VBIOS(val)) { pci_unmap_rom(adev->pdev, bios); return false; } @@ -101,6 +108,38 @@ bool amdgpu_read_bios(struct amdgpu_device *adev) return true; } +static bool amdgpu_read_bios_from_rom(struct amdgpu_device *adev) +{ + u8 header[AMD_VBIOS_SIGNATURE_END+1] = {0}; + int len; + + if (!adev->asic_funcs->read_bios_from_rom) + return false; + + /* validate VBIOS signature */ + if (amdgpu_asic_read_bios_from_rom(adev, &header[0], sizeof(header)) == false) + return false; + header[AMD_VBIOS_SIGNATURE_END] = 0; + + if ((!AMD_IS_VALID_VBIOS(header)) || + 0 != memcmp((char *)&header[AMD_VBIOS_SIGNATURE_OFFSET], + AMD_VBIOS_SIGNATURE, + strlen(AMD_VBIOS_SIGNATURE))) + return false; + + /* valid vbios, go on */ + len = AMD_VBIOS_LENGTH(header); + len = ALIGN(len, 4); + adev->bios = kmalloc(len, GFP_KERNEL); + if (!adev->bios) { + DRM_ERROR("no memory to allocate for BIOS\n"); + return false; + } + + /* read complete BIOS */ + return amdgpu_asic_read_bios_from_rom(adev, adev->bios, len); +} + static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) { uint8_t __iomem *bios; @@ -113,7 +152,7 @@ static bool amdgpu_read_platform_bios(struct amdgpu_device *adev) return false; } - if (size == 0 || bios[0] != 0x55 || bios[1] != 0xaa) { + if (size == 0 || !AMD_IS_VALID_VBIOS(bios)) { return false; } adev->bios = kmemdup(bios, size, GFP_KERNEL); @@ -230,7 +269,7 @@ static bool amdgpu_atrm_get_bios(struct amdgpu_device *adev) break; } - if (i == 0 || adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) { + if (i == 0 || !AMD_IS_VALID_VBIOS(adev->bios)) { kfree(adev->bios); return false; } @@ -320,6 +359,9 @@ bool amdgpu_get_bios(struct amdgpu_device *adev) if (r == false) r = amdgpu_read_bios(adev); if (r == false) { + r = amdgpu_read_bios_from_rom(adev); + } + if (r == false) { r = amdgpu_read_disabled_bios(adev); } if (r == false) { @@ -330,7 +372,7 @@ bool amdgpu_get_bios(struct amdgpu_device *adev) adev->bios = NULL; return false; } - if (adev->bios[0] != 0x55 || adev->bios[1] != 0xaa) { + if (!AMD_IS_VALID_VBIOS(adev->bios)) { printk("BIOS signature incorrect %x %x\n", adev->bios[0], adev->bios[1]); goto free_bios; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c index 8e995148f56e..6fa0feac27f8 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cgs.c @@ -24,6 +24,7 @@ #include <linux/list.h> #include <linux/slab.h> #include <linux/pci.h> +#include <linux/acpi.h> #include <drm/drmP.h> #include <linux/firmware.h> #include <drm/amdgpu_drm.h> @@ -32,7 +33,6 @@ #include "atom.h" #include "amdgpu_ucode.h" - struct amdgpu_cgs_device { struct cgs_device base; struct amdgpu_device *adev; @@ -703,6 +703,9 @@ static int amdgpu_cgs_get_firmware_info(void *cgs_device, case CHIP_TONGA: strcpy(fw_name, "amdgpu/tonga_smc.bin"); break; + case CHIP_FIJI: + strcpy(fw_name, "amdgpu/fiji_smc.bin"); + break; default: DRM_ERROR("SMC firmware not supported\n"); return -EINVAL; @@ -736,6 +739,288 @@ static int amdgpu_cgs_get_firmware_info(void *cgs_device, return 0; } +static int amdgpu_cgs_query_system_info(void *cgs_device, + struct cgs_system_info *sys_info) +{ + CGS_FUNC_ADEV; + + if (NULL == sys_info) + return -ENODEV; + + if (sizeof(struct cgs_system_info) != sys_info->size) + return -ENODEV; + + switch (sys_info->info_id) { + case CGS_SYSTEM_INFO_ADAPTER_BDF_ID: + sys_info->value = adev->pdev->devfn | (adev->pdev->bus->number << 8); + break; + case CGS_SYSTEM_INFO_PCIE_GEN_INFO: + sys_info->value = adev->pm.pcie_gen_mask; + break; + case CGS_SYSTEM_INFO_PCIE_MLW: + sys_info->value = adev->pm.pcie_mlw_mask; + break; + default: + return -ENODEV; + } + + return 0; +} + +static int amdgpu_cgs_get_active_displays_info(void *cgs_device, + struct cgs_display_info *info) +{ + CGS_FUNC_ADEV; + struct amdgpu_crtc *amdgpu_crtc; + struct drm_device *ddev = adev->ddev; + struct drm_crtc *crtc; + uint32_t line_time_us, vblank_lines; + + if (info == NULL) + return -EINVAL; + + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled) { + info->active_display_mask |= (1 << amdgpu_crtc->crtc_id); + info->display_count++; + } + if (info->mode_info != NULL && + crtc->enabled && amdgpu_crtc->enabled && + amdgpu_crtc->hw_mode.clock) { + line_time_us = (amdgpu_crtc->hw_mode.crtc_htotal * 1000) / + amdgpu_crtc->hw_mode.clock; + vblank_lines = amdgpu_crtc->hw_mode.crtc_vblank_end - + amdgpu_crtc->hw_mode.crtc_vdisplay + + (amdgpu_crtc->v_border * 2); + info->mode_info->vblank_time_us = vblank_lines * line_time_us; + info->mode_info->refresh_rate = drm_mode_vrefresh(&amdgpu_crtc->hw_mode); + info->mode_info->ref_clock = adev->clock.spll.reference_freq; + info->mode_info++; + } + } + } + + return 0; +} + +/** \brief evaluate acpi namespace object, handle or pathname must be valid + * \param cgs_device + * \param info input/output arguments for the control method + * \return status + */ + +#if defined(CONFIG_ACPI) +static int amdgpu_cgs_acpi_eval_object(void *cgs_device, + struct cgs_acpi_method_info *info) +{ + CGS_FUNC_ADEV; + acpi_handle handle; + struct acpi_object_list input; + struct acpi_buffer output = { ACPI_ALLOCATE_BUFFER, NULL }; + union acpi_object *params = NULL; + union acpi_object *obj = NULL; + uint8_t name[5] = {'\0'}; + struct cgs_acpi_method_argument *argument = NULL; + uint32_t i, count; + acpi_status status; + int result; + uint32_t func_no = 0xFFFFFFFF; + + handle = ACPI_HANDLE(&adev->pdev->dev); + if (!handle) + return -ENODEV; + + memset(&input, 0, sizeof(struct acpi_object_list)); + + /* validate input info */ + if (info->size != sizeof(struct cgs_acpi_method_info)) + return -EINVAL; + + input.count = info->input_count; + if (info->input_count > 0) { + if (info->pinput_argument == NULL) + return -EINVAL; + argument = info->pinput_argument; + func_no = argument->value; + for (i = 0; i < info->input_count; i++) { + if (((argument->type == ACPI_TYPE_STRING) || + (argument->type == ACPI_TYPE_BUFFER)) + && (argument->pointer == NULL)) + return -EINVAL; + argument++; + } + } + + if (info->output_count > 0) { + if (info->poutput_argument == NULL) + return -EINVAL; + argument = info->poutput_argument; + for (i = 0; i < info->output_count; i++) { + if (((argument->type == ACPI_TYPE_STRING) || + (argument->type == ACPI_TYPE_BUFFER)) + && (argument->pointer == NULL)) + return -EINVAL; + argument++; + } + } + + /* The path name passed to acpi_evaluate_object should be null terminated */ + if ((info->field & CGS_ACPI_FIELD_METHOD_NAME) != 0) { + strncpy(name, (char *)&(info->name), sizeof(uint32_t)); + name[4] = '\0'; + } + + /* parse input parameters */ + if (input.count > 0) { + input.pointer = params = + kzalloc(sizeof(union acpi_object) * input.count, GFP_KERNEL); + if (params == NULL) + return -EINVAL; + + argument = info->pinput_argument; + + for (i = 0; i < input.count; i++) { + params->type = argument->type; + switch (params->type) { + case ACPI_TYPE_INTEGER: + params->integer.value = argument->value; + break; + case ACPI_TYPE_STRING: + params->string.length = argument->method_length; + params->string.pointer = argument->pointer; + break; + case ACPI_TYPE_BUFFER: + params->buffer.length = argument->method_length; + params->buffer.pointer = argument->pointer; + break; + default: + break; + } + params++; + argument++; + } + } + + /* parse output info */ + count = info->output_count; + argument = info->poutput_argument; + + /* evaluate the acpi method */ + status = acpi_evaluate_object(handle, name, &input, &output); + + if (ACPI_FAILURE(status)) { + result = -EIO; + goto error; + } + + /* return the output info */ + obj = output.pointer; + + if (count > 1) { + if ((obj->type != ACPI_TYPE_PACKAGE) || + (obj->package.count != count)) { + result = -EIO; + goto error; + } + params = obj->package.elements; + } else + params = obj; + + if (params == NULL) { + result = -EIO; + goto error; + } + + for (i = 0; i < count; i++) { + if (argument->type != params->type) { + result = -EIO; + goto error; + } + switch (params->type) { + case ACPI_TYPE_INTEGER: + argument->value = params->integer.value; + break; + case ACPI_TYPE_STRING: + if ((params->string.length != argument->data_length) || + (params->string.pointer == NULL)) { + result = -EIO; + goto error; + } + strncpy(argument->pointer, + params->string.pointer, + params->string.length); + break; + case ACPI_TYPE_BUFFER: + if (params->buffer.pointer == NULL) { + result = -EIO; + goto error; + } + memcpy(argument->pointer, + params->buffer.pointer, + argument->data_length); + break; + default: + break; + } + argument++; + params++; + } + +error: + if (obj != NULL) + kfree(obj); + kfree((void *)input.pointer); + return result; +} +#else +static int amdgpu_cgs_acpi_eval_object(void *cgs_device, + struct cgs_acpi_method_info *info) +{ + return -EIO; +} +#endif + +int amdgpu_cgs_call_acpi_method(void *cgs_device, + uint32_t acpi_method, + uint32_t acpi_function, + void *pinput, void *poutput, + uint32_t output_count, + uint32_t input_size, + uint32_t output_size) +{ + struct cgs_acpi_method_argument acpi_input[2] = { {0}, {0} }; + struct cgs_acpi_method_argument acpi_output = {0}; + struct cgs_acpi_method_info info = {0}; + + acpi_input[0].type = CGS_ACPI_TYPE_INTEGER; + acpi_input[0].method_length = sizeof(uint32_t); + acpi_input[0].data_length = sizeof(uint32_t); + acpi_input[0].value = acpi_function; + + acpi_input[1].type = CGS_ACPI_TYPE_BUFFER; + acpi_input[1].method_length = CGS_ACPI_MAX_BUFFER_SIZE; + acpi_input[1].data_length = input_size; + acpi_input[1].pointer = pinput; + + acpi_output.type = CGS_ACPI_TYPE_BUFFER; + acpi_output.method_length = CGS_ACPI_MAX_BUFFER_SIZE; + acpi_output.data_length = output_size; + acpi_output.pointer = poutput; + + info.size = sizeof(struct cgs_acpi_method_info); + info.field = CGS_ACPI_FIELD_METHOD_NAME | CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT; + info.input_count = 2; + info.name = acpi_method; + info.pinput_argument = acpi_input; + info.output_count = output_count; + info.poutput_argument = &acpi_output; + + return amdgpu_cgs_acpi_eval_object(cgs_device, &info); +} + static const struct cgs_ops amdgpu_cgs_ops = { amdgpu_cgs_gpu_mem_info, amdgpu_cgs_gmap_kmem, @@ -768,7 +1053,10 @@ static const struct cgs_ops amdgpu_cgs_ops = { amdgpu_cgs_set_camera_voltages, amdgpu_cgs_get_firmware_info, amdgpu_cgs_set_powergating_state, - amdgpu_cgs_set_clockgating_state + amdgpu_cgs_set_clockgating_state, + amdgpu_cgs_get_active_displays_info, + amdgpu_cgs_call_acpi_method, + amdgpu_cgs_query_system_info, }; static const struct cgs_os_ops amdgpu_cgs_os_ops = { diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c index 4f352ec9dec4..fa0e3276e8da 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_cs.c @@ -388,17 +388,18 @@ static int amdgpu_cs_parser_relocs(struct amdgpu_cs_parser *p) amdgpu_cs_buckets_get_list(&buckets, &p->validated); } - p->vm_bos = amdgpu_vm_get_bos(p->adev, &fpriv->vm, - &p->validated); + INIT_LIST_HEAD(&duplicates); + amdgpu_vm_get_pd_bo(&fpriv->vm, &p->validated, &p->vm_pd); if (need_mmap_lock) down_read(¤t->mm->mmap_sem); - INIT_LIST_HEAD(&duplicates); r = ttm_eu_reserve_buffers(&p->ticket, &p->validated, true, &duplicates); if (unlikely(r != 0)) goto error_reserve; + amdgpu_vm_get_pt_bos(&fpriv->vm, &duplicates); + r = amdgpu_cs_list_validate(p->adev, &fpriv->vm, &p->validated); if (r) goto error_validate; @@ -480,7 +481,6 @@ static void amdgpu_cs_parser_fini(struct amdgpu_cs_parser *parser, int error, bo if (parser->bo_list) amdgpu_bo_list_put(parser->bo_list); - drm_free_large(parser->vm_bos); for (i = 0; i < parser->nchunks; i++) drm_free_large(parser->chunks[i].kdata); kfree(parser->chunks); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c index fec65f01c031..17d1fb12128a 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_ctx.c @@ -25,7 +25,7 @@ #include <drm/drmP.h> #include "amdgpu.h" -int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, +int amdgpu_ctx_init(struct amdgpu_device *adev, enum amd_sched_priority pri, struct amdgpu_ctx *ctx) { unsigned i, j; @@ -35,17 +35,25 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, ctx->adev = adev; kref_init(&ctx->refcount); spin_lock_init(&ctx->ring_lock); - for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - ctx->rings[i].sequence = 1; + ctx->fences = kzalloc(sizeof(struct fence *) * amdgpu_sched_jobs * + AMDGPU_MAX_RINGS, GFP_KERNEL); + if (!ctx->fences) + return -ENOMEM; + for (i = 0; i < AMDGPU_MAX_RINGS; ++i) { + ctx->rings[i].sequence = 1; + ctx->rings[i].fences = (void *)ctx->fences + sizeof(struct fence *) * + amdgpu_sched_jobs * i; + } if (amdgpu_enable_scheduler) { /* create context entity for each ring */ for (i = 0; i < adev->num_rings; i++) { struct amd_sched_rq *rq; - if (kernel) - rq = &adev->rings[i]->sched.kernel_rq; - else - rq = &adev->rings[i]->sched.sched_rq; + if (pri >= AMD_SCHED_MAX_PRIORITY) { + kfree(ctx->fences); + return -EINVAL; + } + rq = &adev->rings[i]->sched.sched_rq[pri]; r = amd_sched_entity_init(&adev->rings[i]->sched, &ctx->rings[i].entity, rq, amdgpu_sched_jobs); @@ -57,7 +65,7 @@ int amdgpu_ctx_init(struct amdgpu_device *adev, bool kernel, for (j = 0; j < i; j++) amd_sched_entity_fini(&adev->rings[j]->sched, &ctx->rings[j].entity); - kfree(ctx); + kfree(ctx->fences); return r; } } @@ -73,8 +81,9 @@ void amdgpu_ctx_fini(struct amdgpu_ctx *ctx) return; for (i = 0; i < AMDGPU_MAX_RINGS; ++i) - for (j = 0; j < AMDGPU_CTX_MAX_CS_PENDING; ++j) + for (j = 0; j < amdgpu_sched_jobs; ++j) fence_put(ctx->rings[i].fences[j]); + kfree(ctx->fences); if (amdgpu_enable_scheduler) { for (i = 0; i < adev->num_rings; i++) @@ -103,9 +112,13 @@ static int amdgpu_ctx_alloc(struct amdgpu_device *adev, return r; } *id = (uint32_t)r; - r = amdgpu_ctx_init(adev, false, ctx); + r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_NORMAL, ctx); + if (r) { + idr_remove(&mgr->ctx_handles, *id); + *id = 0; + kfree(ctx); + } mutex_unlock(&mgr->lock); - return r; } @@ -239,7 +252,7 @@ uint64_t amdgpu_ctx_add_fence(struct amdgpu_ctx *ctx, struct amdgpu_ring *ring, unsigned idx = 0; struct fence *other = NULL; - idx = seq % AMDGPU_CTX_MAX_CS_PENDING; + idx = seq & (amdgpu_sched_jobs - 1); other = cring->fences[idx]; if (other) { signed long r; @@ -274,12 +287,12 @@ struct fence *amdgpu_ctx_get_fence(struct amdgpu_ctx *ctx, } - if (seq + AMDGPU_CTX_MAX_CS_PENDING < cring->sequence) { + if (seq + amdgpu_sched_jobs < cring->sequence) { spin_unlock(&ctx->ring_lock); return NULL; } - fence = fence_get(cring->fences[seq % AMDGPU_CTX_MAX_CS_PENDING]); + fence = fence_get(cring->fences[seq & (amdgpu_sched_jobs - 1)]); spin_unlock(&ctx->ring_lock); return fence; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c index d5b421330145..65531463f88e 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_device.c @@ -38,6 +38,7 @@ #include "amdgpu_i2c.h" #include "atom.h" #include "amdgpu_atombios.h" +#include "amd_pcie.h" #ifdef CONFIG_DRM_AMDGPU_CIK #include "cik.h" #endif @@ -949,6 +950,15 @@ static bool amdgpu_check_pot_argument(int arg) */ static void amdgpu_check_arguments(struct amdgpu_device *adev) { + if (amdgpu_sched_jobs < 4) { + dev_warn(adev->dev, "sched jobs (%d) must be at least 4\n", + amdgpu_sched_jobs); + amdgpu_sched_jobs = 4; + } else if (!amdgpu_check_pot_argument(amdgpu_sched_jobs)){ + dev_warn(adev->dev, "sched jobs (%d) must be a power of 2\n", + amdgpu_sched_jobs); + amdgpu_sched_jobs = roundup_pow_of_two(amdgpu_sched_jobs); + } /* vramlimit must be a power of two */ if (!amdgpu_check_pot_argument(amdgpu_vram_limit)) { dev_warn(adev->dev, "vram limit (%d) must be a power of 2\n", @@ -1214,12 +1224,14 @@ static int amdgpu_early_init(struct amdgpu_device *adev) } else { if (adev->ip_blocks[i].funcs->early_init) { r = adev->ip_blocks[i].funcs->early_init((void *)adev); - if (r == -ENOENT) + if (r == -ENOENT) { adev->ip_block_status[i].valid = false; - else if (r) + } else if (r) { + DRM_ERROR("early_init %d failed %d\n", i, r); return r; - else + } else { adev->ip_block_status[i].valid = true; + } } else { adev->ip_block_status[i].valid = true; } @@ -1237,20 +1249,28 @@ static int amdgpu_init(struct amdgpu_device *adev) if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->sw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("sw_init %d failed %d\n", i, r); return r; + } adev->ip_block_status[i].sw = true; /* need to do gmc hw init early so we can allocate gpu mem */ if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) { r = amdgpu_vram_scratch_init(adev); - if (r) + if (r) { + DRM_ERROR("amdgpu_vram_scratch_init failed %d\n", r); return r; + } r = adev->ip_blocks[i].funcs->hw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("hw_init %d failed %d\n", i, r); return r; + } r = amdgpu_wb_init(adev); - if (r) + if (r) { + DRM_ERROR("amdgpu_wb_init failed %d\n", r); return r; + } adev->ip_block_status[i].hw = true; } } @@ -1262,8 +1282,10 @@ static int amdgpu_init(struct amdgpu_device *adev) if (adev->ip_blocks[i].type == AMD_IP_BLOCK_TYPE_GMC) continue; r = adev->ip_blocks[i].funcs->hw_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("hw_init %d failed %d\n", i, r); return r; + } adev->ip_block_status[i].hw = true; } @@ -1280,12 +1302,16 @@ static int amdgpu_late_init(struct amdgpu_device *adev) /* enable clockgating to save power */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_GATE); - if (r) + if (r) { + DRM_ERROR("set_clockgating_state(gate) %d failed %d\n", i, r); return r; + } if (adev->ip_blocks[i].funcs->late_init) { r = adev->ip_blocks[i].funcs->late_init((void *)adev); - if (r) + if (r) { + DRM_ERROR("late_init %d failed %d\n", i, r); return r; + } } } @@ -1306,10 +1332,15 @@ static int amdgpu_fini(struct amdgpu_device *adev) /* ungate blocks before hw fini so that we can shutdown the blocks safely */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_UNGATE); - if (r) + if (r) { + DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r); return r; + } r = adev->ip_blocks[i].funcs->hw_fini((void *)adev); /* XXX handle errors */ + if (r) { + DRM_DEBUG("hw_fini %d failed %d\n", i, r); + } adev->ip_block_status[i].hw = false; } @@ -1318,6 +1349,9 @@ static int amdgpu_fini(struct amdgpu_device *adev) continue; r = adev->ip_blocks[i].funcs->sw_fini((void *)adev); /* XXX handle errors */ + if (r) { + DRM_DEBUG("sw_fini %d failed %d\n", i, r); + } adev->ip_block_status[i].sw = false; adev->ip_block_status[i].valid = false; } @@ -1335,9 +1369,15 @@ static int amdgpu_suspend(struct amdgpu_device *adev) /* ungate blocks so that suspend can properly shut them down */ r = adev->ip_blocks[i].funcs->set_clockgating_state((void *)adev, AMD_CG_STATE_UNGATE); + if (r) { + DRM_ERROR("set_clockgating_state(ungate) %d failed %d\n", i, r); + } /* XXX handle errors */ r = adev->ip_blocks[i].funcs->suspend(adev); /* XXX handle errors */ + if (r) { + DRM_ERROR("suspend %d failed %d\n", i, r); + } } return 0; @@ -1351,8 +1391,10 @@ static int amdgpu_resume(struct amdgpu_device *adev) if (!adev->ip_block_status[i].valid) continue; r = adev->ip_blocks[i].funcs->resume(adev); - if (r) + if (r) { + DRM_ERROR("resume %d failed %d\n", i, r); return r; + } } return 0; @@ -1484,8 +1526,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, return -EINVAL; } r = amdgpu_atombios_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_atombios_init failed\n"); return r; + } /* Post card if necessary */ if (!amdgpu_card_posted(adev)) { @@ -1499,21 +1543,26 @@ int amdgpu_device_init(struct amdgpu_device *adev, /* Initialize clocks */ r = amdgpu_atombios_get_clock_info(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_atombios_get_clock_info failed\n"); return r; + } /* init i2c buses */ amdgpu_atombios_i2c_init(adev); /* Fence driver */ r = amdgpu_fence_driver_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_fence_driver_init failed\n"); return r; + } /* init the mode config */ drm_mode_config_init(adev->ddev); r = amdgpu_init(adev); if (r) { + dev_err(adev->dev, "amdgpu_init failed\n"); amdgpu_fini(adev); return r; } @@ -1528,7 +1577,7 @@ int amdgpu_device_init(struct amdgpu_device *adev, return r; } - r = amdgpu_ctx_init(adev, true, &adev->kernel_ctx); + r = amdgpu_ctx_init(adev, AMD_SCHED_PRIORITY_KERNEL, &adev->kernel_ctx); if (r) { dev_err(adev->dev, "failed to create kernel context (%d).\n", r); return r; @@ -1570,8 +1619,10 @@ int amdgpu_device_init(struct amdgpu_device *adev, * explicit gating rather than handling it automatically. */ r = amdgpu_late_init(adev); - if (r) + if (r) { + dev_err(adev->dev, "amdgpu_late_init failed\n"); return r; + } return 0; } @@ -1788,6 +1839,7 @@ int amdgpu_resume_kms(struct drm_device *dev, bool resume, bool fbcon) } drm_kms_helper_poll_enable(dev); + drm_helper_hpd_irq_event(dev); if (fbcon) { amdgpu_fbdev_set_suspend(adev, 0); @@ -1881,6 +1933,83 @@ retry: return r; } +void amdgpu_get_pcie_info(struct amdgpu_device *adev) +{ + u32 mask; + int ret; + + if (pci_is_root_bus(adev->pdev->bus)) + return; + + if (amdgpu_pcie_gen2 == 0) + return; + + if (adev->flags & AMD_IS_APU) + return; + + ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); + if (!ret) { + adev->pm.pcie_gen_mask = (CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3); + + if (mask & DRM_PCIE_SPEED_25) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1; + if (mask & DRM_PCIE_SPEED_50) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2; + if (mask & DRM_PCIE_SPEED_80) + adev->pm.pcie_gen_mask |= CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3; + } + ret = drm_pcie_get_max_link_width(adev->ddev, &mask); + if (!ret) { + switch (mask) { + case 32: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 16: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 12: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 8: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 4: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 2: + adev->pm.pcie_mlw_mask = (CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 | + CAIL_PCIE_LINK_WIDTH_SUPPORT_X1); + break; + case 1: + adev->pm.pcie_mlw_mask = CAIL_PCIE_LINK_WIDTH_SUPPORT_X1; + break; + default: + break; + } + } +} /* * Debugfs diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c index 0508c5cd103a..b5dbbb573491 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c @@ -79,9 +79,10 @@ int amdgpu_vm_fault_stop = 0; int amdgpu_vm_debug = 0; int amdgpu_exp_hw_support = 0; int amdgpu_enable_scheduler = 1; -int amdgpu_sched_jobs = 16; +int amdgpu_sched_jobs = 32; int amdgpu_sched_hw_submission = 2; int amdgpu_enable_semaphores = 0; +int amdgpu_powerplay = -1; MODULE_PARM_DESC(vramlimit, "Restrict VRAM for testing, in megabytes"); module_param_named(vramlimit, amdgpu_vram_limit, int, 0600); @@ -155,7 +156,7 @@ module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444); MODULE_PARM_DESC(enable_scheduler, "enable SW GPU scheduler (1 = enable (default), 0 = disable)"); module_param_named(enable_scheduler, amdgpu_enable_scheduler, int, 0444); -MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 16)"); +MODULE_PARM_DESC(sched_jobs, "the max number of jobs supported in the sw queue (default 32)"); module_param_named(sched_jobs, amdgpu_sched_jobs, int, 0444); MODULE_PARM_DESC(sched_hw_submission, "the max number of HW submissions (default 2)"); @@ -164,6 +165,11 @@ module_param_named(sched_hw_submission, amdgpu_sched_hw_submission, int, 0444); MODULE_PARM_DESC(enable_semaphores, "Enable semaphores (1 = enable, 0 = disable (default))"); module_param_named(enable_semaphores, amdgpu_enable_semaphores, int, 0644); +#ifdef CONFIG_DRM_AMD_POWERPLAY +MODULE_PARM_DESC(powerplay, "Powerplay component (1 = enable, 0 = disable, -1 = auto (default))"); +module_param_named(powerplay, amdgpu_powerplay, int, 0444); +#endif + static struct pci_device_id pciidlist[] = { #ifdef CONFIG_DRM_AMDGPU_CIK /* Kaveri */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c index 6fcbbcc2e99e..cfb6caad2a73 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_fb.c @@ -263,7 +263,7 @@ out_unref: } if (fb && ret) { - drm_gem_object_unreference(gobj); + drm_gem_object_unreference_unlocked(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c index f6ea4b43a60c..6d136b260bb3 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_gem.c @@ -448,7 +448,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, struct amdgpu_bo_va *bo_va, uint32_t operation) { struct ttm_validate_buffer tv, *entry; - struct amdgpu_bo_list_entry *vm_bos; + struct amdgpu_bo_list_entry vm_pd; struct ww_acquire_ctx ticket; struct list_head list, duplicates; unsigned domain; @@ -461,15 +461,14 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, tv.shared = true; list_add(&tv.head, &list); - vm_bos = amdgpu_vm_get_bos(adev, bo_va->vm, &list); - if (!vm_bos) - return; + amdgpu_vm_get_pd_bo(bo_va->vm, &list, &vm_pd); /* Provide duplicates to avoid -EALREADY */ r = ttm_eu_reserve_buffers(&ticket, &list, true, &duplicates); if (r) - goto error_free; + goto error_print; + amdgpu_vm_get_pt_bos(bo_va->vm, &duplicates); list_for_each_entry(entry, &list, head) { domain = amdgpu_mem_type_to_domain(entry->bo->mem.mem_type); /* if anything is swapped out don't swap it in here, @@ -491,9 +490,7 @@ static void amdgpu_gem_va_update_vm(struct amdgpu_device *adev, error_unreserve: ttm_eu_backoff_reservation(&ticket, &list); -error_free: - drm_free_large(vm_bos); - +error_print: if (r && r != -ERESTARTSYS) DRM_ERROR("Couldn't update BO_VA (%d)\n", r); } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c index 22a8c7d3a3ab..3b78982abaf1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_pm.c @@ -30,10 +30,16 @@ #include <linux/hwmon.h> #include <linux/hwmon-sysfs.h> +#include "amd_powerplay.h" + static int amdgpu_debugfs_pm_init(struct amdgpu_device *adev); void amdgpu_pm_acpi_event_handler(struct amdgpu_device *adev) { + if (adev->pp_enabled) + /* TODO */ + return; + if (adev->pm.dpm_enabled) { mutex_lock(&adev->pm.mutex); if (power_supply_is_system_supplied() > 0) @@ -52,7 +58,12 @@ static ssize_t amdgpu_get_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amdgpu_pm_state_type pm = adev->pm.dpm.user_state; + enum amd_pm_state_type pm; + + if (adev->pp_enabled) { + pm = amdgpu_dpm_get_current_power_state(adev); + } else + pm = adev->pm.dpm.user_state; return snprintf(buf, PAGE_SIZE, "%s\n", (pm == POWER_STATE_TYPE_BATTERY) ? "battery" : @@ -66,40 +77,57 @@ static ssize_t amdgpu_set_dpm_state(struct device *dev, { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; + enum amd_pm_state_type state; - mutex_lock(&adev->pm.mutex); if (strncmp("battery", buf, strlen("battery")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_BATTERY; + state = POWER_STATE_TYPE_BATTERY; else if (strncmp("balanced", buf, strlen("balanced")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_BALANCED; + state = POWER_STATE_TYPE_BALANCED; else if (strncmp("performance", buf, strlen("performance")) == 0) - adev->pm.dpm.user_state = POWER_STATE_TYPE_PERFORMANCE; + state = POWER_STATE_TYPE_PERFORMANCE; else { - mutex_unlock(&adev->pm.mutex); count = -EINVAL; goto fail; } - mutex_unlock(&adev->pm.mutex); - /* Can't set dpm state when the card is off */ - if (!(adev->flags & AMD_IS_PX) || - (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) - amdgpu_pm_compute_clocks(adev); + if (adev->pp_enabled) { + amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_ENABLE_USER_STATE, &state, NULL); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.user_state = state; + mutex_unlock(&adev->pm.mutex); + + /* Can't set dpm state when the card is off */ + if (!(adev->flags & AMD_IS_PX) || + (ddev->switch_power_state == DRM_SWITCH_POWER_ON)) + amdgpu_pm_compute_clocks(adev); + } fail: return count; } static ssize_t amdgpu_get_dpm_forced_performance_level(struct device *dev, - struct device_attribute *attr, - char *buf) + struct device_attribute *attr, + char *buf) { struct drm_device *ddev = dev_get_drvdata(dev); struct amdgpu_device *adev = ddev->dev_private; - enum amdgpu_dpm_forced_level level = adev->pm.dpm.forced_level; - return snprintf(buf, PAGE_SIZE, "%s\n", - (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" : - (level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + if (adev->pp_enabled) { + enum amd_dpm_forced_level level; + + level = amdgpu_dpm_get_performance_level(adev); + return snprintf(buf, PAGE_SIZE, "%s\n", + (level == AMD_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMD_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + } else { + enum amdgpu_dpm_forced_level level; + + level = adev->pm.dpm.forced_level; + return snprintf(buf, PAGE_SIZE, "%s\n", + (level == AMDGPU_DPM_FORCED_LEVEL_AUTO) ? "auto" : + (level == AMDGPU_DPM_FORCED_LEVEL_LOW) ? "low" : "high"); + } } static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, @@ -112,7 +140,6 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, enum amdgpu_dpm_forced_level level; int ret = 0; - mutex_lock(&adev->pm.mutex); if (strncmp("low", buf, strlen("low")) == 0) { level = AMDGPU_DPM_FORCED_LEVEL_LOW; } else if (strncmp("high", buf, strlen("high")) == 0) { @@ -123,7 +150,11 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, count = -EINVAL; goto fail; } - if (adev->pm.funcs->force_performance_level) { + + if (adev->pp_enabled) + amdgpu_dpm_force_performance_level(adev, level); + else { + mutex_lock(&adev->pm.mutex); if (adev->pm.dpm.thermal_active) { count = -EINVAL; goto fail; @@ -131,6 +162,9 @@ static ssize_t amdgpu_set_dpm_forced_performance_level(struct device *dev, ret = amdgpu_dpm_force_performance_level(adev, level); if (ret) count = -EINVAL; + else + adev->pm.dpm.forced_level = level; + mutex_unlock(&adev->pm.mutex); } fail: mutex_unlock(&adev->pm.mutex); @@ -150,10 +184,10 @@ static ssize_t amdgpu_hwmon_show_temp(struct device *dev, struct amdgpu_device *adev = dev_get_drvdata(dev); int temp; - if (adev->pm.funcs->get_temperature) - temp = amdgpu_dpm_get_temperature(adev); - else + if (!adev->pp_enabled && !adev->pm.funcs->get_temperature) temp = 0; + else + temp = amdgpu_dpm_get_temperature(adev); return snprintf(buf, PAGE_SIZE, "%d\n", temp); } @@ -181,8 +215,10 @@ static ssize_t amdgpu_hwmon_get_pwm1_enable(struct device *dev, struct amdgpu_device *adev = dev_get_drvdata(dev); u32 pwm_mode = 0; - if (adev->pm.funcs->get_fan_control_mode) - pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); + if (!adev->pp_enabled && !adev->pm.funcs->get_fan_control_mode) + return -EINVAL; + + pwm_mode = amdgpu_dpm_get_fan_control_mode(adev); /* never 0 (full-speed), fuse or smc-controlled always */ return sprintf(buf, "%i\n", pwm_mode == FDO_PWM_MODE_STATIC ? 1 : 2); @@ -197,7 +233,7 @@ static ssize_t amdgpu_hwmon_set_pwm1_enable(struct device *dev, int err; int value; - if(!adev->pm.funcs->set_fan_control_mode) + if (!adev->pp_enabled && !adev->pm.funcs->set_fan_control_mode) return -EINVAL; err = kstrtoint(buf, 10, &value); @@ -294,7 +330,7 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, struct amdgpu_device *adev = dev_get_drvdata(dev); umode_t effective_mode = attr->mode; - /* Skip attributes if DPM is not enabled */ + /* Skip limit attributes if DPM is not enabled */ if (!adev->pm.dpm_enabled && (attr == &sensor_dev_attr_temp1_crit.dev_attr.attr || attr == &sensor_dev_attr_temp1_crit_hyst.dev_attr.attr || @@ -304,6 +340,9 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj, attr == &sensor_dev_attr_pwm1_min.dev_attr.attr)) return 0; + if (adev->pp_enabled) + return effective_mode; + /* Skip fan attributes if fan is not present */ if (adev->pm.no_fan && (attr == &sensor_dev_attr_pwm1.dev_attr.attr || @@ -351,7 +390,7 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) container_of(work, struct amdgpu_device, pm.dpm.thermal.work); /* switch to the thermal state */ - enum amdgpu_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; + enum amd_pm_state_type dpm_state = POWER_STATE_TYPE_INTERNAL_THERMAL; if (!adev->pm.dpm_enabled) return; @@ -379,7 +418,7 @@ void amdgpu_dpm_thermal_work_handler(struct work_struct *work) } static struct amdgpu_ps *amdgpu_dpm_pick_power_state(struct amdgpu_device *adev, - enum amdgpu_pm_state_type dpm_state) + enum amd_pm_state_type dpm_state) { int i; struct amdgpu_ps *ps; @@ -516,7 +555,7 @@ static void amdgpu_dpm_change_power_state_locked(struct amdgpu_device *adev) { int i; struct amdgpu_ps *ps; - enum amdgpu_pm_state_type dpm_state; + enum amd_pm_state_type dpm_state; int ret; /* if dpm init failed */ @@ -635,49 +674,54 @@ done: void amdgpu_dpm_enable_uvd(struct amdgpu_device *adev, bool enable) { - if (adev->pm.funcs->powergate_uvd) { - mutex_lock(&adev->pm.mutex); - /* enable/disable UVD */ + if (adev->pp_enabled) amdgpu_dpm_powergate_uvd(adev, !enable); - mutex_unlock(&adev->pm.mutex); - } else { - if (enable) { + else { + if (adev->pm.funcs->powergate_uvd) { mutex_lock(&adev->pm.mutex); - adev->pm.dpm.uvd_active = true; - adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + /* enable/disable UVD */ + amdgpu_dpm_powergate_uvd(adev, !enable); mutex_unlock(&adev->pm.mutex); } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.uvd_active = false; - mutex_unlock(&adev->pm.mutex); + if (enable) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.uvd_active = true; + adev->pm.dpm.state = POWER_STATE_TYPE_INTERNAL_UVD; + mutex_unlock(&adev->pm.mutex); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.uvd_active = false; + mutex_unlock(&adev->pm.mutex); + } + amdgpu_pm_compute_clocks(adev); } - amdgpu_pm_compute_clocks(adev); } } void amdgpu_dpm_enable_vce(struct amdgpu_device *adev, bool enable) { - if (adev->pm.funcs->powergate_vce) { - mutex_lock(&adev->pm.mutex); - /* enable/disable VCE */ + if (adev->pp_enabled) amdgpu_dpm_powergate_vce(adev, !enable); - - mutex_unlock(&adev->pm.mutex); - } else { - if (enable) { + else { + if (adev->pm.funcs->powergate_vce) { mutex_lock(&adev->pm.mutex); - adev->pm.dpm.vce_active = true; - /* XXX select vce level based on ring/task */ - adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL; + amdgpu_dpm_powergate_vce(adev, !enable); mutex_unlock(&adev->pm.mutex); } else { - mutex_lock(&adev->pm.mutex); - adev->pm.dpm.vce_active = false; - mutex_unlock(&adev->pm.mutex); + if (enable) { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.vce_active = true; + /* XXX select vce level based on ring/task */ + adev->pm.dpm.vce_level = AMDGPU_VCE_LEVEL_AC_ALL; + mutex_unlock(&adev->pm.mutex); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.vce_active = false; + mutex_unlock(&adev->pm.mutex); + } + amdgpu_pm_compute_clocks(adev); } - - amdgpu_pm_compute_clocks(adev); } } @@ -685,10 +729,13 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev) { int i; - for (i = 0; i < adev->pm.dpm.num_ps; i++) { - printk("== power state %d ==\n", i); + if (adev->pp_enabled) + /* TO DO */ + return; + + for (i = 0; i < adev->pm.dpm.num_ps; i++) amdgpu_dpm_print_power_state(adev, &adev->pm.dpm.ps[i]); - } + } int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) @@ -698,8 +745,11 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev) if (adev->pm.sysfs_initialized) return 0; - if (adev->pm.funcs->get_temperature == NULL) - return 0; + if (!adev->pp_enabled) { + if (adev->pm.funcs->get_temperature == NULL) + return 0; + } + adev->pm.int_hwmon_dev = hwmon_device_register_with_groups(adev->dev, DRIVER_NAME, adev, hwmon_groups); @@ -748,32 +798,43 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev) if (!adev->pm.dpm_enabled) return; - mutex_lock(&adev->pm.mutex); + if (adev->pp_enabled) { + int i = 0; + + amdgpu_display_bandwidth_update(adev); + mutex_lock(&adev->ring_lock); + for (i = 0; i < AMDGPU_MAX_RINGS; i++) { + struct amdgpu_ring *ring = adev->rings[i]; + if (ring && ring->ready) + amdgpu_fence_wait_empty(ring); + } + mutex_unlock(&adev->ring_lock); - /* update active crtc counts */ - adev->pm.dpm.new_active_crtcs = 0; - adev->pm.dpm.new_active_crtc_count = 0; - if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { - list_for_each_entry(crtc, - &ddev->mode_config.crtc_list, head) { - amdgpu_crtc = to_amdgpu_crtc(crtc); - if (crtc->enabled) { - adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); - adev->pm.dpm.new_active_crtc_count++; + amdgpu_dpm_dispatch_task(adev, AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, NULL, NULL); + } else { + mutex_lock(&adev->pm.mutex); + adev->pm.dpm.new_active_crtcs = 0; + adev->pm.dpm.new_active_crtc_count = 0; + if (adev->mode_info.num_crtc && adev->mode_info.mode_config_initialized) { + list_for_each_entry(crtc, + &ddev->mode_config.crtc_list, head) { + amdgpu_crtc = to_amdgpu_crtc(crtc); + if (crtc->enabled) { + adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id); + adev->pm.dpm.new_active_crtc_count++; + } } } - } - - /* update battery/ac status */ - if (power_supply_is_system_supplied() > 0) - adev->pm.dpm.ac_power = true; - else - adev->pm.dpm.ac_power = false; - - amdgpu_dpm_change_power_state_locked(adev); + /* update battery/ac status */ + if (power_supply_is_system_supplied() > 0) + adev->pm.dpm.ac_power = true; + else + adev->pm.dpm.ac_power = false; - mutex_unlock(&adev->pm.mutex); + amdgpu_dpm_change_power_state_locked(adev); + mutex_unlock(&adev->pm.mutex); + } } /* @@ -787,7 +848,13 @@ static int amdgpu_debugfs_pm_info(struct seq_file *m, void *data) struct drm_device *dev = node->minor->dev; struct amdgpu_device *adev = dev->dev_private; - if (adev->pm.dpm_enabled) { + if (!adev->pm.dpm_enabled) { + seq_printf(m, "dpm not enabled\n"); + return 0; + } + if (adev->pp_enabled) { + amdgpu_dpm_debugfs_print_current_performance_level(adev, m); + } else { mutex_lock(&adev->pm.mutex); if (adev->pm.funcs->debugfs_print_current_performance_level) amdgpu_dpm_debugfs_print_current_performance_level(adev, m); diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c new file mode 100644 index 000000000000..5ee9a0690278 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.c @@ -0,0 +1,317 @@ +/* + * Copyright 2015 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: AMD + * + */ +#include "atom.h" +#include "amdgpu.h" +#include "amd_shared.h" +#include <linux/module.h> +#include <linux/moduleparam.h> +#include "amdgpu_pm.h" +#include <drm/amdgpu_drm.h> +#include "amdgpu_powerplay.h" +#include "cik_dpm.h" +#include "vi_dpm.h" + +static int amdgpu_powerplay_init(struct amdgpu_device *adev) +{ + int ret = 0; + struct amd_powerplay *amd_pp; + + amd_pp = &(adev->powerplay); + + if (adev->pp_enabled) { +#ifdef CONFIG_DRM_AMD_POWERPLAY + struct amd_pp_init *pp_init; + + pp_init = kzalloc(sizeof(struct amd_pp_init), GFP_KERNEL); + + if (pp_init == NULL) + return -ENOMEM; + + pp_init->chip_family = adev->family; + pp_init->chip_id = adev->asic_type; + pp_init->device = amdgpu_cgs_create_device(adev); + + ret = amd_powerplay_init(pp_init, amd_pp); + kfree(pp_init); +#endif + } else { + amd_pp->pp_handle = (void *)adev; + + switch (adev->asic_type) { +#ifdef CONFIG_DRM_AMDGPU_CIK + case CHIP_BONAIRE: + case CHIP_HAWAII: + amd_pp->ip_funcs = &ci_dpm_ip_funcs; + break; + case CHIP_KABINI: + case CHIP_MULLINS: + case CHIP_KAVERI: + amd_pp->ip_funcs = &kv_dpm_ip_funcs; + break; +#endif + case CHIP_TOPAZ: + amd_pp->ip_funcs = &iceland_dpm_ip_funcs; + break; + case CHIP_TONGA: + amd_pp->ip_funcs = &tonga_dpm_ip_funcs; + break; + case CHIP_FIJI: + amd_pp->ip_funcs = &fiji_dpm_ip_funcs; + break; + case CHIP_CARRIZO: + case CHIP_STONEY: + amd_pp->ip_funcs = &cz_dpm_ip_funcs; + break; + default: + ret = -EINVAL; + break; + } + } + return ret; +} + +static int amdgpu_pp_early_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int ret = 0; + +#ifdef CONFIG_DRM_AMD_POWERPLAY + switch (adev->asic_type) { + case CHIP_TONGA: + case CHIP_FIJI: + adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; + break; + default: + adev->pp_enabled = (amdgpu_powerplay > 0) ? true : false; + break; + } +#else + adev->pp_enabled = false; +#endif + + ret = amdgpu_powerplay_init(adev); + if (ret) + return ret; + + if (adev->powerplay.ip_funcs->early_init) + ret = adev->powerplay.ip_funcs->early_init( + adev->powerplay.pp_handle); + return ret; +} + + +static int amdgpu_pp_late_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->late_init) + ret = adev->powerplay.ip_funcs->late_init( + adev->powerplay.pp_handle); + +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (adev->pp_enabled) + amdgpu_pm_sysfs_init(adev); +#endif + return ret; +} + +static int amdgpu_pp_sw_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->sw_init) + ret = adev->powerplay.ip_funcs->sw_init( + adev->powerplay.pp_handle); + +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (adev->pp_enabled) { + if (amdgpu_dpm == 0) + adev->pm.dpm_enabled = false; + else + adev->pm.dpm_enabled = true; + } +#endif + + return ret; +} + +static int amdgpu_pp_sw_fini(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->sw_fini) + ret = adev->powerplay.ip_funcs->sw_fini( + adev->powerplay.pp_handle); + if (ret) + return ret; + +#ifdef CONFIG_DRM_AMD_POWERPLAY + if (adev->pp_enabled) { + amdgpu_pm_sysfs_fini(adev); + amd_powerplay_fini(adev->powerplay.pp_handle); + } +#endif + + return ret; +} + +static int amdgpu_pp_hw_init(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->pp_enabled && adev->firmware.smu_load) + amdgpu_ucode_init_bo(adev); + + if (adev->powerplay.ip_funcs->hw_init) + ret = adev->powerplay.ip_funcs->hw_init( + adev->powerplay.pp_handle); + + return ret; +} + +static int amdgpu_pp_hw_fini(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->hw_fini) + ret = adev->powerplay.ip_funcs->hw_fini( + adev->powerplay.pp_handle); + + if (adev->pp_enabled && adev->firmware.smu_load) + amdgpu_ucode_fini_bo(adev); + + return ret; +} + +static int amdgpu_pp_suspend(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->suspend) + ret = adev->powerplay.ip_funcs->suspend( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_resume(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->resume) + ret = adev->powerplay.ip_funcs->resume( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->set_clockgating_state) + ret = adev->powerplay.ip_funcs->set_clockgating_state( + adev->powerplay.pp_handle, state); + return ret; +} + +static int amdgpu_pp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->set_powergating_state) + ret = adev->powerplay.ip_funcs->set_powergating_state( + adev->powerplay.pp_handle, state); + return ret; +} + + +static bool amdgpu_pp_is_idle(void *handle) +{ + bool ret = true; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->is_idle) + ret = adev->powerplay.ip_funcs->is_idle( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_wait_for_idle(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->wait_for_idle) + ret = adev->powerplay.ip_funcs->wait_for_idle( + adev->powerplay.pp_handle); + return ret; +} + +static int amdgpu_pp_soft_reset(void *handle) +{ + int ret = 0; + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->soft_reset) + ret = adev->powerplay.ip_funcs->soft_reset( + adev->powerplay.pp_handle); + return ret; +} + +static void amdgpu_pp_print_status(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + if (adev->powerplay.ip_funcs->print_status) + adev->powerplay.ip_funcs->print_status( + adev->powerplay.pp_handle); +} + +const struct amd_ip_funcs amdgpu_pp_ip_funcs = { + .early_init = amdgpu_pp_early_init, + .late_init = amdgpu_pp_late_init, + .sw_init = amdgpu_pp_sw_init, + .sw_fini = amdgpu_pp_sw_fini, + .hw_init = amdgpu_pp_hw_init, + .hw_fini = amdgpu_pp_hw_fini, + .suspend = amdgpu_pp_suspend, + .resume = amdgpu_pp_resume, + .is_idle = amdgpu_pp_is_idle, + .wait_for_idle = amdgpu_pp_wait_for_idle, + .soft_reset = amdgpu_pp_soft_reset, + .print_status = amdgpu_pp_print_status, + .set_clockgating_state = amdgpu_pp_set_clockgating_state, + .set_powergating_state = amdgpu_pp_set_powergating_state, +}; diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h new file mode 100644 index 000000000000..da5cf47cfd99 --- /dev/null +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_powerplay.h @@ -0,0 +1,33 @@ +/* + * Copyright 2015 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: AMD + * + */ + +#ifndef __AMDGPU_POPWERPLAY_H__ +#define __AMDGPU_POPWERPLAY_H__ + +#include "amd_shared.h" + +extern const struct amd_ip_funcs amdgpu_pp_ip_funcs; + +#endif /* __AMDSOC_DM_H__ */ diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c index b53d273eb7a1..8f7688e598a1 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c +++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_vm.c @@ -75,50 +75,50 @@ static unsigned amdgpu_vm_directory_size(struct amdgpu_device *adev) } /** - * amdgpu_vm_get_bos - add the vm BOs to a validation list + * amdgpu_vm_get_pd_bo - add the VM PD to a validation list * * @vm: vm providing the BOs - * @head: head of validation list + * @validated: head of validation list + * @entry: entry to add * * Add the page directory to the list of BOs to - * validate for command submission (cayman+). + * validate for command submission. */ -struct amdgpu_bo_list_entry *amdgpu_vm_get_bos(struct amdgpu_device *adev, - struct amdgpu_vm *vm, - struct list_head *head) +void amdgpu_vm_get_pd_bo(struct amdgpu_vm *vm, + struct list_head *validated, + struct amdgpu_bo_list_entry *entry) { - struct amdgpu_bo_list_entry *list; - unsigned i, idx; + entry->robj = vm->page_directory; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &vm->page_directory->tbo; + entry->tv.shared = true; + list_add(&entry->tv.head, validated); +} - list = drm_malloc_ab(vm->max_pde_used + 2, - sizeof(struct amdgpu_bo_list_entry)); - if (!list) { - return NULL; - } +/** + * amdgpu_vm_get_bos - add the vm BOs to a duplicates list + * + * @vm: vm providing the BOs + * @duplicates: head of duplicates list + * + * Add the page directory to the BO duplicates list + * for command submission. + */ +void amdgpu_vm_get_pt_bos(struct amdgpu_vm *vm, struct list_head *duplicates) +{ + unsigned i; /* add the vm page table to the list */ - list[0].robj = vm->page_directory; - list[0].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[0].priority = 0; - list[0].tv.bo = &vm->page_directory->tbo; - list[0].tv.shared = true; - list_add(&list[0].tv.head, head); - - for (i = 0, idx = 1; i <= vm->max_pde_used; i++) { - if (!vm->page_tables[i].bo) + for (i = 0; i <= vm->max_pde_used; ++i) { + struct amdgpu_bo_list_entry *entry = &vm->page_tables[i].entry; + + if (!entry->robj) continue; - list[idx].robj = vm->page_tables[i].bo; - list[idx].prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; - list[idx].priority = 0; - list[idx].tv.bo = &list[idx].robj->tbo; - list[idx].tv.shared = true; - list_add(&list[idx++].tv.head, head); + list_add(&entry->tv.head, duplicates); } - - return list; } /** @@ -461,7 +461,7 @@ int amdgpu_vm_update_page_directory(struct amdgpu_device *adev, /* walk over the address space and update the page directory */ for (pt_idx = 0; pt_idx <= vm->max_pde_used; ++pt_idx) { - struct amdgpu_bo *bo = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *bo = vm->page_tables[pt_idx].entry.robj; uint64_t pde, pt; if (bo == NULL) @@ -638,7 +638,7 @@ static int amdgpu_vm_update_ptes(struct amdgpu_device *adev, /* walk over the address space and update the page tables */ for (addr = start; addr < end; ) { uint64_t pt_idx = addr >> amdgpu_vm_block_size; - struct amdgpu_bo *pt = vm->page_tables[pt_idx].bo; + struct amdgpu_bo *pt = vm->page_tables[pt_idx].entry.robj; unsigned nptes; uint64_t pte; int r; @@ -1010,13 +1010,13 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, return -EINVAL; /* make sure object fit at this offset */ - eaddr = saddr + size; + eaddr = saddr + size - 1; if ((saddr >= eaddr) || (offset + size > amdgpu_bo_size(bo_va->bo))) return -EINVAL; last_pfn = eaddr / AMDGPU_GPU_PAGE_SIZE; - if (last_pfn > adev->vm_manager.max_pfn) { - dev_err(adev->dev, "va above limit (0x%08X > 0x%08X)\n", + if (last_pfn >= adev->vm_manager.max_pfn) { + dev_err(adev->dev, "va above limit (0x%08X >= 0x%08X)\n", last_pfn, adev->vm_manager.max_pfn); return -EINVAL; } @@ -1025,7 +1025,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, eaddr /= AMDGPU_GPU_PAGE_SIZE; spin_lock(&vm->it_lock); - it = interval_tree_iter_first(&vm->va, saddr, eaddr - 1); + it = interval_tree_iter_first(&vm->va, saddr, eaddr); spin_unlock(&vm->it_lock); if (it) { struct amdgpu_bo_va_mapping *tmp; @@ -1046,7 +1046,7 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, INIT_LIST_HEAD(&mapping->list); mapping->it.start = saddr; - mapping->it.last = eaddr - 1; + mapping->it.last = eaddr; mapping->offset = offset; mapping->flags = flags; @@ -1070,9 +1070,11 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, /* walk over the address space and allocate the page tables */ for (pt_idx = saddr; pt_idx <= eaddr; ++pt_idx) { struct reservation_object *resv = vm->page_directory->tbo.resv; + struct amdgpu_bo_list_entry *entry; struct amdgpu_bo *pt; - if (vm->page_tables[pt_idx].bo) + entry = &vm->page_tables[pt_idx].entry; + if (entry->robj) continue; r = amdgpu_bo_create(adev, AMDGPU_VM_PTE_COUNT * 8, @@ -1094,8 +1096,13 @@ int amdgpu_vm_bo_map(struct amdgpu_device *adev, goto error_free; } + entry->robj = pt; + entry->prefered_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->allowed_domains = AMDGPU_GEM_DOMAIN_VRAM; + entry->priority = 0; + entry->tv.bo = &entry->robj->tbo; + entry->tv.shared = true; vm->page_tables[pt_idx].addr = 0; - vm->page_tables[pt_idx].bo = pt; } return 0; @@ -1326,7 +1333,7 @@ void amdgpu_vm_fini(struct amdgpu_device *adev, struct amdgpu_vm *vm) } for (i = 0; i < amdgpu_vm_num_pdes(adev); i++) - amdgpu_bo_unref(&vm->page_tables[i].bo); + amdgpu_bo_unref(&vm->page_tables[i].entry.robj); kfree(vm->page_tables); amdgpu_bo_unref(&vm->page_directory); diff --git a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c index 92b6acadfc52..21aacc1f45c1 100644 --- a/drivers/gpu/drm/amd/amdgpu/atombios_dp.c +++ b/drivers/gpu/drm/amd/amdgpu/atombios_dp.c @@ -243,7 +243,7 @@ static void amdgpu_atombios_dp_get_adjust_train(const u8 link_status[DP_LINK_STA /* convert bits per color to bits per pixel */ /* get bpc from the EDID */ -static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc) +static unsigned amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc) { if (bpc == 0) return 24; @@ -251,64 +251,32 @@ static int amdgpu_atombios_dp_convert_bpc_to_bpp(int bpc) return bpc * 3; } -/* get the max pix clock supported by the link rate and lane num */ -static int amdgpu_atombios_dp_get_max_dp_pix_clock(int link_rate, - int lane_num, - int bpp) -{ - return (link_rate * lane_num * 8) / bpp; -} - /***** amdgpu specific DP functions *****/ -/* First get the min lane# when low rate is used according to pixel clock - * (prefer low rate), second check max lane# supported by DP panel, - * if the max lane# < low rate lane# then use max lane# instead. - */ -static int amdgpu_atombios_dp_get_dp_lane_number(struct drm_connector *connector, +static int amdgpu_atombios_dp_get_dp_link_config(struct drm_connector *connector, const u8 dpcd[DP_DPCD_SIZE], - int pix_clock) -{ - int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector)); - int max_link_rate = drm_dp_max_link_rate(dpcd); - int max_lane_num = drm_dp_max_lane_count(dpcd); - int lane_num; - int max_dp_pix_clock; - - for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { - max_dp_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); - if (pix_clock <= max_dp_pix_clock) - break; - } - - return lane_num; -} - -static int amdgpu_atombios_dp_get_dp_link_clock(struct drm_connector *connector, - const u8 dpcd[DP_DPCD_SIZE], - int pix_clock) + unsigned pix_clock, + unsigned *dp_lanes, unsigned *dp_rate) { - int bpp = amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector)); - int lane_num, max_pix_clock; - - if (amdgpu_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_NUTMEG) - return 270000; - - lane_num = amdgpu_atombios_dp_get_dp_lane_number(connector, dpcd, pix_clock); - max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(162000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 162000; - max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(270000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 270000; - if (amdgpu_connector_is_dp12_capable(connector)) { - max_pix_clock = amdgpu_atombios_dp_get_max_dp_pix_clock(540000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 540000; + unsigned bpp = + amdgpu_atombios_dp_convert_bpc_to_bpp(amdgpu_connector_get_monitor_bpc(connector)); + static const unsigned link_rates[3] = { 162000, 270000, 540000 }; + unsigned max_link_rate = drm_dp_max_link_rate(dpcd); + unsigned max_lane_num = drm_dp_max_lane_count(dpcd); + unsigned lane_num, i, max_pix_clock; + + for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) { + for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) { + max_pix_clock = (lane_num * link_rates[i] * 8) / bpp; + if (max_pix_clock >= pix_clock) { + *dp_lanes = lane_num; + *dp_rate = link_rates[i]; + return 0; + } + } } - return drm_dp_max_link_rate(dpcd); + return -EINVAL; } static u8 amdgpu_atombios_dp_encoder_service(struct amdgpu_device *adev, @@ -422,6 +390,7 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector, { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_connector_atom_dig *dig_connector; + int ret; if (!amdgpu_connector->con_priv) return; @@ -429,10 +398,14 @@ void amdgpu_atombios_dp_set_link_config(struct drm_connector *connector, if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { - dig_connector->dp_clock = - amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); - dig_connector->dp_lane_count = - amdgpu_atombios_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); + ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd, + mode->clock, + &dig_connector->dp_lane_count, + &dig_connector->dp_clock); + if (ret) { + dig_connector->dp_clock = 0; + dig_connector->dp_lane_count = 0; + } } } @@ -441,14 +414,17 @@ int amdgpu_atombios_dp_mode_valid_helper(struct drm_connector *connector, { struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector); struct amdgpu_connector_atom_dig *dig_connector; - int dp_clock; + unsigned dp_lanes, dp_clock; + int ret; if (!amdgpu_connector->con_priv) return MODE_CLOCK_HIGH; dig_connector = amdgpu_connector->con_priv; - dp_clock = - amdgpu_atombios_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + ret = amdgpu_atombios_dp_get_dp_link_config(connector, dig_connector->dpcd, + mode->clock, &dp_lanes, &dp_clock); + if (ret) + return MODE_CLOCK_HIGH; if ((dp_clock == 540000) && (!amdgpu_connector_is_dp12_capable(connector))) diff --git a/drivers/gpu/drm/amd/amdgpu/cik.c b/drivers/gpu/drm/amd/amdgpu/cik.c index 484710cfdf82..fd9c9588ef46 100644 --- a/drivers/gpu/drm/amd/amdgpu/cik.c +++ b/drivers/gpu/drm/amd/amdgpu/cik.c @@ -32,6 +32,7 @@ #include "amdgpu_vce.h" #include "cikd.h" #include "atom.h" +#include "amd_pcie.h" #include "cik.h" #include "gmc_v7_0.h" @@ -65,6 +66,7 @@ #include "oss/oss_2_0_sh_mask.h" #include "amdgpu_amdkfd.h" +#include "amdgpu_powerplay.h" /* * Indirect registers accessor @@ -929,6 +931,37 @@ static bool cik_read_disabled_bios(struct amdgpu_device *adev) return r; } +static bool cik_read_bios_from_rom(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes) +{ + u32 *dw_ptr; + unsigned long flags; + u32 i, length_dw; + + if (bios == NULL) + return false; + if (length_bytes == 0) + return false; + /* APU vbios image is part of sbios image */ + if (adev->flags & AMD_IS_APU) + return false; + + dw_ptr = (u32 *)bios; + length_dw = ALIGN(length_bytes, 4) / 4; + /* take the smc lock since we are using the smc index */ + spin_lock_irqsave(&adev->smc_idx_lock, flags); + /* set rom index to 0 */ + WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); + WREG32(mmSMC_IND_DATA_0, 0); + /* set index to data for continous read */ + WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); + for (i = 0; i < length_dw; i++) + dw_ptr[i] = RREG32(mmSMC_IND_DATA_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return true; +} + static struct amdgpu_allowed_register_entry cik_allowed_read_registers[] = { {mmGRBM_STATUS, false}, {mmGB_ADDR_CONFIG, false}, @@ -1563,8 +1596,8 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) { struct pci_dev *root = adev->pdev->bus->self; int bridge_pos, gpu_pos; - u32 speed_cntl, mask, current_data_rate; - int ret, i; + u32 speed_cntl, current_data_rate; + int i; u16 tmp16; if (pci_is_root_bus(adev->pdev->bus)) @@ -1576,23 +1609,20 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) if (adev->flags & AMD_IS_APU) return; - ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) return; speed_cntl = RREG32_PCIE(ixPCIE_LC_SPEED_CNTL); current_data_rate = (speed_cntl & PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE_MASK) >> PCIE_LC_SPEED_CNTL__LC_CURRENT_DATA_RATE__SHIFT; - if (mask & DRM_PCIE_SPEED_80) { + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { if (current_data_rate == 2) { DRM_INFO("PCIE gen 3 link speeds already enabled\n"); return; } DRM_INFO("enabling PCIE gen 3 link speeds, disable with amdgpu.pcie_gen2=0\n"); - } else if (mask & DRM_PCIE_SPEED_50) { + } else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) { if (current_data_rate == 1) { DRM_INFO("PCIE gen 2 link speeds already enabled\n"); return; @@ -1608,7 +1638,7 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) if (!gpu_pos) return; - if (mask & DRM_PCIE_SPEED_80) { + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) { /* re-try equalization if gen3 is not already enabled */ if (current_data_rate != 2) { u16 bridge_cfg, gpu_cfg; @@ -1703,9 +1733,9 @@ static void cik_pcie_gen3_enable(struct amdgpu_device *adev) pci_read_config_word(adev->pdev, gpu_pos + PCI_EXP_LNKCTL2, &tmp16); tmp16 &= ~0xf; - if (mask & DRM_PCIE_SPEED_80) + if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) tmp16 |= 3; /* gen3 */ - else if (mask & DRM_PCIE_SPEED_50) + else if (adev->pm.pcie_gen_mask & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) tmp16 |= 2; /* gen2 */ else tmp16 |= 1; /* gen1 */ @@ -1922,7 +1952,7 @@ static const struct amdgpu_ip_block_version bonaire_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &ci_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -1990,7 +2020,7 @@ static const struct amdgpu_ip_block_version hawaii_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &ci_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2058,7 +2088,7 @@ static const struct amdgpu_ip_block_version kabini_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2126,7 +2156,7 @@ static const struct amdgpu_ip_block_version mullins_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2194,7 +2224,7 @@ static const struct amdgpu_ip_block_version kaveri_ip_blocks[] = .major = 7, .minor = 0, .rev = 0, - .funcs = &kv_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -2267,6 +2297,7 @@ int cik_set_ip_blocks(struct amdgpu_device *adev) static const struct amdgpu_asic_funcs cik_asic_funcs = { .read_disabled_bios = &cik_read_disabled_bios, + .read_bios_from_rom = &cik_read_bios_from_rom, .read_register = &cik_read_register, .reset = &cik_asic_reset, .set_vga_state = &cik_vga_set_state, @@ -2417,6 +2448,8 @@ static int cik_common_early_init(void *handle) return -EINVAL; } + amdgpu_get_pcie_info(adev); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c index 8f9845d9a986..4b0e45a27129 100644 --- a/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/fiji_dpm.c @@ -24,7 +24,7 @@ #include <linux/firmware.h> #include "drmP.h" #include "amdgpu.h" -#include "fiji_smumgr.h" +#include "fiji_smum.h" MODULE_FIRMWARE("amdgpu/fiji_smc.bin"); diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h deleted file mode 100644 index 3c4824082990..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/fiji_ppsmc.h +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2014 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. - * - */ - -#ifndef FIJI_PP_SMC_H -#define FIJI_PP_SMC_H - -#pragma pack(push, 1) - -#define PPSMC_SWSTATE_FLAG_DC 0x01 -#define PPSMC_SWSTATE_FLAG_UVD 0x02 -#define PPSMC_SWSTATE_FLAG_VCE 0x04 - -#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff - -#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -#define PPSMC_SYSTEMFLAG_GDDR5 0x04 - -#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 - -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 - -#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 -#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 -#define PPSMC_DPM2FLAGS_OCP 0x04 - -#define PPSMC_DISPLAY_WATERMARK_LOW 0 -#define PPSMC_DISPLAY_WATERMARK_HIGH 1 - -#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -#define PPSMC_STATEFLAG_POWERBOOST 0x02 -#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 -#define PPSMC_STATEFLAG_POWERSHIFT 0x08 -#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 -#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 - -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -//Gemini Modes -#define PPSMC_GeminiModeNone 0 //Single GPU board -#define PPSMC_GeminiModeMaster 1 //Master GPU on a Gemini board -#define PPSMC_GeminiModeSlave 2 //Slave GPU on a Gemini board - -#define PPSMC_Result_OK ((uint16_t)0x01) -#define PPSMC_Result_NoMore ((uint16_t)0x02) -#define PPSMC_Result_NotNow ((uint16_t)0x03) -#define PPSMC_Result_Failed ((uint16_t)0xFF) -#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) -#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) - -typedef uint16_t PPSMC_Result; - -#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) - -#define PPSMC_MSG_Halt ((uint16_t)0x10) -#define PPSMC_MSG_Resume ((uint16_t)0x11) -#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) -#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) -#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) -#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) -#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) -#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) -#define PPSMC_MSG_LevelUp ((uint16_t)0x18) -#define PPSMC_MSG_LevelDown ((uint16_t)0x19) -#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) -#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) -#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) -#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) -#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) -#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) -#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) -#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) -#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) -#define PPSMC_MSG_EnableCac ((uint16_t)0x53) -#define PPSMC_MSG_DisableCac ((uint16_t)0x54) -#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) -#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) -#define PPSMC_CACHistoryStart ((uint16_t)0x57) -#define PPSMC_CACHistoryStop ((uint16_t)0x58) -#define PPSMC_TDPClampingActive ((uint16_t)0x59) -#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) -#define PPSMC_StartFanControl ((uint16_t)0x5B) -#define PPSMC_StopFanControl ((uint16_t)0x5C) -#define PPSMC_NoDisplay ((uint16_t)0x5D) -#define PPSMC_HasDisplay ((uint16_t)0x5E) -#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) -#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) -#define PPSMC_MSG_EnableULV ((uint16_t)0x62) -#define PPSMC_MSG_DisableULV ((uint16_t)0x63) -#define PPSMC_MSG_EnterULV ((uint16_t)0x64) -#define PPSMC_MSG_ExitULV ((uint16_t)0x65) -#define PPSMC_PowerShiftActive ((uint16_t)0x6A) -#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) -#define PPSMC_OCPActive ((uint16_t)0x6C) -#define PPSMC_OCPInactive ((uint16_t)0x6D) -#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) -#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) -#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) -#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) -#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) -#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) -#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) -#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) -#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) -#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) -#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) -#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) -#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) -#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) -#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) -#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) -#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) -#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) -#define PPSMC_FlushDataCache ((uint16_t)0x80) -#define PPSMC_FlushInstrCache ((uint16_t)0x81) -#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) -#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) -#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) -#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) -#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) -#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) -#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) -#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) -#define PPSMC_MSG_SmcSpaceWriteDWordInc ((uint16_t)0x8A) -#define PPSMC_MSG_SmcSpaceWriteWordInc ((uint16_t)0x8B) -#define PPSMC_MSG_SmcSpaceWriteByteInc ((uint16_t)0x8C) - -#define PPSMC_MSG_BREAK ((uint16_t)0xF8) - -#define PPSMC_MSG_Test ((uint16_t)0x100) -#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t)0x250) -#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t)0x251) -#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t)0x252) -#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t)0x253) -#define PPSMC_MSG_LoadUcodes ((uint16_t)0x254) - -typedef uint16_t PPSMC_Msg; - -#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 -#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 -#define PPSMC_EVENT_STATUS_DC 0x00000004 -#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smc.c b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c index bda1249eb871..e35340afd3db 100644 --- a/drivers/gpu/drm/amd/amdgpu/fiji_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/fiji_smc.c @@ -25,7 +25,7 @@ #include "drmP.h" #include "amdgpu.h" #include "fiji_ppsmc.h" -#include "fiji_smumgr.h" +#include "fiji_smum.h" #include "smu_ucode_xfer_vi.h" #include "amdgpu_ucode.h" diff --git a/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h b/drivers/gpu/drm/amd/amdgpu/fiji_smum.h index 1cef03deeac3..1cef03deeac3 100644 --- a/drivers/gpu/drm/amd/amdgpu/fiji_smumgr.h +++ b/drivers/gpu/drm/amd/amdgpu/fiji_smum.h diff --git a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c index e1dcab98e249..13235d84e5a6 100644 --- a/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gfx_v8_0.c @@ -66,6 +66,27 @@ #define MACRO_TILE_ASPECT(x) ((x) << GB_MACROTILE_MODE0__MACRO_TILE_ASPECT__SHIFT) #define NUM_BANKS(x) ((x) << GB_MACROTILE_MODE0__NUM_BANKS__SHIFT) +#define RLC_CGTT_MGCG_OVERRIDE__CPF_MASK 0x00000001L +#define RLC_CGTT_MGCG_OVERRIDE__RLC_MASK 0x00000002L +#define RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK 0x00000004L +#define RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK 0x00000008L +#define RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK 0x00000010L +#define RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK 0x00000020L + +/* BPM SERDES CMD */ +#define SET_BPM_SERDES_CMD 1 +#define CLE_BPM_SERDES_CMD 0 + +/* BPM Register Address*/ +enum { + BPM_REG_CGLS_EN = 0, /* Enable/Disable CGLS */ + BPM_REG_CGLS_ON, /* ON/OFF CGLS: shall be controlled by RLC FW */ + BPM_REG_CGCG_OVERRIDE, /* Set/Clear CGCG Override */ + BPM_REG_MGCG_OVERRIDE, /* Set/Clear MGCG Override */ + BPM_REG_FGCG_OVERRIDE, /* Set/Clear FGCG Override */ + BPM_REG_FGCG_MAX +}; + MODULE_FIRMWARE("amdgpu/carrizo_ce.bin"); MODULE_FIRMWARE("amdgpu/carrizo_pfp.bin"); MODULE_FIRMWARE("amdgpu/carrizo_me.bin"); @@ -964,6 +985,322 @@ static int gfx_v8_0_mec_init(struct amdgpu_device *adev) return 0; } +static const u32 vgpr_init_compute_shader[] = +{ + 0x7e000209, 0x7e020208, + 0x7e040207, 0x7e060206, + 0x7e080205, 0x7e0a0204, + 0x7e0c0203, 0x7e0e0202, + 0x7e100201, 0x7e120200, + 0x7e140209, 0x7e160208, + 0x7e180207, 0x7e1a0206, + 0x7e1c0205, 0x7e1e0204, + 0x7e200203, 0x7e220202, + 0x7e240201, 0x7e260200, + 0x7e280209, 0x7e2a0208, + 0x7e2c0207, 0x7e2e0206, + 0x7e300205, 0x7e320204, + 0x7e340203, 0x7e360202, + 0x7e380201, 0x7e3a0200, + 0x7e3c0209, 0x7e3e0208, + 0x7e400207, 0x7e420206, + 0x7e440205, 0x7e460204, + 0x7e480203, 0x7e4a0202, + 0x7e4c0201, 0x7e4e0200, + 0x7e500209, 0x7e520208, + 0x7e540207, 0x7e560206, + 0x7e580205, 0x7e5a0204, + 0x7e5c0203, 0x7e5e0202, + 0x7e600201, 0x7e620200, + 0x7e640209, 0x7e660208, + 0x7e680207, 0x7e6a0206, + 0x7e6c0205, 0x7e6e0204, + 0x7e700203, 0x7e720202, + 0x7e740201, 0x7e760200, + 0x7e780209, 0x7e7a0208, + 0x7e7c0207, 0x7e7e0206, + 0xbf8a0000, 0xbf810000, +}; + +static const u32 sgpr_init_compute_shader[] = +{ + 0xbe8a0100, 0xbe8c0102, + 0xbe8e0104, 0xbe900106, + 0xbe920108, 0xbe940100, + 0xbe960102, 0xbe980104, + 0xbe9a0106, 0xbe9c0108, + 0xbe9e0100, 0xbea00102, + 0xbea20104, 0xbea40106, + 0xbea60108, 0xbea80100, + 0xbeaa0102, 0xbeac0104, + 0xbeae0106, 0xbeb00108, + 0xbeb20100, 0xbeb40102, + 0xbeb60104, 0xbeb80106, + 0xbeba0108, 0xbebc0100, + 0xbebe0102, 0xbec00104, + 0xbec20106, 0xbec40108, + 0xbec60100, 0xbec80102, + 0xbee60004, 0xbee70005, + 0xbeea0006, 0xbeeb0007, + 0xbee80008, 0xbee90009, + 0xbefc0000, 0xbf8a0000, + 0xbf810000, 0x00000000, +}; + +static const u32 vgpr_init_regs[] = +{ + mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xffffffff, + mmCOMPUTE_RESOURCE_LIMITS, 0, + mmCOMPUTE_NUM_THREAD_X, 256*4, + mmCOMPUTE_NUM_THREAD_Y, 1, + mmCOMPUTE_NUM_THREAD_Z, 1, + mmCOMPUTE_PGM_RSRC2, 20, + mmCOMPUTE_USER_DATA_0, 0xedcedc00, + mmCOMPUTE_USER_DATA_1, 0xedcedc01, + mmCOMPUTE_USER_DATA_2, 0xedcedc02, + mmCOMPUTE_USER_DATA_3, 0xedcedc03, + mmCOMPUTE_USER_DATA_4, 0xedcedc04, + mmCOMPUTE_USER_DATA_5, 0xedcedc05, + mmCOMPUTE_USER_DATA_6, 0xedcedc06, + mmCOMPUTE_USER_DATA_7, 0xedcedc07, + mmCOMPUTE_USER_DATA_8, 0xedcedc08, + mmCOMPUTE_USER_DATA_9, 0xedcedc09, +}; + +static const u32 sgpr1_init_regs[] = +{ + mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0x0f, + mmCOMPUTE_RESOURCE_LIMITS, 0x1000000, + mmCOMPUTE_NUM_THREAD_X, 256*5, + mmCOMPUTE_NUM_THREAD_Y, 1, + mmCOMPUTE_NUM_THREAD_Z, 1, + mmCOMPUTE_PGM_RSRC2, 20, + mmCOMPUTE_USER_DATA_0, 0xedcedc00, + mmCOMPUTE_USER_DATA_1, 0xedcedc01, + mmCOMPUTE_USER_DATA_2, 0xedcedc02, + mmCOMPUTE_USER_DATA_3, 0xedcedc03, + mmCOMPUTE_USER_DATA_4, 0xedcedc04, + mmCOMPUTE_USER_DATA_5, 0xedcedc05, + mmCOMPUTE_USER_DATA_6, 0xedcedc06, + mmCOMPUTE_USER_DATA_7, 0xedcedc07, + mmCOMPUTE_USER_DATA_8, 0xedcedc08, + mmCOMPUTE_USER_DATA_9, 0xedcedc09, +}; + +static const u32 sgpr2_init_regs[] = +{ + mmCOMPUTE_STATIC_THREAD_MGMT_SE0, 0xf0, + mmCOMPUTE_RESOURCE_LIMITS, 0x1000000, + mmCOMPUTE_NUM_THREAD_X, 256*5, + mmCOMPUTE_NUM_THREAD_Y, 1, + mmCOMPUTE_NUM_THREAD_Z, 1, + mmCOMPUTE_PGM_RSRC2, 20, + mmCOMPUTE_USER_DATA_0, 0xedcedc00, + mmCOMPUTE_USER_DATA_1, 0xedcedc01, + mmCOMPUTE_USER_DATA_2, 0xedcedc02, + mmCOMPUTE_USER_DATA_3, 0xedcedc03, + mmCOMPUTE_USER_DATA_4, 0xedcedc04, + mmCOMPUTE_USER_DATA_5, 0xedcedc05, + mmCOMPUTE_USER_DATA_6, 0xedcedc06, + mmCOMPUTE_USER_DATA_7, 0xedcedc07, + mmCOMPUTE_USER_DATA_8, 0xedcedc08, + mmCOMPUTE_USER_DATA_9, 0xedcedc09, +}; + +static const u32 sec_ded_counter_registers[] = +{ + mmCPC_EDC_ATC_CNT, + mmCPC_EDC_SCRATCH_CNT, + mmCPC_EDC_UCODE_CNT, + mmCPF_EDC_ATC_CNT, + mmCPF_EDC_ROQ_CNT, + mmCPF_EDC_TAG_CNT, + mmCPG_EDC_ATC_CNT, + mmCPG_EDC_DMA_CNT, + mmCPG_EDC_TAG_CNT, + mmDC_EDC_CSINVOC_CNT, + mmDC_EDC_RESTORE_CNT, + mmDC_EDC_STATE_CNT, + mmGDS_EDC_CNT, + mmGDS_EDC_GRBM_CNT, + mmGDS_EDC_OA_DED, + mmSPI_EDC_CNT, + mmSQC_ATC_EDC_GATCL1_CNT, + mmSQC_EDC_CNT, + mmSQ_EDC_DED_CNT, + mmSQ_EDC_INFO, + mmSQ_EDC_SEC_CNT, + mmTCC_EDC_CNT, + mmTCP_ATC_EDC_GATCL1_CNT, + mmTCP_EDC_CNT, + mmTD_EDC_CNT +}; + +static int gfx_v8_0_do_edc_gpr_workarounds(struct amdgpu_device *adev) +{ + struct amdgpu_ring *ring = &adev->gfx.compute_ring[0]; + struct amdgpu_ib ib; + struct fence *f = NULL; + int r, i; + u32 tmp; + unsigned total_size, vgpr_offset, sgpr_offset; + u64 gpu_addr; + + /* only supported on CZ */ + if (adev->asic_type != CHIP_CARRIZO) + return 0; + + /* bail if the compute ring is not ready */ + if (!ring->ready) + return 0; + + tmp = RREG32(mmGB_EDC_MODE); + WREG32(mmGB_EDC_MODE, 0); + + total_size = + (((ARRAY_SIZE(vgpr_init_regs) / 2) * 3) + 4 + 5 + 2) * 4; + total_size += + (((ARRAY_SIZE(sgpr1_init_regs) / 2) * 3) + 4 + 5 + 2) * 4; + total_size += + (((ARRAY_SIZE(sgpr2_init_regs) / 2) * 3) + 4 + 5 + 2) * 4; + total_size = ALIGN(total_size, 256); + vgpr_offset = total_size; + total_size += ALIGN(sizeof(vgpr_init_compute_shader), 256); + sgpr_offset = total_size; + total_size += sizeof(sgpr_init_compute_shader); + + /* allocate an indirect buffer to put the commands in */ + memset(&ib, 0, sizeof(ib)); + r = amdgpu_ib_get(ring, NULL, total_size, &ib); + if (r) { + DRM_ERROR("amdgpu: failed to get ib (%d).\n", r); + return r; + } + + /* load the compute shaders */ + for (i = 0; i < ARRAY_SIZE(vgpr_init_compute_shader); i++) + ib.ptr[i + (vgpr_offset / 4)] = vgpr_init_compute_shader[i]; + + for (i = 0; i < ARRAY_SIZE(sgpr_init_compute_shader); i++) + ib.ptr[i + (sgpr_offset / 4)] = sgpr_init_compute_shader[i]; + + /* init the ib length to 0 */ + ib.length_dw = 0; + + /* VGPR */ + /* write the register state for the compute dispatch */ + for (i = 0; i < ARRAY_SIZE(vgpr_init_regs); i += 2) { + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1); + ib.ptr[ib.length_dw++] = vgpr_init_regs[i] - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = vgpr_init_regs[i + 1]; + } + /* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */ + gpu_addr = (ib.gpu_addr + (u64)vgpr_offset) >> 8; + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2); + ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr); + ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr); + + /* write dispatch packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3); + ib.ptr[ib.length_dw++] = 8; /* x */ + ib.ptr[ib.length_dw++] = 1; /* y */ + ib.ptr[ib.length_dw++] = 1; /* z */ + ib.ptr[ib.length_dw++] = + REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1); + + /* write CS partial flush packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0); + ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4); + + /* SGPR1 */ + /* write the register state for the compute dispatch */ + for (i = 0; i < ARRAY_SIZE(sgpr1_init_regs); i += 2) { + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1); + ib.ptr[ib.length_dw++] = sgpr1_init_regs[i] - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = sgpr1_init_regs[i + 1]; + } + /* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */ + gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8; + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2); + ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr); + ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr); + + /* write dispatch packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3); + ib.ptr[ib.length_dw++] = 8; /* x */ + ib.ptr[ib.length_dw++] = 1; /* y */ + ib.ptr[ib.length_dw++] = 1; /* z */ + ib.ptr[ib.length_dw++] = + REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1); + + /* write CS partial flush packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0); + ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4); + + /* SGPR2 */ + /* write the register state for the compute dispatch */ + for (i = 0; i < ARRAY_SIZE(sgpr2_init_regs); i += 2) { + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 1); + ib.ptr[ib.length_dw++] = sgpr2_init_regs[i] - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = sgpr2_init_regs[i + 1]; + } + /* write the shader start address: mmCOMPUTE_PGM_LO, mmCOMPUTE_PGM_HI */ + gpu_addr = (ib.gpu_addr + (u64)sgpr_offset) >> 8; + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_SET_SH_REG, 2); + ib.ptr[ib.length_dw++] = mmCOMPUTE_PGM_LO - PACKET3_SET_SH_REG_START; + ib.ptr[ib.length_dw++] = lower_32_bits(gpu_addr); + ib.ptr[ib.length_dw++] = upper_32_bits(gpu_addr); + + /* write dispatch packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_DISPATCH_DIRECT, 3); + ib.ptr[ib.length_dw++] = 8; /* x */ + ib.ptr[ib.length_dw++] = 1; /* y */ + ib.ptr[ib.length_dw++] = 1; /* z */ + ib.ptr[ib.length_dw++] = + REG_SET_FIELD(0, COMPUTE_DISPATCH_INITIATOR, COMPUTE_SHADER_EN, 1); + + /* write CS partial flush packet */ + ib.ptr[ib.length_dw++] = PACKET3(PACKET3_EVENT_WRITE, 0); + ib.ptr[ib.length_dw++] = EVENT_TYPE(7) | EVENT_INDEX(4); + + /* shedule the ib on the ring */ + r = amdgpu_sched_ib_submit_kernel_helper(adev, ring, &ib, 1, NULL, + AMDGPU_FENCE_OWNER_UNDEFINED, + &f); + if (r) { + DRM_ERROR("amdgpu: ib submit failed (%d).\n", r); + goto fail; + } + + /* wait for the GPU to finish processing the IB */ + r = fence_wait(f, false); + if (r) { + DRM_ERROR("amdgpu: fence wait failed (%d).\n", r); + goto fail; + } + + tmp = REG_SET_FIELD(tmp, GB_EDC_MODE, DED_MODE, 2); + tmp = REG_SET_FIELD(tmp, GB_EDC_MODE, PROP_FED, 1); + WREG32(mmGB_EDC_MODE, tmp); + + tmp = RREG32(mmCC_GC_EDC_CONFIG); + tmp = REG_SET_FIELD(tmp, CC_GC_EDC_CONFIG, DIS_EDC, 0) | 1; + WREG32(mmCC_GC_EDC_CONFIG, tmp); + + + /* read back registers to clear the counters */ + for (i = 0; i < ARRAY_SIZE(sec_ded_counter_registers); i++) + RREG32(sec_ded_counter_registers[i]); + +fail: + fence_put(f); + amdgpu_ib_free(adev, &ib); + + return r; +} + static void gfx_v8_0_gpu_early_init(struct amdgpu_device *adev) { u32 gb_addr_config; @@ -1323,1418 +1660,923 @@ static int gfx_v8_0_sw_fini(void *handle) static void gfx_v8_0_tiling_mode_table_init(struct amdgpu_device *adev) { - const u32 num_tile_mode_states = 32; - const u32 num_secondary_tile_mode_states = 16; - u32 reg_offset, gb_tile_moden, split_equal_to_row_size; + uint32_t *modearray, *mod2array; + const u32 num_tile_mode_states = ARRAY_SIZE(adev->gfx.config.tile_mode_array); + const u32 num_secondary_tile_mode_states = ARRAY_SIZE(adev->gfx.config.macrotile_mode_array); + u32 reg_offset; - switch (adev->gfx.config.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; - } + modearray = adev->gfx.config.tile_mode_array; + mod2array = adev->gfx.config.macrotile_mode_array; + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + modearray[reg_offset] = 0; + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + mod2array[reg_offset] = 0; switch (adev->asic_type) { case CHIP_TOPAZ: - for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 1: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 2: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 3: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 4: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 5: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 6: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 8: - gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | - PIPE_CONFIG(ADDR_SURF_P2)); - break; - case 9: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 10: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 11: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 13: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 14: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 15: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 16: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 18: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 19: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 20: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 21: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 22: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 24: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 25: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 26: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 27: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 28: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 29: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 7: - case 12: - case 17: - case 23: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden); - } - for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 1: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 2: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 3: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 4: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 5: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 6: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 8: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 9: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 10: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 11: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 12: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 13: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 14: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 7: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden); - } + modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + PIPE_CONFIG(ADDR_SURF_P2)); + modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + + mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 && + reg_offset != 23) + WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]); + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + if (reg_offset != 7) + WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]); + + break; case CHIP_FIJI: - for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 1: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 2: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 3: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 4: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 5: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 6: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 7: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 8: - gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16)); - break; - case 9: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 10: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 11: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 12: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 13: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 14: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 15: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 16: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 17: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 18: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 19: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 20: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 21: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 22: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 23: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 24: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 25: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 26: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 27: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 28: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 29: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 30: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - default: - gb_tile_moden = 0; - break; - } - adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden); - } - for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 1: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 2: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 3: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 4: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 5: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 6: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 8: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 9: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 10: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 11: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 12: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 13: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 14: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_4_BANK)); - break; - case 7: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - } - adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden); - } + modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16)); + modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P16_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + + mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_4_BANK)); + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]); + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + if (reg_offset != 7) + WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]); + break; case CHIP_TONGA: - for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 1: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 2: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 3: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 4: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 5: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 6: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 7: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 8: - gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16)); - break; - case 9: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 10: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 11: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 12: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 13: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 14: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 15: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 16: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 17: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 18: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 19: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 20: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 21: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 22: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 23: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 24: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 25: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 26: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 27: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 28: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 29: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 30: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P4_16x16) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden); - } - for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 1: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 2: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 3: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 4: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 5: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 6: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 8: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 9: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 10: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 11: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 12: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 13: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_4_BANK)); - break; - case 14: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | - NUM_BANKS(ADDR_SURF_4_BANK)); - break; - case 7: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden); - } + modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[7] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16)); + modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[12] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[17] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[23] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P8_32x32_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[30] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P4_16x16) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + + mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_4_BANK)); + mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_1) | + NUM_BANKS(ADDR_SURF_4_BANK)); + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]); + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + if (reg_offset != 7) + WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]); + break; case CHIP_STONEY: - for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 1: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 2: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 3: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 4: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 5: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 6: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 8: - gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | - PIPE_CONFIG(ADDR_SURF_P2)); - break; - case 9: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 10: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 11: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 13: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 14: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 15: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 16: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 18: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 19: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 20: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 21: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 22: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 24: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 25: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 26: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 27: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 28: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 29: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 7: - case 12: - case 17: - case 23: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden); - } - for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 1: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 2: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 3: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 4: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 5: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 6: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 8: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 9: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 10: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 11: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 12: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 13: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 14: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 7: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden); - } + modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + PIPE_CONFIG(ADDR_SURF_P2)); + modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + + mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 && + reg_offset != 23) + WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]); + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + if (reg_offset != 7) + WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]); + break; - case CHIP_CARRIZO: default: - for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 1: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 2: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 3: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 4: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 5: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 6: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); - break; - case 8: - gb_tile_moden = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | - PIPE_CONFIG(ADDR_SURF_P2)); - break; - case 9: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 10: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 11: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 13: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 14: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 15: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 16: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 18: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 19: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 20: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 21: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 22: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 24: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 25: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 26: - gb_tile_moden = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); - break; - case 27: - gb_tile_moden = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 28: - gb_tile_moden = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); - break; - case 29: - gb_tile_moden = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | - PIPE_CONFIG(ADDR_SURF_P2) | - MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | - SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); - break; - case 7: - case 12: - case 17: - case 23: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.tile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_TILE_MODE0 + reg_offset, gb_tile_moden); - } - for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) { - switch (reg_offset) { - case 0: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 1: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 2: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 3: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 4: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 5: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 6: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 8: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 9: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 10: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 11: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 12: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 13: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | - NUM_BANKS(ADDR_SURF_16_BANK)); - break; - case 14: - gb_tile_moden = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | - BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | - MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | - NUM_BANKS(ADDR_SURF_8_BANK)); - break; - case 7: - /* unused idx */ - continue; - default: - gb_tile_moden = 0; - break; - }; - adev->gfx.config.macrotile_mode_array[reg_offset] = gb_tile_moden; - WREG32(mmGB_MACROTILE_MODE0 + reg_offset, gb_tile_moden); - } + dev_warn(adev->dev, + "Unknown chip type (%d) in function gfx_v8_0_tiling_mode_table_init() falling through to CHIP_CARRIZO\n", + adev->asic_type); + + case CHIP_CARRIZO: + modearray[0] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_64B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[1] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_128B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[2] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_256B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[3] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_512B) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[4] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[5] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[6] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + TILE_SPLIT(ADDR_SURF_TILE_SPLIT_2KB) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DEPTH_MICRO_TILING)); + modearray[8] = (ARRAY_MODE(ARRAY_LINEAR_ALIGNED) | + PIPE_CONFIG(ADDR_SURF_P2)); + modearray[9] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[10] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[11] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_DISPLAY_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[13] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[14] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[15] = (ARRAY_MODE(ARRAY_3D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[16] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + modearray[18] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[19] = (ARRAY_MODE(ARRAY_1D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[20] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[21] = (ARRAY_MODE(ARRAY_3D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[22] = (ARRAY_MODE(ARRAY_PRT_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[24] = (ARRAY_MODE(ARRAY_2D_TILED_THICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THIN_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[25] = (ARRAY_MODE(ARRAY_2D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[26] = (ARRAY_MODE(ARRAY_3D_TILED_XTHICK) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_THICK_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_1)); + modearray[27] = (ARRAY_MODE(ARRAY_1D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[28] = (ARRAY_MODE(ARRAY_2D_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_2)); + modearray[29] = (ARRAY_MODE(ARRAY_PRT_TILED_THIN1) | + PIPE_CONFIG(ADDR_SURF_P2) | + MICRO_TILE_MODE_NEW(ADDR_SURF_ROTATED_MICRO_TILING) | + SAMPLE_SPLIT(ADDR_SURF_SAMPLE_SPLIT_8)); + + mod2array[0] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[1] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[2] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[3] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[4] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[5] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[6] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + mod2array[8] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_8) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[9] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_4) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[10] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_4) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[11] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_2) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[12] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_2) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[13] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_4) | + NUM_BANKS(ADDR_SURF_16_BANK)); + mod2array[14] = (BANK_WIDTH(ADDR_SURF_BANK_WIDTH_1) | + BANK_HEIGHT(ADDR_SURF_BANK_HEIGHT_1) | + MACRO_TILE_ASPECT(ADDR_SURF_MACRO_ASPECT_2) | + NUM_BANKS(ADDR_SURF_8_BANK)); + + for (reg_offset = 0; reg_offset < num_tile_mode_states; reg_offset++) + if (reg_offset != 7 && reg_offset != 12 && reg_offset != 17 && + reg_offset != 23) + WREG32(mmGB_TILE_MODE0 + reg_offset, modearray[reg_offset]); + + for (reg_offset = 0; reg_offset < num_secondary_tile_mode_states; reg_offset++) + if (reg_offset != 7) + WREG32(mmGB_MACROTILE_MODE0 + reg_offset, mod2array[reg_offset]); + + break; } } static u32 gfx_v8_0_create_bitmask(u32 bit_width) { - u32 i, mask = 0; - - for (i = 0; i < bit_width; i++) { - mask <<= 1; - mask |= 1; - } - return mask; + return (u32)((1ULL << bit_width) - 1); } void gfx_v8_0_select_se_sh(struct amdgpu_device *adev, u32 se_num, u32 sh_num) @@ -2809,7 +2651,7 @@ static void gfx_v8_0_setup_rb(struct amdgpu_device *adev, mutex_lock(&adev->grbm_idx_mutex); for (i = 0; i < se_num; i++) { gfx_v8_0_select_se_sh(adev, i, 0xffffffff); - data = 0; + data = RREG32(mmPA_SC_RASTER_CONFIG); for (j = 0; j < sh_per_se; j++) { switch (enabled_rbs & 3) { case 0: @@ -2997,17 +2839,11 @@ static void gfx_v8_0_enable_gui_idle_interrupt(struct amdgpu_device *adev, { u32 tmp = RREG32(mmCP_INT_CNTL_RING0); - if (enable) { - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, 1); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, 1); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, 1); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, 1); - } else { - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, 0); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, 0); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, 0); - tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, 0); - } + tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_BUSY_INT_ENABLE, enable ? 1 : 0); + tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CNTX_EMPTY_INT_ENABLE, enable ? 1 : 0); + tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, CMP_BUSY_INT_ENABLE, enable ? 1 : 0); + tmp = REG_SET_FIELD(tmp, CP_INT_CNTL_RING0, GFX_IDLE_INT_ENABLE, enable ? 1 : 0); + WREG32(mmCP_INT_CNTL_RING0, tmp); } @@ -3087,16 +2923,18 @@ static int gfx_v8_0_rlc_resume(struct amdgpu_device *adev) gfx_v8_0_rlc_reset(adev); - if (!adev->firmware.smu_load) { - /* legacy rlc firmware loading */ - r = gfx_v8_0_rlc_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_RLC_G); - if (r) - return -EINVAL; + if (!adev->pp_enabled) { + if (!adev->firmware.smu_load) { + /* legacy rlc firmware loading */ + r = gfx_v8_0_rlc_load_microcode(adev); + if (r) + return r; + } else { + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_RLC_G); + if (r) + return -EINVAL; + } } gfx_v8_0_rlc_start(adev); @@ -3941,6 +3779,11 @@ static int gfx_v8_0_cp_compute_resume(struct amdgpu_device *adev) tmp = REG_SET_FIELD(tmp, CP_HQD_PERSISTENT_STATE, PRELOAD_SIZE, 0x53); WREG32(mmCP_HQD_PERSISTENT_STATE, tmp); mqd->cp_hqd_persistent_state = tmp; + if (adev->asic_type == CHIP_STONEY) { + tmp = RREG32(mmCP_ME1_PIPE3_INT_CNTL); + tmp = REG_SET_FIELD(tmp, CP_ME1_PIPE3_INT_CNTL, GENERIC2_INT_ENABLE, 1); + WREG32(mmCP_ME1_PIPE3_INT_CNTL, tmp); + } /* activate the queue */ mqd->cp_hqd_active = 1; @@ -3982,35 +3825,37 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev) if (!(adev->flags & AMD_IS_APU)) gfx_v8_0_enable_gui_idle_interrupt(adev, false); - if (!adev->firmware.smu_load) { - /* legacy firmware loading */ - r = gfx_v8_0_cp_gfx_load_microcode(adev); - if (r) - return r; - - r = gfx_v8_0_cp_compute_load_microcode(adev); - if (r) - return r; - } else { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_CE); - if (r) - return -EINVAL; - - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_PFP); - if (r) - return -EINVAL; - - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_ME); - if (r) - return -EINVAL; + if (!adev->pp_enabled) { + if (!adev->firmware.smu_load) { + /* legacy firmware loading */ + r = gfx_v8_0_cp_gfx_load_microcode(adev); + if (r) + return r; - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - AMDGPU_UCODE_ID_CP_MEC1); - if (r) - return -EINVAL; + r = gfx_v8_0_cp_compute_load_microcode(adev); + if (r) + return r; + } else { + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_CP_CE); + if (r) + return -EINVAL; + + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_CP_PFP); + if (r) + return -EINVAL; + + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_CP_ME); + if (r) + return -EINVAL; + + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + AMDGPU_UCODE_ID_CP_MEC1); + if (r) + return -EINVAL; + } } r = gfx_v8_0_cp_gfx_resume(adev); @@ -4458,15 +4303,261 @@ static int gfx_v8_0_early_init(void *handle) return 0; } +static int gfx_v8_0_late_init(void *handle) +{ + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + int r; + + /* requires IBs so do in late init after IB pool is initialized */ + r = gfx_v8_0_do_edc_gpr_workarounds(adev); + if (r) + return r; + + return 0; +} + static int gfx_v8_0_set_powergating_state(void *handle, enum amd_powergating_state state) { return 0; } +static void fiji_send_serdes_cmd(struct amdgpu_device *adev, + uint32_t reg_addr, uint32_t cmd) +{ + uint32_t data; + + gfx_v8_0_select_se_sh(adev, 0xffffffff, 0xffffffff); + + WREG32(mmRLC_SERDES_WR_CU_MASTER_MASK, 0xffffffff); + WREG32(mmRLC_SERDES_WR_NONCU_MASTER_MASK, 0xffffffff); + + data = RREG32(mmRLC_SERDES_WR_CTRL); + data &= ~(RLC_SERDES_WR_CTRL__WRITE_COMMAND_MASK | + RLC_SERDES_WR_CTRL__READ_COMMAND_MASK | + RLC_SERDES_WR_CTRL__P1_SELECT_MASK | + RLC_SERDES_WR_CTRL__P2_SELECT_MASK | + RLC_SERDES_WR_CTRL__RDDATA_RESET_MASK | + RLC_SERDES_WR_CTRL__POWER_DOWN_MASK | + RLC_SERDES_WR_CTRL__POWER_UP_MASK | + RLC_SERDES_WR_CTRL__SHORT_FORMAT_MASK | + RLC_SERDES_WR_CTRL__BPM_DATA_MASK | + RLC_SERDES_WR_CTRL__REG_ADDR_MASK | + RLC_SERDES_WR_CTRL__SRBM_OVERRIDE_MASK); + data |= (RLC_SERDES_WR_CTRL__RSVD_BPM_ADDR_MASK | + (cmd << RLC_SERDES_WR_CTRL__BPM_DATA__SHIFT) | + (reg_addr << RLC_SERDES_WR_CTRL__REG_ADDR__SHIFT) | + (0xff << RLC_SERDES_WR_CTRL__BPM_ADDR__SHIFT)); + + WREG32(mmRLC_SERDES_WR_CTRL, data); +} + +static void fiji_update_medium_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + /* It is disabled by HW by default */ + if (enable) { + /* 1 - RLC memory Light sleep */ + temp = data = RREG32(mmRLC_MEM_SLP_CNTL); + data |= RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK; + if (temp != data) + WREG32(mmRLC_MEM_SLP_CNTL, data); + + /* 2 - CP memory Light sleep */ + temp = data = RREG32(mmCP_MEM_SLP_CNTL); + data |= CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK; + if (temp != data) + WREG32(mmCP_MEM_SLP_CNTL, data); + + /* 3 - RLC_CGTT_MGCG_OVERRIDE */ + temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE); + data &= ~(RLC_CGTT_MGCG_OVERRIDE__CPF_MASK | + RLC_CGTT_MGCG_OVERRIDE__RLC_MASK | + RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK | + RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK); + + if (temp != data) + WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data); + + /* 4 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* 5 - clear mgcg override */ + fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, CLE_BPM_SERDES_CMD); + + /* 6 - Enable CGTS(Tree Shade) MGCG /MGLS */ + temp = data = RREG32(mmCGTS_SM_CTRL_REG); + data &= ~(CGTS_SM_CTRL_REG__SM_MODE_MASK); + data |= (0x2 << CGTS_SM_CTRL_REG__SM_MODE__SHIFT); + data |= CGTS_SM_CTRL_REG__SM_MODE_ENABLE_MASK; + data &= ~CGTS_SM_CTRL_REG__OVERRIDE_MASK; + data &= ~CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK; + data |= CGTS_SM_CTRL_REG__ON_MONITOR_ADD_EN_MASK; + data |= (0x96 << CGTS_SM_CTRL_REG__ON_MONITOR_ADD__SHIFT); + if (temp != data) + WREG32(mmCGTS_SM_CTRL_REG, data); + udelay(50); + + /* 7 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + } else { + /* 1 - MGCG_OVERRIDE[0] for CP and MGCG_OVERRIDE[1] for RLC */ + temp = data = RREG32(mmRLC_CGTT_MGCG_OVERRIDE); + data |= (RLC_CGTT_MGCG_OVERRIDE__CPF_MASK | + RLC_CGTT_MGCG_OVERRIDE__RLC_MASK | + RLC_CGTT_MGCG_OVERRIDE__MGCG_MASK | + RLC_CGTT_MGCG_OVERRIDE__GRBM_MASK); + if (temp != data) + WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data); + + /* 2 - disable MGLS in RLC */ + data = RREG32(mmRLC_MEM_SLP_CNTL); + if (data & RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK) { + data &= ~RLC_MEM_SLP_CNTL__RLC_MEM_LS_EN_MASK; + WREG32(mmRLC_MEM_SLP_CNTL, data); + } + + /* 3 - disable MGLS in CP */ + data = RREG32(mmCP_MEM_SLP_CNTL); + if (data & CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK) { + data &= ~CP_MEM_SLP_CNTL__CP_MEM_LS_EN_MASK; + WREG32(mmCP_MEM_SLP_CNTL, data); + } + + /* 4 - Disable CGTS(Tree Shade) MGCG and MGLS */ + temp = data = RREG32(mmCGTS_SM_CTRL_REG); + data |= (CGTS_SM_CTRL_REG__OVERRIDE_MASK | + CGTS_SM_CTRL_REG__LS_OVERRIDE_MASK); + if (temp != data) + WREG32(mmCGTS_SM_CTRL_REG, data); + + /* 5 - wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* 6 - set mgcg override */ + fiji_send_serdes_cmd(adev, BPM_REG_MGCG_OVERRIDE, SET_BPM_SERDES_CMD); + + udelay(50); + + /* 7- wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + } +} + +static void fiji_update_coarse_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, temp1, data, data1; + + temp = data = RREG32(mmRLC_CGCG_CGLS_CTRL); + + if (enable) { + /* 1 enable cntx_empty_int_enable/cntx_busy_int_enable/ + * Cmp_busy/GFX_Idle interrupts + */ + gfx_v8_0_enable_gui_idle_interrupt(adev, true); + + temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE); + data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK; + if (temp1 != data1) + WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1); + + /* 2 wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* 3 - clear cgcg override */ + fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, CLE_BPM_SERDES_CMD); + + /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* 4 - write cmd to set CGLS */ + fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, SET_BPM_SERDES_CMD); + + /* 5 - enable cgcg */ + data |= RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK; + + /* enable cgls*/ + data |= RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK; + + temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE); + data1 &= ~RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK; + + if (temp1 != data1) + WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1); + + if (temp != data) + WREG32(mmRLC_CGCG_CGLS_CTRL, data); + } else { + /* disable cntx_empty_int_enable & GFX Idle interrupt */ + gfx_v8_0_enable_gui_idle_interrupt(adev, false); + + /* TEST CGCG */ + temp1 = data1 = RREG32(mmRLC_CGTT_MGCG_OVERRIDE); + data1 |= (RLC_CGTT_MGCG_OVERRIDE__CGCG_MASK | + RLC_CGTT_MGCG_OVERRIDE__CGLS_MASK); + if (temp1 != data1) + WREG32(mmRLC_CGTT_MGCG_OVERRIDE, data1); + + /* read gfx register to wake up cgcg */ + RREG32(mmCB_CGTT_SCLK_CTRL); + RREG32(mmCB_CGTT_SCLK_CTRL); + RREG32(mmCB_CGTT_SCLK_CTRL); + RREG32(mmCB_CGTT_SCLK_CTRL); + + /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* write cmd to Set CGCG Overrride */ + fiji_send_serdes_cmd(adev, BPM_REG_CGCG_OVERRIDE, SET_BPM_SERDES_CMD); + + /* wait for RLC_SERDES_CU_MASTER & RLC_SERDES_NONCU_MASTER idle */ + gfx_v8_0_wait_for_rlc_serdes(adev); + + /* write cmd to Clear CGLS */ + fiji_send_serdes_cmd(adev, BPM_REG_CGLS_EN, CLE_BPM_SERDES_CMD); + + /* disable cgcg, cgls should be disabled too. */ + data &= ~(RLC_CGCG_CGLS_CTRL__CGCG_EN_MASK | + RLC_CGCG_CGLS_CTRL__CGLS_EN_MASK); + if (temp != data) + WREG32(mmRLC_CGCG_CGLS_CTRL, data); + } +} +static int fiji_update_gfx_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + if (enable) { + /* CGCG/CGLS should be enabled after MGCG/MGLS/TS(CG/LS) + * === MGCG + MGLS + TS(CG/LS) === + */ + fiji_update_medium_grain_clock_gating(adev, enable); + fiji_update_coarse_grain_clock_gating(adev, enable); + } else { + /* CGCG/CGLS should be disabled before MGCG/MGLS/TS(CG/LS) + * === CGCG + CGLS === + */ + fiji_update_coarse_grain_clock_gating(adev, enable); + fiji_update_medium_grain_clock_gating(adev, enable); + } + return 0; +} + static int gfx_v8_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (adev->asic_type) { + case CHIP_FIJI: + fiji_update_gfx_clock_gating(adev, + state == AMD_CG_STATE_GATE ? true : false); + break; + default: + break; + } return 0; } @@ -4627,7 +4718,7 @@ static void gfx_v8_0_ring_emit_fence_gfx(struct amdgpu_ring *ring, u64 addr, EVENT_TYPE(CACHE_FLUSH_AND_INV_TS_EVENT) | EVENT_INDEX(5))); amdgpu_ring_write(ring, addr & 0xfffffffc); - amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | + amdgpu_ring_write(ring, (upper_32_bits(addr) & 0xffff) | DATA_SEL(write64bit ? 2 : 1) | INT_SEL(int_sel ? 2 : 0)); amdgpu_ring_write(ring, lower_32_bits(seq)); amdgpu_ring_write(ring, upper_32_bits(seq)); @@ -4995,7 +5086,7 @@ static int gfx_v8_0_priv_inst_irq(struct amdgpu_device *adev, const struct amd_ip_funcs gfx_v8_0_ip_funcs = { .early_init = gfx_v8_0_early_init, - .late_init = NULL, + .late_init = gfx_v8_0_late_init, .sw_init = gfx_v8_0_sw_init, .sw_fini = gfx_v8_0_sw_fini, .hw_init = gfx_v8_0_hw_init, diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c index ed8abb58a785..dababe40a685 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v7_0.c @@ -370,6 +370,10 @@ static int gmc_v7_0_mc_init(struct amdgpu_device *adev) adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL; adev->mc.visible_vram_size = adev->mc.aper_size; + /* In case the PCI BAR is larger than the actual amount of vram */ + if (adev->mc.visible_vram_size > adev->mc.real_vram_size) + adev->mc.visible_vram_size = adev->mc.real_vram_size; + /* unless the user had overridden it, set the gart * size equal to the 1024 or vram, whichever is larger. */ diff --git a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c index d39028440814..adc25f87fc18 100644 --- a/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c +++ b/drivers/gpu/drm/amd/amdgpu/gmc_v8_0.c @@ -476,6 +476,10 @@ static int gmc_v8_0_mc_init(struct amdgpu_device *adev) adev->mc.real_vram_size = RREG32(mmCONFIG_MEMSIZE) * 1024ULL * 1024ULL; adev->mc.visible_vram_size = adev->mc.aper_size; + /* In case the PCI BAR is larger than the actual amount of vram */ + if (adev->mc.visible_vram_size > adev->mc.real_vram_size) + adev->mc.visible_vram_size = adev->mc.real_vram_size; + /* unless the user had overridden it, set the gart * size equal to the 1024 or vram, whichever is larger. */ @@ -1324,9 +1328,181 @@ static int gmc_v8_0_process_interrupt(struct amdgpu_device *adev, return 0; } +static void fiji_update_mc_medium_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t data; + + if (enable) { + data = RREG32(mmMC_HUB_MISC_HUB_CG); + data |= MC_HUB_MISC_HUB_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_HUB_CG, data); + + data = RREG32(mmMC_HUB_MISC_SIP_CG); + data |= MC_HUB_MISC_SIP_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_SIP_CG, data); + + data = RREG32(mmMC_HUB_MISC_VM_CG); + data |= MC_HUB_MISC_VM_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_VM_CG, data); + + data = RREG32(mmMC_XPB_CLK_GAT); + data |= MC_XPB_CLK_GAT__ENABLE_MASK; + WREG32(mmMC_XPB_CLK_GAT, data); + + data = RREG32(mmATC_MISC_CG); + data |= ATC_MISC_CG__ENABLE_MASK; + WREG32(mmATC_MISC_CG, data); + + data = RREG32(mmMC_CITF_MISC_WR_CG); + data |= MC_CITF_MISC_WR_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_WR_CG, data); + + data = RREG32(mmMC_CITF_MISC_RD_CG); + data |= MC_CITF_MISC_RD_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_RD_CG, data); + + data = RREG32(mmMC_CITF_MISC_VM_CG); + data |= MC_CITF_MISC_VM_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_VM_CG, data); + + data = RREG32(mmVM_L2_CG); + data |= VM_L2_CG__ENABLE_MASK; + WREG32(mmVM_L2_CG, data); + } else { + data = RREG32(mmMC_HUB_MISC_HUB_CG); + data &= ~MC_HUB_MISC_HUB_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_HUB_CG, data); + + data = RREG32(mmMC_HUB_MISC_SIP_CG); + data &= ~MC_HUB_MISC_SIP_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_SIP_CG, data); + + data = RREG32(mmMC_HUB_MISC_VM_CG); + data &= ~MC_HUB_MISC_VM_CG__ENABLE_MASK; + WREG32(mmMC_HUB_MISC_VM_CG, data); + + data = RREG32(mmMC_XPB_CLK_GAT); + data &= ~MC_XPB_CLK_GAT__ENABLE_MASK; + WREG32(mmMC_XPB_CLK_GAT, data); + + data = RREG32(mmATC_MISC_CG); + data &= ~ATC_MISC_CG__ENABLE_MASK; + WREG32(mmATC_MISC_CG, data); + + data = RREG32(mmMC_CITF_MISC_WR_CG); + data &= ~MC_CITF_MISC_WR_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_WR_CG, data); + + data = RREG32(mmMC_CITF_MISC_RD_CG); + data &= ~MC_CITF_MISC_RD_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_RD_CG, data); + + data = RREG32(mmMC_CITF_MISC_VM_CG); + data &= ~MC_CITF_MISC_VM_CG__ENABLE_MASK; + WREG32(mmMC_CITF_MISC_VM_CG, data); + + data = RREG32(mmVM_L2_CG); + data &= ~VM_L2_CG__ENABLE_MASK; + WREG32(mmVM_L2_CG, data); + } +} + +static void fiji_update_mc_light_sleep(struct amdgpu_device *adev, + bool enable) +{ + uint32_t data; + + if (enable) { + data = RREG32(mmMC_HUB_MISC_HUB_CG); + data |= MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_HUB_CG, data); + + data = RREG32(mmMC_HUB_MISC_SIP_CG); + data |= MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_SIP_CG, data); + + data = RREG32(mmMC_HUB_MISC_VM_CG); + data |= MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_VM_CG, data); + + data = RREG32(mmMC_XPB_CLK_GAT); + data |= MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK; + WREG32(mmMC_XPB_CLK_GAT, data); + + data = RREG32(mmATC_MISC_CG); + data |= ATC_MISC_CG__MEM_LS_ENABLE_MASK; + WREG32(mmATC_MISC_CG, data); + + data = RREG32(mmMC_CITF_MISC_WR_CG); + data |= MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_WR_CG, data); + + data = RREG32(mmMC_CITF_MISC_RD_CG); + data |= MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_RD_CG, data); + + data = RREG32(mmMC_CITF_MISC_VM_CG); + data |= MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_VM_CG, data); + + data = RREG32(mmVM_L2_CG); + data |= VM_L2_CG__MEM_LS_ENABLE_MASK; + WREG32(mmVM_L2_CG, data); + } else { + data = RREG32(mmMC_HUB_MISC_HUB_CG); + data &= ~MC_HUB_MISC_HUB_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_HUB_CG, data); + + data = RREG32(mmMC_HUB_MISC_SIP_CG); + data &= ~MC_HUB_MISC_SIP_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_SIP_CG, data); + + data = RREG32(mmMC_HUB_MISC_VM_CG); + data &= ~MC_HUB_MISC_VM_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_HUB_MISC_VM_CG, data); + + data = RREG32(mmMC_XPB_CLK_GAT); + data &= ~MC_XPB_CLK_GAT__MEM_LS_ENABLE_MASK; + WREG32(mmMC_XPB_CLK_GAT, data); + + data = RREG32(mmATC_MISC_CG); + data &= ~ATC_MISC_CG__MEM_LS_ENABLE_MASK; + WREG32(mmATC_MISC_CG, data); + + data = RREG32(mmMC_CITF_MISC_WR_CG); + data &= ~MC_CITF_MISC_WR_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_WR_CG, data); + + data = RREG32(mmMC_CITF_MISC_RD_CG); + data &= ~MC_CITF_MISC_RD_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_RD_CG, data); + + data = RREG32(mmMC_CITF_MISC_VM_CG); + data &= ~MC_CITF_MISC_VM_CG__MEM_LS_ENABLE_MASK; + WREG32(mmMC_CITF_MISC_VM_CG, data); + + data = RREG32(mmVM_L2_CG); + data &= ~VM_L2_CG__MEM_LS_ENABLE_MASK; + WREG32(mmVM_L2_CG, data); + } +} + static int gmc_v8_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (adev->asic_type) { + case CHIP_FIJI: + fiji_update_mc_medium_grain_clock_gating(adev, + state == AMD_CG_STATE_GATE ? true : false); + fiji_update_mc_light_sleep(adev, + state == AMD_CG_STATE_GATE ? true : false); + break; + default: + break; + } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c index 7253132f04b8..ad54c46751b0 100644 --- a/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/sdma_v3_0.c @@ -727,18 +727,20 @@ static int sdma_v3_0_start(struct amdgpu_device *adev) { int r, i; - if (!adev->firmware.smu_load) { - r = sdma_v3_0_load_microcode(adev); - if (r) - return r; - } else { - for (i = 0; i < adev->sdma.num_instances; i++) { - r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, - (i == 0) ? - AMDGPU_UCODE_ID_SDMA0 : - AMDGPU_UCODE_ID_SDMA1); + if (!adev->pp_enabled) { + if (!adev->firmware.smu_load) { + r = sdma_v3_0_load_microcode(adev); if (r) - return -EINVAL; + return r; + } else { + for (i = 0; i < adev->sdma.num_instances; i++) { + r = adev->smu.smumgr_funcs->check_fw_load_finish(adev, + (i == 0) ? + AMDGPU_UCODE_ID_SDMA0 : + AMDGPU_UCODE_ID_SDMA1); + if (r) + return -EINVAL; + } } } @@ -1427,9 +1429,114 @@ static int sdma_v3_0_process_illegal_inst_irq(struct amdgpu_device *adev, return 0; } +static void fiji_update_sdma_medium_grain_clock_gating( + struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + if (enable) { + temp = data = RREG32(mmSDMA0_CLK_CTRL); + data &= ~(SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK); + if (data != temp) + WREG32(mmSDMA0_CLK_CTRL, data); + + temp = data = RREG32(mmSDMA1_CLK_CTRL); + data &= ~(SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK); + + if (data != temp) + WREG32(mmSDMA1_CLK_CTRL, data); + } else { + temp = data = RREG32(mmSDMA0_CLK_CTRL); + data |= SDMA0_CLK_CTRL__SOFT_OVERRIDE7_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE6_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE5_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE4_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE3_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE2_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE1_MASK | + SDMA0_CLK_CTRL__SOFT_OVERRIDE0_MASK; + + if (data != temp) + WREG32(mmSDMA0_CLK_CTRL, data); + + temp = data = RREG32(mmSDMA1_CLK_CTRL); + data |= SDMA1_CLK_CTRL__SOFT_OVERRIDE7_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE6_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE5_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE4_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE3_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE2_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE1_MASK | + SDMA1_CLK_CTRL__SOFT_OVERRIDE0_MASK; + + if (data != temp) + WREG32(mmSDMA1_CLK_CTRL, data); + } +} + +static void fiji_update_sdma_medium_grain_light_sleep( + struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + if (enable) { + temp = data = RREG32(mmSDMA0_POWER_CNTL); + data |= SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; + + if (temp != data) + WREG32(mmSDMA0_POWER_CNTL, data); + + temp = data = RREG32(mmSDMA1_POWER_CNTL); + data |= SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; + + if (temp != data) + WREG32(mmSDMA1_POWER_CNTL, data); + } else { + temp = data = RREG32(mmSDMA0_POWER_CNTL); + data &= ~SDMA0_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; + + if (temp != data) + WREG32(mmSDMA0_POWER_CNTL, data); + + temp = data = RREG32(mmSDMA1_POWER_CNTL); + data &= ~SDMA1_POWER_CNTL__MEM_POWER_OVERRIDE_MASK; + + if (temp != data) + WREG32(mmSDMA1_POWER_CNTL, data); + } +} + static int sdma_v3_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (adev->asic_type) { + case CHIP_FIJI: + fiji_update_sdma_medium_grain_clock_gating(adev, + state == AMD_CG_STATE_GATE ? true : false); + fiji_update_sdma_medium_grain_light_sleep(adev, + state == AMD_CG_STATE_GATE ? true : false); + break; + default: + break; + } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c index 204903897b4f..f4a1346525fe 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_dpm.c @@ -24,7 +24,7 @@ #include <linux/firmware.h> #include "drmP.h" #include "amdgpu.h" -#include "tonga_smumgr.h" +#include "tonga_smum.h" MODULE_FIRMWARE("amdgpu/tonga_smc.bin"); diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h b/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h deleted file mode 100644 index 811781f69482..000000000000 --- a/drivers/gpu/drm/amd/amdgpu/tonga_ppsmc.h +++ /dev/null @@ -1,198 +0,0 @@ -/* - * Copyright 2014 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. - * - */ - -#ifndef TONGA_PP_SMC_H -#define TONGA_PP_SMC_H - -#pragma pack(push, 1) - -#define PPSMC_SWSTATE_FLAG_DC 0x01 -#define PPSMC_SWSTATE_FLAG_UVD 0x02 -#define PPSMC_SWSTATE_FLAG_VCE 0x04 -#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 - -#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 -#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 -#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff - -#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 -#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 -#define PPSMC_SYSTEMFLAG_GDDR5 0x04 - -#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 - -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 -#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 -#define PPSMC_SYSTEMFLAG_12CHANNEL 0x40 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 -#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 - -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 -#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 - -#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x10 -#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17 0x20 -#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17 0x40 - -#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 -#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 -#define PPSMC_DPM2FLAGS_OCP 0x04 - -#define PPSMC_DISPLAY_WATERMARK_LOW 0 -#define PPSMC_DISPLAY_WATERMARK_HIGH 1 - -#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 -#define PPSMC_STATEFLAG_POWERBOOST 0x02 -#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 -#define PPSMC_STATEFLAG_POWERSHIFT 0x08 -#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 -#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 -#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 - -#define FDO_MODE_HARDWARE 0 -#define FDO_MODE_PIECE_WISE_LINEAR 1 - -enum FAN_CONTROL { - FAN_CONTROL_FUZZY, - FAN_CONTROL_TABLE -}; - -#define PPSMC_Result_OK ((uint16_t)0x01) -#define PPSMC_Result_NoMore ((uint16_t)0x02) -#define PPSMC_Result_NotNow ((uint16_t)0x03) -#define PPSMC_Result_Failed ((uint16_t)0xFF) -#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) -#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) - -typedef uint16_t PPSMC_Result; - -#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) - -#define PPSMC_MSG_Halt ((uint16_t)0x10) -#define PPSMC_MSG_Resume ((uint16_t)0x11) -#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) -#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) -#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) -#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) -#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) -#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) -#define PPSMC_MSG_LevelUp ((uint16_t)0x18) -#define PPSMC_MSG_LevelDown ((uint16_t)0x19) -#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) -#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) -#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) -#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) -#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) -#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) -#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) -#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) -#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) -#define PPSMC_MSG_EnableCac ((uint16_t)0x53) -#define PPSMC_MSG_DisableCac ((uint16_t)0x54) -#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) -#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) -#define PPSMC_CACHistoryStart ((uint16_t)0x57) -#define PPSMC_CACHistoryStop ((uint16_t)0x58) -#define PPSMC_TDPClampingActive ((uint16_t)0x59) -#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) -#define PPSMC_StartFanControl ((uint16_t)0x5B) -#define PPSMC_StopFanControl ((uint16_t)0x5C) -#define PPSMC_NoDisplay ((uint16_t)0x5D) -#define PPSMC_HasDisplay ((uint16_t)0x5E) -#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) -#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) -#define PPSMC_MSG_EnableULV ((uint16_t)0x62) -#define PPSMC_MSG_DisableULV ((uint16_t)0x63) -#define PPSMC_MSG_EnterULV ((uint16_t)0x64) -#define PPSMC_MSG_ExitULV ((uint16_t)0x65) -#define PPSMC_PowerShiftActive ((uint16_t)0x6A) -#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) -#define PPSMC_OCPActive ((uint16_t)0x6C) -#define PPSMC_OCPInactive ((uint16_t)0x6D) -#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) -#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) -#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) -#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) -#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) -#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) -#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) -#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) -#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) -#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) -#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) -#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) -#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) -#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) -#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) -#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) -#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) -#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) -#define PPSMC_FlushDataCache ((uint16_t)0x80) -#define PPSMC_FlushInstrCache ((uint16_t)0x81) -#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) -#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) -#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) -#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) -#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) -#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) -#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) -#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) -#define PPSMC_MSG_SmcSpaceWriteDWordInc ((uint16_t)0x8A) -#define PPSMC_MSG_SmcSpaceWriteWordInc ((uint16_t)0x8B) -#define PPSMC_MSG_SmcSpaceWriteByteInc ((uint16_t)0x8C) -#define PPSMC_MSG_ChangeNearTDPLimit ((uint16_t)0x90) -#define PPSMC_MSG_ChangeSafePowerLimit ((uint16_t)0x91) -#define PPSMC_MSG_DPMStateSweepStart ((uint16_t)0x92) -#define PPSMC_MSG_DPMStateSweepStop ((uint16_t)0x93) -#define PPSMC_MSG_OVRDDisableSCLKDS ((uint16_t)0x94) -#define PPSMC_MSG_CancelDisableOVRDSCLKDS ((uint16_t)0x95) -#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint16_t)0x96) -#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint16_t)0x97) -#define PPSMC_MSG_GPIO17 ((uint16_t)0x98) -#define PPSMC_MSG_API_SetSvi2Volt_Vddc ((uint16_t)0x99) -#define PPSMC_MSG_API_SetSvi2Volt_Vddci ((uint16_t)0x9A) -#define PPSMC_MSG_API_SetSvi2Volt_Mvdd ((uint16_t)0x9B) -#define PPSMC_MSG_API_GetSvi2Volt_Vddc ((uint16_t)0x9C) -#define PPSMC_MSG_API_GetSvi2Volt_Vddci ((uint16_t)0x9D) -#define PPSMC_MSG_API_GetSvi2Volt_Mvdd ((uint16_t)0x9E) - -#define PPSMC_MSG_BREAK ((uint16_t)0xF8) - -#define PPSMC_MSG_Test ((uint16_t)0x100) -#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t)0x250) -#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t)0x251) -#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t)0x252) -#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t)0x253) -#define PPSMC_MSG_LoadUcodes ((uint16_t)0x254) - -typedef uint16_t PPSMC_Msg; - -#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 -#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 -#define PPSMC_EVENT_STATUS_DC 0x00000004 -#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 - -#pragma pack(pop) - -#endif diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_smc.c b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c index 5421309c1862..361c49a82323 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_smc.c +++ b/drivers/gpu/drm/amd/amdgpu/tonga_smc.c @@ -25,7 +25,7 @@ #include "drmP.h" #include "amdgpu.h" #include "tonga_ppsmc.h" -#include "tonga_smumgr.h" +#include "tonga_smum.h" #include "smu_ucode_xfer_vi.h" #include "amdgpu_ucode.h" diff --git a/drivers/gpu/drm/amd/amdgpu/tonga_smumgr.h b/drivers/gpu/drm/amd/amdgpu/tonga_smum.h index c031ff99fe3e..c031ff99fe3e 100644 --- a/drivers/gpu/drm/amd/amdgpu/tonga_smumgr.h +++ b/drivers/gpu/drm/amd/amdgpu/tonga_smum.h diff --git a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c index 121915bbc3b6..3d5913926436 100644 --- a/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c +++ b/drivers/gpu/drm/amd/amdgpu/uvd_v6_0.c @@ -279,6 +279,234 @@ static void uvd_v6_0_mc_resume(struct amdgpu_device *adev) WREG32(mmUVD_VCPU_CACHE_SIZE2, size); } +static void cz_set_uvd_clock_gating_branches(struct amdgpu_device *adev, + bool enable) +{ + u32 data, data1; + + data = RREG32(mmUVD_CGC_GATE); + data1 = RREG32(mmUVD_SUVD_CGC_GATE); + if (enable) { + data |= UVD_CGC_GATE__SYS_MASK | + UVD_CGC_GATE__UDEC_MASK | + UVD_CGC_GATE__MPEG2_MASK | + UVD_CGC_GATE__RBC_MASK | + UVD_CGC_GATE__LMI_MC_MASK | + UVD_CGC_GATE__IDCT_MASK | + UVD_CGC_GATE__MPRD_MASK | + UVD_CGC_GATE__MPC_MASK | + UVD_CGC_GATE__LBSI_MASK | + UVD_CGC_GATE__LRBBM_MASK | + UVD_CGC_GATE__UDEC_RE_MASK | + UVD_CGC_GATE__UDEC_CM_MASK | + UVD_CGC_GATE__UDEC_IT_MASK | + UVD_CGC_GATE__UDEC_DB_MASK | + UVD_CGC_GATE__UDEC_MP_MASK | + UVD_CGC_GATE__WCB_MASK | + UVD_CGC_GATE__VCPU_MASK | + UVD_CGC_GATE__SCPU_MASK; + data1 |= UVD_SUVD_CGC_GATE__SRE_MASK | + UVD_SUVD_CGC_GATE__SIT_MASK | + UVD_SUVD_CGC_GATE__SMP_MASK | + UVD_SUVD_CGC_GATE__SCM_MASK | + UVD_SUVD_CGC_GATE__SDB_MASK | + UVD_SUVD_CGC_GATE__SRE_H264_MASK | + UVD_SUVD_CGC_GATE__SRE_HEVC_MASK | + UVD_SUVD_CGC_GATE__SIT_H264_MASK | + UVD_SUVD_CGC_GATE__SIT_HEVC_MASK | + UVD_SUVD_CGC_GATE__SCM_H264_MASK | + UVD_SUVD_CGC_GATE__SCM_HEVC_MASK | + UVD_SUVD_CGC_GATE__SDB_H264_MASK | + UVD_SUVD_CGC_GATE__SDB_HEVC_MASK; + } else { + data &= ~(UVD_CGC_GATE__SYS_MASK | + UVD_CGC_GATE__UDEC_MASK | + UVD_CGC_GATE__MPEG2_MASK | + UVD_CGC_GATE__RBC_MASK | + UVD_CGC_GATE__LMI_MC_MASK | + UVD_CGC_GATE__LMI_UMC_MASK | + UVD_CGC_GATE__IDCT_MASK | + UVD_CGC_GATE__MPRD_MASK | + UVD_CGC_GATE__MPC_MASK | + UVD_CGC_GATE__LBSI_MASK | + UVD_CGC_GATE__LRBBM_MASK | + UVD_CGC_GATE__UDEC_RE_MASK | + UVD_CGC_GATE__UDEC_CM_MASK | + UVD_CGC_GATE__UDEC_IT_MASK | + UVD_CGC_GATE__UDEC_DB_MASK | + UVD_CGC_GATE__UDEC_MP_MASK | + UVD_CGC_GATE__WCB_MASK | + UVD_CGC_GATE__VCPU_MASK | + UVD_CGC_GATE__SCPU_MASK); + data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK | + UVD_SUVD_CGC_GATE__SIT_MASK | + UVD_SUVD_CGC_GATE__SMP_MASK | + UVD_SUVD_CGC_GATE__SCM_MASK | + UVD_SUVD_CGC_GATE__SDB_MASK | + UVD_SUVD_CGC_GATE__SRE_H264_MASK | + UVD_SUVD_CGC_GATE__SRE_HEVC_MASK | + UVD_SUVD_CGC_GATE__SIT_H264_MASK | + UVD_SUVD_CGC_GATE__SIT_HEVC_MASK | + UVD_SUVD_CGC_GATE__SCM_H264_MASK | + UVD_SUVD_CGC_GATE__SCM_HEVC_MASK | + UVD_SUVD_CGC_GATE__SDB_H264_MASK | + UVD_SUVD_CGC_GATE__SDB_HEVC_MASK); + } + WREG32(mmUVD_CGC_GATE, data); + WREG32(mmUVD_SUVD_CGC_GATE, data1); +} + +static void tonga_set_uvd_clock_gating_branches(struct amdgpu_device *adev, + bool enable) +{ + u32 data, data1; + + data = RREG32(mmUVD_CGC_GATE); + data1 = RREG32(mmUVD_SUVD_CGC_GATE); + if (enable) { + data |= UVD_CGC_GATE__SYS_MASK | + UVD_CGC_GATE__UDEC_MASK | + UVD_CGC_GATE__MPEG2_MASK | + UVD_CGC_GATE__RBC_MASK | + UVD_CGC_GATE__LMI_MC_MASK | + UVD_CGC_GATE__IDCT_MASK | + UVD_CGC_GATE__MPRD_MASK | + UVD_CGC_GATE__MPC_MASK | + UVD_CGC_GATE__LBSI_MASK | + UVD_CGC_GATE__LRBBM_MASK | + UVD_CGC_GATE__UDEC_RE_MASK | + UVD_CGC_GATE__UDEC_CM_MASK | + UVD_CGC_GATE__UDEC_IT_MASK | + UVD_CGC_GATE__UDEC_DB_MASK | + UVD_CGC_GATE__UDEC_MP_MASK | + UVD_CGC_GATE__WCB_MASK | + UVD_CGC_GATE__VCPU_MASK | + UVD_CGC_GATE__SCPU_MASK; + data1 |= UVD_SUVD_CGC_GATE__SRE_MASK | + UVD_SUVD_CGC_GATE__SIT_MASK | + UVD_SUVD_CGC_GATE__SMP_MASK | + UVD_SUVD_CGC_GATE__SCM_MASK | + UVD_SUVD_CGC_GATE__SDB_MASK; + } else { + data &= ~(UVD_CGC_GATE__SYS_MASK | + UVD_CGC_GATE__UDEC_MASK | + UVD_CGC_GATE__MPEG2_MASK | + UVD_CGC_GATE__RBC_MASK | + UVD_CGC_GATE__LMI_MC_MASK | + UVD_CGC_GATE__LMI_UMC_MASK | + UVD_CGC_GATE__IDCT_MASK | + UVD_CGC_GATE__MPRD_MASK | + UVD_CGC_GATE__MPC_MASK | + UVD_CGC_GATE__LBSI_MASK | + UVD_CGC_GATE__LRBBM_MASK | + UVD_CGC_GATE__UDEC_RE_MASK | + UVD_CGC_GATE__UDEC_CM_MASK | + UVD_CGC_GATE__UDEC_IT_MASK | + UVD_CGC_GATE__UDEC_DB_MASK | + UVD_CGC_GATE__UDEC_MP_MASK | + UVD_CGC_GATE__WCB_MASK | + UVD_CGC_GATE__VCPU_MASK | + UVD_CGC_GATE__SCPU_MASK); + data1 &= ~(UVD_SUVD_CGC_GATE__SRE_MASK | + UVD_SUVD_CGC_GATE__SIT_MASK | + UVD_SUVD_CGC_GATE__SMP_MASK | + UVD_SUVD_CGC_GATE__SCM_MASK | + UVD_SUVD_CGC_GATE__SDB_MASK); + } + WREG32(mmUVD_CGC_GATE, data); + WREG32(mmUVD_SUVD_CGC_GATE, data1); +} + +static void uvd_v6_0_set_uvd_dynamic_clock_mode(struct amdgpu_device *adev, + bool swmode) +{ + u32 data, data1 = 0, data2; + + /* Always un-gate UVD REGS bit */ + data = RREG32(mmUVD_CGC_GATE); + data &= ~(UVD_CGC_GATE__REGS_MASK); + WREG32(mmUVD_CGC_GATE, data); + + data = RREG32(mmUVD_CGC_CTRL); + data &= ~(UVD_CGC_CTRL__CLK_OFF_DELAY_MASK | + UVD_CGC_CTRL__CLK_GATE_DLY_TIMER_MASK); + data |= UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK | + 1 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_GATE_DLY_TIMER) | + 4 << REG_FIELD_SHIFT(UVD_CGC_CTRL, CLK_OFF_DELAY); + + data2 = RREG32(mmUVD_SUVD_CGC_CTRL); + if (swmode) { + data &= ~(UVD_CGC_CTRL__UDEC_RE_MODE_MASK | + UVD_CGC_CTRL__UDEC_CM_MODE_MASK | + UVD_CGC_CTRL__UDEC_IT_MODE_MASK | + UVD_CGC_CTRL__UDEC_DB_MODE_MASK | + UVD_CGC_CTRL__UDEC_MP_MODE_MASK | + UVD_CGC_CTRL__SYS_MODE_MASK | + UVD_CGC_CTRL__UDEC_MODE_MASK | + UVD_CGC_CTRL__MPEG2_MODE_MASK | + UVD_CGC_CTRL__REGS_MODE_MASK | + UVD_CGC_CTRL__RBC_MODE_MASK | + UVD_CGC_CTRL__LMI_MC_MODE_MASK | + UVD_CGC_CTRL__LMI_UMC_MODE_MASK | + UVD_CGC_CTRL__IDCT_MODE_MASK | + UVD_CGC_CTRL__MPRD_MODE_MASK | + UVD_CGC_CTRL__MPC_MODE_MASK | + UVD_CGC_CTRL__LBSI_MODE_MASK | + UVD_CGC_CTRL__LRBBM_MODE_MASK | + UVD_CGC_CTRL__WCB_MODE_MASK | + UVD_CGC_CTRL__VCPU_MODE_MASK | + UVD_CGC_CTRL__JPEG_MODE_MASK | + UVD_CGC_CTRL__SCPU_MODE_MASK); + data1 |= UVD_CGC_CTRL2__DYN_OCLK_RAMP_EN_MASK | + UVD_CGC_CTRL2__DYN_RCLK_RAMP_EN_MASK; + data1 &= ~UVD_CGC_CTRL2__GATER_DIV_ID_MASK; + data1 |= 7 << REG_FIELD_SHIFT(UVD_CGC_CTRL2, GATER_DIV_ID); + data2 &= ~(UVD_SUVD_CGC_CTRL__SRE_MODE_MASK | + UVD_SUVD_CGC_CTRL__SIT_MODE_MASK | + UVD_SUVD_CGC_CTRL__SMP_MODE_MASK | + UVD_SUVD_CGC_CTRL__SCM_MODE_MASK | + UVD_SUVD_CGC_CTRL__SDB_MODE_MASK); + } else { + data |= UVD_CGC_CTRL__UDEC_RE_MODE_MASK | + UVD_CGC_CTRL__UDEC_CM_MODE_MASK | + UVD_CGC_CTRL__UDEC_IT_MODE_MASK | + UVD_CGC_CTRL__UDEC_DB_MODE_MASK | + UVD_CGC_CTRL__UDEC_MP_MODE_MASK | + UVD_CGC_CTRL__SYS_MODE_MASK | + UVD_CGC_CTRL__UDEC_MODE_MASK | + UVD_CGC_CTRL__MPEG2_MODE_MASK | + UVD_CGC_CTRL__REGS_MODE_MASK | + UVD_CGC_CTRL__RBC_MODE_MASK | + UVD_CGC_CTRL__LMI_MC_MODE_MASK | + UVD_CGC_CTRL__LMI_UMC_MODE_MASK | + UVD_CGC_CTRL__IDCT_MODE_MASK | + UVD_CGC_CTRL__MPRD_MODE_MASK | + UVD_CGC_CTRL__MPC_MODE_MASK | + UVD_CGC_CTRL__LBSI_MODE_MASK | + UVD_CGC_CTRL__LRBBM_MODE_MASK | + UVD_CGC_CTRL__WCB_MODE_MASK | + UVD_CGC_CTRL__VCPU_MODE_MASK | + UVD_CGC_CTRL__SCPU_MODE_MASK; + data2 |= UVD_SUVD_CGC_CTRL__SRE_MODE_MASK | + UVD_SUVD_CGC_CTRL__SIT_MODE_MASK | + UVD_SUVD_CGC_CTRL__SMP_MODE_MASK | + UVD_SUVD_CGC_CTRL__SCM_MODE_MASK | + UVD_SUVD_CGC_CTRL__SDB_MODE_MASK; + } + WREG32(mmUVD_CGC_CTRL, data); + WREG32(mmUVD_SUVD_CGC_CTRL, data2); + + data = RREG32_UVD_CTX(ixUVD_CGC_CTRL2); + data &= ~(REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) | + REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) | + REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID)); + data1 &= (REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_OCLK_RAMP_EN) | + REG_FIELD_MASK(UVD_CGC_CTRL2, DYN_RCLK_RAMP_EN) | + REG_FIELD_MASK(UVD_CGC_CTRL2, GATER_DIV_ID)); + data |= data1; + WREG32_UVD_CTX(ixUVD_CGC_CTRL2, data); +} + /** * uvd_v6_0_start - start UVD block * @@ -303,8 +531,19 @@ static int uvd_v6_0_start(struct amdgpu_device *adev) uvd_v6_0_mc_resume(adev); - /* disable clock gating */ - WREG32(mmUVD_CGC_GATE, 0); + /* Set dynamic clock gating in S/W control mode */ + if (adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG) { + if (adev->flags & AMD_IS_APU) + cz_set_uvd_clock_gating_branches(adev, false); + else + tonga_set_uvd_clock_gating_branches(adev, false); + uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true); + } else { + /* disable clock gating */ + uint32_t data = RREG32(mmUVD_CGC_CTRL); + data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK; + WREG32(mmUVD_CGC_CTRL, data); + } /* disable interupt */ WREG32_P(mmUVD_MASTINT_EN, 0, ~(1 << 1)); @@ -758,6 +997,24 @@ static int uvd_v6_0_process_interrupt(struct amdgpu_device *adev, static int uvd_v6_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + bool enable = (state == AMD_CG_STATE_GATE) ? true : false; + + if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_UVD_MGCG)) + return 0; + + if (enable) { + if (adev->flags & AMD_IS_APU) + cz_set_uvd_clock_gating_branches(adev, enable); + else + tonga_set_uvd_clock_gating_branches(adev, enable); + uvd_v6_0_set_uvd_dynamic_clock_mode(adev, true); + } else { + uint32_t data = RREG32(mmUVD_CGC_CTRL); + data &= ~UVD_CGC_CTRL__DYN_CLOCK_MODE_MASK; + WREG32(mmUVD_CGC_CTRL, data); + } + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c index 370c6c9d81c2..35f48ad7644d 100644 --- a/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c +++ b/drivers/gpu/drm/amd/amdgpu/vce_v3_0.c @@ -103,6 +103,108 @@ static void vce_v3_0_ring_set_wptr(struct amdgpu_ring *ring) WREG32(mmVCE_RB_WPTR2, ring->wptr); } +static void vce_v3_0_override_vce_clock_gating(struct amdgpu_device *adev, bool override) +{ + u32 tmp, data; + + tmp = data = RREG32(mmVCE_RB_ARB_CTRL); + if (override) + data |= VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; + else + data &= ~VCE_RB_ARB_CTRL__VCE_CGTT_OVERRIDE_MASK; + + if (tmp != data) + WREG32(mmVCE_RB_ARB_CTRL, data); +} + +static void vce_v3_0_set_vce_sw_clock_gating(struct amdgpu_device *adev, + bool gated) +{ + u32 tmp, data; + /* Set Override to disable Clock Gating */ + vce_v3_0_override_vce_clock_gating(adev, true); + + if (!gated) { + /* Force CLOCK ON for VCE_CLOCK_GATING_B, + * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} + * VREG can be FORCE ON or set to Dynamic, but can't be OFF + */ + tmp = data = RREG32(mmVCE_CLOCK_GATING_B); + data |= 0x1ff; + data &= ~0xef0000; + if (tmp != data) + WREG32(mmVCE_CLOCK_GATING_B, data); + + /* Force CLOCK ON for VCE_UENC_CLOCK_GATING, + * {*_FORCE_ON, *_FORCE_OFF} = {1, 0} + */ + tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); + data |= 0x3ff000; + data &= ~0xffc00000; + if (tmp != data) + WREG32(mmVCE_UENC_CLOCK_GATING, data); + + /* set VCE_UENC_CLOCK_GATING_2 */ + tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); + data |= 0x2; + data &= ~0x2; + if (tmp != data) + WREG32(mmVCE_UENC_CLOCK_GATING_2, data); + + /* Force CLOCK ON for VCE_UENC_REG_CLOCK_GATING */ + tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); + data |= 0x37f; + if (tmp != data) + WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); + + /* Force VCE_UENC_DMA_DCLK_CTRL Clock ON */ + tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); + data |= VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | + VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | + VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | + 0x8; + if (tmp != data) + WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); + } else { + /* Force CLOCK OFF for VCE_CLOCK_GATING_B, + * {*, *_FORCE_OFF} = {*, 1} + * set VREG to Dynamic, as it can't be OFF + */ + tmp = data = RREG32(mmVCE_CLOCK_GATING_B); + data &= ~0x80010; + data |= 0xe70008; + if (tmp != data) + WREG32(mmVCE_CLOCK_GATING_B, data); + /* Force CLOCK OFF for VCE_UENC_CLOCK_GATING, + * Force ClOCK OFF takes precedent over Force CLOCK ON setting. + * {*_FORCE_ON, *_FORCE_OFF} = {*, 1} + */ + tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING); + data |= 0xffc00000; + if (tmp != data) + WREG32(mmVCE_UENC_CLOCK_GATING, data); + /* Set VCE_UENC_CLOCK_GATING_2 */ + tmp = data = RREG32(mmVCE_UENC_CLOCK_GATING_2); + data |= 0x10000; + if (tmp != data) + WREG32(mmVCE_UENC_CLOCK_GATING_2, data); + /* Set VCE_UENC_REG_CLOCK_GATING to dynamic */ + tmp = data = RREG32(mmVCE_UENC_REG_CLOCK_GATING); + data &= ~0xffc00000; + if (tmp != data) + WREG32(mmVCE_UENC_REG_CLOCK_GATING, data); + /* Set VCE_UENC_DMA_DCLK_CTRL CG always in dynamic mode */ + tmp = data = RREG32(mmVCE_UENC_DMA_DCLK_CTRL); + data &= ~(VCE_UENC_DMA_DCLK_CTRL__WRDMCLK_FORCEON_MASK | + VCE_UENC_DMA_DCLK_CTRL__RDDMCLK_FORCEON_MASK | + VCE_UENC_DMA_DCLK_CTRL__REGCLK_FORCEON_MASK | + 0x8); + if (tmp != data) + WREG32(mmVCE_UENC_DMA_DCLK_CTRL, data); + } + vce_v3_0_override_vce_clock_gating(adev, false); +} + /** * vce_v3_0_start - start VCE block * @@ -121,7 +223,7 @@ static int vce_v3_0_start(struct amdgpu_device *adev) if (adev->vce.harvest_config & (1 << idx)) continue; - if(idx == 0) + if (idx == 0) WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); else @@ -174,6 +276,10 @@ static int vce_v3_0_start(struct amdgpu_device *adev) /* clear BUSY flag */ WREG32_P(mmVCE_STATUS, 0, ~1); + /* Set Clock-Gating off */ + if (adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG) + vce_v3_0_set_vce_sw_clock_gating(adev, false); + if (r) { DRM_ERROR("VCE not responding, giving up!!!\n"); mutex_unlock(&adev->grbm_idx_mutex); @@ -609,6 +715,47 @@ static int vce_v3_0_process_interrupt(struct amdgpu_device *adev, static int vce_v3_0_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + bool enable = (state == AMD_CG_STATE_GATE) ? true : false; + int i; + + if (!(adev->cg_flags & AMDGPU_CG_SUPPORT_VCE_MGCG)) + return 0; + + mutex_lock(&adev->grbm_idx_mutex); + for (i = 0; i < 2; i++) { + /* Program VCE Instance 0 or 1 if not harvested */ + if (adev->vce.harvest_config & (1 << i)) + continue; + + if (i == 0) + WREG32_P(mmGRBM_GFX_INDEX, 0, + ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); + else + WREG32_P(mmGRBM_GFX_INDEX, + GRBM_GFX_INDEX__VCE_INSTANCE_MASK, + ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); + + if (enable) { + /* initialize VCE_CLOCK_GATING_A: Clock ON/OFF delay */ + uint32_t data = RREG32(mmVCE_CLOCK_GATING_A); + data &= ~(0xf | 0xff0); + data |= ((0x0 << 0) | (0x04 << 4)); + WREG32(mmVCE_CLOCK_GATING_A, data); + + /* initialize VCE_UENC_CLOCK_GATING: Clock ON/OFF delay */ + data = RREG32(mmVCE_UENC_CLOCK_GATING); + data &= ~(0xf | 0xff0); + data |= ((0x0 << 0) | (0x04 << 4)); + WREG32(mmVCE_UENC_CLOCK_GATING, data); + } + + vce_v3_0_set_vce_sw_clock_gating(adev, enable); + } + + WREG32_P(mmGRBM_GFX_INDEX, 0, ~GRBM_GFX_INDEX__VCE_INSTANCE_MASK); + mutex_unlock(&adev->grbm_idx_mutex); + return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/vi.c b/drivers/gpu/drm/amd/amdgpu/vi.c index 2adc1c855e85..652e76644c31 100644 --- a/drivers/gpu/drm/amd/amdgpu/vi.c +++ b/drivers/gpu/drm/amd/amdgpu/vi.c @@ -31,6 +31,7 @@ #include "amdgpu_vce.h" #include "amdgpu_ucode.h" #include "atom.h" +#include "amd_pcie.h" #include "gmc/gmc_8_1_d.h" #include "gmc/gmc_8_1_sh_mask.h" @@ -71,6 +72,7 @@ #include "uvd_v5_0.h" #include "uvd_v6_0.h" #include "vce_v3_0.h" +#include "amdgpu_powerplay.h" /* * Indirect registers accessor @@ -376,6 +378,38 @@ static bool vi_read_disabled_bios(struct amdgpu_device *adev) WREG32_SMC(ixROM_CNTL, rom_cntl); return r; } + +static bool vi_read_bios_from_rom(struct amdgpu_device *adev, + u8 *bios, u32 length_bytes) +{ + u32 *dw_ptr; + unsigned long flags; + u32 i, length_dw; + + if (bios == NULL) + return false; + if (length_bytes == 0) + return false; + /* APU vbios image is part of sbios image */ + if (adev->flags & AMD_IS_APU) + return false; + + dw_ptr = (u32 *)bios; + length_dw = ALIGN(length_bytes, 4) / 4; + /* take the smc lock since we are using the smc index */ + spin_lock_irqsave(&adev->smc_idx_lock, flags); + /* set rom index to 0 */ + WREG32(mmSMC_IND_INDEX_0, ixROM_INDEX); + WREG32(mmSMC_IND_DATA_0, 0); + /* set index to data for continous read */ + WREG32(mmSMC_IND_INDEX_0, ixROM_DATA); + for (i = 0; i < length_dw; i++) + dw_ptr[i] = RREG32(mmSMC_IND_DATA_0); + spin_unlock_irqrestore(&adev->smc_idx_lock, flags); + + return true; +} + static struct amdgpu_allowed_register_entry tonga_allowed_read_registers[] = { {mmGB_MACROTILE_MODE7, true}, }; @@ -1019,9 +1053,6 @@ static int vi_set_vce_clocks(struct amdgpu_device *adev, u32 evclk, u32 ecclk) static void vi_pcie_gen3_enable(struct amdgpu_device *adev) { - u32 mask; - int ret; - if (pci_is_root_bus(adev->pdev->bus)) return; @@ -1031,11 +1062,8 @@ static void vi_pcie_gen3_enable(struct amdgpu_device *adev) if (adev->flags & AMD_IS_APU) return; - ret = drm_pcie_get_speed_cap_mask(adev->ddev, &mask); - if (ret != 0) - return; - - if (!(mask & (DRM_PCIE_SPEED_50 | DRM_PCIE_SPEED_80))) + if (!(adev->pm.pcie_gen_mask & (CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 | + CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3))) return; /* todo */ @@ -1098,7 +1126,7 @@ static const struct amdgpu_ip_block_version topaz_ip_blocks[] = .major = 7, .minor = 1, .rev = 0, - .funcs = &iceland_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_GFX, @@ -1145,7 +1173,7 @@ static const struct amdgpu_ip_block_version tonga_ip_blocks[] = .major = 7, .minor = 1, .rev = 0, - .funcs = &tonga_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -1213,7 +1241,7 @@ static const struct amdgpu_ip_block_version fiji_ip_blocks[] = .major = 7, .minor = 1, .rev = 0, - .funcs = &fiji_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs, }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -1281,7 +1309,7 @@ static const struct amdgpu_ip_block_version cz_ip_blocks[] = .major = 8, .minor = 0, .rev = 0, - .funcs = &cz_dpm_ip_funcs, + .funcs = &amdgpu_pp_ip_funcs }, { .type = AMD_IP_BLOCK_TYPE_DCE, @@ -1354,20 +1382,18 @@ int vi_set_ip_blocks(struct amdgpu_device *adev) static uint32_t vi_get_rev_id(struct amdgpu_device *adev) { - if (adev->asic_type == CHIP_TOPAZ) - return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK) - >> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT; - else if (adev->flags & AMD_IS_APU) + if (adev->flags & AMD_IS_APU) return (RREG32_SMC(ATI_REV_ID_FUSE_MACRO__ADDRESS) & ATI_REV_ID_FUSE_MACRO__MASK) >> ATI_REV_ID_FUSE_MACRO__SHIFT; else - return (RREG32(mmCC_DRM_ID_STRAPS) & CC_DRM_ID_STRAPS__ATI_REV_ID_MASK) - >> CC_DRM_ID_STRAPS__ATI_REV_ID__SHIFT; + return (RREG32(mmPCIE_EFUSE4) & PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID_MASK) + >> PCIE_EFUSE4__STRAP_BIF_ATI_REV_ID__SHIFT; } static const struct amdgpu_asic_funcs vi_asic_funcs = { .read_disabled_bios = &vi_read_disabled_bios, + .read_bios_from_rom = &vi_read_bios_from_rom, .read_register = &vi_read_register, .reset = &vi_asic_reset, .set_vga_state = &vi_vga_set_state, @@ -1416,7 +1442,8 @@ static int vi_common_early_init(void *handle) break; case CHIP_FIJI: adev->has_uvd = true; - adev->cg_flags = 0; + adev->cg_flags = AMDGPU_CG_SUPPORT_UVD_MGCG | + AMDGPU_CG_SUPPORT_VCE_MGCG; adev->pg_flags = 0; adev->external_rev_id = adev->rev_id + 0x3c; break; @@ -1442,6 +1469,8 @@ static int vi_common_early_init(void *handle) if (amdgpu_smc_load_fw && smc_enabled) adev->firmware.smu_load = true; + amdgpu_get_pcie_info(adev); + return 0; } @@ -1515,9 +1544,95 @@ static int vi_common_soft_reset(void *handle) return 0; } +static void fiji_update_bif_medium_grain_light_sleep(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + temp = data = RREG32_PCIE(ixPCIE_CNTL2); + + if (enable) + data |= PCIE_CNTL2__SLV_MEM_LS_EN_MASK | + PCIE_CNTL2__MST_MEM_LS_EN_MASK | + PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK; + else + data &= ~(PCIE_CNTL2__SLV_MEM_LS_EN_MASK | + PCIE_CNTL2__MST_MEM_LS_EN_MASK | + PCIE_CNTL2__REPLAY_MEM_LS_EN_MASK); + + if (temp != data) + WREG32_PCIE(ixPCIE_CNTL2, data); +} + +static void fiji_update_hdp_medium_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + temp = data = RREG32(mmHDP_HOST_PATH_CNTL); + + if (enable) + data &= ~HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK; + else + data |= HDP_HOST_PATH_CNTL__CLOCK_GATING_DIS_MASK; + + if (temp != data) + WREG32(mmHDP_HOST_PATH_CNTL, data); +} + +static void fiji_update_hdp_light_sleep(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + temp = data = RREG32(mmHDP_MEM_POWER_LS); + + if (enable) + data |= HDP_MEM_POWER_LS__LS_ENABLE_MASK; + else + data &= ~HDP_MEM_POWER_LS__LS_ENABLE_MASK; + + if (temp != data) + WREG32(mmHDP_MEM_POWER_LS, data); +} + +static void fiji_update_rom_medium_grain_clock_gating(struct amdgpu_device *adev, + bool enable) +{ + uint32_t temp, data; + + temp = data = RREG32_SMC(ixCGTT_ROM_CLK_CTRL0); + + if (enable) + data &= ~(CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK | + CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK); + else + data |= CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE0_MASK | + CGTT_ROM_CLK_CTRL0__SOFT_OVERRIDE1_MASK; + + if (temp != data) + WREG32_SMC(ixCGTT_ROM_CLK_CTRL0, data); +} + static int vi_common_set_clockgating_state(void *handle, enum amd_clockgating_state state) { + struct amdgpu_device *adev = (struct amdgpu_device *)handle; + + switch (adev->asic_type) { + case CHIP_FIJI: + fiji_update_bif_medium_grain_light_sleep(adev, + state == AMD_CG_STATE_GATE ? true : false); + fiji_update_hdp_medium_grain_clock_gating(adev, + state == AMD_CG_STATE_GATE ? true : false); + fiji_update_hdp_light_sleep(adev, + state == AMD_CG_STATE_GATE ? true : false); + fiji_update_rom_medium_grain_clock_gating(adev, + state == AMD_CG_STATE_GATE ? true : false); + break; + default: + break; + } return 0; } diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h b/drivers/gpu/drm/amd/include/amd_acpi.h index 01a29c3d7011..496360eb3fba 100644 --- a/drivers/gpu/drm/amd/amdgpu/amdgpu_acpi.h +++ b/drivers/gpu/drm/amd/include/amd_acpi.h @@ -21,14 +21,63 @@ * */ -#ifndef AMDGPU_ACPI_H -#define AMDGPU_ACPI_H +#ifndef AMD_ACPI_H +#define AMD_ACPI_H -struct amdgpu_device; -struct acpi_bus_event; +#define ACPI_AC_CLASS "ac_adapter" -int amdgpu_atif_handler(struct amdgpu_device *adev, - struct acpi_bus_event *event); +struct atif_verify_interface { + u16 size; /* structure size in bytes (includes size field) */ + u16 version; /* version */ + u32 notification_mask; /* supported notifications mask */ + u32 function_bits; /* supported functions bit vector */ +} __packed; + +struct atif_system_params { + u16 size; /* structure size in bytes (includes size field) */ + u32 valid_mask; /* valid flags mask */ + u32 flags; /* flags */ + u8 command_code; /* notify command code */ +} __packed; + +struct atif_sbios_requests { + u16 size; /* structure size in bytes (includes size field) */ + u32 pending; /* pending sbios requests */ + u8 panel_exp_mode; /* panel expansion mode */ + u8 thermal_gfx; /* thermal state: target gfx controller */ + u8 thermal_state; /* thermal state: state id (0: exit state, non-0: state) */ + u8 forced_power_gfx; /* forced power state: target gfx controller */ + u8 forced_power_state; /* forced power state: state id */ + u8 system_power_src; /* system power source */ + u8 backlight_level; /* panel backlight level (0-255) */ +} __packed; + +#define ATIF_NOTIFY_MASK 0x3 +#define ATIF_NOTIFY_NONE 0 +#define ATIF_NOTIFY_81 1 +#define ATIF_NOTIFY_N 2 + +struct atcs_verify_interface { + u16 size; /* structure size in bytes (includes size field) */ + u16 version; /* version */ + u32 function_bits; /* supported functions bit vector */ +} __packed; + +#define ATCS_VALID_FLAGS_MASK 0x3 + +struct atcs_pref_req_input { + u16 size; /* structure size in bytes (includes size field) */ + u16 client_id; /* client id (bit 2-0: func num, 7-3: dev num, 15-8: bus num) */ + u16 valid_flags_mask; /* valid flags mask */ + u16 flags; /* flags */ + u8 req_type; /* request type */ + u8 perf_req; /* performance request */ +} __packed; + +struct atcs_pref_req_output { + u16 size; /* structure size in bytes (includes size field) */ + u8 ret_val; /* return value */ +} __packed; /* AMD hw uses four ACPI control methods: * 1. ATIF diff --git a/drivers/gpu/drm/amd/include/amd_pcie.h b/drivers/gpu/drm/amd/include/amd_pcie.h new file mode 100644 index 000000000000..7c2a916c1e63 --- /dev/null +++ b/drivers/gpu/drm/amd/include/amd_pcie.h @@ -0,0 +1,50 @@ +/* + * Copyright 2015 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. + */ + +#ifndef __AMD_PCIE_H__ +#define __AMD_PCIE_H__ + +/* Following flags shows PCIe link speed supported in driver which are decided by chipset and ASIC */ +#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN1 0x00010000 +#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2 0x00020000 +#define CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3 0x00040000 +#define CAIL_PCIE_LINK_SPEED_SUPPORT_MASK 0xFFFF0000 +#define CAIL_PCIE_LINK_SPEED_SUPPORT_SHIFT 16 + +/* Following flags shows PCIe link speed supported by ASIC H/W.*/ +#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1 0x00000001 +#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2 0x00000002 +#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3 0x00000004 +#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK 0x0000FFFF +#define CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_SHIFT 0 + +/* Following flags shows PCIe lane width switch supported in driver which are decided by chipset and ASIC */ +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X1 0x00010000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X2 0x00020000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X4 0x00040000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X8 0x00080000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X12 0x00100000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X16 0x00200000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_X32 0x00400000 +#define CAIL_PCIE_LINK_WIDTH_SUPPORT_SHIFT 16 + +#endif diff --git a/drivers/gpu/drm/amd/include/amd_pcie_helpers.h b/drivers/gpu/drm/amd/include/amd_pcie_helpers.h new file mode 100644 index 000000000000..5725bf85eacc --- /dev/null +++ b/drivers/gpu/drm/amd/include/amd_pcie_helpers.h @@ -0,0 +1,141 @@ +/* + * Copyright 2015 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. + */ + +#ifndef __AMD_PCIE_HELPERS_H__ +#define __AMD_PCIE_HELPERS_H__ + +#include "amd_pcie.h" + +static inline bool is_pcie_gen3_supported(uint32_t pcie_link_speed_cap) +{ + if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + return true; + + return false; +} + +static inline bool is_pcie_gen2_supported(uint32_t pcie_link_speed_cap) +{ + if (pcie_link_speed_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN2) + return true; + + return false; +} + +/* Get the new PCIE speed given the ASIC PCIE Cap and the NewState's requested PCIE speed*/ +static inline uint16_t get_pcie_gen_support(uint32_t pcie_link_speed_cap, + uint16_t ns_pcie_gen) +{ + uint32_t asic_pcie_link_speed_cap = (pcie_link_speed_cap & + CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_MASK); + uint32_t sys_pcie_link_speed_cap = (pcie_link_speed_cap & + CAIL_PCIE_LINK_SPEED_SUPPORT_MASK); + + switch (asic_pcie_link_speed_cap) { + case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN1: + return PP_PCIEGen1; + + case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN2: + return PP_PCIEGen2; + + case CAIL_ASIC_PCIE_LINK_SPEED_SUPPORT_GEN3: + return PP_PCIEGen3; + + default: + if (is_pcie_gen3_supported(sys_pcie_link_speed_cap) && + (ns_pcie_gen == PP_PCIEGen3)) { + return PP_PCIEGen3; + } else if (is_pcie_gen2_supported(sys_pcie_link_speed_cap) && + ((ns_pcie_gen == PP_PCIEGen3) || (ns_pcie_gen == PP_PCIEGen2))) { + return PP_PCIEGen2; + } + } + + return PP_PCIEGen1; +} + +static inline uint16_t get_pcie_lane_support(uint32_t pcie_lane_width_cap, + uint16_t ns_pcie_lanes) +{ + int i, j; + uint16_t new_pcie_lanes = ns_pcie_lanes; + uint16_t pcie_lanes[7] = {1, 2, 4, 8, 12, 16, 32}; + + switch (pcie_lane_width_cap) { + case 0: + printk(KERN_ERR "No valid PCIE lane width reported"); + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X1: + new_pcie_lanes = 1; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X2: + new_pcie_lanes = 2; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X4: + new_pcie_lanes = 4; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X8: + new_pcie_lanes = 8; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X12: + new_pcie_lanes = 12; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X16: + new_pcie_lanes = 16; + break; + case CAIL_PCIE_LINK_WIDTH_SUPPORT_X32: + new_pcie_lanes = 32; + break; + default: + for (i = 0; i < 7; i++) { + if (ns_pcie_lanes == pcie_lanes[i]) { + if (pcie_lane_width_cap & (0x10000 << i)) { + break; + } else { + for (j = i - 1; j >= 0; j--) { + if (pcie_lane_width_cap & (0x10000 << j)) { + new_pcie_lanes = pcie_lanes[j]; + break; + } + } + + if (j < 0) { + for (j = i + 1; j < 7; j++) { + if (pcie_lane_width_cap & (0x10000 << j)) { + new_pcie_lanes = pcie_lanes[j]; + break; + } + } + if (j > 7) + printk(KERN_ERR "Cannot find a valid PCIE lane width!"); + } + } + break; + } + } + break; + } + + return new_pcie_lanes; +} + +#endif diff --git a/drivers/gpu/drm/amd/include/amd_shared.h b/drivers/gpu/drm/amd/include/amd_shared.h index fe28fb353fab..1195d06f55bc 100644 --- a/drivers/gpu/drm/amd/include/amd_shared.h +++ b/drivers/gpu/drm/amd/include/amd_shared.h @@ -85,6 +85,27 @@ enum amd_powergating_state { AMD_PG_STATE_UNGATE, }; +enum amd_pm_state_type { + /* not used for dpm */ + POWER_STATE_TYPE_DEFAULT, + POWER_STATE_TYPE_POWERSAVE, + /* user selectable states */ + POWER_STATE_TYPE_BATTERY, + POWER_STATE_TYPE_BALANCED, + POWER_STATE_TYPE_PERFORMANCE, + /* internal states */ + POWER_STATE_TYPE_INTERNAL_UVD, + POWER_STATE_TYPE_INTERNAL_UVD_SD, + POWER_STATE_TYPE_INTERNAL_UVD_HD, + POWER_STATE_TYPE_INTERNAL_UVD_HD2, + POWER_STATE_TYPE_INTERNAL_UVD_MVC, + POWER_STATE_TYPE_INTERNAL_BOOT, + POWER_STATE_TYPE_INTERNAL_THERMAL, + POWER_STATE_TYPE_INTERNAL_ACPI, + POWER_STATE_TYPE_INTERNAL_ULV, + POWER_STATE_TYPE_INTERNAL_3DPERF, +}; + struct amd_ip_funcs { /* sets up early driver state (pre sw_init), does not configure hw - Optional */ int (*early_init)(void *handle); diff --git a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h index 92b6ba0047af..293329719bba 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/bif/bif_5_0_d.h @@ -596,6 +596,7 @@ #define mmSWRST_EP_CONTROL_0 0x14ac #define mmCPM_CONTROL 0x14b8 #define mmGSKT_CONTROL 0x14bf +#define ixSWRST_COMMAND_1 0x1400103 #define ixLM_CONTROL 0x1400120 #define ixLM_PCIETXMUX0 0x1400121 #define ixLM_PCIETXMUX1 0x1400122 diff --git a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h index daf763ba1a8f..a9b6923192ee 100644 --- a/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h +++ b/drivers/gpu/drm/amd/include/asic_reg/gca/gfx_8_0_d.h @@ -2807,5 +2807,18 @@ #define ixDIDT_DBR_WEIGHT0_3 0x90 #define ixDIDT_DBR_WEIGHT4_7 0x91 #define ixDIDT_DBR_WEIGHT8_11 0x92 +#define mmTD_EDC_CNT 0x252e +#define mmCPF_EDC_TAG_CNT 0x3188 +#define mmCPF_EDC_ROQ_CNT 0x3189 +#define mmCPF_EDC_ATC_CNT 0x318a +#define mmCPG_EDC_TAG_CNT 0x318b +#define mmCPG_EDC_ATC_CNT 0x318c +#define mmCPG_EDC_DMA_CNT 0x318d +#define mmCPC_EDC_SCRATCH_CNT 0x318e +#define mmCPC_EDC_UCODE_CNT 0x318f +#define mmCPC_EDC_ATC_CNT 0x3190 +#define mmDC_EDC_STATE_CNT 0x3191 +#define mmDC_EDC_CSINVOC_CNT 0x3192 +#define mmDC_EDC_RESTORE_CNT 0x3193 #endif /* GFX_8_0_D_H */ diff --git a/drivers/gpu/drm/amd/include/atombios.h b/drivers/gpu/drm/amd/include/atombios.h index 552622675ace..eaf451e26643 100644 --- a/drivers/gpu/drm/amd/include/atombios.h +++ b/drivers/gpu/drm/amd/include/atombios.h @@ -550,6 +550,13 @@ typedef struct _COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 //MPLL_CNTL_FLAG_BYPASS_AD_PLL has a wrong name, should be BYPASS_DQ_PLL #define MPLL_CNTL_FLAG_BYPASS_AD_PLL 0x04 +// use for ComputeMemoryClockParamTable +typedef struct _COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 +{ + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 ulClock; + ULONG ulReserved; +}COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2; + typedef struct _DYNAMICE_MEMORY_SETTINGS_PARAMETER { ATOM_COMPUTE_CLOCK_FREQ ulClock; @@ -4988,6 +4995,78 @@ typedef struct _ATOM_ASIC_PROFILING_INFO_V3_3 ULONG ulSDCMargine; }ATOM_ASIC_PROFILING_INFO_V3_3; +// for Fiji speed EVV algorithm +typedef struct _ATOM_ASIC_PROFILING_INFO_V3_4 +{ + ATOM_COMMON_TABLE_HEADER asHeader; + ULONG ulEvvLkgFactor; + ULONG ulBoardCoreTemp; + ULONG ulMaxVddc; + ULONG ulMinVddc; + ULONG ulLoadLineSlop; + ULONG ulLeakageTemp; + ULONG ulLeakageVoltage; + EFUSE_LINEAR_FUNC_PARAM sCACm; + EFUSE_LINEAR_FUNC_PARAM sCACb; + EFUSE_LOGISTIC_FUNC_PARAM sKt_b; + EFUSE_LOGISTIC_FUNC_PARAM sKv_m; + EFUSE_LOGISTIC_FUNC_PARAM sKv_b; + USHORT usLkgEuseIndex; + UCHAR ucLkgEfuseBitLSB; + UCHAR ucLkgEfuseLength; + ULONG ulLkgEncodeLn_MaxDivMin; + ULONG ulLkgEncodeMax; + ULONG ulLkgEncodeMin; + ULONG ulEfuseLogisticAlpha; + USHORT usPowerDpm0; + USHORT usPowerDpm1; + USHORT usPowerDpm2; + USHORT usPowerDpm3; + USHORT usPowerDpm4; + USHORT usPowerDpm5; + USHORT usPowerDpm6; + USHORT usPowerDpm7; + ULONG ulTdpDerateDPM0; + ULONG ulTdpDerateDPM1; + ULONG ulTdpDerateDPM2; + ULONG ulTdpDerateDPM3; + ULONG ulTdpDerateDPM4; + ULONG ulTdpDerateDPM5; + ULONG ulTdpDerateDPM6; + ULONG ulTdpDerateDPM7; + EFUSE_LINEAR_FUNC_PARAM sRoFuse; + ULONG ulEvvDefaultVddc; + ULONG ulEvvNoCalcVddc; + USHORT usParamNegFlag; + USHORT usSpeed_Model; + ULONG ulSM_A0; + ULONG ulSM_A1; + ULONG ulSM_A2; + ULONG ulSM_A3; + ULONG ulSM_A4; + ULONG ulSM_A5; + ULONG ulSM_A6; + ULONG ulSM_A7; + UCHAR ucSM_A0_sign; + UCHAR ucSM_A1_sign; + UCHAR ucSM_A2_sign; + UCHAR ucSM_A3_sign; + UCHAR ucSM_A4_sign; + UCHAR ucSM_A5_sign; + UCHAR ucSM_A6_sign; + UCHAR ucSM_A7_sign; + ULONG ulMargin_RO_a; + ULONG ulMargin_RO_b; + ULONG ulMargin_RO_c; + ULONG ulMargin_fixed; + ULONG ulMargin_Fmax_mean; + ULONG ulMargin_plat_mean; + ULONG ulMargin_Fmax_sigma; + ULONG ulMargin_plat_sigma; + ULONG ulMargin_DC_sigma; + ULONG ulReserved[8]; // Reserved for future ASIC +}ATOM_ASIC_PROFILING_INFO_V3_4; + typedef struct _ATOM_POWER_SOURCE_OBJECT { UCHAR ucPwrSrcId; // Power source diff --git a/drivers/gpu/drm/amd/include/cgs_common.h b/drivers/gpu/drm/amd/include/cgs_common.h index 992dcd8a5c6a..03affb348f69 100644 --- a/drivers/gpu/drm/amd/include/cgs_common.h +++ b/drivers/gpu/drm/amd/include/cgs_common.h @@ -105,6 +105,23 @@ enum cgs_ucode_id { CGS_UCODE_ID_MAXIMUM, }; +enum cgs_system_info_id { + CGS_SYSTEM_INFO_ADAPTER_BDF_ID = 1, + CGS_SYSTEM_INFO_PCIE_GEN_INFO, + CGS_SYSTEM_INFO_PCIE_MLW, + CGS_SYSTEM_INFO_ID_MAXIMUM, +}; + +struct cgs_system_info { + uint64_t size; + uint64_t info_id; + union { + void *ptr; + uint64_t value; + }; + uint64_t padding[13]; +}; + /** * struct cgs_clock_limits - Clock limits * @@ -127,8 +144,53 @@ struct cgs_firmware_info { void *kptr; }; +struct cgs_mode_info { + uint32_t refresh_rate; + uint32_t ref_clock; + uint32_t vblank_time_us; +}; + +struct cgs_display_info { + uint32_t display_count; + uint32_t active_display_mask; + struct cgs_mode_info *mode_info; +}; + typedef unsigned long cgs_handle_t; +#define CGS_ACPI_METHOD_ATCS 0x53435441 +#define CGS_ACPI_METHOD_ATIF 0x46495441 +#define CGS_ACPI_METHOD_ATPX 0x58505441 +#define CGS_ACPI_FIELD_METHOD_NAME 0x00000001 +#define CGS_ACPI_FIELD_INPUT_ARGUMENT_COUNT 0x00000002 +#define CGS_ACPI_MAX_BUFFER_SIZE 256 +#define CGS_ACPI_TYPE_ANY 0x00 +#define CGS_ACPI_TYPE_INTEGER 0x01 +#define CGS_ACPI_TYPE_STRING 0x02 +#define CGS_ACPI_TYPE_BUFFER 0x03 +#define CGS_ACPI_TYPE_PACKAGE 0x04 + +struct cgs_acpi_method_argument { + uint32_t type; + uint32_t method_length; + uint32_t data_length; + union{ + uint32_t value; + void *pointer; + }; +}; + +struct cgs_acpi_method_info { + uint32_t size; + uint32_t field; + uint32_t input_count; + uint32_t name; + struct cgs_acpi_method_argument *pinput_argument; + uint32_t output_count; + struct cgs_acpi_method_argument *poutput_argument; + uint32_t padding[9]; +}; + /** * cgs_gpu_mem_info() - Return information about memory heaps * @cgs_device: opaque device handle @@ -493,6 +555,21 @@ typedef int(*cgs_set_clockgating_state)(void *cgs_device, enum amd_ip_block_type block_type, enum amd_clockgating_state state); +typedef int(*cgs_get_active_displays_info)( + void *cgs_device, + struct cgs_display_info *info); + +typedef int (*cgs_call_acpi_method)(void *cgs_device, + uint32_t acpi_method, + uint32_t acpi_function, + void *pinput, void *poutput, + uint32_t output_count, + uint32_t input_size, + uint32_t output_size); + +typedef int (*cgs_query_system_info)(void *cgs_device, + struct cgs_system_info *sys_info); + struct cgs_ops { /* memory management calls (similar to KFD interface) */ cgs_gpu_mem_info_t gpu_mem_info; @@ -533,7 +610,12 @@ struct cgs_ops { /* cg pg interface*/ cgs_set_powergating_state set_powergating_state; cgs_set_clockgating_state set_clockgating_state; - /* ACPI (TODO) */ + /* display manager */ + cgs_get_active_displays_info get_active_displays_info; + /* ACPI */ + cgs_call_acpi_method call_acpi_method; + /* get system info */ + cgs_query_system_info query_system_info; }; struct cgs_os_ops; /* To be define in OS-specific CGS header */ @@ -620,5 +702,11 @@ struct cgs_device CGS_CALL(set_powergating_state, dev, block_type, state) #define cgs_set_clockgating_state(dev, block_type, state) \ CGS_CALL(set_clockgating_state, dev, block_type, state) +#define cgs_get_active_displays_info(dev, info) \ + CGS_CALL(get_active_displays_info, dev, info) +#define cgs_call_acpi_method(dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size) \ + CGS_CALL(call_acpi_method, dev, acpi_method, acpi_function, pintput, poutput, output_count, input_size, output_size) +#define cgs_query_system_info(dev, sys_info) \ + CGS_CALL(query_system_info, dev, sys_info) #endif /* _CGS_COMMON_H */ diff --git a/drivers/gpu/drm/amd/powerplay/Kconfig b/drivers/gpu/drm/amd/powerplay/Kconfig new file mode 100644 index 000000000000..af380335b425 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/Kconfig @@ -0,0 +1,6 @@ +config DRM_AMD_POWERPLAY + bool "Enable AMD powerplay component" + depends on DRM_AMDGPU + default n + help + select this option will enable AMD powerplay component. diff --git a/drivers/gpu/drm/amd/powerplay/Makefile b/drivers/gpu/drm/amd/powerplay/Makefile new file mode 100644 index 000000000000..e195bf59da86 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/Makefile @@ -0,0 +1,22 @@ + +subdir-ccflags-y += -Iinclude/drm \ + -Idrivers/gpu/drm/amd/powerplay/inc/ \ + -Idrivers/gpu/drm/amd/include/asic_reg \ + -Idrivers/gpu/drm/amd/include \ + -Idrivers/gpu/drm/amd/powerplay/smumgr\ + -Idrivers/gpu/drm/amd/powerplay/hwmgr \ + -Idrivers/gpu/drm/amd/powerplay/eventmgr + +AMD_PP_PATH = ../powerplay + +PP_LIBS = smumgr hwmgr eventmgr + +AMD_POWERPLAY = $(addsuffix /Makefile,$(addprefix drivers/gpu/drm/amd/powerplay/,$(PP_LIBS))) + +include $(AMD_POWERPLAY) + +POWER_MGR = amd_powerplay.o + +AMD_PP_POWER = $(addprefix $(AMD_PP_PATH)/,$(POWER_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_POWER) diff --git a/drivers/gpu/drm/amd/powerplay/amd_powerplay.c b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c new file mode 100644 index 000000000000..db0370bd60e3 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/amd_powerplay.c @@ -0,0 +1,634 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/gfp.h> +#include <linux/slab.h> +#include "amd_shared.h" +#include "amd_powerplay.h" +#include "pp_instance.h" +#include "power_state.h" +#include "eventmanager.h" + +static int pp_early_init(void *handle) +{ + return 0; +} + +static int pp_sw_init(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_hwmgr *hwmgr; + int ret = 0; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + hwmgr = pp_handle->hwmgr; + + if (hwmgr == NULL || hwmgr->pptable_func == NULL || + hwmgr->hwmgr_func == NULL || + hwmgr->pptable_func->pptable_init == NULL || + hwmgr->hwmgr_func->backend_init == NULL) + return -EINVAL; + + ret = hwmgr->pptable_func->pptable_init(hwmgr); + + if (ret == 0) + ret = hwmgr->hwmgr_func->backend_init(hwmgr); + + return ret; +} + +static int pp_sw_fini(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_hwmgr *hwmgr; + int ret = 0; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + hwmgr = pp_handle->hwmgr; + + if (hwmgr != NULL || hwmgr->hwmgr_func != NULL || + hwmgr->hwmgr_func->backend_fini != NULL) + ret = hwmgr->hwmgr_func->backend_fini(hwmgr); + + return ret; +} + +static int pp_hw_init(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_smumgr *smumgr; + struct pp_eventmgr *eventmgr; + int ret = 0; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + smumgr = pp_handle->smu_mgr; + + if (smumgr == NULL || smumgr->smumgr_funcs == NULL || + smumgr->smumgr_funcs->smu_init == NULL || + smumgr->smumgr_funcs->start_smu == NULL) + return -EINVAL; + + ret = smumgr->smumgr_funcs->smu_init(smumgr); + if (ret) { + printk(KERN_ERR "[ powerplay ] smc initialization failed\n"); + return ret; + } + + ret = smumgr->smumgr_funcs->start_smu(smumgr); + if (ret) { + printk(KERN_ERR "[ powerplay ] smc start failed\n"); + smumgr->smumgr_funcs->smu_fini(smumgr); + return ret; + } + + hw_init_power_state_table(pp_handle->hwmgr); + eventmgr = pp_handle->eventmgr; + + if (eventmgr == NULL || eventmgr->pp_eventmgr_init == NULL) + return -EINVAL; + + ret = eventmgr->pp_eventmgr_init(eventmgr); + return 0; +} + +static int pp_hw_fini(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_smumgr *smumgr; + struct pp_eventmgr *eventmgr; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + eventmgr = pp_handle->eventmgr; + + if (eventmgr != NULL || eventmgr->pp_eventmgr_fini != NULL) + eventmgr->pp_eventmgr_fini(eventmgr); + + smumgr = pp_handle->smu_mgr; + + if (smumgr != NULL || smumgr->smumgr_funcs != NULL || + smumgr->smumgr_funcs->smu_fini != NULL) + smumgr->smumgr_funcs->smu_fini(smumgr); + + return 0; +} + +static bool pp_is_idle(void *handle) +{ + return 0; +} + +static int pp_wait_for_idle(void *handle) +{ + return 0; +} + +static int pp_sw_reset(void *handle) +{ + return 0; +} + +static void pp_print_status(void *handle) +{ + +} + +static int pp_set_clockgating_state(void *handle, + enum amd_clockgating_state state) +{ + return 0; +} + +static int pp_set_powergating_state(void *handle, + enum amd_powergating_state state) +{ + return 0; +} + +static int pp_suspend(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_eventmgr *eventmgr; + struct pem_event_data event_data = { {0} }; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + eventmgr = pp_handle->eventmgr; + pem_handle_event(eventmgr, AMD_PP_EVENT_SUSPEND, &event_data); + return 0; +} + +static int pp_resume(void *handle) +{ + struct pp_instance *pp_handle; + struct pp_eventmgr *eventmgr; + struct pem_event_data event_data = { {0} }; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + eventmgr = pp_handle->eventmgr; + pem_handle_event(eventmgr, AMD_PP_EVENT_RESUME, &event_data); + return 0; +} + +const struct amd_ip_funcs pp_ip_funcs = { + .early_init = pp_early_init, + .late_init = NULL, + .sw_init = pp_sw_init, + .sw_fini = pp_sw_fini, + .hw_init = pp_hw_init, + .hw_fini = pp_hw_fini, + .suspend = pp_suspend, + .resume = pp_resume, + .is_idle = pp_is_idle, + .wait_for_idle = pp_wait_for_idle, + .soft_reset = pp_sw_reset, + .print_status = pp_print_status, + .set_clockgating_state = pp_set_clockgating_state, + .set_powergating_state = pp_set_powergating_state, +}; + +static int pp_dpm_load_fw(void *handle) +{ + return 0; +} + +static int pp_dpm_fw_loading_complete(void *handle) +{ + return 0; +} + +static int pp_dpm_force_performance_level(void *handle, + enum amd_dpm_forced_level level) +{ + struct pp_instance *pp_handle; + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + pp_handle = (struct pp_instance *)handle; + + hwmgr = pp_handle->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->force_dpm_level == NULL) + return -EINVAL; + + hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + + return 0; +} + +static enum amd_dpm_forced_level pp_dpm_get_performance_level( + void *handle) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL) + return -EINVAL; + + return (((struct pp_instance *)handle)->hwmgr->dpm_level); +} + +static int pp_dpm_get_sclk(void *handle, bool low) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->get_sclk == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_sclk(hwmgr, low); +} + +static int pp_dpm_get_mclk(void *handle, bool low) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->get_mclk == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_mclk(hwmgr, low); +} + +static int pp_dpm_powergate_vce(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->powergate_vce == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); +} + +static int pp_dpm_powergate_uvd(void *handle, bool gate) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->powergate_uvd == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); +} + +static enum PP_StateUILabel power_state_convert(enum amd_pm_state_type state) +{ + switch (state) { + case POWER_STATE_TYPE_BATTERY: + return PP_StateUILabel_Battery; + case POWER_STATE_TYPE_BALANCED: + return PP_StateUILabel_Balanced; + case POWER_STATE_TYPE_PERFORMANCE: + return PP_StateUILabel_Performance; + default: + return PP_StateUILabel_None; + } +} + +int pp_dpm_dispatch_tasks(void *handle, enum amd_pp_event event_id, void *input, void *output) +{ + int ret = 0; + struct pp_instance *pp_handle; + struct pem_event_data data = { {0} }; + + pp_handle = (struct pp_instance *)handle; + + if (pp_handle == NULL) + return -EINVAL; + + switch (event_id) { + case AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE: + ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); + break; + case AMD_PP_EVENT_ENABLE_USER_STATE: + { + enum amd_pm_state_type ps; + + if (input == NULL) + return -EINVAL; + ps = *(unsigned long *)input; + + data.requested_ui_label = power_state_convert(ps); + ret = pem_handle_event(pp_handle->eventmgr, event_id, &data); + } + break; + default: + break; + } + return ret; +} + +enum amd_pm_state_type pp_dpm_get_current_power_state(void *handle) +{ + struct pp_hwmgr *hwmgr; + struct pp_power_state *state; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->current_ps == NULL) + return -EINVAL; + + state = hwmgr->current_ps; + + switch (state->classification.ui_label) { + case PP_StateUILabel_Battery: + return POWER_STATE_TYPE_BATTERY; + case PP_StateUILabel_Balanced: + return POWER_STATE_TYPE_BALANCED; + case PP_StateUILabel_Performance: + return POWER_STATE_TYPE_PERFORMANCE; + default: + return POWER_STATE_TYPE_DEFAULT; + } +} + +static void +pp_debugfs_print_current_performance_level(void *handle, + struct seq_file *m) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->print_current_perforce_level == NULL) + return; + + hwmgr->hwmgr_func->print_current_perforce_level(hwmgr, m); +} + +static int pp_dpm_set_fan_control_mode(void *handle, uint32_t mode) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->set_fan_control_mode == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->set_fan_control_mode(hwmgr, mode); +} + +static int pp_dpm_get_fan_control_mode(void *handle) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->get_fan_control_mode == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_fan_control_mode(hwmgr); +} + +static int pp_dpm_set_fan_speed_percent(void *handle, uint32_t percent) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->set_fan_speed_percent == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->set_fan_speed_percent(hwmgr, percent); +} + +static int pp_dpm_get_fan_speed_percent(void *handle, uint32_t *speed) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->get_fan_speed_percent == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_fan_speed_percent(hwmgr, speed); +} + +static int pp_dpm_get_temperature(void *handle) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + if (hwmgr == NULL || hwmgr->hwmgr_func == NULL || + hwmgr->hwmgr_func->get_temperature == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_temperature(hwmgr); +} + +const struct amd_powerplay_funcs pp_dpm_funcs = { + .get_temperature = pp_dpm_get_temperature, + .load_firmware = pp_dpm_load_fw, + .wait_for_fw_loading_complete = pp_dpm_fw_loading_complete, + .force_performance_level = pp_dpm_force_performance_level, + .get_performance_level = pp_dpm_get_performance_level, + .get_current_power_state = pp_dpm_get_current_power_state, + .get_sclk = pp_dpm_get_sclk, + .get_mclk = pp_dpm_get_mclk, + .powergate_vce = pp_dpm_powergate_vce, + .powergate_uvd = pp_dpm_powergate_uvd, + .dispatch_tasks = pp_dpm_dispatch_tasks, + .print_current_performance_level = pp_debugfs_print_current_performance_level, + .set_fan_control_mode = pp_dpm_set_fan_control_mode, + .get_fan_control_mode = pp_dpm_get_fan_control_mode, + .set_fan_speed_percent = pp_dpm_set_fan_speed_percent, + .get_fan_speed_percent = pp_dpm_get_fan_speed_percent, +}; + +static int amd_pp_instance_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp) +{ + int ret; + struct pp_instance *handle; + + handle = kzalloc(sizeof(struct pp_instance), GFP_KERNEL); + if (handle == NULL) + return -ENOMEM; + + ret = smum_init(pp_init, handle); + if (ret) + goto fail_smum; + + ret = hwmgr_init(pp_init, handle); + if (ret) + goto fail_hwmgr; + + ret = eventmgr_init(handle); + if (ret) + goto fail_eventmgr; + + amd_pp->pp_handle = handle; + return 0; + +fail_eventmgr: + hwmgr_fini(handle->hwmgr); +fail_hwmgr: + smum_fini(handle->smu_mgr); +fail_smum: + kfree(handle); + return ret; +} + +static int amd_pp_instance_fini(void *handle) +{ + struct pp_instance *instance = (struct pp_instance *)handle; + + if (instance == NULL) + return -EINVAL; + + eventmgr_fini(instance->eventmgr); + + hwmgr_fini(instance->hwmgr); + + smum_fini(instance->smu_mgr); + + kfree(handle); + return 0; +} + +int amd_powerplay_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp) +{ + int ret; + + if (pp_init == NULL || amd_pp == NULL) + return -EINVAL; + + ret = amd_pp_instance_init(pp_init, amd_pp); + + if (ret) + return ret; + + amd_pp->ip_funcs = &pp_ip_funcs; + amd_pp->pp_funcs = &pp_dpm_funcs; + + return 0; +} + +int amd_powerplay_fini(void *handle) +{ + amd_pp_instance_fini(handle); + + return 0; +} + +/* export this function to DAL */ + +int amd_powerplay_display_configuration_change(void *handle, const void *input) +{ + struct pp_hwmgr *hwmgr; + const struct amd_pp_display_configuration *display_config = input; + + if (handle == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + phm_store_dal_configuration_data(hwmgr, display_config); + return 0; +} + +int amd_powerplay_get_display_power_level(void *handle, + struct amd_pp_dal_clock_info *output) +{ + struct pp_hwmgr *hwmgr; + + if (handle == NULL || output == NULL) + return -EINVAL; + + hwmgr = ((struct pp_instance *)handle)->hwmgr; + + return phm_get_dal_power_level(hwmgr, output); +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile b/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile new file mode 100644 index 000000000000..7509e3850087 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/Makefile @@ -0,0 +1,11 @@ +# +# Makefile for the 'event manager' sub-component of powerplay. +# It provides the event management services for the driver. + +EVENT_MGR = eventmgr.o eventinit.o eventmanagement.o \ + eventactionchains.o eventsubchains.o eventtasks.o psm.o + +AMD_PP_EVENT = $(addprefix $(AMD_PP_PATH)/eventmgr/,$(EVENT_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_EVENT) + diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c new file mode 100644 index 000000000000..9458394aec05 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.c @@ -0,0 +1,288 @@ +/* + * Copyright 2015 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. + * + */ +#include "eventmgr.h" +#include "eventactionchains.h" +#include "eventsubchains.h" + +static const pem_event_action *initialize_event[] = { + block_adjust_power_state_tasks, + power_budget_tasks, + system_config_tasks, + setup_asic_tasks, + enable_dynamic_state_management_tasks, + enable_clock_power_gatings_tasks, + get_2d_performance_state_tasks, + set_performance_state_tasks, + initialize_thermal_controller_tasks, + conditionally_force_3d_performance_state_tasks, + process_vbios_eventinfo_tasks, + broadcast_power_policy_tasks, + NULL +}; + +const struct action_chain initialize_action_chain = { + "Initialize", + initialize_event +}; + +static const pem_event_action *uninitialize_event[] = { + ungate_all_display_phys_tasks, + uninitialize_display_phy_access_tasks, + disable_gfx_voltage_island_power_gating_tasks, + disable_gfx_clock_gating_tasks, + set_boot_state_tasks, + adjust_power_state_tasks, + disable_dynamic_state_management_tasks, + disable_clock_power_gatings_tasks, + cleanup_asic_tasks, + prepare_for_pnp_stop_tasks, + NULL +}; + +const struct action_chain uninitialize_action_chain = { + "Uninitialize", + uninitialize_event +}; + +static const pem_event_action *power_source_change_event_pp_enabled[] = { + set_power_source_tasks, + set_power_saving_state_tasks, + adjust_power_state_tasks, + enable_disable_fps_tasks, + set_nbmcu_state_tasks, + broadcast_power_policy_tasks, + NULL +}; + +const struct action_chain power_source_change_action_chain_pp_enabled = { + "Power source change - PowerPlay enabled", + power_source_change_event_pp_enabled +}; + +static const pem_event_action *power_source_change_event_pp_disabled[] = { + set_power_source_tasks, + set_nbmcu_state_tasks, + NULL +}; + +const struct action_chain power_source_changes_action_chain_pp_disabled = { + "Power source change - PowerPlay disabled", + power_source_change_event_pp_disabled +}; + +static const pem_event_action *power_source_change_event_hardware_dc[] = { + set_power_source_tasks, + set_power_saving_state_tasks, + adjust_power_state_tasks, + enable_disable_fps_tasks, + reset_hardware_dc_notification_tasks, + set_nbmcu_state_tasks, + broadcast_power_policy_tasks, + NULL +}; + +const struct action_chain power_source_change_action_chain_hardware_dc = { + "Power source change - with Hardware DC switching", + power_source_change_event_hardware_dc +}; + +static const pem_event_action *suspend_event[] = { + reset_display_phy_access_tasks, + unregister_interrupt_tasks, + disable_gfx_voltage_island_power_gating_tasks, + disable_gfx_clock_gating_tasks, + notify_smu_suspend_tasks, + disable_smc_firmware_ctf_tasks, + set_boot_state_tasks, + adjust_power_state_tasks, + disable_fps_tasks, + vari_bright_suspend_tasks, + reset_fan_speed_to_default_tasks, + power_down_asic_tasks, + disable_stutter_mode_tasks, + set_connected_standby_tasks, + block_hw_access_tasks, + NULL +}; + +const struct action_chain suspend_action_chain = { + "Suspend", + suspend_event +}; + +static const pem_event_action *resume_event[] = { + unblock_hw_access_tasks, + resume_connected_standby_tasks, + notify_smu_resume_tasks, + reset_display_configCounter_tasks, + update_dal_configuration_tasks, + vari_bright_resume_tasks, + block_adjust_power_state_tasks, + setup_asic_tasks, + enable_stutter_mode_tasks, /*must do this in boot state and before SMC is started */ + enable_dynamic_state_management_tasks, + enable_clock_power_gatings_tasks, + enable_disable_bapm_tasks, + reset_boot_state_tasks, + adjust_power_state_tasks, + enable_disable_fps_tasks, + notify_hw_power_source_tasks, + process_vbios_event_info_tasks, + enable_gfx_clock_gating_tasks, + enable_gfx_voltage_island_power_gating_tasks, + reset_clock_gating_tasks, + notify_smu_vpu_recovery_end_tasks, + disable_vpu_cap_tasks, + execute_escape_sequence_tasks, + NULL +}; + + +const struct action_chain resume_action_chain = { + "resume", + resume_event +}; + +static const pem_event_action *complete_init_event[] = { + adjust_power_state_tasks, + enable_gfx_clock_gating_tasks, + enable_gfx_voltage_island_power_gating_tasks, + notify_power_state_change_tasks, + NULL +}; + +const struct action_chain complete_init_action_chain = { + "complete init", + complete_init_event +}; + +static const pem_event_action *enable_gfx_clock_gating_event[] = { + enable_gfx_clock_gating_tasks, + NULL +}; + +const struct action_chain enable_gfx_clock_gating_action_chain = { + "enable gfx clock gate", + enable_gfx_clock_gating_event +}; + +static const pem_event_action *disable_gfx_clock_gating_event[] = { + disable_gfx_clock_gating_tasks, + NULL +}; + +const struct action_chain disable_gfx_clock_gating_action_chain = { + "disable gfx clock gate", + disable_gfx_clock_gating_event +}; + +static const pem_event_action *enable_cgpg_event[] = { + enable_cgpg_tasks, + NULL +}; + +const struct action_chain enable_cgpg_action_chain = { + "eable cg pg", + enable_cgpg_event +}; + +static const pem_event_action *disable_cgpg_event[] = { + disable_cgpg_tasks, + NULL +}; + +const struct action_chain disable_cgpg_action_chain = { + "disable cg pg", + disable_cgpg_event +}; + + +/* Enable user _2d performance and activate */ + +static const pem_event_action *enable_user_state_event[] = { + create_new_user_performance_state_tasks, + adjust_power_state_tasks, + NULL +}; + +const struct action_chain enable_user_state_action_chain = { + "Enable user state", + enable_user_state_event +}; + +static const pem_event_action *enable_user_2d_performance_event[] = { + enable_user_2d_performance_tasks, + add_user_2d_performance_state_tasks, + set_performance_state_tasks, + adjust_power_state_tasks, + delete_user_2d_performance_state_tasks, + NULL +}; + +const struct action_chain enable_user_2d_performance_action_chain = { + "enable_user_2d_performance_event_activate", + enable_user_2d_performance_event +}; + + +static const pem_event_action *disable_user_2d_performance_event[] = { + disable_user_2d_performance_tasks, + delete_user_2d_performance_state_tasks, + NULL +}; + +const struct action_chain disable_user_2d_performance_action_chain = { + "disable_user_2d_performance_event", + disable_user_2d_performance_event +}; + + +static const pem_event_action *display_config_change_event[] = { + /* countDisplayConfigurationChangeEventTasks, */ + unblock_adjust_power_state_tasks, + set_cpu_power_state, + notify_hw_power_source_tasks, + /* updateDALConfigurationTasks, + variBrightDisplayConfigurationChangeTasks, */ + adjust_power_state_tasks, + /*enableDisableFPSTasks, + setNBMCUStateTasks, + notifyPCIEDeviceReadyTasks,*/ + NULL +}; + +const struct action_chain display_config_change_action_chain = { + "Display configuration change", + display_config_change_event +}; + +static const pem_event_action *readjust_power_state_event[] = { + adjust_power_state_tasks, + NULL +}; + +const struct action_chain readjust_power_state_action_chain = { + "re-adjust power state", + readjust_power_state_event +}; + diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h new file mode 100644 index 000000000000..f181e53cdcda --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventactionchains.h @@ -0,0 +1,62 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _EVENT_ACTION_CHAINS_H_ +#define _EVENT_ACTION_CHAINS_H_ +#include "eventmgr.h" + +extern const struct action_chain initialize_action_chain; + +extern const struct action_chain uninitialize_action_chain; + +extern const struct action_chain power_source_change_action_chain_pp_enabled; + +extern const struct action_chain power_source_changes_action_chain_pp_disabled; + +extern const struct action_chain power_source_change_action_chain_hardware_dc; + +extern const struct action_chain suspend_action_chain; + +extern const struct action_chain resume_action_chain; + +extern const struct action_chain complete_init_action_chain; + +extern const struct action_chain enable_gfx_clock_gating_action_chain; + +extern const struct action_chain disable_gfx_clock_gating_action_chain; + +extern const struct action_chain enable_cgpg_action_chain; + +extern const struct action_chain disable_cgpg_action_chain; + +extern const struct action_chain enable_user_2d_performance_action_chain; + +extern const struct action_chain disable_user_2d_performance_action_chain; + +extern const struct action_chain enable_user_state_action_chain; + +extern const struct action_chain readjust_power_state_action_chain; + +extern const struct action_chain display_config_change_action_chain; + +#endif /*_EVENT_ACTION_CHAINS_H_*/ + diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c new file mode 100644 index 000000000000..d5ec8ccbe97d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.c @@ -0,0 +1,195 @@ +/* + * Copyright 2015 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. + * + */ +#include "eventmgr.h" +#include "eventinit.h" +#include "ppinterrupt.h" +#include "hardwaremanager.h" + +void pem_init_feature_info(struct pp_eventmgr *eventmgr) +{ + + /* PowerPlay info */ + eventmgr->ui_state_info[PP_PowerSource_AC].default_ui_lable = + PP_StateUILabel_Performance; + + eventmgr->ui_state_info[PP_PowerSource_AC].current_ui_label = + PP_StateUILabel_Performance; + + eventmgr->ui_state_info[PP_PowerSource_DC].default_ui_lable = + PP_StateUILabel_Battery; + + eventmgr->ui_state_info[PP_PowerSource_DC].current_ui_label = + PP_StateUILabel_Battery; + + if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_PowerPlaySupport)) { + eventmgr->features[PP_Feature_PowerPlay].supported = true; + eventmgr->features[PP_Feature_PowerPlay].version = PEM_CURRENT_POWERPLAY_FEATURE_VERSION; + eventmgr->features[PP_Feature_PowerPlay].enabled_default = true; + eventmgr->features[PP_Feature_PowerPlay].enabled = true; + } else { + eventmgr->features[PP_Feature_PowerPlay].supported = false; + eventmgr->features[PP_Feature_PowerPlay].enabled = false; + eventmgr->features[PP_Feature_PowerPlay].enabled_default = false; + } + + eventmgr->features[PP_Feature_Force3DClock].supported = true; + eventmgr->features[PP_Feature_Force3DClock].enabled = false; + eventmgr->features[PP_Feature_Force3DClock].enabled_default = false; + eventmgr->features[PP_Feature_Force3DClock].version = 1; + + /* over drive*/ + eventmgr->features[PP_Feature_User2DPerformance].version = 4; + eventmgr->features[PP_Feature_User3DPerformance].version = 4; + eventmgr->features[PP_Feature_OverdriveTest].version = 4; + + eventmgr->features[PP_Feature_OverDrive].version = 4; + eventmgr->features[PP_Feature_OverDrive].enabled = false; + eventmgr->features[PP_Feature_OverDrive].enabled_default = false; + + eventmgr->features[PP_Feature_User2DPerformance].supported = false; + eventmgr->features[PP_Feature_User2DPerformance].enabled = false; + eventmgr->features[PP_Feature_User2DPerformance].enabled_default = false; + + eventmgr->features[PP_Feature_User3DPerformance].supported = false; + eventmgr->features[PP_Feature_User3DPerformance].enabled = false; + eventmgr->features[PP_Feature_User3DPerformance].enabled_default = false; + + eventmgr->features[PP_Feature_OverdriveTest].supported = false; + eventmgr->features[PP_Feature_OverdriveTest].enabled = false; + eventmgr->features[PP_Feature_OverdriveTest].enabled_default = false; + + eventmgr->features[PP_Feature_OverDrive].supported = false; + + eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled_default = false; + eventmgr->features[PP_Feature_PowerBudgetWaiver].version = 1; + eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false; + eventmgr->features[PP_Feature_PowerBudgetWaiver].enabled = false; + + /* Multi UVD States support */ + eventmgr->features[PP_Feature_MultiUVDState].supported = false; + eventmgr->features[PP_Feature_MultiUVDState].enabled = false; + eventmgr->features[PP_Feature_MultiUVDState].enabled_default = false; + + /* Dynamic UVD States support */ + eventmgr->features[PP_Feature_DynamicUVDState].supported = false; + eventmgr->features[PP_Feature_DynamicUVDState].enabled = false; + eventmgr->features[PP_Feature_DynamicUVDState].enabled_default = false; + + /* VCE DPM support */ + eventmgr->features[PP_Feature_VCEDPM].supported = false; + eventmgr->features[PP_Feature_VCEDPM].enabled = false; + eventmgr->features[PP_Feature_VCEDPM].enabled_default = false; + + /* ACP PowerGating support */ + eventmgr->features[PP_Feature_ACP_POWERGATING].supported = false; + eventmgr->features[PP_Feature_ACP_POWERGATING].enabled = false; + eventmgr->features[PP_Feature_ACP_POWERGATING].enabled_default = false; + + /* PPM support */ + eventmgr->features[PP_Feature_PPM].version = 1; + eventmgr->features[PP_Feature_PPM].supported = false; + eventmgr->features[PP_Feature_PPM].enabled = false; + + /* FFC support (enables fan and temp settings, Gemini needs temp settings) */ + if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ODFuzzyFanControlSupport) || + phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_GeminiRegulatorFanControlSupport)) { + eventmgr->features[PP_Feature_FFC].version = 1; + eventmgr->features[PP_Feature_FFC].supported = true; + eventmgr->features[PP_Feature_FFC].enabled = true; + eventmgr->features[PP_Feature_FFC].enabled_default = true; + } else { + eventmgr->features[PP_Feature_FFC].supported = false; + eventmgr->features[PP_Feature_FFC].enabled = false; + eventmgr->features[PP_Feature_FFC].enabled_default = false; + } + + eventmgr->features[PP_Feature_VariBright].supported = false; + eventmgr->features[PP_Feature_VariBright].enabled = false; + eventmgr->features[PP_Feature_VariBright].enabled_default = false; + + eventmgr->features[PP_Feature_BACO].supported = false; + eventmgr->features[PP_Feature_BACO].supported = false; + eventmgr->features[PP_Feature_BACO].enabled_default = false; + + /* PowerDown feature support */ + eventmgr->features[PP_Feature_PowerDown].supported = false; + eventmgr->features[PP_Feature_PowerDown].enabled = false; + eventmgr->features[PP_Feature_PowerDown].enabled_default = false; + + eventmgr->features[PP_Feature_FPS].version = 1; + eventmgr->features[PP_Feature_FPS].supported = false; + eventmgr->features[PP_Feature_FPS].enabled_default = false; + eventmgr->features[PP_Feature_FPS].enabled = false; + + eventmgr->features[PP_Feature_ViPG].version = 1; + eventmgr->features[PP_Feature_ViPG].supported = false; + eventmgr->features[PP_Feature_ViPG].enabled_default = false; + eventmgr->features[PP_Feature_ViPG].enabled = false; +} + +static int thermal_interrupt_callback(void *private_data, + unsigned src_id, const uint32_t *iv_entry) +{ + /* TO DO hanle PEM_Event_ThermalNotification (struct pp_eventmgr *)private_data*/ + printk("current thermal is out of range \n"); + return 0; +} + +int pem_register_interrupts(struct pp_eventmgr *eventmgr) +{ + int result = 0; + struct pp_interrupt_registration_info info; + + info.call_back = thermal_interrupt_callback; + info.context = eventmgr; + + result = phm_register_thermal_interrupt(eventmgr->hwmgr, &info); + + /* TODO: + * 2. Register CTF event interrupt + * 3. Register for vbios events interrupt + * 4. Register External Throttle Interrupt + * 5. Register Smc To Host Interrupt + * */ + return result; +} + + +int pem_unregister_interrupts(struct pp_eventmgr *eventmgr) +{ + return 0; +} + + +void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr) +{ + eventmgr->features[PP_Feature_MultiUVDState].supported = false; + eventmgr->features[PP_Feature_VariBright].supported = false; + eventmgr->features[PP_Feature_PowerBudgetWaiver].supported = false; + eventmgr->features[PP_Feature_OverDrive].supported = false; + eventmgr->features[PP_Feature_OverdriveTest].supported = false; + eventmgr->features[PP_Feature_User3DPerformance].supported = false; + eventmgr->features[PP_Feature_User2DPerformance].supported = false; + eventmgr->features[PP_Feature_PowerPlay].supported = false; + eventmgr->features[PP_Feature_Force3DClock].supported = false; +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h new file mode 100644 index 000000000000..9ef96aab3f24 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventinit.h @@ -0,0 +1,34 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _EVENTINIT_H_ +#define _EVENTINIT_H_ + +#define PEM_CURRENT_POWERPLAY_FEATURE_VERSION 4 + +void pem_init_feature_info(struct pp_eventmgr *eventmgr); +void pem_uninit_featureInfo(struct pp_eventmgr *eventmgr); +int pem_register_interrupts(struct pp_eventmgr *eventmgr); +int pem_unregister_interrupts(struct pp_eventmgr *eventmgr); + +#endif /* _EVENTINIT_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c new file mode 100644 index 000000000000..1e2ad5603080 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.c @@ -0,0 +1,215 @@ +/* + * Copyright 2015 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. + * + */ +#include "eventmanagement.h" +#include "eventmgr.h" +#include "eventactionchains.h" + +int pem_init_event_action_chains(struct pp_eventmgr *eventmgr) +{ + int i; + + for (i = 0; i < AMD_PP_EVENT_MAX; i++) + eventmgr->event_chain[i] = NULL; + + eventmgr->event_chain[AMD_PP_EVENT_SUSPEND] = pem_get_suspend_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_INITIALIZE] = pem_get_initialize_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_UNINITIALIZE] = pem_get_uninitialize_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_POWER_SOURCE_CHANGE] = pem_get_power_source_change_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_HIBERNATE] = pem_get_hibernate_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_RESUME] = pem_get_resume_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_THERMAL_NOTIFICATION] = pem_get_thermal_notification_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_VBIOS_NOTIFICATION] = pem_get_vbios_notification_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENTER_THERMAL_STATE] = pem_get_enter_thermal_state_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_EXIT_THERMAL_STATE] = pem_get_exit_thermal_state_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENABLE_POWER_PLAY] = pem_get_enable_powerplay_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_DISABLE_POWER_PLAY] = pem_get_disable_powerplay_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST] = pem_get_enable_overdrive_test_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST] = pem_get_disable_overdrive_test_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING] = pem_get_enable_gfx_clock_gating_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING] = pem_get_disable_gfx_clock_gating_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENABLE_CGPG] = pem_get_enable_cgpg_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_DISABLE_CGPG] = pem_get_disable_cgpg_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_COMPLETE_INIT] = pem_get_complete_init_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_SCREEN_ON] = pem_get_screen_on_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_SCREEN_OFF] = pem_get_screen_off_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_PRE_SUSPEND] = pem_get_pre_suspend_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_PRE_RESUME] = pem_get_pre_resume_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_ENABLE_USER_STATE] = pem_enable_user_state_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_READJUST_POWER_STATE] = pem_readjust_power_state_action_chain(eventmgr); + eventmgr->event_chain[AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE] = pem_display_config_change_action_chain(eventmgr); + return 0; +} + +int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data) +{ + const pem_event_action **paction_chain; + const pem_event_action *psub_chain; + int tmp_result = 0; + int result = 0; + + if (eventmgr == NULL || event_chain == NULL || event_data == NULL) + return -EINVAL; + + for (paction_chain = event_chain->action_chain; NULL != *paction_chain; paction_chain++) { + if (0 != result) + return result; + + for (psub_chain = *paction_chain; NULL != *psub_chain; psub_chain++) { + tmp_result = (*psub_chain)(eventmgr, event_data); + if (0 == result) + result = tmp_result; + } + } + + return result; +} + +const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr) +{ + return &suspend_action_chain; +} + +const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr) +{ + return &initialize_action_chain; +} + +const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr) +{ + return &uninitialize_action_chain; +} + +const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr) +{ + return &power_source_change_action_chain_pp_enabled; /* other case base on feature info*/ +} + +const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr) +{ + return &resume_action_chain; +} + +const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr) +{ + return &enable_gfx_clock_gating_action_chain; +} + +const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr) +{ + return &disable_gfx_clock_gating_action_chain; +} + +const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr) +{ + return &enable_cgpg_action_chain; +} + +const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr) +{ + return &disable_cgpg_action_chain; +} + +const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr) +{ + return &complete_init_action_chain; +} + +const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr) +{ + return NULL; +} + +const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr) +{ + return &enable_user_state_action_chain; +} + +const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr) +{ + return &readjust_power_state_action_chain; +} + +const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr) +{ + return &display_config_change_action_chain; +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h new file mode 100644 index 000000000000..383d4b295aa9 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmanagement.h @@ -0,0 +1,59 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _EVENT_MANAGEMENT_H_ +#define _EVENT_MANAGEMENT_H_ + +#include "eventmgr.h" + +int pem_init_event_action_chains(struct pp_eventmgr *eventmgr); +int pem_excute_event_chain(struct pp_eventmgr *eventmgr, const struct action_chain *event_chain, struct pem_event_data *event_data); +const struct action_chain *pem_get_suspend_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_initialize_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_uninitialize_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_power_source_change_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_resume_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_hibernate_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_thermal_notification_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_vbios_notification_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_enter_thermal_state_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_exit_thermal_state_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_enable_powerplay_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_disable_powerplay_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_enable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_disable_overdrive_test_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_enable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_disable_gfx_clock_gating_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_enable_cgpg_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_disable_cgpg_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_complete_init_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_screen_on_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_screen_off_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_pre_suspend_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_get_pre_resume_action_chain(struct pp_eventmgr *eventmgr); + +extern const struct action_chain *pem_enable_user_state_action_chain(struct pp_eventmgr *eventmgr); +extern const struct action_chain *pem_readjust_power_state_action_chain(struct pp_eventmgr *eventmgr); +const struct action_chain *pem_display_config_change_action_chain(struct pp_eventmgr *eventmgr); + + +#endif /* _EVENT_MANAGEMENT_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c new file mode 100644 index 000000000000..52a3efc97f05 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventmgr.c @@ -0,0 +1,114 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "eventmgr.h" +#include "hwmgr.h" +#include "eventinit.h" +#include "eventmanagement.h" + +static int pem_init(struct pp_eventmgr *eventmgr) +{ + int result = 0; + struct pem_event_data event_data; + + /* Initialize PowerPlay feature info */ + pem_init_feature_info(eventmgr); + + /* Initialize event action chains */ + pem_init_event_action_chains(eventmgr); + + /* Call initialization event */ + result = pem_handle_event(eventmgr, AMD_PP_EVENT_INITIALIZE, &event_data); + + if (0 != result) + return result; + + /* Register interrupt callback functions */ + result = pem_register_interrupts(eventmgr); + return 0; +} + +static void pem_fini(struct pp_eventmgr *eventmgr) +{ + struct pem_event_data event_data; + + pem_uninit_featureInfo(eventmgr); + pem_unregister_interrupts(eventmgr); + + pem_handle_event(eventmgr, AMD_PP_EVENT_UNINITIALIZE, &event_data); + + if (eventmgr != NULL) + kfree(eventmgr); +} + +int eventmgr_init(struct pp_instance *handle) +{ + int result = 0; + struct pp_eventmgr *eventmgr; + + if (handle == NULL) + return -EINVAL; + + eventmgr = kzalloc(sizeof(struct pp_eventmgr), GFP_KERNEL); + if (eventmgr == NULL) + return -ENOMEM; + + eventmgr->hwmgr = handle->hwmgr; + handle->eventmgr = eventmgr; + + eventmgr->platform_descriptor = &(eventmgr->hwmgr->platform_descriptor); + eventmgr->pp_eventmgr_init = pem_init; + eventmgr->pp_eventmgr_fini = pem_fini; + + return result; +} + +int eventmgr_fini(struct pp_eventmgr *eventmgr) +{ + kfree(eventmgr); + return 0; +} + +static int pem_handle_event_unlocked(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *data) +{ + if (eventmgr == NULL || event >= AMD_PP_EVENT_MAX || data == NULL) + return -EINVAL; + + return pem_excute_event_chain(eventmgr, eventmgr->event_chain[event], data); +} + +int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event, struct pem_event_data *event_data) +{ + int r = 0; + + r = pem_handle_event_unlocked(eventmgr, event, event_data); + + return r; +} + +bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr) +{ + return (eventmgr->block_adjust_power_state || phm_is_hw_access_blocked(eventmgr->hwmgr)); +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c new file mode 100644 index 000000000000..9ef2d90e2886 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.c @@ -0,0 +1,410 @@ +/* + * Copyright 2015 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. + * + */ + +#include "eventmgr.h" +#include "eventsubchains.h" +#include "eventtasks.h" +#include "hardwaremanager.h" + +const pem_event_action reset_display_phy_access_tasks[] = { + pem_task_reset_display_phys_access, + NULL +}; + +const pem_event_action broadcast_power_policy_tasks[] = { + /* PEM_Task_BroadcastPowerPolicyChange, */ + NULL +}; + +const pem_event_action unregister_interrupt_tasks[] = { + pem_task_unregister_interrupts, + NULL +}; + +/* Disable GFX Voltage Islands Power Gating */ +const pem_event_action disable_gfx_voltage_island_powergating_tasks[] = { + pem_task_disable_voltage_island_power_gating, + NULL +}; + +const pem_event_action disable_gfx_clockgating_tasks[] = { + pem_task_disable_gfx_clock_gating, + NULL +}; + +const pem_event_action block_adjust_power_state_tasks[] = { + pem_task_block_adjust_power_state, + NULL +}; + + +const pem_event_action unblock_adjust_power_state_tasks[] = { + pem_task_unblock_adjust_power_state, + NULL +}; + +const pem_event_action set_performance_state_tasks[] = { + pem_task_set_performance_state, + NULL +}; + +const pem_event_action get_2d_performance_state_tasks[] = { + pem_task_get_2D_performance_state_id, + NULL +}; + +const pem_event_action conditionally_force3D_performance_state_tasks[] = { + pem_task_conditionally_force_3d_performance_state, + NULL +}; + +const pem_event_action process_vbios_eventinfo_tasks[] = { + /* PEM_Task_ProcessVbiosEventInfo,*/ + NULL +}; + +const pem_event_action enable_dynamic_state_management_tasks[] = { + /* PEM_Task_ResetBAPMPolicyChangedFlag,*/ + pem_task_get_boot_state_id, + pem_task_enable_dynamic_state_management, + pem_task_register_interrupts, + NULL +}; + +const pem_event_action enable_clock_power_gatings_tasks[] = { + pem_task_enable_clock_power_gatings_tasks, + pem_task_powerdown_uvd_tasks, + pem_task_powerdown_vce_tasks, + NULL +}; + +const pem_event_action setup_asic_tasks[] = { + pem_task_setup_asic, + NULL +}; + +const pem_event_action power_budget_tasks[] = { + /* TODO + * PEM_Task_PowerBudgetWaiverAvailable, + * PEM_Task_PowerBudgetWarningMessage, + * PEM_Task_PruneStatesBasedOnPowerBudget, + */ + NULL +}; + +const pem_event_action system_config_tasks[] = { + /* PEM_Task_PruneStatesBasedOnSystemConfig,*/ + NULL +}; + + +const pem_event_action conditionally_force_3d_performance_state_tasks[] = { + pem_task_conditionally_force_3d_performance_state, + NULL +}; + +const pem_event_action ungate_all_display_phys_tasks[] = { + /* PEM_Task_GetDisplayPhyAccessInfo */ + NULL +}; + +const pem_event_action uninitialize_display_phy_access_tasks[] = { + /* PEM_Task_UninitializeDisplayPhysAccess, */ + NULL +}; + +const pem_event_action disable_gfx_voltage_island_power_gating_tasks[] = { + /* PEM_Task_DisableVoltageIslandPowerGating, */ + NULL +}; + +const pem_event_action disable_gfx_clock_gating_tasks[] = { + pem_task_disable_gfx_clock_gating, + NULL +}; + +const pem_event_action set_boot_state_tasks[] = { + pem_task_get_boot_state_id, + pem_task_set_boot_state, + NULL +}; + +const pem_event_action adjust_power_state_tasks[] = { + pem_task_notify_hw_mgr_display_configuration_change, + pem_task_adjust_power_state, + pem_task_notify_smc_display_config_after_power_state_adjustment, + pem_task_update_allowed_performance_levels, + /* to do pem_task_Enable_disable_bapm, */ + NULL +}; + +const pem_event_action disable_dynamic_state_management_tasks[] = { + pem_task_unregister_interrupts, + pem_task_get_boot_state_id, + pem_task_disable_dynamic_state_management, + NULL +}; + +const pem_event_action disable_clock_power_gatings_tasks[] = { + pem_task_disable_clock_power_gatings_tasks, + NULL +}; + +const pem_event_action cleanup_asic_tasks[] = { + /* PEM_Task_DisableFPS,*/ + pem_task_cleanup_asic, + NULL +}; + +const pem_event_action prepare_for_pnp_stop_tasks[] = { + /* PEM_Task_PrepareForPnpStop,*/ + NULL +}; + +const pem_event_action set_power_source_tasks[] = { + pem_task_set_power_source, + pem_task_notify_hw_of_power_source, + NULL +}; + +const pem_event_action set_power_saving_state_tasks[] = { + pem_task_reset_power_saving_state, + pem_task_get_power_saving_state, + pem_task_set_power_saving_state, + /* PEM_Task_ResetODDCState, + * PEM_Task_GetODDCState, + * PEM_Task_SetODDCState,*/ + NULL +}; + +const pem_event_action enable_disable_fps_tasks[] = { + /* PEM_Task_EnableDisableFPS,*/ + NULL +}; + +const pem_event_action set_nbmcu_state_tasks[] = { + /* PEM_Task_NBMCUStateChange,*/ + NULL +}; + +const pem_event_action reset_hardware_dc_notification_tasks[] = { + /* PEM_Task_ResetHardwareDCNotification,*/ + NULL +}; + + +const pem_event_action notify_smu_suspend_tasks[] = { + /* PEM_Task_NotifySMUSuspend,*/ + NULL +}; + +const pem_event_action disable_smc_firmware_ctf_tasks[] = { + /* PEM_Task_DisableSMCFirmwareCTF,*/ + NULL +}; + +const pem_event_action disable_fps_tasks[] = { + /* PEM_Task_DisableFPS,*/ + NULL +}; + +const pem_event_action vari_bright_suspend_tasks[] = { + /* PEM_Task_VariBright_Suspend,*/ + NULL +}; + +const pem_event_action reset_fan_speed_to_default_tasks[] = { + /* PEM_Task_ResetFanSpeedToDefault,*/ + NULL +}; + +const pem_event_action power_down_asic_tasks[] = { + /* PEM_Task_DisableFPS,*/ + pem_task_power_down_asic, + NULL +}; + +const pem_event_action disable_stutter_mode_tasks[] = { + /* PEM_Task_DisableStutterMode,*/ + NULL +}; + +const pem_event_action set_connected_standby_tasks[] = { + /* PEM_Task_SetConnectedStandby,*/ + NULL +}; + +const pem_event_action block_hw_access_tasks[] = { + pem_task_block_hw_access, + NULL +}; + +const pem_event_action unblock_hw_access_tasks[] = { + pem_task_un_block_hw_access, + NULL +}; + +const pem_event_action resume_connected_standby_tasks[] = { + /* PEM_Task_ResumeConnectedStandby,*/ + NULL +}; + +const pem_event_action notify_smu_resume_tasks[] = { + /* PEM_Task_NotifySMUResume,*/ + NULL +}; + +const pem_event_action reset_display_configCounter_tasks[] = { + pem_task_reset_display_phys_access, + NULL +}; + +const pem_event_action update_dal_configuration_tasks[] = { + /* PEM_Task_CheckVBlankTime,*/ + NULL +}; + +const pem_event_action vari_bright_resume_tasks[] = { + /* PEM_Task_VariBright_Resume,*/ + NULL +}; + +const pem_event_action notify_hw_power_source_tasks[] = { + pem_task_notify_hw_of_power_source, + NULL +}; + +const pem_event_action process_vbios_event_info_tasks[] = { + /* PEM_Task_ProcessVbiosEventInfo,*/ + NULL +}; + +const pem_event_action enable_gfx_clock_gating_tasks[] = { + pem_task_enable_gfx_clock_gating, + NULL +}; + +const pem_event_action enable_gfx_voltage_island_power_gating_tasks[] = { + pem_task_enable_voltage_island_power_gating, + NULL +}; + +const pem_event_action reset_clock_gating_tasks[] = { + /* PEM_Task_ResetClockGating*/ + NULL +}; + +const pem_event_action notify_smu_vpu_recovery_end_tasks[] = { + /* PEM_Task_NotifySmuVPURecoveryEnd,*/ + NULL +}; + +const pem_event_action disable_vpu_cap_tasks[] = { + /* PEM_Task_DisableVPUCap,*/ + NULL +}; + +const pem_event_action execute_escape_sequence_tasks[] = { + /* PEM_Task_ExecuteEscapesequence,*/ + NULL +}; + +const pem_event_action notify_power_state_change_tasks[] = { + pem_task_notify_power_state_change, + NULL +}; + +const pem_event_action enable_cgpg_tasks[] = { + pem_task_enable_cgpg, + NULL +}; + +const pem_event_action disable_cgpg_tasks[] = { + pem_task_disable_cgpg, + NULL +}; + +const pem_event_action enable_user_2d_performance_tasks[] = { + /* PEM_Task_SetUser2DPerformanceFlag,*/ + /* PEM_Task_UpdateUser2DPerformanceEnableEvents,*/ + NULL +}; + +const pem_event_action add_user_2d_performance_state_tasks[] = { + /* PEM_Task_Get2DPerformanceTemplate,*/ + /* PEM_Task_AllocateNewPowerStateMemory,*/ + /* PEM_Task_CopyNewPowerStateInfo,*/ + /* PEM_Task_UpdateNewPowerStateClocks,*/ + /* PEM_Task_UpdateNewPowerStateUser2DPerformanceFlag,*/ + /* PEM_Task_AddPowerState,*/ + /* PEM_Task_ReleaseNewPowerStateMemory,*/ + NULL +}; + +const pem_event_action delete_user_2d_performance_state_tasks[] = { + /* PEM_Task_GetCurrentUser2DPerformanceStateID,*/ + /* PEM_Task_DeletePowerState,*/ + /* PEM_Task_SetCurrentUser2DPerformanceStateID,*/ + NULL +}; + +const pem_event_action disable_user_2d_performance_tasks[] = { + /* PEM_Task_ResetUser2DPerformanceFlag,*/ + /* PEM_Task_UpdateUser2DPerformanceDisableEvents,*/ + NULL +}; + +const pem_event_action enable_stutter_mode_tasks[] = { + pem_task_enable_stutter_mode, + NULL +}; + +const pem_event_action enable_disable_bapm_tasks[] = { + /*PEM_Task_EnableDisableBAPM,*/ + NULL +}; + +const pem_event_action reset_boot_state_tasks[] = { + pem_task_reset_boot_state, + NULL +}; + +const pem_event_action create_new_user_performance_state_tasks[] = { + pem_task_create_user_performance_state, + NULL +}; + +const pem_event_action initialize_thermal_controller_tasks[] = { + pem_task_initialize_thermal_controller, + NULL +}; + +const pem_event_action uninitialize_thermal_controller_tasks[] = { + pem_task_uninitialize_thermal_controller, + NULL +}; + +const pem_event_action set_cpu_power_state[] = { + pem_task_set_cpu_power_state, + NULL +};
\ No newline at end of file diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h new file mode 100644 index 000000000000..7714cb927428 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventsubchains.h @@ -0,0 +1,100 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _EVENT_SUB_CHAINS_H_ +#define _EVENT_SUB_CHAINS_H_ + +#include "eventmgr.h" + +extern const pem_event_action reset_display_phy_access_tasks[]; +extern const pem_event_action broadcast_power_policy_tasks[]; +extern const pem_event_action unregister_interrupt_tasks[]; +extern const pem_event_action disable_GFX_voltage_island_powergating_tasks[]; +extern const pem_event_action disable_GFX_clockgating_tasks[]; +extern const pem_event_action block_adjust_power_state_tasks[]; +extern const pem_event_action unblock_adjust_power_state_tasks[]; +extern const pem_event_action set_performance_state_tasks[]; +extern const pem_event_action get_2D_performance_state_tasks[]; +extern const pem_event_action conditionally_force3D_performance_state_tasks[]; +extern const pem_event_action process_vbios_eventinfo_tasks[]; +extern const pem_event_action enable_dynamic_state_management_tasks[]; +extern const pem_event_action enable_clock_power_gatings_tasks[]; +extern const pem_event_action conditionally_force3D_performance_state_tasks[]; +extern const pem_event_action setup_asic_tasks[]; +extern const pem_event_action power_budget_tasks[]; +extern const pem_event_action system_config_tasks[]; +extern const pem_event_action get_2d_performance_state_tasks[]; +extern const pem_event_action conditionally_force_3d_performance_state_tasks[]; +extern const pem_event_action ungate_all_display_phys_tasks[]; +extern const pem_event_action uninitialize_display_phy_access_tasks[]; +extern const pem_event_action disable_gfx_voltage_island_power_gating_tasks[]; +extern const pem_event_action disable_gfx_clock_gating_tasks[]; +extern const pem_event_action set_boot_state_tasks[]; +extern const pem_event_action adjust_power_state_tasks[]; +extern const pem_event_action disable_dynamic_state_management_tasks[]; +extern const pem_event_action disable_clock_power_gatings_tasks[]; +extern const pem_event_action cleanup_asic_tasks[]; +extern const pem_event_action prepare_for_pnp_stop_tasks[]; +extern const pem_event_action set_power_source_tasks[]; +extern const pem_event_action set_power_saving_state_tasks[]; +extern const pem_event_action enable_disable_fps_tasks[]; +extern const pem_event_action set_nbmcu_state_tasks[]; +extern const pem_event_action reset_hardware_dc_notification_tasks[]; +extern const pem_event_action notify_smu_suspend_tasks[]; +extern const pem_event_action disable_smc_firmware_ctf_tasks[]; +extern const pem_event_action disable_fps_tasks[]; +extern const pem_event_action vari_bright_suspend_tasks[]; +extern const pem_event_action reset_fan_speed_to_default_tasks[]; +extern const pem_event_action power_down_asic_tasks[]; +extern const pem_event_action disable_stutter_mode_tasks[]; +extern const pem_event_action set_connected_standby_tasks[]; +extern const pem_event_action block_hw_access_tasks[]; +extern const pem_event_action unblock_hw_access_tasks[]; +extern const pem_event_action resume_connected_standby_tasks[]; +extern const pem_event_action notify_smu_resume_tasks[]; +extern const pem_event_action reset_display_configCounter_tasks[]; +extern const pem_event_action update_dal_configuration_tasks[]; +extern const pem_event_action vari_bright_resume_tasks[]; +extern const pem_event_action notify_hw_power_source_tasks[]; +extern const pem_event_action process_vbios_event_info_tasks[]; +extern const pem_event_action enable_gfx_clock_gating_tasks[]; +extern const pem_event_action enable_gfx_voltage_island_power_gating_tasks[]; +extern const pem_event_action reset_clock_gating_tasks[]; +extern const pem_event_action notify_smu_vpu_recovery_end_tasks[]; +extern const pem_event_action disable_vpu_cap_tasks[]; +extern const pem_event_action execute_escape_sequence_tasks[]; +extern const pem_event_action notify_power_state_change_tasks[]; +extern const pem_event_action enable_cgpg_tasks[]; +extern const pem_event_action disable_cgpg_tasks[]; +extern const pem_event_action enable_user_2d_performance_tasks[]; +extern const pem_event_action add_user_2d_performance_state_tasks[]; +extern const pem_event_action delete_user_2d_performance_state_tasks[]; +extern const pem_event_action disable_user_2d_performance_tasks[]; +extern const pem_event_action enable_stutter_mode_tasks[]; +extern const pem_event_action enable_disable_bapm_tasks[]; +extern const pem_event_action reset_boot_state_tasks[]; +extern const pem_event_action create_new_user_performance_state_tasks[]; +extern const pem_event_action initialize_thermal_controller_tasks[]; +extern const pem_event_action uninitialize_thermal_controller_tasks[]; +extern const pem_event_action set_cpu_power_state[]; +#endif /* _EVENT_SUB_CHAINS_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c new file mode 100644 index 000000000000..f0700d077925 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.c @@ -0,0 +1,437 @@ +/* + * Copyright 2015 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. + * + */ + +#include "eventmgr.h" +#include "eventinit.h" +#include "eventmanagement.h" +#include "eventmanager.h" +#include "hardwaremanager.h" +#include "eventtasks.h" +#include "power_state.h" +#include "hwmgr.h" +#include "amd_powerplay.h" +#include "psm.h" + +#define TEMP_RANGE_MIN (90 * 1000) +#define TEMP_RANGE_MAX (120 * 1000) + +int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + + if (pem_is_hw_access_blocked(eventmgr)) + return 0; + + phm_force_dpm_levels(eventmgr->hwmgr, AMD_DPM_FORCED_LEVEL_AUTO); + + return 0; +} + +/* eventtasks_generic.c */ +int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + struct pp_hwmgr *hwmgr; + + if (pem_is_hw_access_blocked(eventmgr)) + return 0; + + hwmgr = eventmgr->hwmgr; + if (event_data->pnew_power_state != NULL) + hwmgr->request_ps = event_data->pnew_power_state; + + if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_DynamicPatchPowerState)) + psm_adjust_power_state_dynamic(eventmgr, event_data->skip_state_adjust_rules); + else + psm_adjust_power_state_static(eventmgr, event_data->skip_state_adjust_rules); + + return 0; +} + +int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return pem_unregister_interrupts(eventmgr); +} + +int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + int result; + + result = psm_get_state_by_classification(eventmgr, + PP_StateClassificationFlag_Boot, + &(event_data->requested_state_id) + ); + + if (0 == result) + pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); + else + pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); + + return result; +} + +int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_enable_dynamic_state_management(eventmgr->hwmgr); +} + +int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_enable_clock_power_gatings(eventmgr->hwmgr); +} + +int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_powerdown_uvd(eventmgr->hwmgr); +} + +int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + phm_powergate_uvd(eventmgr->hwmgr, true); + phm_powergate_vce(eventmgr->hwmgr, true); + return 0; +} + +int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_setup_asic(eventmgr->hwmgr); +} + +int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_store_dal_configuration(struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config) +{ + /* TODO */ + return 0; + /*phm_store_dal_configuration_data(eventmgr->hwmgr, display_config) */ +} + +int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + if (pem_is_hw_access_blocked(eventmgr)) + return 0; + + return phm_display_configuration_changed(eventmgr->hwmgr); +} + +int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return 0; +} + +int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + if (pem_is_hw_access_blocked(eventmgr)) + return 0; + + return phm_notify_smc_display_config_after_ps_adjustment(eventmgr->hwmgr); +} + +int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + eventmgr->block_adjust_power_state = true; + /* to do PHM_ResetIPSCounter(pEventMgr->pHwMgr);*/ + return 0; +} + +int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + eventmgr->block_adjust_power_state = false; + return 0; +} + +int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_set_cpu_power_state(eventmgr->hwmgr); +} + +/*powersaving*/ + +int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_enable_clock_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + + +int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + + +/* performance */ +int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + if (pem_is_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID)) + return psm_set_performance_states(eventmgr, &(event_data->requested_state_id)); + + return 0; +} + +int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + /* TODO */ + return 0; +} + +int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + int result; + + if (eventmgr->features[PP_Feature_PowerPlay].supported && + !(eventmgr->features[PP_Feature_PowerPlay].enabled)) + result = psm_get_state_by_classification(eventmgr, + PP_StateClassificationFlag_Boot, + &(event_data->requested_state_id)); + else if (eventmgr->features[PP_Feature_User2DPerformance].enabled) + result = psm_get_state_by_classification(eventmgr, + PP_StateClassificationFlag_User2DPerformance, + &(event_data->requested_state_id)); + else + result = psm_get_ui_state(eventmgr, PP_StateUILabel_Performance, + &(event_data->requested_state_id)); + + if (0 == result) + pem_set_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); + else + pem_unset_event_data_valid(event_data->valid_fields, PEM_EventDataValid_RequestedStateID); + + return result; +} + +int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + struct pp_power_state *state; + int table_entries; + struct pp_hwmgr *hwmgr = eventmgr->hwmgr; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + +restart_search: + for (i = 0; i < table_entries; i++) { + if (state->classification.ui_label & event_data->requested_ui_label) { + event_data->pnew_power_state = state; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + + switch (event_data->requested_ui_label) { + case PP_StateUILabel_Battery: + case PP_StateUILabel_Balanced: + event_data->requested_ui_label = PP_StateUILabel_Performance; + goto restart_search; + default: + break; + } + return -1; +} + +int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + struct PP_TemperatureRange range; + + range.max = TEMP_RANGE_MAX; + range.min = TEMP_RANGE_MIN; + + if (eventmgr == NULL || eventmgr->platform_descriptor == NULL) + return -EINVAL; + + if (phm_cap_enabled(eventmgr->platform_descriptor->platformCaps, PHM_PlatformCaps_ThermalController)) + return phm_start_thermal_controller(eventmgr->hwmgr, &range); + + return 0; +} + +int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data) +{ + return phm_stop_thermal_controller(eventmgr->hwmgr); +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h new file mode 100644 index 000000000000..6c6297e3b598 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/eventtasks.h @@ -0,0 +1,88 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _EVENT_TASKS_H_ +#define _EVENT_TASKS_H_ +#include "eventmgr.h" + +struct amd_display_configuration; + +/* eventtasks_generic.c */ +int pem_task_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_power_down_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_get_boot_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_set_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_reset_boot_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_update_new_power_state_clocks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_system_shutdown(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_register_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_unregister_interrupts(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_dynamic_state_management(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_powerdown_uvd_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_powerdown_vce_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_clock_power_gatings_tasks(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_start_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_stop_asic_block_usage(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_setup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_cleanup_asic(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_store_dal_configuration (struct pp_eventmgr *eventmgr, const struct amd_display_configuration *display_config); +int pem_task_notify_hw_mgr_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_notify_hw_mgr_pre_display_configuration_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_block_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_unblock_adjust_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_notify_power_state_change(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_un_block_hw_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_reset_display_phys_access(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_set_cpu_power_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_notify_smc_display_config_after_power_state_adjustment(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +/*powersaving*/ + +int pem_task_set_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_notify_hw_of_power_source(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_get_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_reset_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_set_power_saving_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_set_screen_state_on(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_set_screen_state_off(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_voltage_island_power_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_cgpg(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_disable_gfx_clock_gating(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_enable_stutter_mode(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); + +/* performance */ +int pem_task_set_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_conditionally_force_3d_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_get_2D_performance_state_id(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_create_user_performance_state(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_update_allowed_performance_levels(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +/*thermal */ +int pem_task_initialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); +int pem_task_uninitialize_thermal_controller(struct pp_eventmgr *eventmgr, struct pem_event_data *event_data); + +#endif /* _EVENT_TASKS_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c new file mode 100644 index 000000000000..5740fbfcbeab --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.c @@ -0,0 +1,118 @@ +/* + * Copyright 2015 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. + * + */ +#include "psm.h" + +int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + struct pp_hwmgr *hwmgr = eventmgr->hwmgr; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.ui_label & ui_label) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -1; +} + +int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + struct pp_hwmgr *hwmgr = eventmgr->hwmgr; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->classification.flags & flag) { + *state_id = state->id; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -1; +} + +int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *state_id) +{ + struct pp_power_state *state; + int table_entries; + struct pp_hwmgr *hwmgr = eventmgr->hwmgr; + int i; + + table_entries = hwmgr->num_ps; + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + if (state->id == *state_id) { + hwmgr->request_ps = state; + return 0; + } + state = (struct pp_power_state *)((unsigned long)state + hwmgr->ps_size); + } + return -1; +} + + +int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip) +{ + + struct pp_power_state *pcurrent; + struct pp_power_state *requested; + struct pp_hwmgr *hwmgr; + bool equal; + + if (skip) + return 0; + + hwmgr = eventmgr->hwmgr; + pcurrent = hwmgr->current_ps; + requested = hwmgr->request_ps; + + if (requested == NULL) + return 0; + + if (pcurrent == NULL || (0 != phm_check_states_equal(hwmgr, &pcurrent->hardware, &requested->hardware, &equal))) + equal = false; + + if (!equal || phm_check_smc_update_required_for_display_configuration(hwmgr)) { + phm_apply_state_adjust_rules(hwmgr, requested, pcurrent); + phm_set_power_state(hwmgr, &pcurrent->hardware, &requested->hardware); + hwmgr->current_ps = requested; + } + return 0; +} + +int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip) +{ + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h new file mode 100644 index 000000000000..1380470fdb1c --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/eventmgr/psm.h @@ -0,0 +1,38 @@ +/* + * Copyright 2015 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. + * + */ +#include "eventmgr.h" +#include "eventinit.h" +#include "eventmanagement.h" +#include "eventmanager.h" +#include "power_state.h" +#include "hardwaremanager.h" + +int psm_get_ui_state(struct pp_eventmgr *eventmgr, enum PP_StateUILabel ui_label, unsigned long *state_id); + +int psm_get_state_by_classification(struct pp_eventmgr *eventmgr, enum PP_StateClassificationFlag flag, unsigned long *state_id); + +int psm_set_performance_states(struct pp_eventmgr *eventmgr, unsigned long *state_id); + +int psm_adjust_power_state_dynamic(struct pp_eventmgr *eventmgr, bool skip); + +int psm_adjust_power_state_static(struct pp_eventmgr *eventmgr, bool skip); diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile new file mode 100644 index 000000000000..b664e34dbcc0 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/Makefile @@ -0,0 +1,15 @@ +# +# Makefile for the 'hw manager' sub-component of powerplay. +# It provides the hardware management services for the driver. + +HARDWARE_MGR = hwmgr.o processpptables.o functiontables.o \ + hardwaremanager.o pp_acpi.o cz_hwmgr.o \ + cz_clockpowergating.o \ + tonga_processpptables.o ppatomctrl.o \ + tonga_hwmgr.o pppcielanes.o tonga_thermal.o\ + fiji_powertune.o fiji_hwmgr.o tonga_clockpowergating.o \ + fiji_clockpowergating.o fiji_thermal.o + +AMD_PP_HWMGR = $(addprefix $(AMD_PP_PATH)/hwmgr/,$(HARDWARE_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_HWMGR) diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c new file mode 100644 index 000000000000..ad7700822a1c --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.c @@ -0,0 +1,252 @@ +/* + * Copyright 2015 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. + * + */ + +#include "hwmgr.h" +#include "cz_clockpowergating.h" +#include "cz_ppsmc.h" + +/* PhyID -> Status Mapping in DDI_PHY_GEN_STATUS + 0 GFX0L (3:0), (27:24), + 1 GFX0H (7:4), (31:28), + 2 GFX1L (3:0), (19:16), + 3 GFX1H (7:4), (23:20), + 4 DDIL (3:0), (11: 8), + 5 DDIH (7:4), (15:12), + 6 DDI2L (3:0), ( 3: 0), + 7 DDI2H (7:4), ( 7: 4), +*/ +#define DDI_PHY_GEN_STATUS_VAL(phyID) (1 << ((3 - ((phyID & 0x07)/2))*8 + (phyID & 0x01)*4)) +#define IS_PHY_ID_USED_BY_PLL(PhyID) (((0xF3 & (1 << PhyID)) & 0xFF) ? true : false) + + +int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating) +{ + int ret = 0; + + switch (block) { + case PHM_AsicBlock_UVD_MVC: + case PHM_AsicBlock_UVD: + case PHM_AsicBlock_UVD_HD: + case PHM_AsicBlock_UVD_SD: + if (gating == PHM_ClockGateSetting_StaticOff) + ret = cz_dpm_powerdown_uvd(hwmgr); + else + ret = cz_dpm_powerup_uvd(hwmgr); + break; + case PHM_AsicBlock_GFX: + default: + break; + } + + return ret; +} + + +bool cz_phm_is_safe_for_asic_block(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *state, enum PHM_AsicBlock block) +{ + return true; +} + + +int cz_phm_enable_disable_gfx_power_gating(struct pp_hwmgr *hwmgr, bool enable) +{ + return 0; +} + +int cz_phm_smu_power_up_down_pcie(struct pp_hwmgr *hwmgr, uint32_t target, bool up, uint32_t args) +{ + /* TODO */ + return 0; +} + +int cz_phm_initialize_display_phy_access(struct pp_hwmgr *hwmgr, bool initialize, bool accesshw) +{ + /* TODO */ + return 0; +} + +int cz_phm_get_display_phy_access_info(struct pp_hwmgr *hwmgr) +{ + /* TODO */ + return 0; +} + +int cz_phm_gate_unused_display_phys(struct pp_hwmgr *hwmgr) +{ + /* TODO */ + return 0; +} + +int cz_phm_ungate_all_display_phys(struct pp_hwmgr *hwmgr) +{ + /* TODO */ + return 0; +} + +static int cz_tf_uvd_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result) +{ + return 0; +} + +static int cz_tf_vce_power_gating_initialize(struct pp_hwmgr *hwmgr, void *pInput, void *pOutput, void *pStorage, int Result) +{ + return 0; +} + +int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + uint32_t dpm_features = 0; + + if (enable && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM)) { + cz_hwmgr->dpm_flags |= DPMFlags_UVD_Enabled; + dpm_features |= UVD_DPM_MASK; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_EnableAllSmuFeatures, dpm_features); + } else { + dpm_features |= UVD_DPM_MASK; + cz_hwmgr->dpm_flags &= ~DPMFlags_UVD_Enabled; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_DisableAllSmuFeatures, dpm_features); + } + return 0; +} + +int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + uint32_t dpm_features = 0; + + if (enable && phm_cap_enabled( + hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEDPM)) { + cz_hwmgr->dpm_flags |= DPMFlags_VCE_Enabled; + dpm_features |= VCE_DPM_MASK; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_EnableAllSmuFeatures, dpm_features); + } else { + dpm_features |= VCE_DPM_MASK; + cz_hwmgr->dpm_flags &= ~DPMFlags_VCE_Enabled; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_DisableAllSmuFeatures, dpm_features); + } + + return 0; +} + + +int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + if (cz_hwmgr->uvd_power_gated == bgate) + return 0; + + cz_hwmgr->uvd_power_gated = bgate; + + if (bgate) { + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + cz_dpm_update_uvd_dpm(hwmgr, true); + cz_dpm_powerdown_uvd(hwmgr); + } else { + cz_dpm_powerup_uvd(hwmgr); + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + cz_dpm_update_uvd_dpm(hwmgr, false); + } + + return 0; +} + +int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating)) { + if (cz_hwmgr->vce_power_gated != bgate) { + if (bgate) { + cgs_set_clockgating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + cz_enable_disable_vce_dpm(hwmgr, false); + /* TODO: to figure out why vce can't be poweroff*/ + cz_hwmgr->vce_power_gated = true; + } else { + cz_dpm_powerup_vce(hwmgr); + cz_hwmgr->vce_power_gated = false; + cgs_set_clockgating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + cgs_set_powergating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); + cz_dpm_update_vce_dpm(hwmgr); + cz_enable_disable_vce_dpm(hwmgr, true); + return 0; + } + } + } else { + cz_dpm_update_vce_dpm(hwmgr); + cz_enable_disable_vce_dpm(hwmgr, true); + return 0; + } + + if (!cz_hwmgr->vce_power_gated) + cz_dpm_update_vce_dpm(hwmgr); + + return 0; +} + + +static struct phm_master_table_item cz_enable_clock_power_gatings_list[] = { + /*we don't need an exit table here, because there is only D3 cold on Kv*/ + { phm_cf_want_uvd_power_gating, cz_tf_uvd_power_gating_initialize }, + { phm_cf_want_vce_power_gating, cz_tf_vce_power_gating_initialize }, + /* to do { NULL, cz_tf_xdma_power_gating_enable }, */ + { NULL, NULL } +}; + +struct phm_master_table_header cz_phm_enable_clock_power_gatings_master = { + 0, + PHM_MasterTableFlag_None, + cz_enable_clock_power_gatings_list +}; diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h new file mode 100644 index 000000000000..bbbc0571320e --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_clockpowergating.h @@ -0,0 +1,37 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _CZ_CLOCK_POWER_GATING_H_ +#define _CZ_CLOCK_POWER_GATING_H_ + +#include "cz_hwmgr.h" +#include "pp_asicblocks.h" + +extern int cz_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating); +extern struct phm_master_table_header cz_phm_enable_clock_power_gatings_master; +extern struct phm_master_table_header cz_phm_disable_clock_power_gatings_master; +extern int cz_dpm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +extern int cz_dpm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +extern int cz_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); +extern int cz_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable); +#endif /* _CZ_CLOCK_POWER_GATING_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c new file mode 100644 index 000000000000..5bac36baa13c --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.c @@ -0,0 +1,1682 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "atom-types.h" +#include "atombios.h" +#include "processpptables.h" +#include "pp_debug.h" +#include "cgs_common.h" +#include "smu/smu_8_0_d.h" +#include "smu8_fusion.h" +#include "smu/smu_8_0_sh_mask.h" +#include "smumgr.h" +#include "hwmgr.h" +#include "hardwaremanager.h" +#include "cz_ppsmc.h" +#include "cz_hwmgr.h" +#include "power_state.h" +#include "cz_clockpowergating.h" +#include "pp_debug.h" + +#define ixSMUSVI_NB_CURRENTVID 0xD8230044 +#define CURRENT_NB_VID_MASK 0xff000000 +#define CURRENT_NB_VID__SHIFT 24 +#define ixSMUSVI_GFX_CURRENTVID 0xD8230048 +#define CURRENT_GFX_VID_MASK 0xff000000 +#define CURRENT_GFX_VID__SHIFT 24 + +static const unsigned long PhwCz_Magic = (unsigned long) PHM_Cz_Magic; + +static struct cz_power_state *cast_PhwCzPowerState(struct pp_hw_power_state *hw_ps) +{ + if (PhwCz_Magic != hw_ps->magic) + return NULL; + + return (struct cz_power_state *)hw_ps; +} + +static const struct cz_power_state *cast_const_PhwCzPowerState( + const struct pp_hw_power_state *hw_ps) +{ + if (PhwCz_Magic != hw_ps->magic) + return NULL; + + return (struct cz_power_state *)hw_ps; +} + +uint32_t cz_get_eclk_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_vce_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + switch (msg) { + case PPSMC_MSG_SetEclkSoftMin: + case PPSMC_MSG_SetEclkHardMin: + for (i = 0; i < (int)ptable->count; i++) { + if (clock <= ptable->entries[i].ecclk) + break; + } + break; + + case PPSMC_MSG_SetEclkSoftMax: + case PPSMC_MSG_SetEclkHardMax: + for (i = ptable->count - 1; i >= 0; i--) { + if (clock >= ptable->entries[i].ecclk) + break; + } + break; + + default: + break; + } + + return i; +} + +static uint32_t cz_get_sclk_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + switch (msg) { + case PPSMC_MSG_SetSclkSoftMin: + case PPSMC_MSG_SetSclkHardMin: + for (i = 0; i < (int)table->count; i++) { + if (clock <= table->entries[i].clk) + break; + } + break; + + case PPSMC_MSG_SetSclkSoftMax: + case PPSMC_MSG_SetSclkHardMax: + for (i = table->count - 1; i >= 0; i--) { + if (clock >= table->entries[i].clk) + break; + } + break; + + default: + break; + } + return i; +} + +static uint32_t cz_get_uvd_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint32_t msg) +{ + int i = 0; + struct phm_uvd_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + switch (msg) { + case PPSMC_MSG_SetUvdSoftMin: + case PPSMC_MSG_SetUvdHardMin: + for (i = 0; i < (int)ptable->count; i++) { + if (clock <= ptable->entries[i].vclk) + break; + } + break; + + case PPSMC_MSG_SetUvdSoftMax: + case PPSMC_MSG_SetUvdHardMax: + for (i = ptable->count - 1; i >= 0; i--) { + if (clock >= ptable->entries[i].vclk) + break; + } + break; + + default: + break; + } + + return i; +} + +static uint32_t cz_get_max_sclk_level(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + if (cz_hwmgr->max_sclk_level == 0) { + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxSclkLevel); + cz_hwmgr->max_sclk_level = smum_get_argument(hwmgr->smumgr) + 1; + } + + return cz_hwmgr->max_sclk_level; +} + +static int cz_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + uint32_t i; + + cz_hwmgr->gfx_ramp_step = 256*25/100; + + cz_hwmgr->gfx_ramp_delay = 1; /* by default, we delay 1us */ + + for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) + cz_hwmgr->activity_target[i] = CZ_AT_DFLT; + + cz_hwmgr->mgcg_cgtt_local0 = 0x00000000; + cz_hwmgr->mgcg_cgtt_local1 = 0x00000000; + + cz_hwmgr->clock_slow_down_freq = 25000; + + cz_hwmgr->skip_clock_slow_down = 1; + + cz_hwmgr->enable_nb_ps_policy = 1; /* disable until UNB is ready, Enabled */ + + cz_hwmgr->voltage_drop_in_dce_power_gating = 0; /* disable until fully verified */ + + cz_hwmgr->voting_rights_clients = 0x00C00033; + + cz_hwmgr->static_screen_threshold = 8; + + cz_hwmgr->ddi_power_gating_disabled = 0; + + cz_hwmgr->bapm_enabled = 1; + + cz_hwmgr->voltage_drop_threshold = 0; + + cz_hwmgr->gfx_power_gating_threshold = 500; + + cz_hwmgr->vce_slow_sclk_threshold = 20000; + + cz_hwmgr->dce_slow_sclk_threshold = 30000; + + cz_hwmgr->disable_driver_thermal_policy = 1; + + cz_hwmgr->disable_nb_ps3_in_battery = 0; + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ABM); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_NonABMSupportInPPLib); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicM3Arbiter); + + cz_hwmgr->override_dynamic_mgpg = 1; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + cz_hwmgr->thermal_auto_throttling_treshold = 0; + + cz_hwmgr->tdr_clock = 0; + + cz_hwmgr->disable_gfx_power_gating_in_uvd = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + + cz_hwmgr->cc6_settings.cpu_cc6_disable = false; + cz_hwmgr->cc6_settings.cpu_pstate_disable = false; + cz_hwmgr->cc6_settings.nb_pstate_switch_disable = false; + cz_hwmgr->cc6_settings.cpu_pstate_separation_time = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableVoltageIsland); + + return 0; +} + +static uint32_t cz_convert_8Bit_index_to_voltage( + struct pp_hwmgr *hwmgr, uint16_t voltage) +{ + return 6200 - (voltage * 25); +} + +static int cz_construct_max_power_limits_table(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *table) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend; + struct cz_sys_info *sys_info = &cz_hwmgr->sys_info; + struct phm_clock_voltage_dependency_table *dep_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + if (dep_table->count > 0) { + table->sclk = dep_table->entries[dep_table->count-1].clk; + table->vddc = cz_convert_8Bit_index_to_voltage(hwmgr, + (uint16_t)dep_table->entries[dep_table->count-1].v); + } + table->mclk = sys_info->nbp_memory_clock[0]; + return 0; +} + +static int cz_init_dynamic_state_adjustment_rule_settings( + struct pp_hwmgr *hwmgr, + ATOM_CLK_VOLT_CAPABILITY *disp_voltage_table) +{ + uint32_t table_size = + sizeof(struct phm_clock_voltage_dependency_table) + + (7 * sizeof(struct phm_clock_voltage_dependency_record)); + + struct phm_clock_voltage_dependency_table *table_clk_vlt = + kzalloc(table_size, GFP_KERNEL); + + if (NULL == table_clk_vlt) { + printk(KERN_ERR "[ powerplay ] Can not allocate memory!\n"); + return -ENOMEM; + } + + table_clk_vlt->count = 8; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_0; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_1; + table_clk_vlt->entries[1].v = 1; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_2; + table_clk_vlt->entries[2].v = 2; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_3; + table_clk_vlt->entries[3].v = 3; + table_clk_vlt->entries[4].clk = PP_DAL_POWERLEVEL_4; + table_clk_vlt->entries[4].v = 4; + table_clk_vlt->entries[5].clk = PP_DAL_POWERLEVEL_5; + table_clk_vlt->entries[5].v = 5; + table_clk_vlt->entries[6].clk = PP_DAL_POWERLEVEL_6; + table_clk_vlt->entries[6].v = 6; + table_clk_vlt->entries[7].clk = PP_DAL_POWERLEVEL_7; + table_clk_vlt->entries[7].v = 7; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + + return 0; +} + +static int cz_get_system_info_data(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)hwmgr->backend; + ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *info = NULL; + uint32_t i; + int result = 0; + uint8_t frev, crev; + uint16_t size; + + info = (ATOM_INTEGRATED_SYSTEM_INFO_V1_9 *) cgs_atom_get_data_table( + hwmgr->device, + GetIndexIntoMasterTable(DATA, IntegratedSystemInfo), + &size, &frev, &crev); + + if (crev != 9) { + printk(KERN_ERR "[ powerplay ] Unsupported IGP table: %d %d\n", frev, crev); + return -EINVAL; + } + + if (info == NULL) { + printk(KERN_ERR "[ powerplay ] Could not retrieve the Integrated System Info Table!\n"); + return -EINVAL; + } + + cz_hwmgr->sys_info.bootup_uma_clock = + le32_to_cpu(info->ulBootUpUMAClock); + + cz_hwmgr->sys_info.bootup_engine_clock = + le32_to_cpu(info->ulBootUpEngineClock); + + cz_hwmgr->sys_info.dentist_vco_freq = + le32_to_cpu(info->ulDentistVCOFreq); + + cz_hwmgr->sys_info.system_config = + le32_to_cpu(info->ulSystemConfig); + + cz_hwmgr->sys_info.bootup_nb_voltage_index = + le16_to_cpu(info->usBootUpNBVoltage); + + cz_hwmgr->sys_info.htc_hyst_lmt = + (info->ucHtcHystLmt == 0) ? 5 : info->ucHtcHystLmt; + + cz_hwmgr->sys_info.htc_tmp_lmt = + (info->ucHtcTmpLmt == 0) ? 203 : info->ucHtcTmpLmt; + + if (cz_hwmgr->sys_info.htc_tmp_lmt <= + cz_hwmgr->sys_info.htc_hyst_lmt) { + printk(KERN_ERR "[ powerplay ] The htcTmpLmt should be larger than htcHystLmt.\n"); + return -EINVAL; + } + + cz_hwmgr->sys_info.nb_dpm_enable = + cz_hwmgr->enable_nb_ps_policy && + (le32_to_cpu(info->ulSystemConfig) >> 3 & 0x1); + + for (i = 0; i < CZ_NUM_NBPSTATES; i++) { + if (i < CZ_NUM_NBPMEMORYCLOCK) { + cz_hwmgr->sys_info.nbp_memory_clock[i] = + le32_to_cpu(info->ulNbpStateMemclkFreq[i]); + } + cz_hwmgr->sys_info.nbp_n_clock[i] = + le32_to_cpu(info->ulNbpStateNClkFreq[i]); + } + + for (i = 0; i < MAX_DISPLAY_CLOCK_LEVEL; i++) { + cz_hwmgr->sys_info.display_clock[i] = + le32_to_cpu(info->sDispClkVoltageMapping[i].ulMaximumSupportedCLK); + } + + /* Here use 4 levels, make sure not exceed */ + for (i = 0; i < CZ_NUM_NBPSTATES; i++) { + cz_hwmgr->sys_info.nbp_voltage_index[i] = + le16_to_cpu(info->usNBPStateVoltage[i]); + } + + if (!cz_hwmgr->sys_info.nb_dpm_enable) { + for (i = 1; i < CZ_NUM_NBPSTATES; i++) { + if (i < CZ_NUM_NBPMEMORYCLOCK) { + cz_hwmgr->sys_info.nbp_memory_clock[i] = + cz_hwmgr->sys_info.nbp_memory_clock[0]; + } + cz_hwmgr->sys_info.nbp_n_clock[i] = + cz_hwmgr->sys_info.nbp_n_clock[0]; + cz_hwmgr->sys_info.nbp_voltage_index[i] = + cz_hwmgr->sys_info.nbp_voltage_index[0]; + } + } + + if (le32_to_cpu(info->ulGPUCapInfo) & + SYS_INFO_GPUCAPS__ENABEL_DFS_BYPASS) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableDFSBypass); + } + + cz_hwmgr->sys_info.uma_channel_number = info->ucUMAChannelNumber; + + cz_construct_max_power_limits_table (hwmgr, + &hwmgr->dyn_state.max_clock_voltage_on_ac); + + cz_init_dynamic_state_adjustment_rule_settings(hwmgr, + &info->sDISPCLK_Voltage[0]); + + return result; +} + +static int cz_construct_boot_state(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + cz_hwmgr->boot_power_level.engineClock = + cz_hwmgr->sys_info.bootup_engine_clock; + + cz_hwmgr->boot_power_level.vddcIndex = + (uint8_t)cz_hwmgr->sys_info.bootup_nb_voltage_index; + + cz_hwmgr->boot_power_level.dsDividerIndex = 0; + + cz_hwmgr->boot_power_level.ssDividerIndex = 0; + + cz_hwmgr->boot_power_level.allowGnbSlow = 1; + + cz_hwmgr->boot_power_level.forceNBPstate = 0; + + cz_hwmgr->boot_power_level.hysteresis_up = 0; + + cz_hwmgr->boot_power_level.numSIMDToPowerDown = 0; + + cz_hwmgr->boot_power_level.display_wm = 0; + + cz_hwmgr->boot_power_level.vce_wm = 0; + + return 0; +} + +static int cz_tf_reset_active_process_mask(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + return 0; +} + +static int cz_tf_upload_pptable_to_smu(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct SMU8_Fusion_ClkTable *clock_table; + int ret; + uint32_t i; + void *table = NULL; + pp_atomctrl_clock_dividers_kong dividers; + + struct phm_clock_voltage_dependency_table *vddc_table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *vdd_gfx_table = + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk; + struct phm_acp_clock_voltage_dependency_table *acp_table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + if (!hwmgr->need_pp_table_upload) + return 0; + + ret = smum_download_powerplay_table(hwmgr->smumgr, &table); + + PP_ASSERT_WITH_CODE((0 == ret && NULL != table), + "Fail to get clock table from SMU!", return -EINVAL;); + + clock_table = (struct SMU8_Fusion_ClkTable *)table; + + /* patch clock table */ + PP_ASSERT_WITH_CODE((vddc_table->count <= CZ_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((vdd_gfx_table->count <= CZ_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((acp_table->count <= CZ_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((uvd_table->count <= CZ_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + PP_ASSERT_WITH_CODE((vce_table->count <= CZ_MAX_HARDWARE_POWERLEVELS), + "Dependency table entry exceeds max limit!", return -EINVAL;); + + for (i = 0; i < CZ_MAX_HARDWARE_POWERLEVELS; i++) { + + /* vddc_sclk */ + clock_table->SclkBreakdownTable.ClkLevel[i].GnbVid = + (i < vddc_table->count) ? (uint8_t)vddc_table->entries[i].v : 0; + clock_table->SclkBreakdownTable.ClkLevel[i].Frequency = + (i < vddc_table->count) ? vddc_table->entries[i].clk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->SclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->SclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + /* vddgfx_sclk */ + clock_table->SclkBreakdownTable.ClkLevel[i].GfxVid = + (i < vdd_gfx_table->count) ? (uint8_t)vdd_gfx_table->entries[i].v : 0; + + /* acp breakdown */ + clock_table->AclkBreakdownTable.ClkLevel[i].GfxVid = + (i < acp_table->count) ? (uint8_t)acp_table->entries[i].v : 0; + clock_table->AclkBreakdownTable.ClkLevel[i].Frequency = + (i < acp_table->count) ? acp_table->entries[i].acpclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->AclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->AclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + + /* uvd breakdown */ + clock_table->VclkBreakdownTable.ClkLevel[i].GfxVid = + (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; + clock_table->VclkBreakdownTable.ClkLevel[i].Frequency = + (i < uvd_table->count) ? uvd_table->entries[i].vclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->VclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->VclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + clock_table->DclkBreakdownTable.ClkLevel[i].GfxVid = + (i < uvd_table->count) ? (uint8_t)uvd_table->entries[i].v : 0; + clock_table->DclkBreakdownTable.ClkLevel[i].Frequency = + (i < uvd_table->count) ? uvd_table->entries[i].dclk : 0; + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->DclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->DclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + /* vce breakdown */ + clock_table->EclkBreakdownTable.ClkLevel[i].GfxVid = + (i < vce_table->count) ? (uint8_t)vce_table->entries[i].v : 0; + clock_table->EclkBreakdownTable.ClkLevel[i].Frequency = + (i < vce_table->count) ? vce_table->entries[i].ecclk : 0; + + + atomctrl_get_engine_pll_dividers_kong(hwmgr, + clock_table->EclkBreakdownTable.ClkLevel[i].Frequency, + ÷rs); + + clock_table->EclkBreakdownTable.ClkLevel[i].DfsDid = + (uint8_t)dividers.pll_post_divider; + + } + ret = smum_upload_powerplay_table(hwmgr->smumgr); + + return ret; +} + +static int cz_tf_init_sclk_limit(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + unsigned long clock = 0, level; + + if (NULL == table && table->count <= 0) + return -EINVAL; + + cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk; + cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk; + + level = cz_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + clock = table->entries[level].clk; + else + clock = table->entries[table->count - 1].clk; + + cz_hwmgr->sclk_dpm.soft_max_clk = clock; + cz_hwmgr->sclk_dpm.hard_max_clk = clock; + + return 0; +} + +static int cz_tf_init_uvd_limit(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_uvd_clock_voltage_dependency_table *table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + unsigned long clock = 0, level; + + if (NULL == table && table->count <= 0) + return -EINVAL; + + cz_hwmgr->uvd_dpm.soft_min_clk = 0; + cz_hwmgr->uvd_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxUvdLevel); + level = smum_get_argument(hwmgr->smumgr); + + if (level < table->count) + clock = table->entries[level].vclk; + else + clock = table->entries[table->count - 1].vclk; + + cz_hwmgr->uvd_dpm.soft_max_clk = clock; + cz_hwmgr->uvd_dpm.hard_max_clk = clock; + + return 0; +} + +static int cz_tf_init_vce_limit(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_vce_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + unsigned long clock = 0, level; + + if (NULL == table && table->count <= 0) + return -EINVAL; + + cz_hwmgr->vce_dpm.soft_min_clk = 0; + cz_hwmgr->vce_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxEclkLevel); + level = smum_get_argument(hwmgr->smumgr); + + if (level < table->count) + clock = table->entries[level].ecclk; + else + clock = table->entries[table->count - 1].ecclk; + + cz_hwmgr->vce_dpm.soft_max_clk = clock; + cz_hwmgr->vce_dpm.hard_max_clk = clock; + + return 0; +} + +static int cz_tf_init_acp_limit(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_acp_clock_voltage_dependency_table *table = + hwmgr->dyn_state.acp_clock_voltage_dependency_table; + unsigned long clock = 0, level; + + if (NULL == table && table->count <= 0) + return -EINVAL; + + cz_hwmgr->acp_dpm.soft_min_clk = 0; + cz_hwmgr->acp_dpm.hard_min_clk = 0; + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetMaxAclkLevel); + level = smum_get_argument(hwmgr->smumgr); + + if (level < table->count) + clock = table->entries[level].acpclk; + else + clock = table->entries[table->count - 1].acpclk; + + cz_hwmgr->acp_dpm.soft_max_clk = clock; + cz_hwmgr->acp_dpm.hard_max_clk = clock; + return 0; +} + +static int cz_tf_init_power_gate_state(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + cz_hwmgr->uvd_power_gated = false; + cz_hwmgr->vce_power_gated = false; + cz_hwmgr->samu_power_gated = false; + cz_hwmgr->acp_power_gated = false; + cz_hwmgr->pgacpinit = true; + + return 0; +} + +static int cz_tf_init_sclk_threshold(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + cz_hwmgr->low_sclk_interrupt_threshold = 0; + + return 0; +} +static int cz_tf_update_sclk_limit(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + unsigned long clock = 0; + unsigned long level; + unsigned long stable_pstate_sclk; + struct PP_Clocks clocks; + unsigned long percentage; + + cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk; + level = cz_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[level].clk; + else + cz_hwmgr->sclk_dpm.soft_max_clk = table->entries[table->count - 1].clk; + + /*PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks);*/ + clock = clocks.engineClock; + + if (cz_hwmgr->sclk_dpm.hard_min_clk != clock) { + cz_hwmgr->sclk_dpm.hard_min_clk = clock; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkHardMin, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.hard_min_clk, + PPSMC_MSG_SetSclkHardMin)); + } + + clock = cz_hwmgr->sclk_dpm.soft_min_clk; + + /* update minimum clocks for Stable P-State feature */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + percentage = 75; + /*Sclk - calculate sclk value based on percentage and find FLOOR sclk from VddcDependencyOnSCLK table */ + stable_pstate_sclk = (hwmgr->dyn_state.max_clock_voltage_on_ac.mclk * + percentage) / 100; + + if (clock < stable_pstate_sclk) + clock = stable_pstate_sclk; + } else { + if (clock < hwmgr->gfx_arbiter.sclk) + clock = hwmgr->gfx_arbiter.sclk; + } + + if (cz_hwmgr->sclk_dpm.soft_min_clk != clock) { + cz_hwmgr->sclk_dpm.soft_min_clk = clock; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMin, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin)); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState) && + cz_hwmgr->sclk_dpm.soft_max_clk != clock) { + cz_hwmgr->sclk_dpm.soft_max_clk = clock; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMax, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax)); + } + + return 0; +} + +static int cz_tf_set_deep_sleep_sclk_threshold(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + uint32_t clks = hwmgr->display_config.min_core_set_clock_in_sr; + if (clks == 0) + clks = CZ_MIN_DEEP_SLEEP_SCLK; + + PP_DBG_LOG("Setting Deep Sleep Clock: %d\n", clks); + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetMinDeepSleepSclk, + clks); + } + + return 0; +} + +static int cz_tf_set_watermark_threshold(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = + (struct cz_hwmgr *)(hwmgr->backend); + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetWatermarkFrequency, + cz_hwmgr->sclk_dpm.soft_max_clk); + + return 0; +} + +static int cz_tf_set_enabled_levels(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + return 0; +} + + +static int cz_tf_enable_nb_dpm(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + int ret = 0; + + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + unsigned long dpm_features = 0; + + if (!cz_hwmgr->is_nb_dpm_enabled) { + PP_DBG_LOG("enabling ALL SMU features.\n"); + dpm_features |= NB_DPM_MASK; + ret = smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features); + if (ret == 0) + cz_hwmgr->is_nb_dpm_enabled = true; + } + + return ret; +} + +static int cz_nbdpm_pstate_enable_disable(struct pp_hwmgr *hwmgr, bool enable, bool lock) +{ + struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + + if (hw_data->is_nb_dpm_enabled) { + if (enable) { + PP_DBG_LOG("enable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_EnableLowMemoryPstate, + (lock ? 1 : 0)); + } else { + PP_DBG_LOG("disable Low Memory PState.\n"); + + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_DisableLowMemoryPstate, + (lock ? 1 : 0)); + } + } + + return 0; +} + +static int cz_tf_update_low_mem_pstate(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + bool disable_switch; + bool enable_low_mem_state; + struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + const struct phm_set_power_state_input *states = (struct phm_set_power_state_input *)input; + const struct cz_power_state *pnew_state = cast_const_PhwCzPowerState(states->pnew_state); + + if (hw_data->sys_info.nb_dpm_enable) { + disable_switch = hw_data->cc6_settings.nb_pstate_switch_disable ? true : false; + enable_low_mem_state = hw_data->cc6_settings.nb_pstate_switch_disable ? false : true; + + if (pnew_state->action == FORCE_HIGH) + cz_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch); + else if(pnew_state->action == CANCEL_FORCE_HIGH) + cz_nbdpm_pstate_enable_disable(hwmgr, false, disable_switch); + else + cz_nbdpm_pstate_enable_disable(hwmgr, enable_low_mem_state, disable_switch); + } + return 0; +} + +static struct phm_master_table_item cz_set_power_state_list[] = { + {NULL, cz_tf_update_sclk_limit}, + {NULL, cz_tf_set_deep_sleep_sclk_threshold}, + {NULL, cz_tf_set_watermark_threshold}, + {NULL, cz_tf_set_enabled_levels}, + {NULL, cz_tf_enable_nb_dpm}, + {NULL, cz_tf_update_low_mem_pstate}, + {NULL, NULL} +}; + +static struct phm_master_table_header cz_set_power_state_master = { + 0, + PHM_MasterTableFlag_None, + cz_set_power_state_list +}; + +static struct phm_master_table_item cz_setup_asic_list[] = { + {NULL, cz_tf_reset_active_process_mask}, + {NULL, cz_tf_upload_pptable_to_smu}, + {NULL, cz_tf_init_sclk_limit}, + {NULL, cz_tf_init_uvd_limit}, + {NULL, cz_tf_init_vce_limit}, + {NULL, cz_tf_init_acp_limit}, + {NULL, cz_tf_init_power_gate_state}, + {NULL, cz_tf_init_sclk_threshold}, + {NULL, NULL} +}; + +static struct phm_master_table_header cz_setup_asic_master = { + 0, + PHM_MasterTableFlag_None, + cz_setup_asic_list +}; + +static int cz_tf_program_voting_clients(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + PHMCZ_WRITE_SMC_REGISTER(hwmgr->device, CG_FREQ_TRAN_VOTING_0, + PPCZ_VOTINGRIGHTSCLIENTS_DFLT0); + return 0; +} + +static int cz_tf_start_dpm(struct pp_hwmgr *hwmgr, void *input, void *output, + void *storage, int result) +{ + int res = 0xff; + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + unsigned long dpm_features = 0; + + cz_hwmgr->dpm_flags |= DPMFlags_SCLK_Enabled; + dpm_features |= SCLK_DPM_MASK; + + res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_EnableAllSmuFeatures, + dpm_features); + + return res; +} + +static int cz_tf_program_bootup_state(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + cz_hwmgr->sclk_dpm.soft_min_clk = cz_hwmgr->sys_info.bootup_engine_clock; + cz_hwmgr->sclk_dpm.soft_max_clk = cz_hwmgr->sys_info.bootup_engine_clock; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMin, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin)); + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMax, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax)); + + return 0; +} + +int cz_tf_reset_acp_boot_level(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + cz_hwmgr->acp_boot_level = 0xff; + return 0; +} + +static bool cz_dpm_check_smu_features(struct pp_hwmgr *hwmgr, + unsigned long check_feature) +{ + int result; + unsigned long features; + + result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_GetFeatureStatus, 0); + if (result == 0) { + features = smum_get_argument(hwmgr->smumgr); + if (features & check_feature) + return true; + } + + return result; +} + +static int cz_tf_check_for_dpm_disabled(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + if (cz_dpm_check_smu_features(hwmgr, SMU_EnabledFeatureScoreboard_SclkDpmOn)) + return PP_Result_TableImmediateExit; + return 0; +} + +static int cz_tf_enable_didt(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result) +{ + /* TO DO */ + return 0; +} + +static int cz_tf_check_for_dpm_enabled(struct pp_hwmgr *hwmgr, + void *input, void *output, + void *storage, int result) +{ + if (!cz_dpm_check_smu_features(hwmgr, + SMU_EnabledFeatureScoreboard_SclkDpmOn)) + return PP_Result_TableImmediateExit; + return 0; +} + +static struct phm_master_table_item cz_disable_dpm_list[] = { + { NULL, cz_tf_check_for_dpm_enabled}, + {NULL, NULL}, +}; + + +static struct phm_master_table_header cz_disable_dpm_master = { + 0, + PHM_MasterTableFlag_None, + cz_disable_dpm_list +}; + +static struct phm_master_table_item cz_enable_dpm_list[] = { + { NULL, cz_tf_check_for_dpm_disabled }, + { NULL, cz_tf_program_voting_clients }, + { NULL, cz_tf_start_dpm}, + { NULL, cz_tf_program_bootup_state}, + { NULL, cz_tf_enable_didt }, + { NULL, cz_tf_reset_acp_boot_level }, + {NULL, NULL}, +}; + +static struct phm_master_table_header cz_enable_dpm_master = { + 0, + PHM_MasterTableFlag_None, + cz_enable_dpm_list +}; + +static int cz_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps) +{ + struct cz_power_state *cz_ps = + cast_PhwCzPowerState(&prequest_ps->hardware); + + const struct cz_power_state *cz_current_ps = + cast_const_PhwCzPowerState(&pcurrent_ps->hardware); + + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct PP_Clocks clocks; + bool force_high; + unsigned long num_of_active_displays = 4; + + cz_ps->evclk = hwmgr->vce_arbiter.evclk; + cz_ps->ecclk = hwmgr->vce_arbiter.ecclk; + + cz_ps->need_dfs_bypass = true; + + cz_hwmgr->video_start = (hwmgr->uvd_arbiter.vclk != 0 || hwmgr->uvd_arbiter.dclk != 0 || + hwmgr->vce_arbiter.evclk != 0 || hwmgr->vce_arbiter.ecclk != 0); + + cz_hwmgr->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); + + /* to do PECI_GetMinClockSettings(pHwMgr->pPECI, &clocks); */ + /* PECI_GetNumberOfActiveDisplays(pHwMgr->pPECI, &numOfActiveDisplays); */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + clocks.memoryClock = hwmgr->dyn_state.max_clock_voltage_on_ac.mclk; + else + clocks.memoryClock = 0; + + if (clocks.memoryClock < hwmgr->gfx_arbiter.mclk) + clocks.memoryClock = hwmgr->gfx_arbiter.mclk; + + force_high = (clocks.memoryClock > cz_hwmgr->sys_info.nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK - 1]) + || (num_of_active_displays >= 3); + + cz_ps->action = cz_current_ps->action; + + if ((force_high == false) && (cz_ps->action == FORCE_HIGH)) + cz_ps->action = CANCEL_FORCE_HIGH; + else if ((force_high == true) && (cz_ps->action != FORCE_HIGH)) + cz_ps->action = FORCE_HIGH; + else + cz_ps->action = DO_NOTHING; + + return 0; +} + +static int cz_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + + result = cz_initialize_dpm_defaults(hwmgr); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] cz_initialize_dpm_defaults failed\n"); + return result; + } + + result = cz_get_system_info_data(hwmgr); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] cz_get_system_info_data failed\n"); + return result; + } + + cz_construct_boot_state(hwmgr); + + result = phm_construct_table(hwmgr, &cz_setup_asic_master, + &(hwmgr->setup_asic)); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] Fail to construct setup ASIC\n"); + return result; + } + + result = phm_construct_table(hwmgr, &cz_disable_dpm_master, + &(hwmgr->disable_dynamic_state_management)); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] Fail to disable_dynamic_state\n"); + return result; + } + result = phm_construct_table(hwmgr, &cz_enable_dpm_master, + &(hwmgr->enable_dynamic_state_management)); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] Fail to enable_dynamic_state\n"); + return result; + } + result = phm_construct_table(hwmgr, &cz_set_power_state_master, + &(hwmgr->set_power_state)); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] Fail to construct set_power_state\n"); + return result; + } + + result = phm_construct_table(hwmgr, &cz_phm_enable_clock_power_gatings_master, &(hwmgr->enable_clock_power_gatings)); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] Fail to construct enable_clock_power_gatings\n"); + return result; + } + return result; +} + +static int cz_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + if (hwmgr != NULL || hwmgr->backend != NULL) { + kfree(hwmgr->backend); + kfree(hwmgr); + } + return 0; +} + +int cz_phm_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + if (cz_hwmgr->sclk_dpm.soft_min_clk != + cz_hwmgr->sclk_dpm.soft_max_clk) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMin, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMin)); + return 0; +} + +int cz_phm_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + unsigned long clock = 0, level; + + if (NULL == table && table->count <= 0) + return -EINVAL; + + cz_hwmgr->sclk_dpm.soft_min_clk = table->entries[0].clk; + cz_hwmgr->sclk_dpm.hard_min_clk = table->entries[0].clk; + + level = cz_get_max_sclk_level(hwmgr) - 1; + + if (level < table->count) + clock = table->entries[level].clk; + else + clock = table->entries[table->count - 1].clk; + + cz_hwmgr->sclk_dpm.soft_max_clk = clock; + cz_hwmgr->sclk_dpm.hard_max_clk = clock; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMin, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_min_clk, + PPSMC_MSG_SetSclkSoftMin)); + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMax, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax)); + + return 0; +} + +int cz_phm_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + if (cz_hwmgr->sclk_dpm.soft_min_clk != + cz_hwmgr->sclk_dpm.soft_max_clk) { + cz_hwmgr->sclk_dpm.soft_max_clk = + cz_hwmgr->sclk_dpm.soft_min_clk; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetSclkSoftMax, + cz_get_sclk_level(hwmgr, + cz_hwmgr->sclk_dpm.soft_max_clk, + PPSMC_MSG_SetSclkSoftMax)); + } + + return 0; +} + +static int cz_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = cz_phm_force_dpm_highest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = cz_phm_force_dpm_lowest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = cz_phm_unforce_dpm_levels(hwmgr); + if (ret) + return ret; + break; + default: + break; + } + + hwmgr->dpm_level = level; + + return ret; +} + +int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_UVDPowerOFF); + return 0; +} + +int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDPowerGating)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDynamicPowerGating)) { + return smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + PPSMC_MSG_UVDPowerON, 1); + } else { + return smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + PPSMC_MSG_UVDPowerON, 0); + } + } + + return 0; +} + +int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_uvd_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + if (!bgate) { + /* Stable Pstate is enabled and we need to set the UVD DPM to highest level */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + cz_hwmgr->uvd_dpm.hard_min_clk = + ptable->entries[ptable->count - 1].vclk; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetUvdHardMin, + cz_get_uvd_level(hwmgr, + cz_hwmgr->uvd_dpm.hard_min_clk, + PPSMC_MSG_SetUvdHardMin)); + + cz_enable_disable_uvd_dpm(hwmgr, true); + } else + cz_enable_disable_uvd_dpm(hwmgr, true); + } else + cz_enable_disable_uvd_dpm(hwmgr, false); + + return 0; +} + +int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct phm_vce_clock_voltage_dependency_table *ptable = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + /* Stable Pstate is enabled and we need to set the VCE DPM to highest level */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + cz_hwmgr->vce_dpm.hard_min_clk = + ptable->entries[ptable->count - 1].ecclk; + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetEclkHardMin, + cz_get_eclk_level(hwmgr, + cz_hwmgr->vce_dpm.hard_min_clk, + PPSMC_MSG_SetEclkHardMin)); + } else { + /*EPR# 419220 -HW limitation to to */ + cz_hwmgr->vce_dpm.hard_min_clk = hwmgr->vce_arbiter.ecclk; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetEclkHardMin, + cz_get_eclk_level(hwmgr, + cz_hwmgr->vce_dpm.hard_min_clk, + PPSMC_MSG_SetEclkHardMin)); + + } + return 0; +} + +int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_VCEPowerOFF); + return 0; +} + +int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_VCEPowerGating)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_VCEPowerON); + return 0; +} + +static int cz_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + return cz_hwmgr->sys_info.bootup_uma_clock; +} + +static int cz_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct cz_power_state *cz_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + cz_ps = cast_PhwCzPowerState(&ps->hardware); + + if (low) + return cz_ps->levels[0].engineClock; + else + return cz_ps->levels[cz_ps->level-1].engineClock; +} + +static int cz_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps); + + cz_ps->level = 1; + cz_ps->nbps_flags = 0; + cz_ps->bapm_flags = 0; + cz_ps->levels[0] = cz_hwmgr->boot_power_level; + + return 0; +} + +static int cz_dpm_get_pp_table_entry_callback( + struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps, + unsigned int index, + const void *clock_info) +{ + struct cz_power_state *cz_ps = cast_PhwCzPowerState(hw_ps); + + const ATOM_PPLIB_CZ_CLOCK_INFO *cz_clock_info = clock_info; + + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + uint8_t clock_info_index = cz_clock_info->index; + + if (clock_info_index > (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1)) + clock_info_index = (uint8_t)(hwmgr->platform_descriptor.hardwareActivityPerformanceLevels - 1); + + cz_ps->levels[index].engineClock = table->entries[clock_info_index].clk; + cz_ps->levels[index].vddcIndex = (uint8_t)table->entries[clock_info_index].v; + + cz_ps->level = index + 1; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + cz_ps->levels[index].dsDividerIndex = 5; + cz_ps->levels[index].ssDividerIndex = 5; + } + + return 0; +} + +static int cz_dpm_get_num_of_pp_table_entries(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned long ret = 0; + + result = pp_tables_get_num_of_entries(hwmgr, &ret); + + return result ? 0 : ret; +} + +static int cz_dpm_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry, struct pp_power_state *ps) +{ + int result; + struct cz_power_state *cz_ps; + + ps->hardware.magic = PhwCz_Magic; + + cz_ps = cast_PhwCzPowerState(&(ps->hardware)); + + result = pp_tables_get_entry(hwmgr, entry, ps, + cz_dpm_get_pp_table_entry_callback); + + cz_ps->uvd_clocks.vclk = ps->uvd_clocks.VCLK; + cz_ps->uvd_clocks.dclk = ps->uvd_clocks.DCLK; + + return result; +} + +int cz_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct cz_power_state); +} + +static void +cz_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m) +{ + struct cz_hwmgr *cz_hwmgr = (struct cz_hwmgr *)(hwmgr->backend); + + struct phm_clock_voltage_dependency_table *table = + hwmgr->dyn_state.vddc_dependency_on_sclk; + + struct phm_vce_clock_voltage_dependency_table *vce_table = + hwmgr->dyn_state.vce_clock_voltage_dependency_table; + + struct phm_uvd_clock_voltage_dependency_table *uvd_table = + hwmgr->dyn_state.uvd_clock_voltage_dependency_table; + + uint32_t sclk_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX), + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX); + uint32_t uvd_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_UVD_INDEX); + uint32_t vce_index = PHM_GET_FIELD(cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixTARGET_AND_CURRENT_PROFILE_INDEX_2), + TARGET_AND_CURRENT_PROFILE_INDEX_2, CURR_VCE_INDEX); + + uint32_t sclk, vclk, dclk, ecclk, tmp, active_percent; + uint16_t vddnb, vddgfx; + int result; + + if (sclk_index >= NUM_SCLK_LEVELS) { + seq_printf(m, "\n invalid sclk dpm profile %d\n", sclk_index); + } else { + sclk = table->entries[sclk_index].clk; + seq_printf(m, "\n index: %u sclk: %u MHz\n", sclk_index, sclk/100); + } + + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_NB_CURRENTVID) & + CURRENT_NB_VID_MASK) >> CURRENT_NB_VID__SHIFT; + vddnb = cz_convert_8Bit_index_to_voltage(hwmgr, tmp); + tmp = (cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixSMUSVI_GFX_CURRENTVID) & + CURRENT_GFX_VID_MASK) >> CURRENT_GFX_VID__SHIFT; + vddgfx = cz_convert_8Bit_index_to_voltage(hwmgr, (u16)tmp); + seq_printf(m, "\n vddnb: %u vddgfx: %u\n", vddnb, vddgfx); + + seq_printf(m, "\n uvd %sabled\n", cz_hwmgr->uvd_power_gated ? "dis" : "en"); + if (!cz_hwmgr->uvd_power_gated) { + if (uvd_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "\n invalid uvd dpm level %d\n", uvd_index); + } else { + vclk = uvd_table->entries[uvd_index].vclk; + dclk = uvd_table->entries[uvd_index].dclk; + seq_printf(m, "\n index: %u uvd vclk: %u MHz dclk: %u MHz\n", uvd_index, vclk/100, dclk/100); + } + } + + seq_printf(m, "\n vce %sabled\n", cz_hwmgr->vce_power_gated ? "dis" : "en"); + if (!cz_hwmgr->vce_power_gated) { + if (vce_index >= CZ_MAX_HARDWARE_POWERLEVELS) { + seq_printf(m, "\n invalid vce dpm level %d\n", vce_index); + } else { + ecclk = vce_table->entries[vce_index].ecclk; + seq_printf(m, "\n index: %u vce ecclk: %u MHz\n", vce_index, ecclk/100); + } + } + + result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_GetAverageGraphicsActivity); + if (0 == result) { + active_percent = cgs_read_register(hwmgr->device, mmSMU_MP1_SRBM2P_ARG_0); + active_percent = active_percent > 100 ? 100 : active_percent; + } else { + active_percent = 50; + } + + seq_printf(m, "\n [GPU load]: %u %%\n\n", active_percent); +} + +static void cz_hw_print_display_cfg( + const struct cc6_settings *cc6_settings) +{ + PP_DBG_LOG("New Display Configuration:\n"); + + PP_DBG_LOG(" cpu_cc6_disable: %d\n", + cc6_settings->cpu_cc6_disable); + PP_DBG_LOG(" cpu_pstate_disable: %d\n", + cc6_settings->cpu_pstate_disable); + PP_DBG_LOG(" nb_pstate_switch_disable: %d\n", + cc6_settings->nb_pstate_switch_disable); + PP_DBG_LOG(" cpu_pstate_separation_time: %d\n\n", + cc6_settings->cpu_pstate_separation_time); +} + + static int cz_set_cpu_power_state(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + uint32_t data = 0; + + if (hw_data->cc6_settings.cc6_setting_changed == true) { + + hw_data->cc6_settings.cc6_setting_changed = false; + + cz_hw_print_display_cfg(&hw_data->cc6_settings); + + data |= (hw_data->cc6_settings.cpu_pstate_separation_time + & PWRMGT_SEPARATION_TIME_MASK) + << PWRMGT_SEPARATION_TIME_SHIFT; + + data|= (hw_data->cc6_settings.cpu_cc6_disable ? 0x1 : 0x0) + << PWRMGT_DISABLE_CPU_CSTATES_SHIFT; + + data|= (hw_data->cc6_settings.cpu_pstate_disable ? 0x1 : 0x0) + << PWRMGT_DISABLE_CPU_PSTATES_SHIFT; + + PP_DBG_LOG("SetDisplaySizePowerParams data: 0x%X\n", + data); + + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetDisplaySizePowerParams, + data); + } + + return 0; +} + + + static int cz_store_cc6_data(struct pp_hwmgr *hwmgr, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, bool pstate_switch_disable) + { + struct cz_hwmgr *hw_data = (struct cz_hwmgr *)(hwmgr->backend); + + if (separation_time != + hw_data->cc6_settings.cpu_pstate_separation_time + || cc6_disable != + hw_data->cc6_settings.cpu_cc6_disable + || pstate_disable != + hw_data->cc6_settings.cpu_pstate_disable + || pstate_switch_disable != + hw_data->cc6_settings.nb_pstate_switch_disable) { + + hw_data->cc6_settings.cc6_setting_changed = true; + + hw_data->cc6_settings.cpu_pstate_separation_time = + separation_time; + hw_data->cc6_settings.cpu_cc6_disable = + cc6_disable; + hw_data->cc6_settings.cpu_pstate_disable = + pstate_disable; + hw_data->cc6_settings.nb_pstate_switch_disable = + pstate_switch_disable; + + } + + return 0; +} + + static int cz_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_dal_clock_info*info) +{ + uint32_t i; + const struct phm_clock_voltage_dependency_table * table = + hwmgr->dyn_state.vddc_dep_on_dal_pwrl; + const struct phm_clock_and_voltage_limits* limits = + &hwmgr->dyn_state.max_clock_voltage_on_ac; + + info->engine_max_clock = limits->sclk; + info->memory_max_clock = limits->mclk; + + for (i = table->count - 1; i > 0; i--) { + + if (limits->vddc >= table->entries[i].v) { + info->level = table->entries[i].clk; + return 0; + } + } + return -EINVAL; +} + +static const struct pp_hwmgr_func cz_hwmgr_funcs = { + .backend_init = cz_hwmgr_backend_init, + .backend_fini = cz_hwmgr_backend_fini, + .asic_setup = NULL, + .apply_state_adjust_rules = cz_apply_state_adjust_rules, + .force_dpm_level = cz_dpm_force_dpm_level, + .get_power_state_size = cz_get_power_state_size, + .powerdown_uvd = cz_dpm_powerdown_uvd, + .powergate_uvd = cz_dpm_powergate_uvd, + .powergate_vce = cz_dpm_powergate_vce, + .get_mclk = cz_dpm_get_mclk, + .get_sclk = cz_dpm_get_sclk, + .patch_boot_state = cz_dpm_patch_boot_state, + .get_pp_table_entry = cz_dpm_get_pp_table_entry, + .get_num_of_pp_table_entries = cz_dpm_get_num_of_pp_table_entries, + .print_current_perforce_level = cz_print_current_perforce_level, + .set_cpu_power_state = cz_set_cpu_power_state, + .store_cc6_data = cz_store_cc6_data, + .get_dal_power_level= cz_get_dal_power_level, +}; + +int cz_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + struct cz_hwmgr *cz_hwmgr; + int ret = 0; + + cz_hwmgr = kzalloc(sizeof(struct cz_hwmgr), GFP_KERNEL); + if (cz_hwmgr == NULL) + return -ENOMEM; + + hwmgr->backend = cz_hwmgr; + hwmgr->hwmgr_func = &cz_hwmgr_funcs; + hwmgr->pptable_func = &pptable_funcs; + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h new file mode 100644 index 000000000000..c477f1cf3f23 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/cz_hwmgr.h @@ -0,0 +1,326 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _CZ_HWMGR_H_ +#define _CZ_HWMGR_H_ + +#include "cgs_common.h" +#include "ppatomctrl.h" + +#define CZ_NUM_NBPSTATES 4 +#define CZ_NUM_NBPMEMORYCLOCK 2 +#define MAX_DISPLAY_CLOCK_LEVEL 8 +#define CZ_AT_DFLT 30 +#define CZ_MAX_HARDWARE_POWERLEVELS 8 +#define PPCZ_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 +#define CZ_MIN_DEEP_SLEEP_SCLK 800 + +/* Carrizo device IDs */ +#define DEVICE_ID_CZ_9870 0x9870 +#define DEVICE_ID_CZ_9874 0x9874 +#define DEVICE_ID_CZ_9875 0x9875 +#define DEVICE_ID_CZ_9876 0x9876 +#define DEVICE_ID_CZ_9877 0x9877 + +#define PHMCZ_WRITE_SMC_REGISTER(device, reg, value) \ + cgs_write_ind_register(device, CGS_IND_REG__SMC, ix##reg, value) + +struct cz_dpm_entry { + uint32_t soft_min_clk; + uint32_t hard_min_clk; + uint32_t soft_max_clk; + uint32_t hard_max_clk; +}; + +struct cz_sys_info { + uint32_t bootup_uma_clock; + uint32_t bootup_engine_clock; + uint32_t dentist_vco_freq; + uint32_t nb_dpm_enable; + uint32_t nbp_memory_clock[CZ_NUM_NBPMEMORYCLOCK]; + uint32_t nbp_n_clock[CZ_NUM_NBPSTATES]; + uint16_t nbp_voltage_index[CZ_NUM_NBPSTATES]; + uint32_t display_clock[MAX_DISPLAY_CLOCK_LEVEL]; + uint16_t bootup_nb_voltage_index; + uint8_t htc_tmp_lmt; + uint8_t htc_hyst_lmt; + uint32_t system_config; + uint32_t uma_channel_number; +}; + +#define MAX_DISPLAYPHY_IDS 0x8 +#define DISPLAYPHY_LANEMASK 0xF +#define UNKNOWN_TRANSMITTER_PHY_ID (-1) + +#define DISPLAYPHY_PHYID_SHIFT 24 +#define DISPLAYPHY_LANESELECT_SHIFT 16 + +#define DISPLAYPHY_RX_SELECT 0x1 +#define DISPLAYPHY_TX_SELECT 0x2 +#define DISPLAYPHY_CORE_SELECT 0x4 + +#define DDI_POWERGATING_ARG(phyID, lanemask, rx, tx, core) \ + (((uint32_t)(phyID))<<DISPLAYPHY_PHYID_SHIFT | \ + ((uint32_t)(lanemask))<<DISPLAYPHY_LANESELECT_SHIFT | \ + ((rx) ? DISPLAYPHY_RX_SELECT : 0) | \ + ((tx) ? DISPLAYPHY_TX_SELECT : 0) | \ + ((core) ? DISPLAYPHY_CORE_SELECT : 0)) + +struct cz_display_phy_info_entry { + uint8_t phy_present; + uint8_t active_lane_mapping; + uint8_t display_config_type; + uint8_t active_number_of_lanes; +}; + +#define CZ_MAX_DISPLAYPHY_IDS 10 + +struct cz_display_phy_info { + bool display_phy_access_initialized; + struct cz_display_phy_info_entry entries[CZ_MAX_DISPLAYPHY_IDS]; +}; + +struct cz_power_level { + uint32_t engineClock; + uint8_t vddcIndex; + uint8_t dsDividerIndex; + uint8_t ssDividerIndex; + uint8_t allowGnbSlow; + uint8_t forceNBPstate; + uint8_t display_wm; + uint8_t vce_wm; + uint8_t numSIMDToPowerDown; + uint8_t hysteresis_up; + uint8_t rsv[3]; +}; + +struct cz_uvd_clocks { + uint32_t vclk; + uint32_t dclk; + uint32_t vclk_low_divider; + uint32_t vclk_high_divider; + uint32_t dclk_low_divider; + uint32_t dclk_high_divider; +}; + +enum cz_pstate_previous_action { + DO_NOTHING = 1, + FORCE_HIGH, + CANCEL_FORCE_HIGH +}; + +struct pp_disable_nb_ps_flags { + union { + struct { + uint32_t entry : 1; + uint32_t display : 1; + uint32_t driver: 1; + uint32_t vce : 1; + uint32_t uvd : 1; + uint32_t acp : 1; + uint32_t reserved: 26; + } bits; + uint32_t u32All; + }; +}; + +struct cz_power_state { + unsigned int magic; + uint32_t level; + struct cz_uvd_clocks uvd_clocks; + uint32_t evclk; + uint32_t ecclk; + uint32_t samclk; + uint32_t acpclk; + bool need_dfs_bypass; + uint32_t nbps_flags; + uint32_t bapm_flags; + uint8_t dpm_0_pg_nb_ps_low; + uint8_t dpm_0_pg_nb_ps_high; + uint8_t dpm_x_nb_ps_low; + uint8_t dpm_x_nb_ps_high; + enum cz_pstate_previous_action action; + struct cz_power_level levels[CZ_MAX_HARDWARE_POWERLEVELS]; + struct pp_disable_nb_ps_flags disable_nb_ps_flag; +}; + +#define DPMFlags_SCLK_Enabled 0x00000001 +#define DPMFlags_UVD_Enabled 0x00000002 +#define DPMFlags_VCE_Enabled 0x00000004 +#define DPMFlags_ACP_Enabled 0x00000008 +#define DPMFlags_ForceHighestValid 0x40000000 +#define DPMFlags_Debug 0x80000000 + +#define SMU_EnabledFeatureScoreboard_AcpDpmOn 0x00000001 /* bit 0 */ +#define SMU_EnabledFeatureScoreboard_SclkDpmOn 0x00200000 +#define SMU_EnabledFeatureScoreboard_UvdDpmOn 0x00800000 /* bit 23 */ +#define SMU_EnabledFeatureScoreboard_VceDpmOn 0x01000000 /* bit 24 */ + +struct cc6_settings { + bool cc6_setting_changed; + bool nb_pstate_switch_disable;/* controls NB PState switch */ + bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ + bool cpu_pstate_disable; + uint32_t cpu_pstate_separation_time; +}; + +struct cz_hwmgr { + uint32_t activity_target[CZ_MAX_HARDWARE_POWERLEVELS]; + uint32_t dpm_interval; + + uint32_t voltage_drop_threshold; + + uint32_t voting_rights_clients; + + uint32_t disable_driver_thermal_policy; + + uint32_t static_screen_threshold; + + uint32_t gfx_power_gating_threshold; + + uint32_t activity_hysteresis; + uint32_t bootup_sclk_divider; + uint32_t gfx_ramp_step; + uint32_t gfx_ramp_delay; /* in micro-seconds */ + + uint32_t thermal_auto_throttling_treshold; + + struct cz_sys_info sys_info; + + struct cz_power_level boot_power_level; + struct cz_power_state *cz_current_ps; + struct cz_power_state *cz_requested_ps; + + uint32_t mgcg_cgtt_local0; + uint32_t mgcg_cgtt_local1; + + uint32_t tdr_clock; /* in 10khz unit */ + + uint32_t ddi_power_gating_disabled; + uint32_t disable_gfx_power_gating_in_uvd; + uint32_t disable_nb_ps3_in_battery; + + uint32_t lock_nb_ps_in_uvd_play_back; + + struct cz_display_phy_info display_phy_info; + uint32_t vce_slow_sclk_threshold; /* default 200mhz */ + uint32_t dce_slow_sclk_threshold; /* default 300mhz */ + uint32_t min_sclk_did; /* minimum sclk divider */ + + bool disp_clk_bypass; + bool disp_clk_bypass_pending; + uint32_t bapm_enabled; + uint32_t clock_slow_down_freq; + uint32_t skip_clock_slow_down; + uint32_t enable_nb_ps_policy; + uint32_t voltage_drop_in_dce_power_gating; + uint32_t uvd_dpm_interval; + uint32_t override_dynamic_mgpg; + uint32_t lclk_deep_enabled; + + uint32_t uvd_performance; + + bool video_start; + bool battery_state; + uint32_t lowest_valid; + uint32_t highest_valid; + uint32_t high_voltage_threshold; + uint32_t is_nb_dpm_enabled; + struct cc6_settings cc6_settings; + uint32_t is_voltage_island_enabled; + + bool pgacpinit; + + uint8_t disp_config; + + /* PowerTune */ + uint32_t power_containment_features; + bool cac_enabled; + bool disable_uvd_power_tune_feature; + bool enable_ba_pm_feature; + bool enable_tdc_limit_feature; + + uint32_t sram_end; + uint32_t dpm_table_start; + uint32_t soft_regs_start; + + uint8_t uvd_level_count; + uint8_t vce_level_count; + + uint8_t acp_level_count; + uint8_t samu_level_count; + uint32_t fps_high_threshold; + uint32_t fps_low_threshold; + + uint32_t dpm_flags; + struct cz_dpm_entry sclk_dpm; + struct cz_dpm_entry uvd_dpm; + struct cz_dpm_entry vce_dpm; + struct cz_dpm_entry acp_dpm; + + uint8_t uvd_boot_level; + uint8_t vce_boot_level; + uint8_t acp_boot_level; + uint8_t samu_boot_level; + uint8_t uvd_interval; + uint8_t vce_interval; + uint8_t acp_interval; + uint8_t samu_interval; + + uint8_t graphics_interval; + uint8_t graphics_therm_throttle_enable; + uint8_t graphics_voltage_change_enable; + + uint8_t graphics_clk_slow_enable; + uint8_t graphics_clk_slow_divider; + + uint32_t display_cac; + uint32_t low_sclk_interrupt_threshold; + + uint32_t dram_log_addr_h; + uint32_t dram_log_addr_l; + uint32_t dram_log_phy_addr_h; + uint32_t dram_log_phy_addr_l; + uint32_t dram_log_buff_size; + + bool uvd_power_gated; + bool vce_power_gated; + bool samu_power_gated; + bool acp_power_gated; + bool acp_power_up_no_dsp; + uint32_t active_process_mask; + + uint32_t max_sclk_level; + uint32_t num_of_clk_entries; +}; + +struct pp_hwmgr; + +int cz_hwmgr_init(struct pp_hwmgr *hwmgr); +int cz_dpm_powerdown_uvd(struct pp_hwmgr *hwmgr); +int cz_dpm_powerup_uvd(struct pp_hwmgr *hwmgr); +int cz_dpm_powerdown_vce(struct pp_hwmgr *hwmgr); +int cz_dpm_powerup_vce(struct pp_hwmgr *hwmgr); +int cz_dpm_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int cz_dpm_update_vce_dpm(struct pp_hwmgr *hwmgr); +#endif /* _CZ_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c new file mode 100644 index 000000000000..e68edf06ed73 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.c @@ -0,0 +1,114 @@ +/* + * Copyright 2015 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. + * + */ + +#include "hwmgr.h" +#include "fiji_clockpowergating.h" +#include "fiji_ppsmc.h" +#include "fiji_hwmgr.h" + +int fiji_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + data->samu_power_gated = false; + data->acp_power_gated = false; + + return 0; +} + +int fiji_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (data->uvd_power_gated == bgate) + return 0; + + data->uvd_power_gated = bgate; + + if (bgate) + fiji_update_uvd_dpm(hwmgr, true); + else + fiji_update_uvd_dpm(hwmgr, false); + + return 0; +} + +int fiji_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_set_power_state_input states; + const struct pp_power_state *pcurrent; + struct pp_power_state *requested; + + if (data->vce_power_gated == bgate) + return 0; + + data->vce_power_gated = bgate; + + pcurrent = hwmgr->current_ps; + requested = hwmgr->request_ps; + + states.pcurrent_state = &(pcurrent->hardware); + states.pnew_state = &(requested->hardware); + + fiji_update_vce_dpm(hwmgr, &states); + fiji_enable_disable_vce_dpm(hwmgr, !bgate); + + return 0; +} + +int fiji_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (data->samu_power_gated == bgate) + return 0; + + data->samu_power_gated = bgate; + + if (bgate) + fiji_update_samu_dpm(hwmgr, true); + else + fiji_update_samu_dpm(hwmgr, false); + + return 0; +} + +int fiji_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (data->acp_power_gated == bgate) + return 0; + + data->acp_power_gated = bgate; + + if (bgate) + fiji_update_acp_dpm(hwmgr, true); + else + fiji_update_acp_dpm(hwmgr, false); + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h new file mode 100644 index 000000000000..33af5f511ab8 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_clockpowergating.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _FIJI_CLOCK_POWER_GATING_H_ +#define _FIJI_CLOCK_POWER_GATING_H_ + +#include "fiji_hwmgr.h" +#include "pp_asicblocks.h" + +extern int fiji_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +extern int fiji_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +extern int fiji_phm_powergate_samu(struct pp_hwmgr *hwmgr, bool bgate); +extern int fiji_phm_powergate_acp(struct pp_hwmgr *hwmgr, bool bgate); +extern int fiji_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr); +#endif /* _TONGA_CLOCK_POWER_GATING_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h new file mode 100644 index 000000000000..32d43e8fecb2 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_dyn_defaults.h @@ -0,0 +1,105 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef FIJI_DYN_DEFAULTS_H +#define FIJI_DYN_DEFAULTS_H + +/** \file +* Volcanic Islands Dynamic default parameters. +*/ + +enum FIJIdpm_TrendDetection +{ + FIJIAdpm_TrendDetection_AUTO, + FIJIAdpm_TrendDetection_UP, + FIJIAdpm_TrendDetection_DOWN +}; +typedef enum FIJIdpm_TrendDetection FIJIdpm_TrendDetection; + +/* We need to fill in the default values!!!!!!!!!!!!!!!!!!!!!!! */ + +/* Bit vector representing same fields as hardware register. */ +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 /* CP_Gfx_busy ???? + * HDP_busy + * IH_busy + * UVD_busy + * VCE_busy + * ACP_busy + * SAMU_busy + * SDMA enabled */ +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT1 0x000400 /* FE_Gfx_busy - Intended for primary usage. Rest are for flexibility. ???? + * SH_Gfx_busy + * RB_Gfx_busy + * VCE_busy */ + +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT2 0xC00080 /* SH_Gfx_busy - Intended for primary usage. Rest are for flexibility. + * FE_Gfx_busy + * RB_Gfx_busy + * ACP_busy */ + +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT3 0xC00200 /* RB_Gfx_busy - Intended for primary usage. Rest are for flexibility. + * FE_Gfx_busy + * SH_Gfx_busy + * UVD_busy */ + +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT4 0xC01680 /* UVD_busy + * VCE_busy + * ACP_busy + * SAMU_busy */ + +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT5 0xC00033 /* GFX, HDP */ +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT6 0xC00033 /* GFX, HDP */ +#define PPFIJI_VOTINGRIGHTSCLIENTS_DFLT7 0x3FFFC000 /* GFX, HDP */ + + +/* thermal protection counter (units). */ +#define PPFIJI_THERMALPROTECTCOUNTER_DFLT 0x200 /* ~19us */ + +/* static screen threshold unit */ +#define PPFIJI_STATICSCREENTHRESHOLDUNIT_DFLT 0 + +/* static screen threshold */ +#define PPFIJI_STATICSCREENTHRESHOLD_DFLT 0x00C8 + +/* gfx idle clock stop threshold */ +#define PPFIJI_GFXIDLECLOCKSTOPTHRESHOLD_DFLT 0x200 /* ~19us with static screen threshold unit of 0 */ + +/* Fixed reference divider to use when building baby stepping tables. */ +#define PPFIJI_REFERENCEDIVIDER_DFLT 4 + +/* ULV voltage change delay time + * Used to be delay_vreg in N.I. split for S.I. + * Using N.I. delay_vreg value as default + * ReferenceClock = 2700 + * VoltageResponseTime = 1000 + * VDDCDelayTime = (VoltageResponseTime * ReferenceClock) / 1600 = 1687 + */ +#define PPFIJI_ULVVOLTAGECHANGEDELAY_DFLT 1687 + +#define PPFIJI_CGULVPARAMETER_DFLT 0x00040035 +#define PPFIJI_CGULVCONTROL_DFLT 0x00007450 +#define PPFIJI_TARGETACTIVITY_DFLT 30 /* 30%*/ +#define PPFIJI_MCLK_TARGETACTIVITY_DFLT 10 /* 10% */ + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c new file mode 100644 index 000000000000..94f404c121b7 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.c @@ -0,0 +1,5117 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include "linux/delay.h" + +#include "hwmgr.h" +#include "fiji_smumgr.h" +#include "atombios.h" +#include "hardwaremanager.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "cgs_common.h" +#include "fiji_dyn_defaults.h" +#include "fiji_powertune.h" +#include "smu73.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "dce/dce_10_0_d.h" +#include "dce/dce_10_0_sh_mask.h" +#include "pppcielanes.h" +#include "fiji_hwmgr.h" +#include "tonga_processpptables.h" +#include "tonga_pptable.h" +#include "pp_debug.h" +#include "pp_acpi.h" +#include "amd_pcie_helpers.h" +#include "cgs_linux.h" +#include "ppinterrupt.h" + +#include "fiji_clockpowergating.h" +#include "fiji_thermal.h" + +#define VOLTAGE_SCALE 4 +#define SMC_RAM_END 0x40000 +#define VDDC_VDDCI_DELTA 300 + +#define MC_SEQ_MISC0_GDDR5_SHIFT 28 +#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 +#define MC_SEQ_MISC0_GDDR5_VALUE 5 + +#define MC_CG_ARB_FREQ_F0 0x0a /* boot-up default */ +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +/* From smc_reg.h */ +#define SMC_CG_IND_START 0xc0030000 +#define SMC_CG_IND_END 0xc0040000 /* First byte after SMC_CG_IND */ + +#define VOLTAGE_SCALE 4 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 + +#define VDDC_VDDCI_DELTA 300 + +#define ixSWRST_COMMAND_1 0x1400103 +#define MC_SEQ_CNTL__CAC_EN_MASK 0x40000000 + +/** Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ +enum DPM_EVENT_SRC { + DPM_EVENT_SRC_ANALOG = 0, /* Internal analog trip point */ + DPM_EVENT_SRC_EXTERNAL = 1, /* External (GPIO 17) signal */ + DPM_EVENT_SRC_DIGITAL = 2, /* Internal digital trip point (DIG_THERM_DPM) */ + DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, /* Internal analog or external */ + DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 /* Internal digital or external */ +}; + + +/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs + * not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] + */ +uint16_t fiji_clock_stretcher_lookup_table[2][4] = { {600, 1050, 3, 0}, + {600, 1050, 6, 1} }; + +/* [FF, SS] type, [] 4 voltage ranges, and + * [Floor Freq, Boundary Freq, VID min , VID max] + */ +uint32_t fiji_clock_stretcher_ddt_table[2][4][4] = +{ { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] + * (coming from PWR_CKS_CNTL.stretch_amount reg spec) + */ +uint8_t fiji_clock_stretch_amount_conversion[2][6] = { {0, 1, 3, 2, 4, 5}, + {0, 2, 4, 5, 6, 5} }; + +const unsigned long PhwFiji_Magic = (unsigned long)(PHM_VIslands_Magic); + +struct fiji_power_state *cast_phw_fiji_power_state( + struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (struct fiji_power_state *)hw_ps; +} + +const struct fiji_power_state *cast_const_phw_fiji_power_state( + const struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwFiji_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (const struct fiji_power_state *)hw_ps; +} + +static bool fiji_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + return (1 == PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, FEATURE_STATUS, VOLTAGE_CONTROLLER_ON)) + ? true : false; +} + +static void fiji_init_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_ulv_parm *ulv = &data->ulv; + + ulv->cg_ulv_parameter = PPFIJI_CGULVPARAMETER_DFLT; + data->voting_rights_clients0 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT0; + data->voting_rights_clients1 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT1; + data->voting_rights_clients2 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT2; + data->voting_rights_clients3 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT3; + data->voting_rights_clients4 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT4; + data->voting_rights_clients5 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT5; + data->voting_rights_clients6 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT6; + data->voting_rights_clients7 = PPFIJI_VOTINGRIGHTSCLIENTS_DFLT7; + + data->static_screen_threshold_unit = + PPFIJI_STATICSCREENTHRESHOLDUNIT_DFLT; + data->static_screen_threshold = + PPFIJI_STATICSCREENTHRESHOLD_DFLT; + + /* Unset ABM cap as it moved to DAL. + * Add PHM_PlatformCaps_NonABMSupportInPPLib + * for re-direct ABM related request to DAL + */ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ABM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_NonABMSupportInPPLib); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicACTiming); + + fiji_initialize_power_tune_defaults(hwmgr); + + data->mclk_stutter_mode_threshold = 60000; + data->pcie_gen_performance.max = PP_PCIEGen1; + data->pcie_gen_performance.min = PP_PCIEGen3; + data->pcie_gen_power_saving.max = PP_PCIEGen1; + data->pcie_gen_power_saving.min = PP_PCIEGen3; + data->pcie_lane_performance.max = 0; + data->pcie_lane_performance.min = 16; + data->pcie_lane_power_saving.max = 0; + data->pcie_lane_power_saving.min = 16; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); +} + +static int fiji_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *sclk) +{ + uint8_t entryId; + uint8_t voltageId; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ + for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) { + voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd; + if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id) + break; + } + + PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count, + "Can't find requested voltage id in vdd_dep_on_sclk table!", + return -EINVAL; + ); + + *sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk; + + return 0; +} + +/** +* Get Leakage VDDC based on leakage ID. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_get_evv_voltages(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint16_t vv_id; + uint16_t vddc = 0; + uint16_t evv_default = 1150; + uint16_t i, j; + uint32_t sclk = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + int result; + + for (i = 0; i < FIJI_MAX_LEAKAGE_COUNT; i++) { + vv_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + if (!fiji_get_sclk_for_voltage_evv(hwmgr, + table_info->vddc_lookup_table, vv_id, &sclk)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + for (j = 1; j < sclk_table->count; j++) { + if (sclk_table->entries[j].clk == sclk && + sclk_table->entries[j].cks_enable == 0) { + sclk += 5000; + break; + } + } + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableDriverEVV)) + result = atomctrl_calculate_voltage_evv_on_sclk(hwmgr, + VOLTAGE_TYPE_VDDC, sclk, vv_id, &vddc, i, true); + else + result = -EINVAL; + + if (result) + result = atomctrl_get_voltage_evv_on_sclk(hwmgr, + VOLTAGE_TYPE_VDDC, sclk,vv_id, &vddc); + + /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ + PP_ASSERT_WITH_CODE((vddc < 2000), + "Invalid VDDC value, greater than 2v!", result = -EINVAL;); + + if (result) + /* 1.15V is the default safe value for Fiji */ + vddc = evv_default; + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddc != 0 && vddc != vv_id) { + data->vddc_leakage.actual_voltage + [data->vddc_leakage.count] = vddc; + data->vddc_leakage.leakage_id + [data->vddc_leakage.count] = vv_id; + data->vddc_leakage.count++; + } + } + } + return 0; +} + +/** + * Change virtual leakage voltage to actual value. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to changing voltage + * @param pointer to leakage table + */ +static void fiji_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr, + uint16_t *voltage, struct fiji_leakage_voltage *leakage_table) +{ + uint32_t index; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 */ + for (index = 0; index < leakage_table->count; index++) { + /* if this voltage matches a leakage voltage ID */ + /* patch with actual leakage voltage */ + if (leakage_table->leakage_id[index] == *voltage) { + *voltage = leakage_table->actual_voltage[index]; + break; + } + } + + if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) + printk(KERN_ERR "Voltage value looks like a Leakage ID but it's not patched \n"); +} + +/** +* Patch voltage lookup table by EVV leakages. +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pointer to voltage lookup table +* @param pointer to leakage table +* @return always 0 +*/ +static int fiji_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + struct fiji_leakage_voltage *leakage_table) +{ + uint32_t i; + + for (i = 0; i < lookup_table->count; i++) + fiji_patch_with_vdd_leakage(hwmgr, + &lookup_table->entries[i].us_vdd, leakage_table); + + return 0; +} + +static int fiji_patch_clock_voltage_limits_with_vddc_leakage( + struct pp_hwmgr *hwmgr, struct fiji_leakage_voltage *leakage_table, + uint16_t *vddc) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + fiji_patch_with_vdd_leakage(hwmgr, (uint16_t *)vddc, leakage_table); + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + table_info->max_clock_voltage_on_dc.vddc; + return 0; +} + +static int fiji_patch_voltage_dependency_tables_with_lookup_table( + struct pp_hwmgr *hwmgr) +{ + uint8_t entryId; + uint8_t voltageId; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *mclk_table = + table_info->vdd_dep_on_mclk; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + + for (entryId = 0; entryId < sclk_table->count; ++entryId) { + voltageId = sclk_table->entries[entryId].vddInd; + sclk_table->entries[entryId].vddc = + table_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + + for (entryId = 0; entryId < mclk_table->count; ++entryId) { + voltageId = mclk_table->entries[entryId].vddInd; + mclk_table->entries[entryId].vddc = + table_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + + for (entryId = 0; entryId < mm_table->count; ++entryId) { + voltageId = mm_table->entries[entryId].vddcInd; + mm_table->entries[entryId].vddc = + table_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + + return 0; + +} + +static int fiji_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr) +{ + /* Need to determine if we need calculated voltage. */ + return 0; +} + +static int fiji_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr) +{ + /* Need to determine if we need calculated voltage from mm table. */ + return 0; +} + +static int fiji_sort_lookup_table(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + uint32_t table_size, i, j; + struct phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record; + table_size = lookup_table->count; + + PP_ASSERT_WITH_CODE(0 != lookup_table->count, + "Lookup table is empty", return -EINVAL); + + /* Sorting voltages */ + for (i = 0; i < table_size - 1; i++) { + for (j = i + 1; j > 0; j--) { + if (lookup_table->entries[j].us_vdd < + lookup_table->entries[j - 1].us_vdd) { + tmp_voltage_lookup_record = lookup_table->entries[j - 1]; + lookup_table->entries[j - 1] = lookup_table->entries[j]; + lookup_table->entries[j] = tmp_voltage_lookup_record; + } + } + } + + return 0; +} + +static int fiji_complete_dependency_tables(struct pp_hwmgr *hwmgr) +{ + int result = 0; + int tmp_result; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + tmp_result = fiji_patch_lookup_table_with_leakage(hwmgr, + table_info->vddc_lookup_table, &(data->vddc_leakage)); + if (tmp_result) + result = tmp_result; + + tmp_result = fiji_patch_clock_voltage_limits_with_vddc_leakage(hwmgr, + &(data->vddc_leakage), &table_info->max_clock_voltage_on_dc.vddc); + if (tmp_result) + result = tmp_result; + + tmp_result = fiji_patch_voltage_dependency_tables_with_lookup_table(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = fiji_calc_voltage_dependency_tables(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = fiji_calc_mm_voltage_dependency_table(hwmgr); + if (tmp_result) + result = tmp_result; + + tmp_result = fiji_sort_lookup_table(hwmgr, table_info->vddc_lookup_table); + if(tmp_result) + result = tmp_result; + + return result; +} + +static int fiji_set_private_data_based_on_pptable(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = + table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL, + "VDD dependency on SCLK table is missing. \ + This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, + "VDD dependency on SCLK table has to have is missing. \ + This table is mandatory", return -EINVAL); + + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL, + "VDD dependency on MCLK table is missing. \ + This table is mandatory", return -EINVAL); + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, + "VDD dependency on MCLK table has to have is missing. \ + This table is mandatory", return -EINVAL); + + data->min_vddc_in_pptable = (uint16_t)allowed_sclk_vdd_table->entries[0].vddc; + data->max_vddc_in_pptable = (uint16_t)allowed_sclk_vdd_table-> + entries[allowed_sclk_vdd_table->count - 1].vddc; + + table_info->max_clock_voltage_on_ac.sclk = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.mclk = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; + table_info->max_clock_voltage_on_ac.vddc = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + table_info->max_clock_voltage_on_ac.vddci = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; + + hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = + table_info->max_clock_voltage_on_ac.sclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = + table_info->max_clock_voltage_on_ac.mclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = + table_info->max_clock_voltage_on_ac.vddc; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = + table_info->max_clock_voltage_on_ac.vddci; + + return 0; +} + +static uint16_t fiji_get_current_pcie_speed(struct pp_hwmgr *hwmgr) +{ + uint32_t speedCntl = 0; + + /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ + speedCntl = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__PCIE, + ixPCIE_LC_SPEED_CNTL); + return((uint16_t)PHM_GET_FIELD(speedCntl, + PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); +} + +static int fiji_get_current_pcie_lane_number(struct pp_hwmgr *hwmgr) +{ + uint32_t link_width; + + /* mmPCIE_PORT_INDEX rename as mmPCIE_INDEX */ + link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, + PCIE_LC_LINK_WIDTH_CNTL, LC_LINK_WIDTH_RD); + + PP_ASSERT_WITH_CODE((7 >= link_width), + "Invalid PCIe lane width!", return 0); + + return decode_pcie_lane_width(link_width); +} + +/** Patch the Boot State to match VBIOS boot clocks and voltage. +* +* @param hwmgr Pointer to the hardware manager. +* @param pPowerState The address of the PowerState instance being created. +* +*/ +static int fiji_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_power_state *ps = (struct fiji_power_state *)hw_ps; + ATOM_FIRMWARE_INFO_V2_2 *fw_info; + uint16_t size; + uint8_t frev, crev; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + + /* First retrieve the Boot clocks and VDDC from the firmware info table. + * We assume here that fw_info is unchanged if this call fails. + */ + fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table( + hwmgr->device, index, + &size, &frev, &crev); + if (!fw_info) + /* During a test, there is no firmware info table. */ + return 0; + + /* Patch the state. */ + data->vbios_boot_state.sclk_bootup_value = + le32_to_cpu(fw_info->ulDefaultEngineClock); + data->vbios_boot_state.mclk_bootup_value = + le32_to_cpu(fw_info->ulDefaultMemoryClock); + data->vbios_boot_state.mvdd_bootup_value = + le16_to_cpu(fw_info->usBootUpMVDDCVoltage); + data->vbios_boot_state.vddc_bootup_value = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + data->vbios_boot_state.vddci_bootup_value = + le16_to_cpu(fw_info->usBootUpVDDCIVoltage); + data->vbios_boot_state.pcie_gen_bootup_value = + fiji_get_current_pcie_speed(hwmgr); + data->vbios_boot_state.pcie_lane_bootup_value = + (uint16_t)fiji_get_current_pcie_lane_number(hwmgr); + + /* set boot power state */ + ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value; + ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value; + ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value; + ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value; + + return 0; +} + +static int fiji_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t i; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + bool stay_in_boot; + int result; + + data->dll_default_on = false; + data->sram_end = SMC_RAM_END; + + for (i = 0; i < SMU73_MAX_LEVELS_GRAPHICS; i++) + data->activity_target[i] = FIJI_AT_DFLT; + + data->vddc_vddci_delta = VDDC_VDDCI_DELTA; + + data->mclk_activity_target = PPFIJI_MCLK_TARGETACTIVITY_DFLT; + data->mclk_dpm0_activity_target = 0xa; + + data->sclk_dpm_key_disabled = 0; + data->mclk_dpm_key_disabled = 0; + data->pcie_dpm_key_disabled = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep); + + data->gpio_debug = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + /* need to set voltage control types before EVV patching */ + data->voltage_control = FIJI_VOLTAGE_CONTROL_NONE; + data->vddci_control = FIJI_VOLTAGE_CONTROL_NONE; + data->mvdd_control = FIJI_VOLTAGE_CONTROL_NONE; + + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) + data->voltage_control = FIJI_VOLTAGE_CONTROL_BY_SVID2; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl)) + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) + data->mvdd_control = FIJI_VOLTAGE_CONTROL_BY_GPIO; + + if (data->mvdd_control == FIJI_VOLTAGE_CONTROL_NONE) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI)) { + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) + data->vddci_control = FIJI_VOLTAGE_CONTROL_BY_GPIO; + else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) + data->vddci_control = FIJI_VOLTAGE_CONTROL_BY_SVID2; + } + + if (data->vddci_control == FIJI_VOLTAGE_CONTROL_NONE) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + if (table_info && table_info->cac_dtp_table->usClockStretchAmount) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + + fiji_init_dpm_defaults(hwmgr); + + /* Get leakage voltage based on leakage ID. */ + fiji_get_evv_voltages(hwmgr); + + /* Patch our voltage dependency table with actual leakage voltage + * We need to perform leakage translation before it's used by other functions + */ + fiji_complete_dependency_tables(hwmgr); + + /* Parse pptable data read from VBIOS */ + fiji_set_private_data_based_on_pptable(hwmgr); + + /* ULV Support */ + data->ulv.ulv_supported = true; /* ULV feature is enabled by default */ + + /* Initalize Dynamic State Adjustment Rule Settings */ + result = tonga_initializa_dynamic_state_adjustment_rule_settings(hwmgr); + + if (!result) { + data->uvd_enabled = false; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + data->vddc_phase_shed_control = false; + } + + stay_in_boot = phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StayInBootState); + + if (0 == result) { + struct cgs_system_info sys_info = {0}; + + data->is_tlu_enabled = 0; + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + FIJI_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM); + + if (table_info->cac_dtp_table->usDefaultTargetOperatingTemp && + hwmgr->thermal_controller. + advanceFanControlParameters.ucFanControlMode) { + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM; + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM; + hwmgr->dyn_state.cac_dtp_table->usOperatingTempMinLimit = + table_info->cac_dtp_table->usOperatingTempMinLimit; + hwmgr->dyn_state.cac_dtp_table->usOperatingTempMaxLimit = + table_info->cac_dtp_table->usOperatingTempMaxLimit; + hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = + table_info->cac_dtp_table->usDefaultTargetOperatingTemp; + hwmgr->dyn_state.cac_dtp_table->usOperatingTempStep = + table_info->cac_dtp_table->usOperatingTempStep; + hwmgr->dyn_state.cac_dtp_table->usTargetOperatingTemp = + table_info->cac_dtp_table->usTargetOperatingTemp; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport); + } + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO; + result = cgs_query_system_info(hwmgr->device, &sys_info); + if (result) + data->pcie_gen_cap = 0x30007; + else + data->pcie_gen_cap = (uint32_t)sys_info.value; + if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + data->pcie_spc_cap = 20; + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW; + result = cgs_query_system_info(hwmgr->device, &sys_info); + if (result) + data->pcie_lane_cap = 0x2f0000; + else + data->pcie_lane_cap = (uint32_t)sys_info.value; + } else { + /* Ignore return value in here, we are cleaning up a mess. */ + tonga_hwmgr_backend_fini(hwmgr); + } + + return 0; +} + +/** + * Read clock related registers. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int fiji_read_clock_registers(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + data->clock_registers.vCG_SPLL_FUNC_CNTL = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_FUNC_CNTL); + data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_FUNC_CNTL_2); + data->clock_registers.vCG_SPLL_FUNC_CNTL_3 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_FUNC_CNTL_3); + data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_FUNC_CNTL_4); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_SPREAD_SPECTRUM); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_SPLL_SPREAD_SPECTRUM_2); + + return 0; +} + +/** + * Find out if memory is GDDR5. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int fiji_get_memory_type(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t temp; + + temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0); + + data->is_memory_gddr5 = (MC_SEQ_MISC0_GDDR5_VALUE == + ((temp & MC_SEQ_MISC0_GDDR5_MASK) >> + MC_SEQ_MISC0_GDDR5_SHIFT)); + + return 0; +} + +/** + * Enables Dynamic Power Management by SMC + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int fiji_enable_acpi_power_management(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, STATIC_PM_EN, 1); + + return 0; +} + +/** + * Initialize PowerGating States for different engines + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +static int fiji_init_power_gate_state(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + data->samu_power_gated = false; + data->acp_power_gated = false; + data->pg_acp_init = true; + + return 0; +} + +static int fiji_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + data->low_sclk_interrupt_threshold = 0; + + return 0; +} + +static int fiji_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = fiji_read_clock_registers(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to read clock registers!", result = tmp_result); + + tmp_result = fiji_get_memory_type(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get memory type!", result = tmp_result); + + tmp_result = fiji_enable_acpi_power_management(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable ACPI power management!", result = tmp_result); + + tmp_result = fiji_init_power_gate_state(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init power gate state!", result = tmp_result); + + tmp_result = tonga_get_mc_microcode_version(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get MC microcode version!", result = tmp_result); + + tmp_result = fiji_init_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init sclk threshold!", result = tmp_result); + + return result; +} + +/** +* Checks if we want to support voltage control +* +* @param hwmgr the address of the powerplay hardware manager. +*/ +static bool fiji_voltage_control(const struct pp_hwmgr *hwmgr) +{ + const struct fiji_hwmgr *data = + (const struct fiji_hwmgr *)(hwmgr->backend); + + return (FIJI_VOLTAGE_CONTROL_NONE != data->voltage_control); +} + +/** +* Enable voltage control +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_enable_voltage_control(struct pp_hwmgr *hwmgr) +{ + /* enable voltage control */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1); + + return 0; +} + +/** +* Remove repeated voltage values and create table with unique values. +* +* @param hwmgr the address of the powerplay hardware manager. +* @param vol_table the pointer to changing voltage table +* @return 0 in success +*/ + +static int fiji_trim_voltage_table(struct pp_hwmgr *hwmgr, + struct pp_atomctrl_voltage_table *vol_table) +{ + uint32_t i, j; + uint16_t vvalue; + bool found = false; + struct pp_atomctrl_voltage_table *table; + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "Voltage Table empty.", return -EINVAL); + table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), + GFP_KERNEL); + + if (NULL == table) + return -EINVAL; + + table->mask_low = vol_table->mask_low; + table->phase_delay = vol_table->phase_delay; + + for (i = 0; i < vol_table->count; i++) { + vvalue = vol_table->entries[i].value; + found = false; + + for (j = 0; j < table->count; j++) { + if (vvalue == table->entries[j].value) { + found = true; + break; + } + } + + if (!found) { + table->entries[table->count].value = vvalue; + table->entries[table->count].smio_low = + vol_table->entries[i].smio_low; + table->count++; + } + } + + memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); + kfree(table); + + return 0; +} +static int fiji_get_svi2_mvdd_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_voltage_table *vol_table = &(data->mvdd_voltage_table); + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].mvdd; + vol_table->entries[i].smio_low = 0; + } + + result = fiji_trim_voltage_table(hwmgr, vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim MVDD table.", return result); + + return 0; +} + +static int fiji_get_svi2_vddci_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_voltage_table *vol_table = &(data->vddci_voltage_table); + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].vddci; + vol_table->entries[i].smio_low = 0; + } + + result = fiji_trim_voltage_table(hwmgr, vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim VDDCI table.", return result); + + return 0; +} + +static int fiji_get_svi2_vdd_voltage_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + int i = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_voltage_table *vol_table = &(data->vddc_voltage_table); + + PP_ASSERT_WITH_CODE((0 != lookup_table->count), + "Voltage Lookup Table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + + vol_table->count = lookup_table->count; + + for (i = 0; i < vol_table->count; i++) { + vol_table->entries[i].value = lookup_table->entries[i].us_vdd; + vol_table->entries[i].smio_low = 0; + } + + return 0; +} + +/* ---- Voltage Tables ---- + * If the voltage table would be bigger than + * what will fit into the state table on + * the SMC keep only the higher entries. + */ +static void fiji_trim_voltage_table_to_fit_state_table(struct pp_hwmgr *hwmgr, + uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table) +{ + unsigned int i, diff; + + if (vol_table->count <= max_vol_steps) + return; + + diff = vol_table->count - max_vol_steps; + + for (i = 0; i < max_vol_steps; i++) + vol_table->entries[i] = vol_table->entries[i + diff]; + + vol_table->count = max_vol_steps; + + return; +} + +/** +* Create Voltage Tables. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_construct_voltage_tables(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + int result; + + if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, + &(data->mvdd_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve MVDD table.", + return result); + } else if (FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + result = fiji_get_svi2_mvdd_voltage_table(hwmgr, + table_info->vdd_dep_on_mclk); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 MVDD table from dependancy table.", + return result;); + } + + if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, + &(data->vddci_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve VDDCI table.", + return result); + } else if (FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + result = fiji_get_svi2_vddci_voltage_table(hwmgr, + table_info->vdd_dep_on_mclk); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDCI table from dependancy table.", + return result); + } + + if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + result = fiji_get_svi2_vdd_voltage_table(hwmgr, + table_info->vddc_lookup_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDC table from lookup table.", + return result); + } + + PP_ASSERT_WITH_CODE( + (data->vddc_voltage_table.count <= (SMU73_MAX_LEVELS_VDDC)), + "Too many voltage values for VDDC. Trimming to fit state table.", + fiji_trim_voltage_table_to_fit_state_table(hwmgr, + SMU73_MAX_LEVELS_VDDC, &(data->vddc_voltage_table))); + + PP_ASSERT_WITH_CODE( + (data->vddci_voltage_table.count <= (SMU73_MAX_LEVELS_VDDCI)), + "Too many voltage values for VDDCI. Trimming to fit state table.", + fiji_trim_voltage_table_to_fit_state_table(hwmgr, + SMU73_MAX_LEVELS_VDDCI, &(data->vddci_voltage_table))); + + PP_ASSERT_WITH_CODE( + (data->mvdd_voltage_table.count <= (SMU73_MAX_LEVELS_MVDD)), + "Too many voltage values for MVDD. Trimming to fit state table.", + fiji_trim_voltage_table_to_fit_state_table(hwmgr, + SMU73_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table))); + + return 0; +} + +static int fiji_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + /* Program additional LP registers + * that are no longer programmed by VBIOS + */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, + cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + + return 0; +} + +/** +* Programs static screed detection parameters +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_program_static_screen_threshold_parameters( + struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* Set static screen threshold unit */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT, + data->static_screen_threshold_unit); + /* Set static screen threshold */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, + data->static_screen_threshold); + + return 0; +} + +/** +* Setup display gap for glitch free memory clock switching. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_enable_display_gap(struct pp_hwmgr *hwmgr) +{ + uint32_t displayGap = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL); + + displayGap = PHM_SET_FIELD(displayGap, CG_DISPLAY_GAP_CNTL, + DISP_GAP, DISPLAY_GAP_IGNORE); + + displayGap = PHM_SET_FIELD(displayGap, CG_DISPLAY_GAP_CNTL, + DISP_GAP_MCHG, DISPLAY_GAP_VBLANK); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL, displayGap); + + return 0; +} + +/** +* Programs activity state transition voting clients +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_program_voting_clients(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* Clear reset for voting clients before enabling DPM */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7); + + return 0; +} + +/** +* Get the location of various tables inside the FW image. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_smumgr *smu_data = (struct fiji_smumgr *)(hwmgr->smumgr->backend); + uint32_t tmp; + int result; + bool error = false; + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, DpmTable), + &tmp, data->sram_end); + + if (0 == result) + data->dpm_table_start = tmp; + + error |= (0 != result); + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, SoftRegisters), + &tmp, data->sram_end); + + if (!result) { + data->soft_regs_start = tmp; + smu_data->soft_regs_start = tmp; + } + + error |= (0 != result); + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcRegisterTable), + &tmp, data->sram_end); + + if (!result) + data->mc_reg_table_start = tmp; + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, FanTable), + &tmp, data->sram_end); + + if (!result) + data->fan_table_start = tmp; + + error |= (0 != result); + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, mcArbDramTimingTable), + &tmp, data->sram_end); + + if (!result) + data->arb_table_start = tmp; + + error |= (0 != result); + + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, Version), + &tmp, data->sram_end); + + if (!result) + hwmgr->microcode_version_info.SMC = tmp; + + error |= (0 != result); + + return error ? -1 : 0; +} + +/* Copy one arb setting to another and then switch the active set. + * arb_src and arb_dest is one of the MC_CG_ARB_FREQ_Fx constants. + */ +static int fiji_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, + uint32_t arb_src, uint32_t arb_dest) +{ + uint32_t mc_arb_dram_timing; + uint32_t mc_arb_dram_timing2; + uint32_t burst_time; + uint32_t mc_cg_config; + + switch (arb_src) { + case MC_CG_ARB_FREQ_F0: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + break; + case MC_CG_ARB_FREQ_F1: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1); + break; + default: + return -EINVAL; + } + + switch (arb_dest) { + case MC_CG_ARB_FREQ_F0: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time); + break; + case MC_CG_ARB_FREQ_F1: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time); + break; + default: + return -EINVAL; + } + + mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); + mc_cg_config |= 0x0000000F; + cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arb_dest); + + return 0; +} + +/** +* Initial switch from ARB F0->F1 +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +* This function is to be called from the SetPowerState table. +*/ +static int fiji_initial_switch_from_arbf0_to_f1(struct pp_hwmgr *hwmgr) +{ + return fiji_copy_and_switch_arb_sets(hwmgr, + MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); +} + +static int fiji_reset_single_dpm_table(struct pp_hwmgr *hwmgr, + struct fiji_single_dpm_table *dpm_table, uint32_t count) +{ + int i; + PP_ASSERT_WITH_CODE(count <= MAX_REGULAR_DPM_NUMBER, + "Fatal error, can not set up single DPM table entries " + "to exceed max number!",); + + dpm_table->count = count; + for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++) + dpm_table->dpm_levels[i].enabled = false; + + return 0; +} + +static void fiji_setup_pcie_table_entry( + struct fiji_single_dpm_table *dpm_table, + uint32_t index, uint32_t pcie_gen, + uint32_t pcie_lanes) +{ + dpm_table->dpm_levels[index].value = pcie_gen; + dpm_table->dpm_levels[index].param1 = pcie_lanes; + dpm_table->dpm_levels[index].enabled = 1; +} + +static int fiji_setup_default_pcie_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint32_t i, max_entry; + + PP_ASSERT_WITH_CODE((data->use_pcie_performance_levels || + data->use_pcie_power_saving_levels), "No pcie performance levels!", + return -EINVAL); + + if (data->use_pcie_performance_levels && + !data->use_pcie_power_saving_levels) { + data->pcie_gen_power_saving = data->pcie_gen_performance; + data->pcie_lane_power_saving = data->pcie_lane_performance; + } else if (!data->use_pcie_performance_levels && + data->use_pcie_power_saving_levels) { + data->pcie_gen_performance = data->pcie_gen_power_saving; + data->pcie_lane_performance = data->pcie_lane_power_saving; + } + + fiji_reset_single_dpm_table(hwmgr, + &data->dpm_table.pcie_speed_table, SMU73_MAX_LEVELS_LINK); + + if (pcie_table != NULL) { + /* max_entry is used to make sure we reserve one PCIE level + * for boot level (fix for A+A PSPP issue). + * If PCIE table from PPTable have ULV entry + 8 entries, + * then ignore the last entry.*/ + max_entry = (SMU73_MAX_LEVELS_LINK < pcie_table->count) ? + SMU73_MAX_LEVELS_LINK : pcie_table->count; + for (i = 1; i < max_entry; i++) { + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i - 1, + get_pcie_gen_support(data->pcie_gen_cap, + pcie_table->entries[i].gen_speed), + get_pcie_lane_support(data->pcie_lane_cap, + pcie_table->entries[i].lane_width)); + } + data->dpm_table.pcie_speed_table.count = max_entry - 1; + } else { + /* Hardcode Pcie Table */ + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + + data->dpm_table.pcie_speed_table.count = 6; + } + /* Populate last level for boot PCIE level, but do not increment count. */ + fiji_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, + data->dpm_table.pcie_speed_table.count, + get_pcie_gen_support(data->pcie_gen_cap, + PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, + PP_Max_PCIELane)); + + return 0; +} + +/* + * This function is to initalize all DPM state tables + * for SMU7 based on the dependency table. + * Dynamic state patching function will then trim these + * state tables to the allowed range based + * on the power policy or external client requests, + * such as UVD request, etc. + */ +static int fiji_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i; + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_sclk_table = + table_info->vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(dep_sclk_table != NULL, + "SCLK dependency table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_sclk_table->count >= 1, + "SCLK dependency table has to have is missing. " + "This table is mandatory", + return -EINVAL); + + PP_ASSERT_WITH_CODE(dep_mclk_table != NULL, + "MCLK dependency table is missing. This table is mandatory", + return -EINVAL); + PP_ASSERT_WITH_CODE(dep_mclk_table->count >= 1, + "MCLK dependency table has to have is missing. " + "This table is mandatory", + return -EINVAL); + + /* clear the state table to reset everything to default */ + fiji_reset_single_dpm_table(hwmgr, + &data->dpm_table.sclk_table, SMU73_MAX_LEVELS_GRAPHICS); + fiji_reset_single_dpm_table(hwmgr, + &data->dpm_table.mclk_table, SMU73_MAX_LEVELS_MEMORY); + + /* Initialize Sclk DPM table based on allow Sclk values */ + data->dpm_table.sclk_table.count = 0; + for (i = 0; i < dep_sclk_table->count; i++) { + if (i == 0 || data->dpm_table.sclk_table.dpm_levels + [data->dpm_table.sclk_table.count - 1].value != + dep_sclk_table->entries[i].clk) { + data->dpm_table.sclk_table.dpm_levels + [data->dpm_table.sclk_table.count].value = + dep_sclk_table->entries[i].clk; + data->dpm_table.sclk_table.dpm_levels + [data->dpm_table.sclk_table.count].enabled = + (i == 0) ? true : false; + data->dpm_table.sclk_table.count++; + } + } + + /* Initialize Mclk DPM table based on allow Mclk values */ + data->dpm_table.mclk_table.count = 0; + for (i=0; i<dep_mclk_table->count; i++) { + if ( i==0 || data->dpm_table.mclk_table.dpm_levels + [data->dpm_table.mclk_table.count - 1].value != + dep_mclk_table->entries[i].clk) { + data->dpm_table.mclk_table.dpm_levels + [data->dpm_table.mclk_table.count].value = + dep_mclk_table->entries[i].clk; + data->dpm_table.mclk_table.dpm_levels + [data->dpm_table.mclk_table.count].enabled = + (i == 0) ? true : false; + data->dpm_table.mclk_table.count++; + } + } + + /* setup PCIE gen speed levels */ + fiji_setup_default_pcie_table(hwmgr); + + /* save a copy of the default DPM table */ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), + sizeof(struct fiji_dpm_table)); + + return 0; +} + +/** + * @brief PhwFiji_GetVoltageOrder + * Returns index of requested voltage record in lookup(table) + * @param lookup_table - lookup list to search in + * @param voltage - voltage to look for + * @return 0 on success + */ +uint8_t fiji_get_voltage_index( + struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) +{ + uint8_t count = (uint8_t) (lookup_table->count); + uint8_t i; + + PP_ASSERT_WITH_CODE((NULL != lookup_table), + "Lookup Table empty.", return 0); + PP_ASSERT_WITH_CODE((0 != count), + "Lookup Table empty.", return 0); + + for (i = 0; i < lookup_table->count; i++) { + /* find first voltage equal or bigger than requested */ + if (lookup_table->entries[i].us_vdd >= voltage) + return i; + } + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + +/** +* Preparation of vddc and vddgfx CAC tables for SMC. +* +* @param hwmgr the address of the hardware manager +* @param table the SMC DPM table structure to be populated +* @return always 0 +*/ +static int fiji_populate_cac_table(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + int result = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *lookup_table = + table_info->vddc_lookup_table; + /* tables is already swapped, so in order to use the value from it, + * we need to swap it back. + * We are populating vddc CAC data to BapmVddc table + * in split and merged mode + */ + for( count = 0; count<lookup_table->count; count++) { + index = fiji_get_voltage_index(lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = (uint8_t) ((6200 - + (lookup_table->entries[index].us_cac_low * + VOLTAGE_SCALE)) / 25); + table->BapmVddcVidHiSidd[count] = (uint8_t) ((6200 - + (lookup_table->entries[index].us_cac_high * + VOLTAGE_SCALE)) / 25); + } + + return result; +} + +/** +* Preparation of voltage tables for SMC. +* +* @param hwmgr the address of the hardware manager +* @param table the SMC DPM table structure to be populated +* @return always 0 +*/ + +int fiji_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result; + + result = fiji_populate_cac_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate CAC voltage tables to SMC", + return -EINVAL); + + return 0; +} + +static int fiji_populate_ulv_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_Ulv *state) +{ + int result = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + state->CcPwrDynRm = 0; + state->CcPwrDynRm1 = 0; + + state->VddcOffset = (uint16_t) table_info->us_ulv_voltage_offset; + state->VddcOffsetVid = (uint8_t)( table_info->us_ulv_voltage_offset * + VOLTAGE_VID_OFFSET_SCALE2 / VOLTAGE_VID_OFFSET_SCALE1 ); + + state->VddcPhase = (data->vddc_phase_shed_control) ? 0 : 1; + + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(state->CcPwrDynRm1); + CONVERT_FROM_HOST_TO_SMC_US(state->VddcOffset); + } + return result; +} + +static int fiji_populate_ulv_state(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + return fiji_populate_ulv_level(hwmgr, &table->Ulv); +} + +static int32_t fiji_get_dpm_level_enable_mask_value( + struct fiji_single_dpm_table* dpm_table) +{ + int32_t i; + int32_t mask = 0; + + for (i = dpm_table->count; i > 0; i--) { + mask = mask << 1; + if (dpm_table->dpm_levels[i - 1].enabled) + mask |= 0x1; + else + mask &= 0xFFFFFFFE; + } + return mask; +} + +static int fiji_populate_smc_link_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_dpm_table *dpm_table = &data->dpm_table; + int i; + + /* Index (dpm_table->pcie_speed_table.count) + * is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = (uint8_t)encode_pcie_lane_width( + dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = 1; + table->LinkLevel[i].SPC = (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = PP_HOST_TO_SMC_UL(30); + } + + data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +/** +* Calculates the SCLK dividers using the provided engine clock +* +* @param hwmgr the address of the hardware manager +* @param clock the engine clock to use to populate the structure +* @param sclk the SMC SCLK structure to be populated +*/ +static int fiji_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_GraphicsLevel *sclk) +{ + const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t ref_clock; + uint32_t ref_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref. */ + ref_clock = atomctrl_get_reference_clock(hwmgr); + ref_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider */ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup */ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, CG_SPLL_FUNC_CNTL_3, + SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + struct pp_atomctrl_internal_ss_info ssInfo; + + uint32_t vco_freq = clock * dividers.uc_pll_post_div; + if (!atomctrl_get_engine_clock_spread_spectrum(hwmgr, + vco_freq, &ssInfo)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + * + * clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 + */ + uint32_t clk_s = ref_clock * 5 / + (ref_divider * ssInfo.speed_spectrum_rate); + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clk_v = 4 * ssInfo.speed_spectrum_percentage * + fbdiv / (clk_s * 10000); + + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, CLKS, clk_s); + cg_spll_spread_spectrum = PHM_SET_FIELD(cg_spll_spread_spectrum, + CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = PHM_SET_FIELD(cg_spll_spread_spectrum_2, + CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clk_v); + } + } + + sclk->SclkFrequency = clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +static uint16_t fiji_find_closest_vddci(struct pp_hwmgr *hwmgr, uint16_t vddci) +{ + uint32_t i; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct pp_atomctrl_voltage_table *vddci_table = + &(data->vddci_voltage_table); + + for (i = 0; i < vddci_table->count; i++) { + if (vddci_table->entries[i].value >= vddci) + return vddci_table->entries[i].value; + } + + PP_ASSERT_WITH_CODE(false, + "VDDCI is larger than max VDDCI in VDDCI Voltage Table!", + return vddci_table->entries[i].value); +} + +static int fiji_get_dependency_volt_by_clk(struct pp_hwmgr *hwmgr, + struct phm_ppt_v1_clock_voltage_dependency_table* dep_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i; + uint16_t vddci; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + *voltage = *mvdd = 0; + + /* clock - voltage dependency table is empty table */ + if (dep_table->count == 0) + return -EINVAL; + + for (i = 0; i < dep_table->count; i++) { + /* find first sclk bigger than request */ + if (dep_table->entries[i].clk >= clock) { + *voltage |= (dep_table->entries[i].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + if (FIJI_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i].vddci) + *voltage |= (dep_table->entries[i].vddci * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else { + vddci = fiji_find_closest_vddci(hwmgr, + (dep_table->entries[i].vddc - + (uint16_t)data->vddc_vddci_delta)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i].mvdd * + VOLTAGE_SCALE; + + *voltage |= 1 << PHASES_SHIFT; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + *voltage |= (dep_table->entries[i - 1].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + + if (FIJI_VOLTAGE_CONTROL_NONE == data->vddci_control) + *voltage |= (data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE) << VDDCI_SHIFT; + else if (dep_table->entries[i-1].vddci) { + vddci = fiji_find_closest_vddci(hwmgr, + (dep_table->entries[i].vddc - + (uint16_t)data->vddc_vddci_delta)); + *voltage |= (vddci * VOLTAGE_SCALE) << VDDCI_SHIFT; + } + + if (FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control) + *mvdd = data->vbios_boot_state.mvdd_bootup_value * VOLTAGE_SCALE; + else if (dep_table->entries[i].mvdd) + *mvdd = (uint32_t) dep_table->entries[i - 1].mvdd * VOLTAGE_SCALE; + + return 0; +} +/** +* Populates single SMC SCLK structure using the provided engine clock +* +* @param hwmgr the address of the hardware manager +* @param clock the engine clock to use to populate the structure +* @param sclk the SMC SCLK structure to be populated +*/ + +static int fiji_populate_single_graphic_level(struct pp_hwmgr *hwmgr, + uint32_t clock, uint16_t sclk_al_threshold, + struct SMU73_Discrete_GraphicsLevel *level) +{ + int result; + /* PP_Clocks minClocks; */ + uint32_t threshold, mvdd; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + result = fiji_calculate_sclk_params(hwmgr, clock, level); + + /* populate graphics levels */ + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, clock, + &level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for " + "VDDC engine clock dependency table", + return result); + + level->SclkFrequency = clock; + level->ActivityLevel = sclk_al_threshold; + level->CcPwrDynRm = 0; + level->CcPwrDynRm1 = 0; + level->EnabledForActivity = 0; + level->EnabledForThrottle = 1; + level->UpHyst = 10; + level->DownHyst = 0; + level->VoltageDownHyst = 0; + level->PowerThrottle = 0; + + threshold = clock * data->fast_watermark_threshold / 100; + + /* + * TODO: get minimum clocks from dal configaration + * PECI_GetMinClockSettings(hwmgr->pPECI, &minClocks); + */ + /* data->DisplayTiming.minClockInSR = minClocks.engineClockInSR; */ + + /* get level->DeepSleepDivId + if (phm_cap_enabled(hwmgr->platformDescriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + { + level->DeepSleepDivId = PhwFiji_GetSleepDividerIdFromClock(hwmgr, clock, minClocks.engineClockInSR); + } */ + + /* Default to slow, highest DPM level will be + * set to PPSMC_DISPLAY_WATERMARK_LOW later. + */ + level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + CONVERT_FROM_HOST_TO_SMC_UL(level->MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(level->CcPwrDynRm1); + + return 0; +} +/** +* Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states +* +* @param hwmgr the address of the hardware manager +*/ +static int fiji_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_dpm_table *dpm_table = &data->dpm_table; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_pcie_table *pcie_table = table_info->pcie_table; + uint8_t pcie_entry_cnt = (uint8_t) data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t array = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + uint32_t array_size = sizeof(struct SMU73_Discrete_GraphicsLevel) * + SMU73_MAX_LEVELS_GRAPHICS; + struct SMU73_Discrete_GraphicsLevel *levels = + data->smc_state_table.GraphicsLevel; + uint32_t i, max_entry; + uint8_t hightest_pcie_level_enabled = 0, + lowest_pcie_level_enabled = 0, + mid_pcie_level_enabled = 0, + count = 0; + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = fiji_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)data->activity_target[i], + &levels[i]); + if (result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + levels[i].DeepSleepDivId = 0; + } + + /* Only enable level 0 for now.*/ + levels[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + levels[dpm_table->sclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((1 <= pcie_entry_cnt), + "There must be 1 or more PCIE levels defined in PPTable.", + return -EINVAL); + max_entry = pcie_entry_cnt - 1; + for (i = 0; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = + (uint8_t) ((i < max_entry)? i : max_entry); + } else { + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (hightest_pcie_level_enabled + 1))) != 0 )) + hightest_pcie_level_enabled++; + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << lowest_pcie_level_enabled)) == 0 )) + lowest_pcie_level_enabled++; + + while ((count < hightest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1 << (lowest_pcie_level_enabled + 1 + count))) == 0 )) + count++; + + mid_pcie_level_enabled = (lowest_pcie_level_enabled + 1+ count) < + hightest_pcie_level_enabled? + (lowest_pcie_level_enabled + 1 + count) : + hightest_pcie_level_enabled; + + /* set pcieDpmLevel to hightest_pcie_level_enabled */ + for(i = 2; i < dpm_table->sclk_table.count; i++) + levels[i].pcieDpmLevel = hightest_pcie_level_enabled; + + /* set pcieDpmLevel to lowest_pcie_level_enabled */ + levels[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled */ + levels[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change */ + result = fiji_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + (uint32_t)array_size, data->sram_end); + + return result; +} + +/** + * MCLK Frequency Ratio + * SEQ_CG_RESP Bit[31:24] - 0x0 + * Bit[27:24] \96 DDR3 Frequency ratio + * 0x0 <= 100MHz, 450 < 0x8 <= 500MHz + * 100 < 0x1 <= 150MHz, 500 < 0x9 <= 550MHz + * 150 < 0x2 <= 200MHz, 550 < 0xA <= 600MHz + * 200 < 0x3 <= 250MHz, 600 < 0xB <= 650MHz + * 250 < 0x4 <= 300MHz, 650 < 0xC <= 700MHz + * 300 < 0x5 <= 350MHz, 700 < 0xD <= 750MHz + * 350 < 0x6 <= 400MHz, 750 < 0xE <= 800MHz + * 400 < 0x7 <= 450MHz, 800 < 0xF + */ +static uint8_t fiji_get_mclk_frequency_ratio(uint32_t mem_clock) +{ + if (mem_clock <= 10000) return 0x0; + if (mem_clock <= 15000) return 0x1; + if (mem_clock <= 20000) return 0x2; + if (mem_clock <= 25000) return 0x3; + if (mem_clock <= 30000) return 0x4; + if (mem_clock <= 35000) return 0x5; + if (mem_clock <= 40000) return 0x6; + if (mem_clock <= 45000) return 0x7; + if (mem_clock <= 50000) return 0x8; + if (mem_clock <= 55000) return 0x9; + if (mem_clock <= 60000) return 0xa; + if (mem_clock <= 65000) return 0xb; + if (mem_clock <= 70000) return 0xc; + if (mem_clock <= 75000) return 0xd; + if (mem_clock <= 80000) return 0xe; + /* mem_clock > 800MHz */ + return 0xf; +} + +/** +* Populates the SMC MCLK structure using the provided memory clock +* +* @param hwmgr the address of the hardware manager +* @param clock the memory clock to use to populate the structure +* @param sclk the SMC SCLK structure to be populated +*/ +static int fiji_calculate_mclk_params(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mclk) +{ + struct pp_atomctrl_memory_clock_param mem_param; + int result; + + result = atomctrl_get_memory_pll_dividers_vi(hwmgr, clock, &mem_param); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to get Memory PLL Dividers.",); + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = clock; + mclk->MclkDivider = (uint8_t)mem_param.mpll_post_divider; + mclk->FreqRange = fiji_get_mclk_frequency_ratio(clock); + + return result; +} + +static int fiji_populate_single_memory_level(struct pp_hwmgr *hwmgr, + uint32_t clock, struct SMU73_Discrete_MemoryLevel *mem_level) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + + if (table_info->vdd_dep_on_mclk) { + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, clock, + &mem_level->MinVoltage, &mem_level->MinMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory " + "VDDC voltage dependency table", return result); + } + + mem_level->EnabledForThrottle = 1; + mem_level->EnabledForActivity = 0; + mem_level->UpHyst = 0; + mem_level->DownHyst = 100; + mem_level->VoltageDownHyst = 0; + mem_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + mem_level->StutterEnable = false; + + mem_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + /* enable stutter mode if all the follow condition applied + * PECI_GetNumberOfActiveDisplays(hwmgr->pPECI, + * &(data->DisplayTiming.numExistingDisplays)); + */ + data->display_timing.num_existing_displays = 1; + + if ((data->mclk_stutter_mode_threshold) && + (clock <= data->mclk_stutter_mode_threshold) && + (!data->is_uvd_enabled) && + (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, + STUTTER_ENABLE) & 0x1)) + mem_level->StutterEnable = true; + + result = fiji_calculate_mclk_params(hwmgr, clock, mem_level); + if (!result) { + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinMvdd); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(mem_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(mem_level->MinVoltage); + } + return result; +} + +/** +* Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states +* +* @param hwmgr the address of the hardware manager +*/ +static int fiji_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_dpm_table *dpm_table = &data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t array = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, MemoryLevel); + uint32_t array_size = sizeof(SMU73_Discrete_MemoryLevel) * + SMU73_MAX_LEVELS_MEMORY; + struct SMU73_Discrete_MemoryLevel *levels = + data->smc_state_table.MemoryLevel; + uint32_t i; + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", + return -EINVAL); + result = fiji_populate_single_memory_level(hwmgr, + dpm_table->mclk_table.dpm_levels[i].value, + &levels[i]); + if (result) + return result; + } + + /* Only enable level 0 for now. */ + levels[0].EnabledForActivity = 1; + + /* in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in + * a higher state by default such that we are not effected by + * up threshold or and MCLK DPM latency. + */ + levels[0].ActivityLevel = (uint16_t)data->mclk_dpm0_activity_target; + CONVERT_FROM_HOST_TO_SMC_US(levels[0].ActivityLevel); + + data->smc_state_table.MemoryDpmLevelCount = + (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high */ + levels[dpm_table->mclk_table.count - 1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change */ + result = fiji_copy_bytes_to_smc(hwmgr->smumgr, array, (uint8_t *)levels, + (uint32_t)array_size, data->sram_end); + + return result; +} + +/** +* Populates the SMC MVDD structure using the provided memory clock. +* +* @param hwmgr the address of the hardware manager +* @param mclk the MCLK value to be used in the decision if MVDD should be high or low. +* @param voltage the SMC VOLTAGE structure to be populated +*/ +int fiji_populate_mvdd_value(struct pp_hwmgr *hwmgr, + uint32_t mclk, SMIO_Pattern *smio_pat) +{ + const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (FIJI_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < table_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= table_info->vdd_dep_on_mclk->entries[i].clk) { + smio_pat->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + PP_ASSERT_WITH_CODE(i < table_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", + return -EINVAL); + } else + return -EINVAL; + + return 0; +} + +static int fiji_populate_smc_acpi_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = 0; + const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct pp_atomctrl_clock_dividers_vi dividers; + SMIO_Pattern vol_level; + uint32_t mvdd; + uint16_t us_mvdd; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + if (!data->sclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, + * already converted to SMC_UL */ + table->ACPILevel.SclkFrequency = + data->dpm_table.sclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_sclk, + table->ACPILevel.SclkFrequency, + &table->ACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDC voltage value " + "in Clock Dependency Table",); + } else { + table->ACPILevel.SclkFrequency = + data->vbios_boot_state.sclk_bootup_value; + table->ACPILevel.MinVoltage = + data->vbios_boot_state.vddc_bootup_value * VOLTAGE_SCALE; + } + + /* get the engine clock dividers for this clock value */ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", + return result); + + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, CG_SPLL_FUNC_CNTL, + SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, CG_SPLL_FUNC_CNTL_2, + SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.MinVoltage); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + if (!data->mclk_dpm_key_disabled) { + /* Get MinVoltage and Frequency from DPM0, already converted to SMC_UL */ + table->MemoryACPILevel.MclkFrequency = + data->dpm_table.mclk_table.dpm_levels[0].value; + result = fiji_get_dependency_volt_by_clk(hwmgr, + table_info->vdd_dep_on_mclk, + table->MemoryACPILevel.MclkFrequency, + &table->MemoryACPILevel.MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "Cannot find ACPI VDDCI voltage value " + "in Clock Dependency Table",); + } else { + table->MemoryACPILevel.MclkFrequency = + data->vbios_boot_state.mclk_bootup_value; + table->MemoryACPILevel.MinVoltage = + data->vbios_boot_state.vddci_bootup_value * VOLTAGE_SCALE; + } + + us_mvdd = 0; + if ((FIJI_VOLTAGE_CONTROL_NONE == data->mvdd_control) || + (data->mclk_dpm_key_disabled)) + us_mvdd = data->vbios_boot_state.mvdd_bootup_value; + else { + if (!fiji_populate_mvdd_value(hwmgr, + data->dpm_table.mclk_table.dpm_levels[0].value, + &vol_level)) + us_mvdd = vol_level.Voltage; + } + + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(us_mvdd * VOLTAGE_SCALE); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + table->MemoryACPILevel.ActivityLevel = + PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = false; + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage); + + return result; +} + +static int fiji_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + table->VceLevelCount = (uint8_t)(mm_table->count); + table->VceBootLevel = 0; + + for(count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage |= + (mm_table->entries[count].vddc * VOLTAGE_SCALE) << VDDC_SHIFT; + table->VceLevel[count].MinVoltage |= + ((mm_table->entries[count].vddc - data->vddc_vddci_delta) * + VOLTAGE_SCALE) << VDDCI_SHIFT; + table->VceLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /*retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", + return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + table->AcpLevelCount = (uint8_t)(mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = mm_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->AcpLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->AcpLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t)(mm_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + /* not sure whether we need evclk or not */ + table->SamuLevel[count].Frequency = mm_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->SamuLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->SamuLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].MinVoltage); + } + return result; +} + +static int fiji_populate_memory_timing_parameters(struct pp_hwmgr *hwmgr, + int32_t eng_clock, int32_t mem_clock, + struct SMU73_Discrete_MCArbDramTimingTableEntry *arb_regs) +{ + uint32_t dram_timing; + uint32_t dram_timing2; + uint32_t burstTime; + ULONG state, trrds, trrdl; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + eng_clock, mem_clock); + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = cgs_read_register(hwmgr->device, mmMC_ARB_BURST_TIME); + + state = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, STATE0); + trrds = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDS0); + trrdl = PHM_GET_FIELD(burstTime, MC_ARB_BURST_TIME, TRRDL0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dram_timing); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dram_timing2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + arb_regs->TRRDS = (uint8_t)trrds; + arb_regs->TRRDL = (uint8_t)trrdl; + + return 0; +} + +static int fiji_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct SMU73_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + int result = 0; + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = fiji_populate_memory_timing_parameters(hwmgr, + data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + if (result) + break; + } + } + + if (!result) + result = fiji_copy_bytes_to_smc( + hwmgr->smumgr, + data->arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU73_Discrete_MCArbDramTimingTable), + data->sram_end); + return result; +} + +static int fiji_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = -EINVAL; + uint8_t count; + struct pp_atomctrl_clock_dividers_vi dividers; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = + table_info->mm_dep_table; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + table->UvdLevelCount = (uint8_t)(mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage |= (mm_table->entries[count].vddc * + VOLTAGE_SCALE) << VDDC_SHIFT; + table->UvdLevel[count].MinVoltage |= ((mm_table->entries[count].vddc - + data->vddc_vddci_delta) * VOLTAGE_SCALE) << VDDCI_SHIFT; + table->UvdLevel[count].MinVoltage |= 1 << PHASES_SHIFT; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].MinVoltage); + + } + return result; +} + +static int fiji_find_boot_level(struct fiji_single_dpm_table *table, + uint32_t value, uint32_t *boot_level) +{ + int result = -EINVAL; + uint32_t i; + + for (i = 0; i < table->count; i++) { + if (value == table->dpm_levels[i].value) { + *boot_level = i; + result = 0; + } + } + return result; +} + +static int fiji_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + int result = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; + table->MemoryBootLevel = 0; + + /* find boot level from dpm table */ + result = fiji_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(table->GraphicsBootLevel)); + + result = fiji_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(table->MemoryBootLevel)); + + table->BootVddc = data->vbios_boot_state.vddc_bootup_value * + VOLTAGE_SCALE; + table->BootVddci = data->vbios_boot_state.vddci_bootup_value * + VOLTAGE_SCALE; + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value * + VOLTAGE_SCALE; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddc); + CONVERT_FROM_HOST_TO_SMC_US(table->BootVddci); + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return 0; +} + +static int fiji_populate_smc_initailial_state(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t)(table_info->vdd_dep_on_sclk->count); + for (level = 0; level < count; level++) { + if(table_info->vdd_dep_on_sclk->entries[level].clk >= + data->vbios_boot_state.sclk_bootup_value) { + data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t)(table_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if(table_info->vdd_dep_on_mclk->entries[level].clk >= + data->vbios_boot_state.mclk_bootup_value) { + data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +static int fiji_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + uint32_t ro, efuse, efuse2, clock_freq, volt_without_cks, + volt_with_cks, value; + uint16_t clock_freq_u16; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint8_t type, i, j, cks_setting, stretch_amount, stretch_amount2, + volt_offset = 0; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *sclk_table = + table_info->vdd_dep_on_sclk; + + stretch_amount = (uint8_t)table_info->cac_dtp_table->usClockStretchAmount; + + /* Read SMU_Eefuse to read and calculate RO and determine + * if the part is SS or FF. if RO >= 1660MHz, part is FF. + */ + efuse = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (146 * 4)); + efuse2 = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixSMU_EFUSE_0 + (148 * 4)); + efuse &= 0xFF000000; + efuse = efuse >> 24; + efuse2 &= 0xF; + + if (efuse2 == 1) + ro = (2300 - 1350) * efuse / 255 + 1350; + else + ro = (2500 - 1000) * efuse / 255 + 1000; + + if (ro >= 1660) + type = 0; + else + type = 1; + + /* Populate Stretch amount */ + data->smc_state_table.ClockStretcherAmount = stretch_amount; + + /* Populate Sclk_CKS_masterEn0_7 and Sclk_voltageOffset */ + for (i = 0; i < sclk_table->count; i++) { + data->smc_state_table.Sclk_CKS_masterEn0_7 |= + sclk_table->entries[i].cks_enable << i; + volt_without_cks = (uint32_t)((14041 * + (sclk_table->entries[i].clk/100) / 10000 + 3571 + 75 - ro) * 1000 / + (4026 - (13924 * (sclk_table->entries[i].clk/100) / 10000))); + volt_with_cks = (uint32_t)((13946 * + (sclk_table->entries[i].clk/100) / 10000 + 3320 + 45 - ro) * 1000 / + (3664 - (11454 * (sclk_table->entries[i].clk/100) / 10000))); + if (volt_without_cks >= volt_with_cks) + volt_offset = (uint8_t)(((volt_without_cks - volt_with_cks + + sclk_table->entries[i].cks_voffset) * 100 / 625) + 1); + data->smc_state_table.Sclk_voltageOffset[i] = volt_offset; + } + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + STRETCH_ENABLE, 0x0); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + staticEnable, 0x1); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, PWR_CKS_ENABLE, + masterReset, 0x0); + + /* Populate CKS Lookup Table */ + if (stretch_amount == 1 || stretch_amount == 2 || stretch_amount == 5) + stretch_amount2 = 0; + else if (stretch_amount == 3 || stretch_amount == 4) + stretch_amount2 = 1; + else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + PP_ASSERT_WITH_CODE(false, + "Stretch Amount in PPTable not supported\n", + return -EINVAL); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL); + value &= 0xFFC2FF87; + data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].minFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][0]; + data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].maxFreq = + fiji_clock_stretcher_lookup_table[stretch_amount2][1]; + clock_freq_u16 = (uint16_t)(PP_SMC_TO_HOST_UL(data->smc_state_table. + GraphicsLevel[data->smc_state_table.GraphicsDpmLevelCount - 1]. + SclkFrequency) / 100); + if (fiji_clock_stretcher_lookup_table[stretch_amount2][0] < + clock_freq_u16 && + fiji_clock_stretcher_lookup_table[stretch_amount2][1] > + clock_freq_u16) { + /* Program PWR_CKS_CNTL. CKS_USE_FOR_LOW_FREQ */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 16; + /* Program PWR_CKS_CNTL. CKS_LDO_REFSEL */ + value |= (fiji_clock_stretcher_lookup_table[stretch_amount2][2]) << 18; + /* Program PWR_CKS_CNTL. CKS_STRETCH_AMOUNT */ + value |= (fiji_clock_stretch_amount_conversion + [fiji_clock_stretcher_lookup_table[stretch_amount2][3]] + [stretch_amount]) << 3; + } + CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].minFreq); + CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.CKS_LOOKUPTable. + CKS_LOOKUPTableEntry[0].maxFreq); + data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting = + fiji_clock_stretcher_lookup_table[stretch_amount2][2] & 0x7F; + data->smc_state_table.CKS_LOOKUPTable.CKS_LOOKUPTableEntry[0].setting |= + (fiji_clock_stretcher_lookup_table[stretch_amount2][3]) << 7; + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixPWR_CKS_CNTL, value); + + /* Populate DDT Lookup Table */ + for (i = 0; i < 4; i++) { + /* Assign the minimum and maximum VID stored + * in the last row of Clock Stretcher Voltage Table. + */ + data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].minVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][2]; + data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].maxVID = + (uint8_t) fiji_clock_stretcher_ddt_table[type][i][3]; + /* Loop through each SCLK and check the frequency + * to see if it lies within the frequency for clock stretcher. + */ + for (j = 0; j < data->smc_state_table.GraphicsDpmLevelCount; j++) { + cks_setting = 0; + clock_freq = PP_SMC_TO_HOST_UL( + data->smc_state_table.GraphicsLevel[j].SclkFrequency); + /* Check the allowed frequency against the sclk level[j]. + * Sclk's endianness has already been converted, + * and it's in 10Khz unit, + * as opposed to Data table, which is in Mhz unit. + */ + if (clock_freq >= + (fiji_clock_stretcher_ddt_table[type][i][0]) * 100) { + cks_setting |= 0x2; + if (clock_freq < + (fiji_clock_stretcher_ddt_table[type][i][1]) * 100) + cks_setting |= 0x1; + } + data->smc_state_table.ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting |= cks_setting << (j * 2); + } + CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table. + ClockStretcherDataTable. + ClockStretcherDataTableEntry[i].setting); + } + + value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL); + value &= 0xFFFFFFFE; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixPWR_CKS_CNTL, value); + + return 0; +} + +/** +* Populates the SMC VRConfig field in DPM table. +* +* @param hwmgr the address of the hardware manager +* @param table the SMC DPM table structure to be populated +* @return always 0 +*/ +static int fiji_populate_vr_config(struct pp_hwmgr *hwmgr, + struct SMU73_Discrete_DpmTable *table) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint16_t config; + + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config << VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + PP_ASSERT_WITH_CODE(false, + "VDDC should be on SVI2 control in merged mode!",); + } + /* Set Vddci Voltage Controller */ + if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->vddci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else if (FIJI_VOLTAGE_CONTROL_BY_GPIO == data->vddci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_VDDCI_SHIFT); + } + /* Set Mvdd Voltage Controller */ + if(FIJI_VOLTAGE_CONTROL_BY_SVID2 == data->mvdd_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else if(FIJI_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } else { + config = VR_STATIC_VOLTAGE; + table->VRConfig |= (config << VRCONF_MVDD_SHIFT); + } + + return 0; +} + +/** +* Initializes the SMC table and uploads it +* +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data (PowerState) +* @return always 0 +*/ +static int fiji_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct SMU73_Discrete_DpmTable *table = &(data->smc_state_table); + const struct fiji_ulv_parm *ulv = &(data->ulv); + uint8_t i; + struct pp_atomctrl_gpio_pin_assignment gpio_pin; + + result = fiji_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to setup default DPM tables!", return result); + + if(FIJI_VOLTAGE_CONTROL_NONE != data->voltage_control) + fiji_populate_smc_voltage_tables(hwmgr, table); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + + if (data->is_memory_gddr5) + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + + if (ulv->ulv_supported && table_info->us_ulv_voltage_offset) { + result = fiji_populate_ulv_state(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, ulv->cg_ulv_parameter); + } + + result = fiji_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result); + + result = fiji_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result); + + result = fiji_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result); + + result = fiji_populate_smc_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result); + + result = fiji_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result); + + result = fiji_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result); + + result = fiji_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result); + + /* Since only the initial state is completely set up at this point + * (the other states are just copies of the boot state) we only + * need to populate the ARB settings for the initial state. + */ + result = fiji_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result); + + result = fiji_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result); + + result = fiji_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result); + + result = fiji_populate_smc_initailial_state(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot State!", return result); + + result = fiji_populate_bapm_parameters_in_dpm_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate BAPM Parameters!", return result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = fiji_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", + return result); + } + + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + table_info->cac_dtp_table->usTargetOperatingTemp * + FIJI_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (table_info->cac_dtp_table->usTargetOperatingTemp - 1) * + FIJI_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + table->PCIeBootLinkLevel = 0; /* 0:Gen1 1:Gen2 2:Gen3*/ + table->PCIeGenInterval = 1; + + result = fiji_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + if (atomctrl_get_pp_assign_pin(hwmgr, VDDC_VRHOT_GPIO_PINID, &gpio_pin)) { + table->VRHotGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = FIJI_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + if (atomctrl_get_pp_assign_pin(hwmgr, PP_AC_DC_SWITCH_GPIO_PINID, + &gpio_pin)) { + table->AcDcGpio = gpio_pin.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = FIJI_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + /* Thermal Output GPIO */ + if (atomctrl_get_pp_assign_pin(hwmgr, THERMAL_INT_OUTPUT_GPIO_PINID, + &gpio_pin)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin.uc_gpio_pin_bit_shift; + + /* For porlarity read GPIOPAD_A with assigned Gpio pin + * since VBIOS will program this register to set 'inactive state', + * driver can then determine 'active state' from this and + * program SMU with correct polarity + */ + table->ThermOutPolarity = (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin.uc_gpio_pin_bit_shift))) ? 1:0; + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO */ + if(phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)) + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU73_MAX_ENTRIES_SMIO; i++) + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = fiji_copy_bytes_to_smc(hwmgr->smumgr, + data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU73_Discrete_DpmTable) - 3 * sizeof(SMU73_PIDController), + data->sram_end); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result); + + return 0; +} + +/** +* Initialize the ARB DRAM timing table's index field. +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always 0 +*/ +static int fiji_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + const struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t tmp; + int result; + + /* This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU73_Discrete_MCArbDramTimingTable structure + * is the field 'current'. + * This solution is ugly, but we never write the whole table only + * individual fields in it. + * In reality this field should not be in that structure + * but in a soft register. + */ + result = fiji_read_smc_sram_dword(hwmgr->smumgr, + data->arb_table_start, &tmp, data->sram_end); + + if (result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return fiji_write_smc_sram_dword(hwmgr->smumgr, + data->arb_table_start, tmp, data->sram_end); +} + +static int fiji_enable_vrhot_gpio_interrupt(struct pp_hwmgr *hwmgr) +{ + if(phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_EnableVRHotGPIOInterrupt); + + return 0; +} + +static int fiji_enable_sclk_control(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + SCLK_PWRMGT_OFF, 0); + return 0; +} + +static int fiji_enable_ulv(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_ulv_parm *ulv = &(data->ulv); + + if (ulv->ulv_supported) + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_EnableULV); + + return 0; +} + +static int fiji_enable_deep_sleep_master_switch(struct pp_hwmgr *hwmgr) +{ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkDeepSleep)) { + if (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_MASTER_DeepSleep_ON)) + PP_ASSERT_WITH_CODE(false, + "Attempt to enable Master Deep Sleep switch failed!", + return -1); + } else { + if (smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MASTER_DeepSleep_OFF)) { + PP_ASSERT_WITH_CODE(false, + "Attempt to disable Master Deep Sleep switch failed!", + return -1); + } + } + + return 0; +} + +static int fiji_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t val, val0, val2; + uint32_t i, cpl_cntl, cpl_threshold, mc_threshold; + + /* enable SCLK dpm */ + if(!data->sclk_dpm_key_disabled) + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_DPM_Enable)), + "Failed to enable SCLK DPM during DPM Start Function!", + return -1); + + /* enable MCLK dpm */ + if(0 == data->mclk_dpm_key_disabled) { + cpl_threshold = 0; + mc_threshold = 0; + + /* Read per MCD tile (0 - 7) */ + for (i = 0; i < 8; i++) { + PHM_WRITE_FIELD(hwmgr->device, MC_CONFIG_MCD, MC_RD_ENABLE, i); + val = cgs_read_register(hwmgr->device, mmMC_SEQ_RESERVE_0_S) & 0xf0000000; + if (0xf0000000 != val) { + /* count number of MCQ that has channel(s) enabled */ + cpl_threshold++; + /* only harvest 3 or full 4 supported */ + mc_threshold = val ? 3 : 4; + } + } + PP_ASSERT_WITH_CODE(0 != cpl_threshold, + "Number of MCQ is zero!", return -EINVAL;); + + mc_threshold = ((mc_threshold & LCAC_MC0_CNTL__MC0_THRESHOLD_MASK) << + LCAC_MC0_CNTL__MC0_THRESHOLD__SHIFT) | + LCAC_MC0_CNTL__MC0_ENABLE_MASK; + cpl_cntl = ((cpl_threshold & LCAC_CPL_CNTL__CPL_THRESHOLD_MASK) << + LCAC_CPL_CNTL__CPL_THRESHOLD__SHIFT) | + LCAC_CPL_CNTL__CPL_ENABLE_MASK; + cpl_cntl = (cpl_cntl | (8 << LCAC_CPL_CNTL__CPL_BLOCK_ID__SHIFT)); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC0_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC1_CNTL, mc_threshold); + if (8 == cpl_threshold) { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC2_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC3_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC4_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC5_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC6_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC7_CNTL, mc_threshold); + } + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_CPL_CNTL, cpl_cntl); + + udelay(5); + + mc_threshold = mc_threshold | + (1 << LCAC_MC0_CNTL__MC0_SIGNAL_ID__SHIFT); + cpl_cntl = cpl_cntl | (1 << LCAC_CPL_CNTL__CPL_SIGNAL_ID__SHIFT); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC0_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC1_CNTL, mc_threshold); + if (8 == cpl_threshold) { + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC2_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC3_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC4_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC5_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC6_CNTL, mc_threshold); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC7_CNTL, mc_threshold); + } + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_CPL_CNTL, cpl_cntl); + + /* Program CAC_EN per MCD (0-7) Tile */ + val0 = val = cgs_read_register(hwmgr->device, mmMC_CONFIG_MCD); + val &= ~(MC_CONFIG_MCD__MCD0_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD1_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD2_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD3_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD4_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD5_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD6_WR_ENABLE_MASK | + MC_CONFIG_MCD__MCD7_WR_ENABLE_MASK | + MC_CONFIG_MCD__MC_RD_ENABLE_MASK); + + for (i = 0; i < 8; i++) { + /* Enable MCD i Tile read & write */ + val2 = (val | (i << MC_CONFIG_MCD__MC_RD_ENABLE__SHIFT) | + (1 << i)); + cgs_write_register(hwmgr->device, mmMC_CONFIG_MCD, val2); + /* Enbale CAC_ON MCD i Tile */ + val2 = cgs_read_register(hwmgr->device, mmMC_SEQ_CNTL); + val2 |= MC_SEQ_CNTL__CAC_EN_MASK; + cgs_write_register(hwmgr->device, mmMC_SEQ_CNTL, val2); + } + /* Set MC_CONFIG_MCD back to its default setting val0 */ + cgs_write_register(hwmgr->device, mmMC_CONFIG_MCD, val0); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_Enable)), + "Failed to enable MCLK DPM during DPM Start Function!", + return -1); + } + return 0; +} + +static int fiji_start_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /*enable general power management */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + GLOBAL_PWRMGT_EN, 1); + /* enable sclk deep sleep */ + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, + DYNAMIC_PM_EN, 1); + /* prepare for PCIE DPM */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + offsetof(SMU73_SoftRegisters, + VoltageChangeTimeout), 0x1000); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, + SWRST_COMMAND_1, RESETLC, 0x0); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_Voltage_Cntl_Enable)), + "Failed to enable voltage DPM during DPM Start Function!", + return -1); + + if (fiji_enable_sclk_mclk_dpm(hwmgr)) { + printk(KERN_ERR "Failed to enable Sclk DPM and Mclk DPM!"); + return -1; + } + + /* enable PCIE dpm */ + if(!data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_Enable)), + "Failed to enable pcie DPM during DPM Start Function!", + return -1); + } + + return 0; +} + +static void fiji_set_dpm_event_sources(struct pp_hwmgr *hwmgr, + uint32_t sources) +{ + bool protection; + enum DPM_EVENT_SRC src; + + switch (sources) { + default: + printk(KERN_ERR "Unknown throttling event sources."); + /* fall through */ + case 0: + protection = false; + /* src is unused */ + break; + case (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL; + break; + case (1 << PHM_AutoThrottleSource_External): + protection = true; + src = DPM_EVENT_SRC_EXTERNAL; + break; + case (1 << PHM_AutoThrottleSource_External) | + (1 << PHM_AutoThrottleSource_Thermal): + protection = true; + src = DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL; + break; + } + /* Order matters - don't enable thermal protection for the wrong source. */ + if (protection) { + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, + DPM_EVENT_SRC, src); + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)); + } else + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, + THERMAL_PROTECTION_DIS, 1); +} + +static int fiji_enable_auto_throttle_source(struct pp_hwmgr *hwmgr, + PHM_AutoThrottleSource source) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (!(data->active_auto_throttle_sources & (1 << source))) { + data->active_auto_throttle_sources |= 1 << source; + fiji_set_dpm_event_sources(hwmgr, data->active_auto_throttle_sources); + } + return 0; +} + +static int fiji_enable_thermal_auto_throttle(struct pp_hwmgr *hwmgr) +{ + return fiji_enable_auto_throttle_source(hwmgr, PHM_AutoThrottleSource_Thermal); +} + +static int fiji_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = (!fiji_is_dpm_running(hwmgr))? 0 : -1; + PP_ASSERT_WITH_CODE(result == 0, + "DPM is already running right now, no need to enable DPM!", + return 0); + + if (fiji_voltage_control(hwmgr)) { + tmp_result = fiji_enable_voltage_control(hwmgr); + PP_ASSERT_WITH_CODE(tmp_result == 0, + "Failed to enable voltage control!", + result = tmp_result); + } + + if (fiji_voltage_control(hwmgr)) { + tmp_result = fiji_construct_voltage_tables(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to contruct voltage tables!", + result = tmp_result); + } + + tmp_result = fiji_initialize_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize MC reg table!", result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, DYN_SPREAD_SPECTRUM_EN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalController)) + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + GENERAL_PWRMGT, THERMAL_PROTECTION_DIS, 0); + + tmp_result = fiji_program_static_screen_threshold_parameters(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program static screen threshold parameters!", + result = tmp_result); + + tmp_result = fiji_enable_display_gap(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable display gap!", result = tmp_result); + + tmp_result = fiji_program_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program voting clients!", result = tmp_result); + + tmp_result = fiji_process_firmware_header(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to process firmware header!", result = tmp_result); + + tmp_result = fiji_initial_switch_from_arbf0_to_f1(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize switch from ArbF0 to F1!", + result = tmp_result); + + tmp_result = fiji_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize SMC table!", result = tmp_result); + + tmp_result = fiji_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize ARB table index!", result = tmp_result); + + tmp_result = fiji_populate_pm_fuses(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate PM fuses!", result = tmp_result); + + tmp_result = fiji_enable_vrhot_gpio_interrupt(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable VR hot GPIO interrupt!", result = tmp_result); + + tmp_result = tonga_notify_smc_display_change(hwmgr, false); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify no display!", result = tmp_result); + + tmp_result = fiji_enable_sclk_control(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable SCLK control!", result = tmp_result); + + tmp_result = fiji_enable_ulv(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable ULV!", result = tmp_result); + + tmp_result = fiji_enable_deep_sleep_master_switch(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable deep sleep master switch!", result = tmp_result); + + tmp_result = fiji_start_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to start DPM!", result = tmp_result); + + tmp_result = fiji_enable_smc_cac(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable SMC CAC!", result = tmp_result); + + tmp_result = fiji_enable_power_containment(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable power containment!", result = tmp_result); + + tmp_result = fiji_power_control_set_level(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to power control set level!", result = tmp_result); + + tmp_result = fiji_enable_thermal_auto_throttle(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable thermal auto throttle!", result = tmp_result); + + return result; +} + +static int fiji_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t level, tmp; + + if (!data->sclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; + while (tmp >>= 1) + level++; + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + (1 << level)); + } + } + + if (!data->mclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask; + while (tmp >>= 1) + level++; + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + (1 << level)); + } + } + + if (!data->pcie_dpm_key_disabled) { + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { + level = 0; + tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask; + while (tmp >>= 1) + level++; + if (level) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_ForceLevel, + (1 << level)); + } + } + return 0; +} + +static void fiji_apply_dal_min_voltage_request(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)hwmgr->pptable; + struct phm_clock_voltage_dependency_table *table = + table_info->vddc_dep_on_dal_pwrl; + struct phm_ppt_v1_clock_voltage_dependency_table *vddc_table; + enum PP_DAL_POWERLEVEL dal_power_level = hwmgr->dal_power_level; + uint32_t req_vddc = 0, req_volt, i; + + if (!table && !(dal_power_level >= PP_DAL_POWERLEVEL_ULTRALOW && + dal_power_level <= PP_DAL_POWERLEVEL_PERFORMANCE)) + return; + + for (i= 0; i < table->count; i++) { + if (dal_power_level == table->entries[i].clk) { + req_vddc = table->entries[i].v; + break; + } + } + + vddc_table = table_info->vdd_dep_on_sclk; + for (i= 0; i < vddc_table->count; i++) { + if (req_vddc <= vddc_table->entries[i].vddc) { + req_volt = (((uint32_t)vddc_table->entries[i].vddc) * VOLTAGE_SCALE) + << VDDC_SHIFT; + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_VddC_Request, req_volt); + return; + } + } + printk(KERN_ERR "DAL requested level can not" + " found a available voltage in VDDC DPM Table \n"); +} + +static int fiji_upload_dpmlevel_enable_mask(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + fiji_apply_dal_min_voltage_request(hwmgr); + + if (!data->sclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + } + return 0; +} + +static int fiji_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (!fiji_is_dpm_running(hwmgr)) + return -EINVAL; + + if (!data->pcie_dpm_key_disabled) { + smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_UnForceLevel); + } + + return fiji_upload_dpmlevel_enable_mask(hwmgr); +} + +static uint32_t fiji_get_lowest_enabled_level( + struct pp_hwmgr *hwmgr, uint32_t mask) +{ + uint32_t level = 0; + + while(0 == (mask & (1 << level))) + level++; + + return level; +} + +static int fiji_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = + (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t level; + + if (!data->sclk_dpm_key_disabled) + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = fiji_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + (1 << level)); + + } + + if (!data->mclk_dpm_key_disabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + level = fiji_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.mclk_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + (1 << level)); + } + } + + if (!data->pcie_dpm_key_disabled) { + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask) { + level = fiji_get_lowest_enabled_level(hwmgr, + data->dpm_level_enable_mask.pcie_dpm_enable_mask); + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_ForceLevel, + (1 << level)); + } + } + + return 0; + +} +static int fiji_dpm_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = fiji_force_dpm_highest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = fiji_force_dpm_lowest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = fiji_unforce_dpm_levels(hwmgr); + if (ret) + return ret; + break; + default: + break; + } + + hwmgr->dpm_level = level; + + return ret; +} + +static int fiji_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct fiji_power_state); +} + +static int fiji_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr, + void *state, struct pp_power_state *power_state, + void *pp_table, uint32_t classification_flag) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_power_state *fiji_power_state = + (struct fiji_power_state *)(&(power_state->hardware)); + struct fiji_performance_level *performance_level; + ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state; + ATOM_Tonga_POWERPLAYTABLE *powerplay_table = + (ATOM_Tonga_POWERPLAYTABLE *)pp_table; + ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = + (ATOM_Tonga_SCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (ATOM_Tonga_MCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + + /* The following fields are not initialized here: id orderedList allStatesList */ + power_state->classification.ui_label = + (le16_to_cpu(state_entry->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> + ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + power_state->classification.flags = classification_flag; + /* NOTE: There is a classification2 flag in BIOS that is not being used right now */ + + power_state->classification.temporary_state = false; + power_state->classification.to_be_deleted = false; + + power_state->validation.disallowOnDC = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Tonga_DISALLOW_ON_DC)); + + power_state->pcie.lanes = 0; + + power_state->display.disableFrameModulation = false; + power_state->display.limitRefreshrate = false; + power_state->display.enableVariBright = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & + ATOM_Tonga_ENABLE_VARIBRIGHT)); + + power_state->validation.supportedPowerLevels = 0; + power_state->uvd_clocks.VCLK = 0; + power_state->uvd_clocks.DCLK = 0; + power_state->temperatures.min = 0; + power_state->temperatures.max = 0; + + performance_level = &(fiji_power_state->performance_levels + [fiji_power_state->performance_level_count++]); + + PP_ASSERT_WITH_CODE( + (fiji_power_state->performance_level_count < SMU73_MAX_LEVELS_GRAPHICS), + "Performance levels exceeds SMC limit!", + return -1); + + PP_ASSERT_WITH_CODE( + (fiji_power_state->performance_level_count <= + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), + "Performance levels exceeds Driver limit!", + return -1); + + /* Performance levels are arranged from low to high. */ + performance_level->memory_clock = mclk_dep_table->entries + [state_entry->ucMemoryClockIndexLow].ulMclk; + performance_level->engine_clock = sclk_dep_table->entries + [state_entry->ucEngineClockIndexLow].ulSclk; + performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, + state_entry->ucPCIEGenLow); + performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, + state_entry->ucPCIELaneHigh); + + performance_level = &(fiji_power_state->performance_levels + [fiji_power_state->performance_level_count++]); + performance_level->memory_clock = mclk_dep_table->entries + [state_entry->ucMemoryClockIndexHigh].ulMclk; + performance_level->engine_clock = sclk_dep_table->entries + [state_entry->ucEngineClockIndexHigh].ulSclk; + performance_level->pcie_gen = get_pcie_gen_support(data->pcie_gen_cap, + state_entry->ucPCIEGenHigh); + performance_level->pcie_lane = get_pcie_lane_support(data->pcie_lane_cap, + state_entry->ucPCIELaneHigh); + + return 0; +} + +static int fiji_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *state) +{ + int result; + struct fiji_power_state *ps; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + + state->hardware.magic = PHM_VIslands_Magic; + + ps = (struct fiji_power_state *)(&state->hardware); + + result = tonga_get_powerplay_table_entry(hwmgr, entry_index, state, + fiji_get_pp_table_entry_callback_func); + + /* This is the earliest time we have all the dependency table and the VBIOS boot state + * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state + * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state + */ + if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { + if (dep_mclk_table->entries[0].clk != + data->vbios_boot_state.mclk_bootup_value) + printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table " + "does not match VBIOS boot MCLK level"); + if (dep_mclk_table->entries[0].vddci != + data->vbios_boot_state.vddci_bootup_value) + printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table " + "does not match VBIOS boot VDDCI level"); + } + + /* set DC compatible flag if this state supports DC */ + if (!state->validation.disallowOnDC) + ps->dc_compatible = true; + + if (state->classification.flags & PP_StateClassificationFlag_ACPI) + data->acpi_pcie_gen = ps->performance_levels[0].pcie_gen; + + ps->uvd_clks.vclk = state->uvd_clocks.VCLK; + ps->uvd_clks.dclk = state->uvd_clocks.DCLK; + + if (!result) { + uint32_t i; + + switch (state->classification.ui_label) { + case PP_StateUILabel_Performance: + data->use_pcie_performance_levels = true; + + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_performance.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_performance.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_performance.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.max = + ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_performance.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.min = + ps->performance_levels[i].pcie_lane; + } + break; + case PP_StateUILabel_Battery: + data->use_pcie_power_saving_levels = true; + + for (i = 0; i < ps->performance_level_count; i++) { + if (data->pcie_gen_power_saving.max < + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.max = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_power_saving.min > + ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.min = + ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_power_saving.max < + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.max = + ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_power_saving.min > + ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.min = + ps->performance_levels[i].pcie_lane; + } + break; + default: + break; + } + } + return 0; +} + +static int fiji_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *request_ps, + const struct pp_power_state *current_ps) +{ + struct fiji_power_state *fiji_ps = + cast_phw_fiji_power_state(&request_ps->hardware); + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; + bool disable_mclk_switching; + bool disable_mclk_switching_for_frame_lock; + struct cgs_display_info info = {0}; + const struct phm_clock_and_voltage_limits *max_limits; + uint32_t i; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int32_t count; + int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + + data->battery_state = (PP_StateUILabel_Battery == + request_ps->classification.ui_label); + + PP_ASSERT_WITH_CODE(fiji_ps->performance_level_count == 2, + "VI should always have 2 performance levels",); + + max_limits = (PP_PowerSource_AC == hwmgr->power_source) ? + &(hwmgr->dyn_state.max_clock_voltage_on_ac) : + &(hwmgr->dyn_state.max_clock_voltage_on_dc); + + /* Cap clock DPM tables at DC MAX if it is in DC. */ + if (PP_PowerSource_DC == hwmgr->power_source) { + for (i = 0; i < fiji_ps->performance_level_count; i++) { + if (fiji_ps->performance_levels[i].memory_clock > max_limits->mclk) + fiji_ps->performance_levels[i].memory_clock = max_limits->mclk; + if (fiji_ps->performance_levels[i].engine_clock > max_limits->sclk) + fiji_ps->performance_levels[i].engine_clock = max_limits->sclk; + } + } + + fiji_ps->vce_clks.evclk = hwmgr->vce_arbiter.evclk; + fiji_ps->vce_clks.ecclk = hwmgr->vce_arbiter.ecclk; + + fiji_ps->acp_clk = hwmgr->acp_arbiter.acpclk; + + cgs_get_active_displays_info(hwmgr->device, &info); + + /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ + + /* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */ + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); + stable_pstate_sclk = (max_limits->sclk * 75) / 100; + + for (count = table_info->vdd_dep_on_sclk->count - 1; + count >= 0; count--) { + if (stable_pstate_sclk >= + table_info->vdd_dep_on_sclk->entries[count].clk) { + stable_pstate_sclk = + table_info->vdd_dep_on_sclk->entries[count].clk; + break; + } + } + + if (count < 0) + stable_pstate_sclk = table_info->vdd_dep_on_sclk->entries[0].clk; + + stable_pstate_mclk = max_limits->mclk; + + minimum_clocks.engineClock = stable_pstate_sclk; + minimum_clocks.memoryClock = stable_pstate_mclk; + } + + if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk) + minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk; + + if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk) + minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk; + + fiji_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold; + + if (0 != hwmgr->gfx_arbiter.sclk_over_drive) { + PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <= + hwmgr->platform_descriptor.overdriveLimit.engineClock), + "Overdrive sclk exceeds limit", + hwmgr->gfx_arbiter.sclk_over_drive = + hwmgr->platform_descriptor.overdriveLimit.engineClock); + + if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk) + fiji_ps->performance_levels[1].engine_clock = + hwmgr->gfx_arbiter.sclk_over_drive; + } + + if (0 != hwmgr->gfx_arbiter.mclk_over_drive) { + PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <= + hwmgr->platform_descriptor.overdriveLimit.memoryClock), + "Overdrive mclk exceeds limit", + hwmgr->gfx_arbiter.mclk_over_drive = + hwmgr->platform_descriptor.overdriveLimit.memoryClock); + + if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk) + fiji_ps->performance_levels[1].memory_clock = + hwmgr->gfx_arbiter.mclk_over_drive; + } + + disable_mclk_switching_for_frame_lock = phm_cap_enabled( + hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + + disable_mclk_switching = (1 < info.display_count) || + disable_mclk_switching_for_frame_lock; + + sclk = fiji_ps->performance_levels[0].engine_clock; + mclk = fiji_ps->performance_levels[0].memory_clock; + + if (disable_mclk_switching) + mclk = fiji_ps->performance_levels + [fiji_ps->performance_level_count - 1].memory_clock; + + if (sclk < minimum_clocks.engineClock) + sclk = (minimum_clocks.engineClock > max_limits->sclk) ? + max_limits->sclk : minimum_clocks.engineClock; + + if (mclk < minimum_clocks.memoryClock) + mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? + max_limits->mclk : minimum_clocks.memoryClock; + + fiji_ps->performance_levels[0].engine_clock = sclk; + fiji_ps->performance_levels[0].memory_clock = mclk; + + fiji_ps->performance_levels[1].engine_clock = + (fiji_ps->performance_levels[1].engine_clock >= + fiji_ps->performance_levels[0].engine_clock) ? + fiji_ps->performance_levels[1].engine_clock : + fiji_ps->performance_levels[0].engine_clock; + + if (disable_mclk_switching) { + if (mclk < fiji_ps->performance_levels[1].memory_clock) + mclk = fiji_ps->performance_levels[1].memory_clock; + + fiji_ps->performance_levels[0].memory_clock = mclk; + fiji_ps->performance_levels[1].memory_clock = mclk; + } else { + if (fiji_ps->performance_levels[1].memory_clock < + fiji_ps->performance_levels[0].memory_clock) + fiji_ps->performance_levels[1].memory_clock = + fiji_ps->performance_levels[0].memory_clock; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + for (i = 0; i < fiji_ps->performance_level_count; i++) { + fiji_ps->performance_levels[i].engine_clock = stable_pstate_sclk; + fiji_ps->performance_levels[i].memory_clock = stable_pstate_mclk; + fiji_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max; + fiji_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max; + } + } + + return 0; +} + +static int fiji_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + const struct fiji_power_state *fiji_ps = + cast_const_phw_fiji_power_state(states->pnew_state); + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_single_dpm_table *sclk_table = &(data->dpm_table.sclk_table); + uint32_t sclk = fiji_ps->performance_levels + [fiji_ps->performance_level_count - 1].engine_clock; + struct fiji_single_dpm_table *mclk_table = &(data->dpm_table.mclk_table); + uint32_t mclk = fiji_ps->performance_levels + [fiji_ps->performance_level_count - 1].memory_clock; + struct PP_Clocks min_clocks = {0}; + uint32_t i; + struct cgs_display_info info = {0}; + + data->need_update_smu7_dpm_table = 0; + + for (i = 0; i < sclk_table->count; i++) { + if (sclk == sclk_table->dpm_levels[i].value) + break; + } + + if (i >= sclk_table->count) + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + else { + /* TODO: Check SCLK in DAL's minimum clocks + * in case DeepSleep divider update is required. + */ + if(data->display_timing.min_clock_in_sr != min_clocks.engineClockInSR) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK; + } + + for (i = 0; i < mclk_table->count; i++) { + if (mclk == mclk_table->dpm_levels[i].value) + break; + } + + if (i >= mclk_table->count) + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + + cgs_get_active_displays_info(hwmgr->device, &info); + + if (data->display_timing.num_existing_displays != info.display_count) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; + + return 0; +} + +static uint16_t fiji_get_maximum_link_speed(struct pp_hwmgr *hwmgr, + const struct fiji_power_state *fiji_ps) +{ + uint32_t i; + uint32_t sclk, max_sclk = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_dpm_table *dpm_table = &data->dpm_table; + + for (i = 0; i < fiji_ps->performance_level_count; i++) { + sclk = fiji_ps->performance_levels[i].engine_clock; + if (max_sclk < sclk) + max_sclk = sclk; + } + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + if (dpm_table->sclk_table.dpm_levels[i].value == max_sclk) + return (uint16_t) ((i >= dpm_table->pcie_speed_table.count) ? + dpm_table->pcie_speed_table.dpm_levels + [dpm_table->pcie_speed_table.count - 1].value : + dpm_table->pcie_speed_table.dpm_levels[i].value); + } + + return 0; +} + +static int fiji_request_link_speed_change_before_state_change( + struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + const struct fiji_power_state *fiji_nps = + cast_const_phw_fiji_power_state(states->pnew_state); + const struct fiji_power_state *fiji_cps = + cast_const_phw_fiji_power_state(states->pcurrent_state); + + uint16_t target_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_nps); + uint16_t current_link_speed; + + if (data->force_pcie_gen == PP_PCIEGenInvalid) + current_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_cps); + else + current_link_speed = data->force_pcie_gen; + + data->force_pcie_gen = PP_PCIEGenInvalid; + data->pspp_notify_required = false; + if (target_link_speed > current_link_speed) { + switch(target_link_speed) { + case PP_PCIEGen3: + if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false)) + break; + data->force_pcie_gen = PP_PCIEGen2; + if (current_link_speed == PP_PCIEGen2) + break; + case PP_PCIEGen2: + if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false)) + break; + default: + data->force_pcie_gen = fiji_get_current_pcie_speed(hwmgr); + break; + } + } else { + if (target_link_speed < current_link_speed) + data->pspp_notify_required = true; + } + + return 0; +} + +static int fiji_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr), + "Trying to freeze SCLK DPM when DPM is disabled",); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_FreezeLevel), + "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", + return -1); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + DPMTABLE_OD_UPDATE_MCLK)) { + PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr), + "Trying to freeze MCLK DPM when DPM is disabled",); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_FreezeLevel), + "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", + return -1); + } + + return 0; +} + +static int fiji_populate_and_upload_sclk_mclk_dpm_levels( + struct pp_hwmgr *hwmgr, const void *input) +{ + int result = 0; + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + const struct fiji_power_state *fiji_ps = + cast_const_phw_fiji_power_state(states->pnew_state); + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t sclk = fiji_ps->performance_levels + [fiji_ps->performance_level_count - 1].engine_clock; + uint32_t mclk = fiji_ps->performance_levels + [fiji_ps->performance_level_count - 1].memory_clock; + struct fiji_dpm_table *dpm_table = &data->dpm_table; + + struct fiji_dpm_table *golden_dpm_table = &data->golden_dpm_table; + uint32_t dpm_count, clock_percent; + uint32_t i; + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { + dpm_table->sclk_table.dpm_levels + [dpm_table->sclk_table.count - 1].value = sclk; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinACSupport) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinDCSupport)) { + /* Need to do calculation based on the golden DPM table + * as the Heatmap GPU Clock axis is also based on the default values + */ + PP_ASSERT_WITH_CODE( + (golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count - 1].value != 0), + "Divide by 0!", + return -1); + dpm_count = dpm_table->sclk_table.count < 2 ? + 0 : dpm_table->sclk_table.count - 2; + for (i = dpm_count; i > 1; i--) { + if (sclk > golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count-1].value) { + clock_percent = + ((sclk - golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count-1].value) * 100) / + golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count-1].value; + + dpm_table->sclk_table.dpm_levels[i].value = + golden_dpm_table->sclk_table.dpm_levels[i].value + + (golden_dpm_table->sclk_table.dpm_levels[i].value * + clock_percent)/100; + + } else if (golden_dpm_table->sclk_table.dpm_levels + [dpm_table->sclk_table.count-1].value > sclk) { + clock_percent = + ((golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count - 1].value - sclk) * + 100) / + golden_dpm_table->sclk_table.dpm_levels + [golden_dpm_table->sclk_table.count-1].value; + + dpm_table->sclk_table.dpm_levels[i].value = + golden_dpm_table->sclk_table.dpm_levels[i].value - + (golden_dpm_table->sclk_table.dpm_levels[i].value * + clock_percent) / 100; + } else + dpm_table->sclk_table.dpm_levels[i].value = + golden_dpm_table->sclk_table.dpm_levels[i].value; + } + } + } + + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { + dpm_table->mclk_table.dpm_levels + [dpm_table->mclk_table.count - 1].value = mclk; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinACSupport) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OD6PlusinDCSupport)) { + + PP_ASSERT_WITH_CODE( + (golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value != 0), + "Divide by 0!", + return -1); + dpm_count = dpm_table->mclk_table.count < 2 ? + 0 : dpm_table->mclk_table.count - 2; + for (i = dpm_count; i > 1; i--) { + if (mclk > golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value) { + clock_percent = ((mclk - + golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value) * 100) / + golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value; + + dpm_table->mclk_table.dpm_levels[i].value = + golden_dpm_table->mclk_table.dpm_levels[i].value + + (golden_dpm_table->mclk_table.dpm_levels[i].value * + clock_percent) / 100; + + } else if (golden_dpm_table->mclk_table.dpm_levels + [dpm_table->mclk_table.count-1].value > mclk) { + clock_percent = ((golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value - mclk) * 100) / + golden_dpm_table->mclk_table.dpm_levels + [golden_dpm_table->mclk_table.count-1].value; + + dpm_table->mclk_table.dpm_levels[i].value = + golden_dpm_table->mclk_table.dpm_levels[i].value - + (golden_dpm_table->mclk_table.dpm_levels[i].value * + clock_percent) / 100; + } else + dpm_table->mclk_table.dpm_levels[i].value = + golden_dpm_table->mclk_table.dpm_levels[i].value; + } + } + } + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) { + result = fiji_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { + /*populate MCLK dpm table to SMU7 */ + result = fiji_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + return result; +} + +static int fiji_trim_single_dpm_states(struct pp_hwmgr *hwmgr, + struct fiji_single_dpm_table * dpm_table, + uint32_t low_limit, uint32_t high_limit) +{ + uint32_t i; + + for (i = 0; i < dpm_table->count; i++) { + if ((dpm_table->dpm_levels[i].value < low_limit) || + (dpm_table->dpm_levels[i].value > high_limit)) + dpm_table->dpm_levels[i].enabled = false; + else + dpm_table->dpm_levels[i].enabled = true; + } + return 0; +} + +static int fiji_trim_dpm_states(struct pp_hwmgr *hwmgr, + const struct fiji_power_state *fiji_ps) +{ + int result = 0; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t high_limit_count; + + PP_ASSERT_WITH_CODE((fiji_ps->performance_level_count >= 1), + "power state did not have any performance level", + return -1); + + high_limit_count = (1 == fiji_ps->performance_level_count) ? 0 : 1; + + fiji_trim_single_dpm_states(hwmgr, + &(data->dpm_table.sclk_table), + fiji_ps->performance_levels[0].engine_clock, + fiji_ps->performance_levels[high_limit_count].engine_clock); + + fiji_trim_single_dpm_states(hwmgr, + &(data->dpm_table.mclk_table), + fiji_ps->performance_levels[0].memory_clock, + fiji_ps->performance_levels[high_limit_count].memory_clock); + + return result; +} + +static int fiji_generate_dpm_level_enable_mask( + struct pp_hwmgr *hwmgr, const void *input) +{ + int result; + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + const struct fiji_power_state *fiji_ps = + cast_const_phw_fiji_power_state(states->pnew_state); + + result = fiji_trim_dpm_states(hwmgr, fiji_ps); + if (result) + return result; + + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table); + data->dpm_level_enable_mask.mclk_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table); + data->last_mclk_dpm_enable_mask = + data->dpm_level_enable_mask.mclk_dpm_enable_mask; + + if (data->uvd_enabled) { + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask & 1) + data->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE; + } + + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + fiji_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table); + + return 0; +} + +int fiji_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable : + (PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable); +} + +int fiji_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable? + PPSMC_MSG_VCEDPM_Enable : + PPSMC_MSG_VCEDPM_Disable); +} + +int fiji_enable_disable_samu_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable? + PPSMC_MSG_SAMUDPM_Enable : + PPSMC_MSG_SAMUDPM_Disable); +} + +int fiji_enable_disable_acp_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable? + PPSMC_MSG_ACPDPM_Enable : + PPSMC_MSG_ACPDPM_Disable); +} + +int fiji_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.UvdBootLevel = 0; + if (table_info->mm_dep_table->count > 0) + data->smc_state_table.UvdBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.UvdBootLevel)); + } + + return fiji_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +int fiji_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + const struct fiji_power_state *fiji_nps = + cast_const_phw_fiji_power_state(states->pnew_state); + const struct fiji_power_state *fiji_cps = + cast_const_phw_fiji_power_state(states->pcurrent_state); + + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (fiji_nps->vce_clks.evclk >0 && + (fiji_cps == NULL || fiji_cps->vce_clks.evclk == 0)) { + data->smc_state_table.VceBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) { + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)1 << data->smc_state_table.VceBootLevel); + + fiji_enable_disable_vce_dpm(hwmgr, true); + } else if (fiji_nps->vce_clks.evclk == 0 && + fiji_cps != NULL && + fiji_cps->vce_clks.evclk > 0) + fiji_enable_disable_vce_dpm(hwmgr, false); + } + + return 0; +} + +int fiji_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.SamuBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, SamuBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFFFFFF00; + mm_boot_level_value |= data->smc_state_table.SamuBootLevel << 0; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SAMUDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.SamuBootLevel)); + } + + return fiji_enable_disable_samu_dpm(hwmgr, !bgate); +} + +int fiji_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.AcpBootLevel = + (uint8_t) (table_info->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, AcpBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFFFF00FF; + mm_boot_level_value |= data->smc_state_table.AcpBootLevel << 8; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_ACPDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.AcpBootLevel)); + } + + return fiji_enable_disable_acp_dpm(hwmgr, !bgate); +} + +static int fiji_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != + data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = + hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = + data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = fiji_copy_bytes_to_smc( + hwmgr->smumgr, + data->dpm_table_start + + offsetof(SMU73_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + data->sram_end); + } + + return result; +} + +static int fiji_program_mem_timing_parameters(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return fiji_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int fiji_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + + PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr), + "Trying to Unfreeze SCLK DPM when DPM is disabled",); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_UnfreezeLevel), + "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", + return -1); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { + + PP_ASSERT_WITH_CODE(true == fiji_is_dpm_running(hwmgr), + "Trying to Unfreeze MCLK DPM when DPM is disabled",); + PP_ASSERT_WITH_CODE(0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_UnfreezeLevel), + "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", + return -1); + } + + data->need_update_smu7_dpm_table = 0; + + return 0; +} + +/* Look up the voltaged based on DAL's requested level. + * and then send the requested VDDC voltage to SMC + */ +static void fiji_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr) +{ + return; +} + +int fiji_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) +{ + int result; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* Apply minimum voltage based on DAL's request level */ + fiji_apply_dal_minimum_voltage_request(hwmgr); + + if (0 == data->sclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, + * we should skip this message. + */ + if (!fiji_is_dpm_running(hwmgr)) + printk(KERN_ERR "[ powerplay ] " + "Trying to set Enable Mask when DPM is disabled \n"); + + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == result), + "Set Sclk Dpm enable Mask failed", return -1); + } + } + + if (0 == data->mclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, + * we should skip this message. + */ + if (!fiji_is_dpm_running(hwmgr)) + printk(KERN_ERR "[ powerplay ]" + " Trying to set Enable Mask when DPM is disabled \n"); + + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.mclk_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == result), + "Set Mclk Dpm enable Mask failed", return -1); + } + } + + return 0; +} + +static int fiji_notify_link_speed_change_after_state_change( + struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = + (const struct phm_set_power_state_input *)input; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + const struct fiji_power_state *fiji_ps = + cast_const_phw_fiji_power_state(states->pnew_state); + uint16_t target_link_speed = fiji_get_maximum_link_speed(hwmgr, fiji_ps); + uint8_t request; + + if (data->pspp_notify_required) { + if (target_link_speed == PP_PCIEGen3) + request = PCIE_PERF_REQ_GEN3; + else if (target_link_speed == PP_PCIEGen2) + request = PCIE_PERF_REQ_GEN2; + else + request = PCIE_PERF_REQ_GEN1; + + if(request == PCIE_PERF_REQ_GEN1 && + fiji_get_current_pcie_speed(hwmgr) > 0) + return 0; + + if (acpi_pcie_perf_request(hwmgr->device, request, false)) { + if (PP_PCIEGen2 == target_link_speed) + printk("PSPP request to switch to Gen2 from Gen3 Failed!"); + else + printk("PSPP request to switch to Gen1 from Gen2 Failed!"); + } + } + + return 0; +} + +static int fiji_set_power_state_tasks(struct pp_hwmgr *hwmgr, + const void *input) +{ + int tmp_result, result = 0; + + tmp_result = fiji_find_dpm_states_clocks_in_dpm_table(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to find DPM states clocks in DPM table!", + result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = + fiji_request_link_speed_change_before_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to request link speed change before state change!", + result = tmp_result); + } + + tmp_result = fiji_freeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to freeze SCLK MCLK DPM!", result = tmp_result); + + tmp_result = fiji_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate and upload SCLK MCLK DPM levels!", + result = tmp_result); + + tmp_result = fiji_generate_dpm_level_enable_mask(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to generate DPM level enabled mask!", + result = tmp_result); + + tmp_result = fiji_update_vce_dpm(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to update VCE DPM!", + result = tmp_result); + + tmp_result = fiji_update_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to update SCLK threshold!", + result = tmp_result); + + tmp_result = fiji_program_mem_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program memory timing parameters!", + result = tmp_result); + + tmp_result = fiji_unfreeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to unfreeze SCLK MCLK DPM!", + result = tmp_result); + + tmp_result = fiji_upload_dpm_level_enable_mask(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to upload DPM level enabled mask!", + result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = + fiji_notify_link_speed_change_after_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify link speed change after state change!", + result = tmp_result); + } + + return result; +} + +static int fiji_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct fiji_power_state *fiji_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + fiji_ps = cast_phw_fiji_power_state(&ps->hardware); + + if (low) + return fiji_ps->performance_levels[0].engine_clock; + else + return fiji_ps->performance_levels + [fiji_ps->performance_level_count-1].engine_clock; +} + +static int fiji_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct fiji_power_state *fiji_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + fiji_ps = cast_phw_fiji_power_state(&ps->hardware); + + if (low) + return fiji_ps->performance_levels[0].memory_clock; + else + return fiji_ps->performance_levels + [fiji_ps->performance_level_count-1].memory_clock; +} + +static void fiji_print_current_perforce_level( + struct pp_hwmgr *hwmgr, struct seq_file *m) +{ + uint32_t sclk, mclk; + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetSclkFrequency); + + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + + smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_API_GetMclkFrequency); + + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n", + mclk / 100, sclk / 100); +} + +static int fiji_program_display_gap(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t num_active_displays = 0; + uint32_t display_gap = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); + uint32_t display_gap2; + uint32_t pre_vbi_time_in_us; + uint32_t frame_time_in_us; + uint32_t ref_clock; + uint32_t refresh_rate = 0; + struct cgs_display_info info = {0}; + struct cgs_mode_info mode_info; + + info.mode_info = &mode_info; + + cgs_get_active_displays_info(hwmgr->device, &info); + num_active_displays = info.display_count; + + display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, + DISP_GAP, (num_active_displays > 0)? + DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL, display_gap); + + ref_clock = mode_info.ref_clock; + refresh_rate = mode_info.refresh_rate; + + if (refresh_rate == 0) + refresh_rate = 60; + + frame_time_in_us = 1000000 / refresh_rate; + + pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us; + display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL2, display_gap2); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + offsetof(SMU73_SoftRegisters, PreVBlankGap), 0x64); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + data->soft_regs_start + + offsetof(SMU73_SoftRegisters, VBlankTimeout), + (frame_time_in_us - pre_vbi_time_in_us)); + + if (num_active_displays == 1) + tonga_notify_smc_display_change(hwmgr, true); + + return 0; +} + +int fiji_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + return fiji_program_display_gap(hwmgr); +} + +static int fiji_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, + uint16_t us_max_fan_pwm) +{ + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; + + if (phm_is_hw_access_blocked(hwmgr)) + return 0; + + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm); +} + +static int fiji_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, + uint16_t us_max_fan_rpm) +{ + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM = us_max_fan_rpm; + + if (phm_is_hw_access_blocked(hwmgr)) + return 0; + + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanRpmMax, us_max_fan_rpm); +} + +int fiji_dpm_set_interrupt_state(void *private_data, + unsigned src_id, unsigned type, + int enabled) +{ + uint32_t cg_thermal_int; + struct pp_hwmgr *hwmgr = ((struct pp_eventmgr *)private_data)->hwmgr; + + if (hwmgr == NULL) + return -EINVAL; + + switch (type) { + case AMD_THERMAL_IRQ_LOW_TO_HIGH: + if (enabled) { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } else { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } + break; + + case AMD_THERMAL_IRQ_HIGH_TO_LOW: + if (enabled) { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } else { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + cgs_write_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } + break; + default: + break; + } + return 0; +} + +int fiji_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, + const void *thermal_interrupt_info) +{ + int result; + const struct pp_interrupt_registration_info *info = + (const struct pp_interrupt_registration_info *) + thermal_interrupt_info; + + if (info == NULL) + return -EINVAL; + + result = cgs_add_irq_source(hwmgr->device, 230, AMD_THERMAL_IRQ_LAST, + fiji_dpm_set_interrupt_state, + info->call_back, info->context); + + if (result) + return -EINVAL; + + result = cgs_add_irq_source(hwmgr->device, 231, AMD_THERMAL_IRQ_LAST, + fiji_dpm_set_interrupt_state, + info->call_back, info->context); + + if (result) + return -EINVAL; + + return 0; +} + +static int fiji_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + if (mode) { + /* stop auto-manage */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + fiji_fan_ctrl_stop_smc_fan_control(hwmgr); + fiji_fan_ctrl_set_static_mode(hwmgr, mode); + } else + /* restart auto-manage */ + fiji_fan_ctrl_reset_fan_speed_to_default(hwmgr); + + return 0; +} + +static int fiji_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->fan_ctrl_is_in_default_mode) + return hwmgr->fan_ctrl_default_mode; + else + return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE); +} + +static const struct pp_hwmgr_func fiji_hwmgr_funcs = { + .backend_init = &fiji_hwmgr_backend_init, + .backend_fini = &tonga_hwmgr_backend_fini, + .asic_setup = &fiji_setup_asic_task, + .dynamic_state_management_enable = &fiji_enable_dpm_tasks, + .force_dpm_level = &fiji_dpm_force_dpm_level, + .get_num_of_pp_table_entries = &tonga_get_number_of_powerplay_table_entries, + .get_power_state_size = &fiji_get_power_state_size, + .get_pp_table_entry = &fiji_get_pp_table_entry, + .patch_boot_state = &fiji_patch_boot_state, + .apply_state_adjust_rules = &fiji_apply_state_adjust_rules, + .power_state_set = &fiji_set_power_state_tasks, + .get_sclk = &fiji_dpm_get_sclk, + .get_mclk = &fiji_dpm_get_mclk, + .print_current_perforce_level = &fiji_print_current_perforce_level, + .powergate_uvd = &fiji_phm_powergate_uvd, + .powergate_vce = &fiji_phm_powergate_vce, + .disable_clock_power_gating = &fiji_phm_disable_clock_power_gating, + .notify_smc_display_config_after_ps_adjustment = + &tonga_notify_smc_display_config_after_ps_adjustment, + .display_config_changed = &fiji_display_configuration_changed_task, + .set_max_fan_pwm_output = fiji_set_max_fan_pwm_output, + .set_max_fan_rpm_output = fiji_set_max_fan_rpm_output, + .get_temperature = fiji_thermal_get_temperature, + .stop_thermal_controller = fiji_thermal_stop_thermal_controller, + .get_fan_speed_info = fiji_fan_ctrl_get_fan_speed_info, + .get_fan_speed_percent = fiji_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = fiji_fan_ctrl_set_fan_speed_percent, + .reset_fan_speed_to_default = fiji_fan_ctrl_reset_fan_speed_to_default, + .get_fan_speed_rpm = fiji_fan_ctrl_get_fan_speed_rpm, + .set_fan_speed_rpm = fiji_fan_ctrl_set_fan_speed_rpm, + .uninitialize_thermal_controller = fiji_thermal_ctrl_uninitialize_thermal_controller, + .register_internal_thermal_interrupt = fiji_register_internal_thermal_interrupt, + .set_fan_control_mode = fiji_set_fan_control_mode, + .get_fan_control_mode = fiji_get_fan_control_mode, +}; + +int fiji_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data; + int ret = 0; + + data = kzalloc(sizeof(struct fiji_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + + hwmgr->backend = data; + hwmgr->hwmgr_func = &fiji_hwmgr_funcs; + hwmgr->pptable_func = &tonga_pptable_funcs; + pp_fiji_thermal_initialize(hwmgr); + return ret; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h new file mode 100644 index 000000000000..22e273b1c1c5 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_hwmgr.h @@ -0,0 +1,361 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _FIJI_HWMGR_H_ +#define _FIJI_HWMGR_H_ + +#include "hwmgr.h" +#include "smu73.h" +#include "smu73_discrete.h" +#include "ppatomctrl.h" +#include "fiji_ppsmc.h" + +#define FIJI_MAX_HARDWARE_POWERLEVELS 2 +#define FIJI_AT_DFLT 30 + +#define FIJI_VOLTAGE_CONTROL_NONE 0x0 +#define FIJI_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define FIJI_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define FIJI_VOLTAGE_CONTROL_MERGED 0x3 + +#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 +#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 +#define DPMTABLE_UPDATE_SCLK 0x00000004 +#define DPMTABLE_UPDATE_MCLK 0x00000008 + +struct fiji_performance_level { + uint32_t memory_clock; + uint32_t engine_clock; + uint16_t pcie_gen; + uint16_t pcie_lane; +}; + +struct fiji_uvd_clocks { + uint32_t vclk; + uint32_t dclk; +}; + +struct fiji_vce_clocks { + uint32_t evclk; + uint32_t ecclk; +}; + +struct fiji_power_state { + uint32_t magic; + struct fiji_uvd_clocks uvd_clks; + struct fiji_vce_clocks vce_clks; + uint32_t sam_clk; + uint32_t acp_clk; + uint16_t performance_level_count; + bool dc_compatible; + uint32_t sclk_threshold; + struct fiji_performance_level performance_levels[FIJI_MAX_HARDWARE_POWERLEVELS]; +}; + +struct fiji_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +#define FIJI_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 8 +#define FIJI_MINIMUM_ENGINE_CLOCK 2500 + +struct fiji_single_dpm_table { + uint32_t count; + struct fiji_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct fiji_dpm_table { + struct fiji_single_dpm_table sclk_table; + struct fiji_single_dpm_table mclk_table; + struct fiji_single_dpm_table pcie_speed_table; + struct fiji_single_dpm_table vddc_table; + struct fiji_single_dpm_table vddci_table; + struct fiji_single_dpm_table mvdd_table; +}; + +struct fiji_clock_registers { + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t vDLL_CNTL; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_SS1; + uint32_t vMPLL_SS2; +}; + +struct fiji_voltage_smio_registers { + uint32_t vS0_VID_LOWER_SMIO_CNTL; +}; + +#define FIJI_MAX_LEAKAGE_COUNT 8 +struct fiji_leakage_voltage { + uint16_t count; + uint16_t leakage_id[FIJI_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[FIJI_MAX_LEAKAGE_COUNT]; +}; + +struct fiji_vbios_boot_state { + uint16_t mvdd_bootup_value; + uint16_t vddc_bootup_value; + uint16_t vddci_bootup_value; + uint32_t sclk_bootup_value; + uint32_t mclk_bootup_value; + uint16_t pcie_gen_bootup_value; + uint16_t pcie_lane_bootup_value; +}; + +struct fiji_bacos { + uint32_t best_match; + uint32_t baco_flags; + struct fiji_performance_level performance_level; +}; + +/* Ultra Low Voltage parameter structure */ +struct fiji_ulv_parm { + bool ulv_supported; + uint32_t cg_ulv_parameter; + uint32_t ulv_volt_change_delay; + struct fiji_performance_level ulv_power_level; +}; + +struct fiji_display_timing { + uint32_t min_clock_in_sr; + uint32_t num_existing_displays; +}; + +struct fiji_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t acp_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; + uint32_t pcie_dpm_enable_mask; +}; + +struct fiji_pcie_perf_range { + uint16_t max; + uint16_t min; +}; + +struct fiji_hwmgr { + struct fiji_dpm_table dpm_table; + struct fiji_dpm_table golden_dpm_table; + + uint32_t voting_rights_clients0; + uint32_t voting_rights_clients1; + uint32_t voting_rights_clients2; + uint32_t voting_rights_clients3; + uint32_t voting_rights_clients4; + uint32_t voting_rights_clients5; + uint32_t voting_rights_clients6; + uint32_t voting_rights_clients7; + uint32_t static_screen_threshold_unit; + uint32_t static_screen_threshold; + uint32_t voltage_control; + uint32_t vddc_vddci_delta; + + uint32_t active_auto_throttle_sources; + + struct fiji_clock_registers clock_registers; + struct fiji_voltage_smio_registers voltage_smio_registers; + + bool is_memory_gddr5; + uint16_t acpi_vddc; + bool pspp_notify_required; + uint16_t force_pcie_gen; + uint16_t acpi_pcie_gen; + uint32_t pcie_gen_cap; + uint32_t pcie_lane_cap; + uint32_t pcie_spc_cap; + struct fiji_leakage_voltage vddc_leakage; + struct fiji_leakage_voltage Vddci_leakage; + + uint32_t mvdd_control; + uint32_t vddc_mask_low; + uint32_t mvdd_mask_low; + uint16_t max_vddc_in_pptable; + uint16_t min_vddc_in_pptable; + uint16_t max_vddci_in_pptable; + uint16_t min_vddci_in_pptable; + uint32_t mclk_strobe_mode_threshold; + uint32_t mclk_stutter_mode_threshold; + uint32_t mclk_edc_enable_threshold; + uint32_t mclk_edcwr_enable_threshold; + bool is_uvd_enabled; + struct fiji_vbios_boot_state vbios_boot_state; + + bool battery_state; + bool is_tlu_enabled; + + /* ---- SMC SRAM Address of firmware header tables ---- */ + uint32_t sram_end; + uint32_t dpm_table_start; + uint32_t soft_regs_start; + uint32_t mc_reg_table_start; + uint32_t fan_table_start; + uint32_t arb_table_start; + struct SMU73_Discrete_DpmTable smc_state_table; + struct SMU73_Discrete_Ulv ulv_setting; + + /* ---- Stuff originally coming from Evergreen ---- */ + uint32_t vddci_control; + struct pp_atomctrl_voltage_table vddc_voltage_table; + struct pp_atomctrl_voltage_table vddci_voltage_table; + struct pp_atomctrl_voltage_table mvdd_voltage_table; + + uint32_t mgcg_cgtt_local2; + uint32_t mgcg_cgtt_local3; + uint32_t gpio_debug; + uint32_t mc_micro_code_feature; + uint32_t highest_mclk; + uint16_t acpi_vddci; + uint8_t mvdd_high_index; + uint8_t mvdd_low_index; + bool dll_default_on; + bool performance_request_registered; + + /* ---- Low Power Features ---- */ + struct fiji_bacos bacos; + struct fiji_ulv_parm ulv; + + /* ---- CAC Stuff ---- */ + uint32_t cac_table_start; + bool cac_configuration_required; + bool driver_calculate_cac_leakage; + bool cac_enabled; + + /* ---- DPM2 Parameters ---- */ + uint32_t power_containment_features; + bool enable_dte_feature; + bool enable_tdc_limit_feature; + bool enable_pkg_pwr_tracking_feature; + bool disable_uvd_power_tune_feature; + struct fiji_pt_defaults *power_tune_defaults; + struct SMU73_Discrete_PmFuses power_tune_table; + uint32_t dte_tj_offset; + uint32_t fast_watermark_threshold; + + /* ---- Phase Shedding ---- */ + bool vddc_phase_shed_control; + + /* ---- DI/DT ---- */ + struct fiji_display_timing display_timing; + + /* ---- Thermal Temperature Setting ---- */ + struct fiji_dpmlevel_enable_mask dpm_level_enable_mask; + uint32_t need_update_smu7_dpm_table; + uint32_t sclk_dpm_key_disabled; + uint32_t mclk_dpm_key_disabled; + uint32_t pcie_dpm_key_disabled; + uint32_t min_engine_clocks; + struct fiji_pcie_perf_range pcie_gen_performance; + struct fiji_pcie_perf_range pcie_lane_performance; + struct fiji_pcie_perf_range pcie_gen_power_saving; + struct fiji_pcie_perf_range pcie_lane_power_saving; + bool use_pcie_performance_levels; + bool use_pcie_power_saving_levels; + uint32_t activity_target[SMU73_MAX_LEVELS_GRAPHICS]; + uint32_t mclk_activity_target; + uint32_t mclk_dpm0_activity_target; + uint32_t low_sclk_interrupt_threshold; + uint32_t last_mclk_dpm_enable_mask; + bool uvd_enabled; + + /* ---- Power Gating States ---- */ + bool uvd_power_gated; + bool vce_power_gated; + bool samu_power_gated; + bool acp_power_gated; + bool pg_acp_init; + bool frtc_enabled; + bool frtc_status_changed; +}; + +/* To convert to Q8.8 format for firmware */ +#define FIJI_Q88_FORMAT_CONVERSION_UNIT 256 + +enum Fiji_I2CLineID { + Fiji_I2CLineID_DDC1 = 0x90, + Fiji_I2CLineID_DDC2 = 0x91, + Fiji_I2CLineID_DDC3 = 0x92, + Fiji_I2CLineID_DDC4 = 0x93, + Fiji_I2CLineID_DDC5 = 0x94, + Fiji_I2CLineID_DDC6 = 0x95, + Fiji_I2CLineID_SCLSDA = 0x96, + Fiji_I2CLineID_DDCVGA = 0x97 +}; + +#define Fiji_I2C_DDC1DATA 0 +#define Fiji_I2C_DDC1CLK 1 +#define Fiji_I2C_DDC2DATA 2 +#define Fiji_I2C_DDC2CLK 3 +#define Fiji_I2C_DDC3DATA 4 +#define Fiji_I2C_DDC3CLK 5 +#define Fiji_I2C_SDA 40 +#define Fiji_I2C_SCL 41 +#define Fiji_I2C_DDC4DATA 65 +#define Fiji_I2C_DDC4CLK 66 +#define Fiji_I2C_DDC5DATA 0x48 +#define Fiji_I2C_DDC5CLK 0x49 +#define Fiji_I2C_DDC6DATA 0x4a +#define Fiji_I2C_DDC6CLK 0x4b +#define Fiji_I2C_DDCVGADATA 0x4c +#define Fiji_I2C_DDCVGACLK 0x4d + +#define FIJI_UNUSED_GPIO_PIN 0x7F + +extern int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); +extern int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); +extern int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr); +extern int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); +extern int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display); +int fiji_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input); +int fiji_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int fiji_update_samu_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int fiji_update_acp_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int fiji_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); + +#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X) +#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X) + +#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X) +#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X) + +#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X)) +#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X)) + +#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X)) + +#endif /* _FIJI_HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c new file mode 100644 index 000000000000..f89c98fd759e --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.c @@ -0,0 +1,553 @@ +/* + * Copyright 2015 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. + * + */ + +#include "hwmgr.h" +#include "smumgr.h" +#include "fiji_hwmgr.h" +#include "fiji_powertune.h" +#include "fiji_smumgr.h" +#include "smu73_discrete.h" +#include "pp_debug.h" + +#define VOLTAGE_SCALE 4 +#define POWERTUNE_DEFAULT_SET_MAX 1 + +struct fiji_pt_defaults fiji_power_tune_data_set_array[POWERTUNE_DEFAULT_SET_MAX] = { + /*sviLoadLIneEn, SviLoadLineVddC, TDC_VDDC_ThrottleReleaseLimitPerc */ + {1, 0xF, 0xFD, + /* TDC_MAWt, TdcWaterfallCtl, DTEAmbientTempBase */ + 0x19, 5, 45} +}; + +void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *fiji_hwmgr = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t tmp = 0; + + if(table_info && + table_info->cac_dtp_table->usPowerTuneDataSetID <= POWERTUNE_DEFAULT_SET_MAX && + table_info->cac_dtp_table->usPowerTuneDataSetID) + fiji_hwmgr->power_tune_defaults = + &fiji_power_tune_data_set_array + [table_info->cac_dtp_table->usPowerTuneDataSetID - 1]; + else + fiji_hwmgr->power_tune_defaults = &fiji_power_tune_data_set_array[0]; + + /* Assume disabled */ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SQRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DBRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TDRamping); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TCPRamping); + + fiji_hwmgr->dte_tj_offset = tmp; + + if (!tmp) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC); + + fiji_hwmgr->fast_watermark_threshold = 100; + + tmp = 1; + fiji_hwmgr->enable_dte_feature = tmp ? false : true; + fiji_hwmgr->enable_tdc_limit_feature = tmp ? true : false; + fiji_hwmgr->enable_pkg_pwr_tracking_feature = tmp ? true : false; + } +} + +/* PPGen has the gain setting generated in x * 100 unit + * This function is to convert the unit to x * 4096(0x1000) unit. + * This is the unit expected by SMC firmware + */ +static uint16_t scale_fan_gain_settings(uint16_t raw_setting) +{ + uint32_t tmp; + tmp = raw_setting * 4096 / 100; + return (uint16_t)tmp; +} + +static void get_scl_sda_value(uint8_t line, uint8_t *scl, uint8_t* sda) +{ + switch (line) { + case Fiji_I2CLineID_DDC1 : + *scl = Fiji_I2C_DDC1CLK; + *sda = Fiji_I2C_DDC1DATA; + break; + case Fiji_I2CLineID_DDC2 : + *scl = Fiji_I2C_DDC2CLK; + *sda = Fiji_I2C_DDC2DATA; + break; + case Fiji_I2CLineID_DDC3 : + *scl = Fiji_I2C_DDC3CLK; + *sda = Fiji_I2C_DDC3DATA; + break; + case Fiji_I2CLineID_DDC4 : + *scl = Fiji_I2C_DDC4CLK; + *sda = Fiji_I2C_DDC4DATA; + break; + case Fiji_I2CLineID_DDC5 : + *scl = Fiji_I2C_DDC5CLK; + *sda = Fiji_I2C_DDC5DATA; + break; + case Fiji_I2CLineID_DDC6 : + *scl = Fiji_I2C_DDC6CLK; + *sda = Fiji_I2C_DDC6DATA; + break; + case Fiji_I2CLineID_SCLSDA : + *scl = Fiji_I2C_SCL; + *sda = Fiji_I2C_SDA; + break; + case Fiji_I2CLineID_DDCVGA : + *scl = Fiji_I2C_DDCVGACLK; + *sda = Fiji_I2C_DDCVGADATA; + break; + default: + *scl = 0; + *sda = 0; + break; + } +} + +int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_pt_defaults *defaults = data->power_tune_defaults; + SMU73_Discrete_DpmTable *dpm_table = &(data->smc_state_table); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_dtp_table = table_info->cac_dtp_table; + struct pp_advance_fan_control_parameters *fan_table= + &hwmgr->thermal_controller.advanceFanControlParameters; + uint8_t uc_scl, uc_sda; + + /* TDP number of fraction bits are changed from 8 to 7 for Fiji + * as requested by SMC team + */ + dpm_table->DefaultTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + dpm_table->TargetTdp = PP_HOST_TO_SMC_US( + (uint16_t)(cac_dtp_table->usTDP * 128)); + + PP_ASSERT_WITH_CODE(cac_dtp_table->usTargetOperatingTemp <= 255, + "Target Operating Temp is out of Range!",); + + dpm_table->GpuTjMax = (uint8_t)(cac_dtp_table->usTargetOperatingTemp); + dpm_table->GpuTjHyst = 8; + + dpm_table->DTEAmbientTempBase = defaults->DTEAmbientTempBase; + + /* The following are for new Fiji Multi-input fan/thermal control */ + dpm_table->TemperatureLimitEdge = PP_HOST_TO_SMC_US( + cac_dtp_table->usTargetOperatingTemp * 256); + dpm_table->TemperatureLimitHotspot = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitHotspot * 256); + dpm_table->TemperatureLimitLiquid1 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid1 * 256); + dpm_table->TemperatureLimitLiquid2 = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitLiquid2 * 256); + dpm_table->TemperatureLimitVrVddc = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrVddc * 256); + dpm_table->TemperatureLimitVrMvdd = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitVrMvdd * 256); + dpm_table->TemperatureLimitPlx = PP_HOST_TO_SMC_US( + cac_dtp_table->usTemperatureLimitPlx * 256); + + dpm_table->FanGainEdge = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainEdge)); + dpm_table->FanGainHotspot = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHotspot)); + dpm_table->FanGainLiquid = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainLiquid)); + dpm_table->FanGainVrVddc = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrVddc)); + dpm_table->FanGainVrMvdd = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainVrMvdd)); + dpm_table->FanGainPlx = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainPlx)); + dpm_table->FanGainHbm = PP_HOST_TO_SMC_US( + scale_fan_gain_settings(fan_table->usFanGainHbm)); + + dpm_table->Liquid1_I2C_address = cac_dtp_table->ucLiquid1_I2C_address; + dpm_table->Liquid2_I2C_address = cac_dtp_table->ucLiquid2_I2C_address; + dpm_table->Vr_I2C_address = cac_dtp_table->ucVr_I2C_address; + dpm_table->Plx_I2C_address = cac_dtp_table->ucPlx_I2C_address; + + get_scl_sda_value(cac_dtp_table->ucLiquid_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Liquid_I2C_LineSCL = uc_scl; + dpm_table->Liquid_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucVr_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Vr_I2C_LineSCL = uc_scl; + dpm_table->Vr_I2C_LineSDA = uc_sda; + + get_scl_sda_value(cac_dtp_table->ucPlx_I2C_Line, &uc_scl, &uc_sda); + dpm_table->Plx_I2C_LineSCL = uc_scl; + dpm_table->Plx_I2C_LineSDA = uc_sda; + + return 0; +} + +static int fiji_populate_svi_load_line(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_pt_defaults *defaults = data->power_tune_defaults; + + data->power_tune_table.SviLoadLineEn = defaults->SviLoadLineEn; + data->power_tune_table.SviLoadLineVddC = defaults->SviLoadLineVddC; + data->power_tune_table.SviLoadLineTrimVddC = 3; + data->power_tune_table.SviLoadLineOffsetVddC = 0; + + return 0; +} + +static int fiji_populate_tdc_limit(struct pp_hwmgr *hwmgr) +{ + uint16_t tdc_limit; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct fiji_pt_defaults *defaults = data->power_tune_defaults; + + /* TDC number of fraction bits are changed from 8 to 7 + * for Fiji as requested by SMC team + */ + tdc_limit = (uint16_t)(table_info->cac_dtp_table->usTDC * 128); + data->power_tune_table.TDC_VDDC_PkgLimit = + CONVERT_FROM_HOST_TO_SMC_US(tdc_limit); + data->power_tune_table.TDC_VDDC_ThrottleReleaseLimitPerc = + defaults->TDC_VDDC_ThrottleReleaseLimitPerc; + data->power_tune_table.TDC_MAWt = defaults->TDC_MAWt; + + return 0; +} + +static int fiji_populate_dw8(struct pp_hwmgr *hwmgr, uint32_t fuse_table_offset) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct fiji_pt_defaults *defaults = data->power_tune_defaults; + uint32_t temp; + + if (fiji_read_smc_sram_dword(hwmgr->smumgr, + fuse_table_offset + + offsetof(SMU73_Discrete_PmFuses, TdcWaterfallCtl), + (uint32_t *)&temp, data->sram_end)) + PP_ASSERT_WITH_CODE(false, + "Attempt to read PmFuses.DW6 (SviLoadLineEn) from SMC Failed!", + return -EINVAL); + else { + data->power_tune_table.TdcWaterfallCtl = defaults->TdcWaterfallCtl; + data->power_tune_table.LPMLTemperatureMin = + (uint8_t)((temp >> 16) & 0xff); + data->power_tune_table.LPMLTemperatureMax = + (uint8_t)((temp >> 8) & 0xff); + data->power_tune_table.Reserved = (uint8_t)(temp & 0xff); + } + return 0; +} + +static int fiji_populate_temperature_scaler(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + data->power_tune_table.LPMLTemperatureScaler[i] = 0; + + return 0; +} + +static int fiji_populate_fuzzy_fan(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if( (hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity & (1 << 15)) || + 0 == hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity ) + hwmgr->thermal_controller.advanceFanControlParameters. + usFanOutputSensitivity = hwmgr->thermal_controller. + advanceFanControlParameters.usDefaultFanOutputSensitivity; + + data->power_tune_table.FuzzyFan_PwmSetDelta = + PP_HOST_TO_SMC_US(hwmgr->thermal_controller. + advanceFanControlParameters.usFanOutputSensitivity); + return 0; +} + +static int fiji_populate_gnb_lpml(struct pp_hwmgr *hwmgr) +{ + int i; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + /* Currently not used. Set all to zero. */ + for (i = 0; i < 16; i++) + data->power_tune_table.GnbLPML[i] = 0; + + return 0; +} + +static int fiji_min_max_vgnb_lpml_id_from_bapm_vddc(struct pp_hwmgr *hwmgr) +{ + /* int i, min, max; + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint8_t * pHiVID = data->power_tune_table.BapmVddCVidHiSidd; + uint8_t * pLoVID = data->power_tune_table.BapmVddCVidLoSidd; + + min = max = pHiVID[0]; + for (i = 0; i < 8; i++) { + if (0 != pHiVID[i]) { + if (min > pHiVID[i]) + min = pHiVID[i]; + if (max < pHiVID[i]) + max = pHiVID[i]; + } + + if (0 != pLoVID[i]) { + if (min > pLoVID[i]) + min = pLoVID[i]; + if (max < pLoVID[i]) + max = pLoVID[i]; + } + } + + PP_ASSERT_WITH_CODE((0 != min) && (0 != max), "BapmVddcVidSidd table does not exist!", return int_Failed); + data->power_tune_table.GnbLPMLMaxVid = (uint8_t)max; + data->power_tune_table.GnbLPMLMinVid = (uint8_t)min; +*/ + return 0; +} + +static int fiji_populate_bapm_vddc_base_leakage_sidd(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint16_t HiSidd = data->power_tune_table.BapmVddCBaseLeakageHiSidd; + uint16_t LoSidd = data->power_tune_table.BapmVddCBaseLeakageLoSidd; + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + + HiSidd = (uint16_t)(cac_table->usHighCACLeakage / 100 * 256); + LoSidd = (uint16_t)(cac_table->usLowCACLeakage / 100 * 256); + + data->power_tune_table.BapmVddCBaseLeakageHiSidd = + CONVERT_FROM_HOST_TO_SMC_US(HiSidd); + data->power_tune_table.BapmVddCBaseLeakageLoSidd = + CONVERT_FROM_HOST_TO_SMC_US(LoSidd); + + return 0; +} + +int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + uint32_t pm_fuse_table_offset; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (fiji_read_smc_sram_dword(hwmgr->smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, PmFuseTable), + &pm_fuse_table_offset, data->sram_end)) + PP_ASSERT_WITH_CODE(false, + "Attempt to get pm_fuse_table_offset Failed!", + return -EINVAL); + + /* DW6 */ + if (fiji_populate_svi_load_line(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate SviLoadLine Failed!", + return -EINVAL); + /* DW7 */ + if (fiji_populate_tdc_limit(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TDCLimit Failed!", return -EINVAL); + /* DW8 */ + if (fiji_populate_dw8(hwmgr, pm_fuse_table_offset)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate TdcWaterfallCtl, " + "LPMLTemperature Min and Max Failed!", + return -EINVAL); + + /* DW9-DW12 */ + if (0 != fiji_populate_temperature_scaler(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate LPMLTemperatureScaler Failed!", + return -EINVAL); + + /* DW13-DW14 */ + if(fiji_populate_fuzzy_fan(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate Fuzzy Fan Control parameters Failed!", + return -EINVAL); + + /* DW15-DW18 */ + if (fiji_populate_gnb_lpml(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Failed!", + return -EINVAL); + + /* DW19 */ + if (fiji_min_max_vgnb_lpml_id_from_bapm_vddc(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate GnbLPML Min and Max Vid Failed!", + return -EINVAL); + + /* DW20 */ + if (fiji_populate_bapm_vddc_base_leakage_sidd(hwmgr)) + PP_ASSERT_WITH_CODE(false, + "Attempt to populate BapmVddCBaseLeakage Hi and Lo " + "Sidd Failed!", return -EINVAL); + + if (fiji_copy_bytes_to_smc(hwmgr->smumgr, pm_fuse_table_offset, + (uint8_t *)&data->power_tune_table, + sizeof(struct SMU73_Discrete_PmFuses), data->sram_end)) + PP_ASSERT_WITH_CODE(false, + "Attempt to download PmFuseTable Failed!", + return -EINVAL); + } + return 0; +} + +int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CAC)) { + int smc_result; + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_EnableCac)); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable CAC in SMC.", result = -1); + + data->cac_enabled = (0 == smc_result) ? true : false; + } + return result; +} + +int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + + if(data->power_containment_features & + POWERCONTAINMENT_FEATURE_PkgPwrLimit) + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_PkgPwrSetLimit, n); + return 0; +} + +static int fiji_set_overdriver_target_tdp(struct pp_hwmgr *pHwMgr, uint32_t target_tdp) +{ + return smum_send_msg_to_smc_with_parameter(pHwMgr->smumgr, + PPSMC_MSG_OverDriveSetTargetTdp, target_tdp); +} + +int fiji_enable_power_containment(struct pp_hwmgr *hwmgr) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + int smc_result; + int result = 0; + + data->power_containment_features = 0; + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + if (data->enable_dte_feature) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_EnableDTE)); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable DTE in SMC.", result = -1;); + if (0 == smc_result) + data->power_containment_features |= POWERCONTAINMENT_FEATURE_DTE; + } + + if (data->enable_tdc_limit_feature) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_TDCLimitEnable)); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable TDCLimit in SMC.", result = -1;); + if (0 == smc_result) + data->power_containment_features |= + POWERCONTAINMENT_FEATURE_TDCLimit; + } + + if (data->enable_pkg_pwr_tracking_feature) { + smc_result = smum_send_msg_to_smc(hwmgr->smumgr, + (uint16_t)(PPSMC_MSG_PkgPwrLimitEnable)); + PP_ASSERT_WITH_CODE((0 == smc_result), + "Failed to enable PkgPwrTracking in SMC.", result = -1;); + if (0 == smc_result) { + struct phm_cac_tdp_table *cac_table = + table_info->cac_dtp_table; + uint32_t default_limit = + (uint32_t)(cac_table->usMaximumPowerDeliveryLimit * 256); + + data->power_containment_features |= + POWERCONTAINMENT_FEATURE_PkgPwrLimit; + + if (fiji_set_power_limit(hwmgr, default_limit)) + printk(KERN_ERR "Failed to set Default Power Limit in SMC!"); + } + } + } + return result; +} + +int fiji_power_control_set_level(struct pp_hwmgr *hwmgr) +{ + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_cac_tdp_table *cac_table = table_info->cac_dtp_table; + int adjust_percent, target_tdp; + int result = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerContainment)) { + /* adjustment percentage has already been validated */ + adjust_percent = hwmgr->platform_descriptor.TDPAdjustmentPolarity ? + hwmgr->platform_descriptor.TDPAdjustment : + (-1 * hwmgr->platform_descriptor.TDPAdjustment); + /* SMC requested that target_tdp to be 7 bit fraction in DPM table + * but message to be 8 bit fraction for messages + */ + target_tdp = ((100 + adjust_percent) * (int)(cac_table->usTDP * 256)) / 100; + result = fiji_set_overdriver_target_tdp(hwmgr, (uint32_t)target_tdp); + } + + return result; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h new file mode 100644 index 000000000000..55e58200f33a --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_powertune.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef FIJI_POWERTUNE_H +#define FIJI_POWERTUNE_H + +enum fiji_pt_config_reg_type { + FIJI_CONFIGREG_MMR = 0, + FIJI_CONFIGREG_SMC_IND, + FIJI_CONFIGREG_DIDT_IND, + FIJI_CONFIGREG_CACHE, + FIJI_CONFIGREG_MAX +}; + +/* PowerContainment Features */ +#define POWERCONTAINMENT_FEATURE_DTE 0x00000001 +#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 +#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 + +struct fiji_pt_config_reg { + uint32_t offset; + uint32_t mask; + uint32_t shift; + uint32_t value; + enum fiji_pt_config_reg_type type; +}; + +struct fiji_pt_defaults +{ + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + uint8_t TdcWaterfallCtl; + uint8_t DTEAmbientTempBase; +}; + +void fiji_initialize_power_tune_defaults(struct pp_hwmgr *hwmgr); +int fiji_populate_bapm_parameters_in_dpm_table(struct pp_hwmgr *hwmgr); +int fiji_populate_pm_fuses(struct pp_hwmgr *hwmgr); +int fiji_enable_smc_cac(struct pp_hwmgr *hwmgr); +int fiji_enable_power_containment(struct pp_hwmgr *hwmgr); +int fiji_set_power_limit(struct pp_hwmgr *hwmgr, uint32_t n); +int fiji_power_control_set_level(struct pp_hwmgr *hwmgr); + +#endif /* FIJI_POWERTUNE_H */ + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c new file mode 100644 index 000000000000..def57d0675ed --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.c @@ -0,0 +1,687 @@ +/* + * Copyright 2015 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. + * + */ + +#include "fiji_thermal.h" +#include "fiji_hwmgr.h" +#include "fiji_smumgr.h" +#include "fiji_ppsmc.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" + +int fiji_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, + struct phm_fan_speed_info *fan_speed_info) +{ + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + fan_speed_info->supports_percent_read = true; + fan_speed_info->supports_percent_write = true; + fan_speed_info->min_percent = 0; + fan_speed_info->max_percent = 100; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM) && + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; + fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM; + } else { + fan_speed_info->min_rpm = 0; + fan_speed_info->max_rpm = 0; + } + + return 0; +} + +int fiji_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t *speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_STATUS, FDO_PWM_DUTY); + + if (duty100 == 0) + return -EINVAL; + + + tmp64 = (uint64_t)duty * 100; + do_div(tmp64, duty100); + *speed = (uint32_t)tmp64; + + if (*speed > 100) + *speed = 100; + + return 0; +} + +int fiji_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + uint32_t tach_period; + uint32_t crystal_clock_freq; + + if (hwmgr->thermal_controller.fanInfo.bNoFan || + (hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution == 0)) + return 0; + + tach_period = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_STATUS, TACH_PERIOD); + + if (tach_period == 0) + return -EINVAL; + + crystal_clock_freq = tonga_get_xclk(hwmgr); + + *speed = 60 * crystal_clock_freq * 10000/ tach_period; + + return 0; +} + +/** +* Set Fan Speed Control to static mode, so that the user can decide what speed to use. +* @param hwmgr the address of the powerplay hardware manager. +* mode the fan control mode, 0 default, 1 by percent, 5, by RPM +* @exception Should always succeed. +*/ +int fiji_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + + if (hwmgr->fan_ctrl_is_in_default_mode) { + hwmgr->fan_ctrl_default_mode = + PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE); + hwmgr->tmin = + PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN); + hwmgr->fan_ctrl_is_in_default_mode = false; + } + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN, 0); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE, mode); + + return 0; +} + +/** +* Reset Fan Speed Control to default mode. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Should always succeed. +*/ +int fiji_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->fan_ctrl_is_in_default_mode) { + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TMIN, hwmgr->tmin); + hwmgr->fan_ctrl_is_in_default_mode = true; + } + + return 0; +} + +int fiji_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + int result; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ODFuzzyFanControlSupport)) { + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY); + result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_FanSpeedInTableIsRPM)) + hwmgr->hwmgr_func->set_max_fan_rpm_output(hwmgr, + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanRPM); + else + hwmgr->hwmgr_func->set_max_fan_pwm_output(hwmgr, + hwmgr->thermal_controller. + advanceFanControlParameters.usMaxFanPWM); + + } else { + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE); + result = smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl); + } + + if (!result && hwmgr->thermal_controller. + advanceFanControlParameters.ucTargetTemperature) + result = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanTemperatureTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ucTargetTemperature); + + return result; +} + + +int fiji_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl); +} + +/** +* Set Fan Speed in percent. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (0% - 100%) to be set. +* @exception Fails is the 100% setting appears to be 0. +*/ +int fiji_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, + uint32_t speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (speed > 100) + speed = 100; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + fiji_fan_ctrl_stop_smc_fan_control(hwmgr); + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) + return -EINVAL; + + tmp64 = (uint64_t)speed * 100; + do_div(tmp64, duty100); + duty = (uint32_t)tmp64; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); + + return fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +/** +* Reset Fan Speed to default. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Always succeeds. +*/ +int fiji_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) +{ + int result; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) { + result = fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + if (!result) + result = fiji_fan_ctrl_start_smc_fan_control(hwmgr); + } else + result = fiji_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set Fan Speed in RPM. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (min - max) to be set. +* @exception Fails is the speed not lie between min and max. +*/ +int fiji_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + uint32_t tach_period; + uint32_t crystal_clock_freq; + + if (hwmgr->thermal_controller.fanInfo.bNoFan || + (hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution == 0) || + (speed < hwmgr->thermal_controller.fanInfo.ulMinRPM) || + (speed > hwmgr->thermal_controller.fanInfo.ulMaxRPM)) + return 0; + + crystal_clock_freq = tonga_get_xclk(hwmgr); + + tach_period = 60 * crystal_clock_freq * 10000 / (8 * speed); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_STATUS, TACH_PERIOD, tach_period); + + return fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int fiji_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + int temp; + + temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_STATUS, CTF_TEMP); + + /* Bit 9 means the reading is lower than the lowest usable value. */ + if (temp & 0x200) + temp = FIJI_THERMAL_MAXIMUM_TEMP_READING; + else + temp = temp & 0x1ff; + + temp *= PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + uint32_t low_temp, uint32_t high_temp) +{ + uint32_t low = FIJI_THERMAL_MINIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + uint32_t high = FIJI_THERMAL_MAXIMUM_ALERT_TEMP * + PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + if (low < low_temp) + low = low_temp; + if (high > high_temp) + high = high_temp; + + if (low > high) + return -EINVAL; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, DIG_THERM_INTH, + (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, DIG_THERM_INTL, + (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_CTRL, DIG_THERM_DPM, + (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + + return 0; +} + +/** +* Programs thermal controller one-time setting registers +* +* @param hwmgr The address of the hardware manager. +*/ +static int fiji_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_CTRL, EDGE_PER_REV, + hwmgr->thermal_controller.fanInfo. + ucTachometerPulsesPerRevolution - 1); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static int fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK); + alert &= ~(FIJI_THERMAL_HIGH_ALERT_MASK | FIJI_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to enable internal thermal interrupts */ + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable); +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +static int fiji_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK); + alert |= (FIJI_THERMAL_HIGH_ALERT_MASK | FIJI_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to disable internal thermal interrupts */ + return smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable); +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int fiji_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = fiji_thermal_disable_alert(hwmgr); + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + fiji_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set up the fan table to control the fan using the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_fiji_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ + struct fiji_hwmgr *data = (struct fiji_hwmgr *)(hwmgr->backend); + SMU73_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (data->fan_table_start == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL1, FMAX_DUTY100); + + if (duty100 == 0) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters. + usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - + hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr-> + thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr-> + thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = tonga_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr-> + thermal_controller.advanceFanControlParameters.ulCycleDelay * + reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD( + hwmgr->device, CGS_IND_REG__SMC, + CG_MULT_THERMAL_CTRL, TEMP_SEL); + + res = fiji_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start, + (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), + data->sram_end); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanMinPwm, + hwmgr->thermal_controller. + advanceFanControlParameters.ucMinimumPWMLimit); + + if (!res && hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit) + res = smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_SetFanSclkTarget, + hwmgr->thermal_controller. + advanceFanControlParameters.ulMinFanSCLKAcousticLimit); + + if (res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + return 0; +} + +/** +* Start the fan control on the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_fiji_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ +/* If the fantable setup has failed we could have disabled + * PHM_PlatformCaps_MicrocodeFanControl even after + * this function was included in the table. + * Make sure that we still think controlling the fan is OK. +*/ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) { + fiji_fan_ctrl_start_smc_fan_control(hwmgr); + fiji_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + } + + return 0; +} + +/** +* Set temperature range for high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ + struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input; + + if (range == NULL) + return -EINVAL; + + return fiji_thermal_set_temperature_range(hwmgr, range->min, range->max); +} + +/** +* Programs one-time setting registers +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from initialize thermal controller routine +*/ +int tf_fiji_thermal_initialize(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ + return fiji_thermal_initialize(hwmgr); +} + +/** +* Enable high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from enable alert routine +*/ +int tf_fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ + return fiji_thermal_enable_alert(hwmgr); +} + +/** +* Disable high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from disable alert routine +*/ +static int tf_fiji_thermal_disable_alert(struct pp_hwmgr *hwmgr, + void *input, void *output, void *storage, int result) +{ + return fiji_thermal_disable_alert(hwmgr); +} + +static struct phm_master_table_item +fiji_thermal_start_thermal_controller_master_list[] = { + {NULL, tf_fiji_thermal_initialize}, + {NULL, tf_fiji_thermal_set_temperature_range}, + {NULL, tf_fiji_thermal_enable_alert}, +/* We should restrict performance levels to low before we halt the SMC. + * On the other hand we are still in boot state when we do this + * so it would be pointless. + * If this assumption changes we have to revisit this table. + */ + {NULL, tf_fiji_thermal_setup_fan_table}, + {NULL, tf_fiji_thermal_start_smc_fan_control}, + {NULL, NULL} +}; + +static struct phm_master_table_header +fiji_thermal_start_thermal_controller_master = { + 0, + PHM_MasterTableFlag_None, + fiji_thermal_start_thermal_controller_master_list +}; + +static struct phm_master_table_item +fiji_thermal_set_temperature_range_master_list[] = { + {NULL, tf_fiji_thermal_disable_alert}, + {NULL, tf_fiji_thermal_set_temperature_range}, + {NULL, tf_fiji_thermal_enable_alert}, + {NULL, NULL} +}; + +struct phm_master_table_header +fiji_thermal_set_temperature_range_master = { + 0, + PHM_MasterTableFlag_None, + fiji_thermal_set_temperature_range_master_list +}; + +int fiji_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->thermal_controller.fanInfo.bNoFan) + fiji_fan_ctrl_set_default_mode(hwmgr); + return 0; +} + +/** +* Initializes the thermal controller related functions in the Hardware Manager structure. +* @param hwmgr The address of the hardware manager. +* @exception Any error code from the low-level communication. +*/ +int pp_fiji_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + int result; + + result = phm_construct_table(hwmgr, + &fiji_thermal_set_temperature_range_master, + &(hwmgr->set_temperature_range)); + + if (!result) { + result = phm_construct_table(hwmgr, + &fiji_thermal_start_thermal_controller_master, + &(hwmgr->start_thermal_controller)); + if (result) + phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range)); + } + + if (!result) + hwmgr->fan_ctrl_is_in_default_mode = true; + return result; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h new file mode 100644 index 000000000000..8621493b8574 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/fiji_thermal.h @@ -0,0 +1,62 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef FIJI_THERMAL_H +#define FIJI_THERMAL_H + +#include "hwmgr.h" + +#define FIJI_THERMAL_HIGH_ALERT_MASK 0x1 +#define FIJI_THERMAL_LOW_ALERT_MASK 0x2 + +#define FIJI_THERMAL_MINIMUM_TEMP_READING -256 +#define FIJI_THERMAL_MAXIMUM_TEMP_READING 255 + +#define FIJI_THERMAL_MINIMUM_ALERT_TEMP 0 +#define FIJI_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + + +extern int tf_fiji_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); +extern int tf_fiji_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); +extern int tf_fiji_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); + +extern int fiji_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int fiji_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern int fiji_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); +extern int fiji_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int fiji_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); +extern int fiji_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode); +extern int fiji_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int fiji_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); +extern int pp_fiji_thermal_initialize(struct pp_hwmgr *hwmgr); +extern int fiji_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr); +extern int fiji_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int fiji_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int fiji_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); +extern uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c new file mode 100644 index 000000000000..5abde8f6d108 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/functiontables.c @@ -0,0 +1,154 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "hwmgr.h" + +static int phm_run_table(struct pp_hwmgr *hwmgr, + struct phm_runtime_table_header *rt_table, + void *input, + void *output, + void *temp_storage) +{ + int result = 0; + phm_table_function *function; + + for (function = rt_table->function_list; NULL != *function; function++) { + int tmp = (*function)(hwmgr, input, output, temp_storage, result); + + if (tmp == PP_Result_TableImmediateExit) + break; + if (tmp) { + if (0 == result) + result = tmp; + if (rt_table->exit_error) + break; + } + } + + return result; +} + +int phm_dispatch_table(struct pp_hwmgr *hwmgr, + struct phm_runtime_table_header *rt_table, + void *input, void *output) +{ + int result = 0; + void *temp_storage = NULL; + + if (hwmgr == NULL || rt_table == NULL || rt_table->function_list == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n"); + return 0; /*temp return ture because some function not implement on some asic */ + } + + if (0 != rt_table->storage_size) { + temp_storage = kzalloc(rt_table->storage_size, GFP_KERNEL); + if (temp_storage == NULL) { + printk(KERN_ERR "[ powerplay ] Could not allocate table temporary storage\n"); + return -1; + } + } + + result = phm_run_table(hwmgr, rt_table, input, output, temp_storage); + + if (NULL != temp_storage) + kfree(temp_storage); + + return result; +} + +int phm_construct_table(struct pp_hwmgr *hwmgr, + struct phm_master_table_header *master_table, + struct phm_runtime_table_header *rt_table) +{ + uint32_t function_count = 0; + const struct phm_master_table_item *table_item; + uint32_t size; + phm_table_function *run_time_list; + phm_table_function *rtf; + + if (hwmgr == NULL || master_table == NULL || rt_table == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Parameter!\n"); + return -1; + } + + for (table_item = master_table->master_list; + NULL != table_item->tableFunction; table_item++) { + if ((NULL == table_item->isFunctionNeededInRuntimeTable) || + (table_item->isFunctionNeededInRuntimeTable(hwmgr))) + function_count++; + } + + size = (function_count + 1) * sizeof(phm_table_function); + run_time_list = kzalloc(size, GFP_KERNEL); + if (NULL == run_time_list) + return -1; + + rtf = run_time_list; + for (table_item = master_table->master_list; + NULL != table_item->tableFunction; table_item++) { + if ((rtf - run_time_list) > function_count) { + printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); + kfree(run_time_list); + return -1; + } + + if ((NULL == table_item->isFunctionNeededInRuntimeTable) || + (table_item->isFunctionNeededInRuntimeTable(hwmgr))) { + *(rtf++) = table_item->tableFunction; + } + } + + if ((rtf - run_time_list) > function_count) { + printk(KERN_ERR "[ powerplay ] Check function results have changed\n"); + kfree(run_time_list); + return -1; + } + + *rtf = NULL; + rt_table->function_list = run_time_list; + rt_table->exit_error = (0 != (master_table->flags & PHM_MasterTableFlag_ExitOnError)); + rt_table->storage_size = master_table->storage_size; + return 0; +} + +int phm_destroy_table(struct pp_hwmgr *hwmgr, + struct phm_runtime_table_header *rt_table) +{ + if (hwmgr == NULL || rt_table == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Parameter\n"); + return -1; + } + + if (NULL == rt_table->function_list) + return 0; + + kfree(rt_table->function_list); + + rt_table->function_list = NULL; + rt_table->storage_size = 0; + rt_table->exit_error = false; + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c new file mode 100644 index 000000000000..001b8bb4143d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hardwaremanager.c @@ -0,0 +1,320 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/errno.h> +#include "hwmgr.h" +#include "hardwaremanager.h" +#include "power_state.h" +#include "pp_acpi.h" +#include "amd_acpi.h" +#include "amd_powerplay.h" + +#define PHM_FUNC_CHECK(hw) \ + do { \ + if ((hw) == NULL || (hw)->hwmgr_func == NULL) \ + return -EINVAL; \ + } while (0) + +void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr) +{ + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableVoltageTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableEngineTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMemoryTransition); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGClockGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMGCGTSSM); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLSClockGating); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_Force3DClockSupport); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableLightSleep); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableMCLS); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisablePowerGating); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableDPM); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_DisableSMUUVDHandshake); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ThermalAutoThrottling); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_NoOD5Support); + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UserMaxClockForMultiDisplays); + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VpuRecoveryInProgress); + + if (acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST) && + acpi_atcs_functions_supported(hwmgr->device, ATCS_FUNCTION_PCIE_DEVICE_READY_NOTIFICATION)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest); +} + +bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr) +{ + return hwmgr->block_hw_access; +} + +int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block) +{ + hwmgr->block_hw_access = block; + return 0; +} + +int phm_setup_asic(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (NULL != hwmgr->hwmgr_func->asic_setup) + return hwmgr->hwmgr_func->asic_setup(hwmgr); + } else { + return phm_dispatch_table(hwmgr, &(hwmgr->setup_asic), + NULL, NULL); + } + + return 0; +} + +int phm_set_power_state(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pcurrent_state, + const struct pp_hw_power_state *pnew_power_state) +{ + struct phm_set_power_state_input states; + + PHM_FUNC_CHECK(hwmgr); + + states.pcurrent_state = pcurrent_state; + states.pnew_state = pnew_power_state; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (NULL != hwmgr->hwmgr_func->power_state_set) + return hwmgr->hwmgr_func->power_state_set(hwmgr, &states); + } else { + return phm_dispatch_table(hwmgr, &(hwmgr->set_power_state), &states, NULL); + } + + return 0; +} + +int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (NULL != hwmgr->hwmgr_func->dynamic_state_management_enable) + return hwmgr->hwmgr_func->dynamic_state_management_enable(hwmgr); + } else { + return phm_dispatch_table(hwmgr, + &(hwmgr->enable_dynamic_state_management), + NULL, NULL); + } + return 0; +} + +int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->force_dpm_level != NULL) + return hwmgr->hwmgr_func->force_dpm_level(hwmgr, level); + + return 0; +} + +int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *adjusted_ps, + const struct pp_power_state *current_ps) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->apply_state_adjust_rules != NULL) + return hwmgr->hwmgr_func->apply_state_adjust_rules( + hwmgr, + adjusted_ps, + current_ps); + return 0; +} + +int phm_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->powerdown_uvd != NULL) + return hwmgr->hwmgr_func->powerdown_uvd(hwmgr); + return 0; +} + +int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->powergate_uvd != NULL) + return hwmgr->hwmgr_func->powergate_uvd(hwmgr, gate); + return 0; +} + +int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->powergate_vce != NULL) + return hwmgr->hwmgr_func->powergate_vce(hwmgr, gate); + return 0; +} + +int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (NULL != hwmgr->hwmgr_func->enable_clock_power_gating) + return hwmgr->hwmgr_func->enable_clock_power_gating(hwmgr); + } else { + return phm_dispatch_table(hwmgr, &(hwmgr->enable_clock_power_gatings), NULL, NULL); + } + return 0; +} + +int phm_display_configuration_changed(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) { + if (NULL != hwmgr->hwmgr_func->display_config_changed) + hwmgr->hwmgr_func->display_config_changed(hwmgr); + } else + return phm_dispatch_table(hwmgr, &hwmgr->display_configuration_changed, NULL, NULL); + return 0; +} + +int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface)) + if (NULL != hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment) + hwmgr->hwmgr_func->notify_smc_display_config_after_ps_adjustment(hwmgr); + + return 0; +} + +int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->stop_thermal_controller == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->stop_thermal_controller(hwmgr); +} + +int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->register_internal_thermal_interrupt == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->register_internal_thermal_interrupt(hwmgr, info); +} + +/** +* Initializes the thermal controller subsystem. +* +* @param pHwMgr the address of the powerplay hardware manager. +* @param pTemperatureRange the address of the structure holding the temperature range. +* @exception PP_Result_Failed if any of the paramters is NULL, otherwise the return value from the dispatcher. +*/ +int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range) +{ + + return phm_dispatch_table(hwmgr, &(hwmgr->start_thermal_controller), temperature_range, NULL); +} + + +bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->check_smc_update_required_for_display_configuration(hwmgr); +} + + +int phm_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->check_states_equal == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->check_states_equal(hwmgr, pstate1, pstate2, equal); +} + +int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->store_cc6_data == NULL) + return -EINVAL; + + hwmgr->display_config = *display_config; + /* to do pass other display configuration in furture */ + + if (hwmgr->hwmgr_func->store_cc6_data) + hwmgr->hwmgr_func->store_cc6_data(hwmgr, + display_config->cpu_pstate_separation_time, + display_config->cpu_cc6_disable, + display_config->cpu_pstate_disable, + display_config->nb_pstate_switch_disable); + + return 0; +} + +int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_dal_clock_info *info) +{ + PHM_FUNC_CHECK(hwmgr); + + if (info == NULL || hwmgr->hwmgr_func->get_dal_power_level == NULL) + return -EINVAL; + + return hwmgr->hwmgr_func->get_dal_power_level(hwmgr, info); +} + +int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr) +{ + PHM_FUNC_CHECK(hwmgr); + + if (hwmgr->hwmgr_func->set_cpu_power_state != NULL) + return hwmgr->hwmgr_func->set_cpu_power_state(hwmgr); + + return 0; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c new file mode 100644 index 000000000000..ca4554b402f9 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr.c @@ -0,0 +1,560 @@ +/* + * Copyright 2015 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. + * + */ +#include "linux/delay.h" +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "cgs_common.h" +#include "power_state.h" +#include "hwmgr.h" +#include "pppcielanes.h" +#include "pp_debug.h" +#include "ppatomctrl.h" + +extern int cz_hwmgr_init(struct pp_hwmgr *hwmgr); +extern int tonga_hwmgr_init(struct pp_hwmgr *hwmgr); +extern int fiji_hwmgr_init(struct pp_hwmgr *hwmgr); + +int hwmgr_init(struct amd_pp_init *pp_init, struct pp_instance *handle) +{ + struct pp_hwmgr *hwmgr; + + if ((handle == NULL) || (pp_init == NULL)) + return -EINVAL; + + hwmgr = kzalloc(sizeof(struct pp_hwmgr), GFP_KERNEL); + if (hwmgr == NULL) + return -ENOMEM; + + handle->hwmgr = hwmgr; + hwmgr->smumgr = handle->smu_mgr; + hwmgr->device = pp_init->device; + hwmgr->chip_family = pp_init->chip_family; + hwmgr->chip_id = pp_init->chip_id; + hwmgr->hw_revision = pp_init->rev_id; + hwmgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; + hwmgr->power_source = PP_PowerSource_AC; + + switch (hwmgr->chip_family) { + case AMD_FAMILY_CZ: + cz_hwmgr_init(hwmgr); + break; + case AMD_FAMILY_VI: + switch (hwmgr->chip_id) { + case CHIP_TONGA: + tonga_hwmgr_init(hwmgr); + break; + case CHIP_FIJI: + fiji_hwmgr_init(hwmgr); + break; + default: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + phm_init_dynamic_caps(hwmgr); + + return 0; +} + +int hwmgr_fini(struct pp_hwmgr *hwmgr) +{ + if (hwmgr == NULL || hwmgr->ps == NULL) + return -EINVAL; + + kfree(hwmgr->ps); + kfree(hwmgr); + return 0; +} + +int hw_init_power_state_table(struct pp_hwmgr *hwmgr) +{ + int result; + unsigned int i; + unsigned int table_entries; + struct pp_power_state *state; + int size; + + if (hwmgr->hwmgr_func->get_num_of_pp_table_entries == NULL) + return -EINVAL; + + if (hwmgr->hwmgr_func->get_power_state_size == NULL) + return -EINVAL; + + hwmgr->num_ps = table_entries = hwmgr->hwmgr_func->get_num_of_pp_table_entries(hwmgr); + + hwmgr->ps_size = size = hwmgr->hwmgr_func->get_power_state_size(hwmgr) + + sizeof(struct pp_power_state); + + hwmgr->ps = kzalloc(size * table_entries, GFP_KERNEL); + + state = hwmgr->ps; + + for (i = 0; i < table_entries; i++) { + result = hwmgr->hwmgr_func->get_pp_table_entry(hwmgr, i, state); + + if (state->classification.flags & PP_StateClassificationFlag_Boot) { + hwmgr->boot_ps = state; + hwmgr->current_ps = hwmgr->request_ps = state; + } + + state->id = i + 1; /* assigned unique num for every power state id */ + + if (state->classification.flags & PP_StateClassificationFlag_Uvd) + hwmgr->uvd_ps = state; + state = (struct pp_power_state *)((unsigned long)state + size); + } + + return 0; +} + + +/** + * Returns once the part of the register indicated by the mask has + * reached the given value. + */ +int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (hwmgr == NULL || hwmgr->device == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); + return -EINVAL; + } + + for (i = 0; i < hwmgr->usec_timeout; i++) { + cur_value = cgs_read_register(hwmgr->device, index); + if ((cur_value & mask) == (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic*/ + if (i == hwmgr->usec_timeout) + return -1; + return 0; +} + +int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (hwmgr == NULL || hwmgr->device == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); + return -EINVAL; + } + + for (i = 0; i < hwmgr->usec_timeout; i++) { + cur_value = cgs_read_register(hwmgr->device, index); + if ((cur_value & mask) != (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic*/ + if (i == hwmgr->usec_timeout) + return -1; + return 0; +} + + +/** + * Returns once the part of the register indicated by the mask has + * reached the given value.The indirect space is described by giving + * the memory-mapped index of the indirect index register. + */ +void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (hwmgr == NULL || hwmgr->device == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); + return; + } + + cgs_write_register(hwmgr->device, indirect_port, index); + phm_wait_on_register(hwmgr, indirect_port + 1, mask, value); +} + +void phm_wait_for_indirect_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (hwmgr == NULL || hwmgr->device == NULL) { + printk(KERN_ERR "[ powerplay ] Invalid Hardware Manager!"); + return; + } + + cgs_write_register(hwmgr->device, indirect_port, index); + phm_wait_for_register_unequal(hwmgr, indirect_port + 1, + value, mask); +} + +bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr) +{ + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDPowerGating); +} + +bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr) +{ + return phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_VCEPowerGating); +} + + +int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table) +{ + uint32_t i, j; + uint16_t vvalue; + bool found = false; + struct pp_atomctrl_voltage_table *table; + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "Voltage Table empty.", return -EINVAL); + + table = kzalloc(sizeof(struct pp_atomctrl_voltage_table), + GFP_KERNEL); + + if (NULL == table) + return -EINVAL; + + table->mask_low = vol_table->mask_low; + table->phase_delay = vol_table->phase_delay; + + for (i = 0; i < vol_table->count; i++) { + vvalue = vol_table->entries[i].value; + found = false; + + for (j = 0; j < table->count; j++) { + if (vvalue == table->entries[j].value) { + found = true; + break; + } + } + + if (!found) { + table->entries[table->count].value = vvalue; + table->entries[table->count].smio_low = + vol_table->entries[i].smio_low; + table->count++; + } + } + + memcpy(vol_table, table, sizeof(struct pp_atomctrl_voltage_table)); + kfree(table); + + return 0; +} + +int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].mvdd; + vol_table->entries[i].smio_low = 0; + } + + result = phm_trim_voltage_table(vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim MVDD table.", return result); + + return 0; +} + +int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_clock_voltage_dependency_table *dep_table) +{ + uint32_t i; + int result; + + PP_ASSERT_WITH_CODE((0 != dep_table->count), + "Voltage Dependency Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + vol_table->count = dep_table->count; + + for (i = 0; i < dep_table->count; i++) { + vol_table->entries[i].value = dep_table->entries[i].vddci; + vol_table->entries[i].smio_low = 0; + } + + result = phm_trim_voltage_table(vol_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim VDDCI table.", return result); + + return 0; +} + +int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, + phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + int i = 0; + + PP_ASSERT_WITH_CODE((0 != lookup_table->count), + "Voltage Lookup Table empty.", return -EINVAL); + + PP_ASSERT_WITH_CODE((NULL != vol_table), + "vol_table empty.", return -EINVAL); + + vol_table->mask_low = 0; + vol_table->phase_delay = 0; + + vol_table->count = lookup_table->count; + + for (i = 0; i < vol_table->count; i++) { + vol_table->entries[i].value = lookup_table->entries[i].us_vdd; + vol_table->entries[i].smio_low = 0; + } + + return 0; +} + +void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, + struct pp_atomctrl_voltage_table *vol_table) +{ + unsigned int i, diff; + + if (vol_table->count <= max_vol_steps) + return; + + diff = vol_table->count - max_vol_steps; + + for (i = 0; i < max_vol_steps; i++) + vol_table->entries[i] = vol_table->entries[i + diff]; + + vol_table->count = max_vol_steps; + + return; +} + +int phm_reset_single_dpm_table(void *table, + uint32_t count, int max) +{ + int i; + + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + PP_ASSERT_WITH_CODE(count <= max, + "Fatal error, can not set up single DPM table entries to exceed max number!", + ); + + dpm_table->count = count; + for (i = 0; i < max; i++) + dpm_table->dpm_level[i].enabled = false; + + return 0; +} + +void phm_setup_pcie_table_entry( + void *table, + uint32_t index, uint32_t pcie_gen, + uint32_t pcie_lanes) +{ + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + dpm_table->dpm_level[index].value = pcie_gen; + dpm_table->dpm_level[index].param1 = pcie_lanes; + dpm_table->dpm_level[index].enabled = 1; +} + +int32_t phm_get_dpm_level_enable_mask_value(void *table) +{ + int32_t i; + int32_t mask = 0; + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + for (i = dpm_table->count; i > 0; i--) { + mask = mask << 1; + if (dpm_table->dpm_level[i - 1].enabled) + mask |= 0x1; + else + mask &= 0xFFFFFFFE; + } + + return mask; +} + +uint8_t phm_get_voltage_index( + struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage) +{ + uint8_t count = (uint8_t) (lookup_table->count); + uint8_t i; + + PP_ASSERT_WITH_CODE((NULL != lookup_table), + "Lookup Table empty.", return 0); + PP_ASSERT_WITH_CODE((0 != count), + "Lookup Table empty.", return 0); + + for (i = 0; i < lookup_table->count; i++) { + /* find first voltage equal or bigger than requested */ + if (lookup_table->entries[i].us_vdd >= voltage) + return i; + } + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + +uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci) +{ + uint32_t i; + + for (i = 0; i < vddci_table->count; i++) { + if (vddci_table->entries[i].value >= vddci) + return vddci_table->entries[i].value; + } + + PP_ASSERT_WITH_CODE(false, + "VDDCI is larger than max VDDCI in VDDCI Voltage Table!", + return vddci_table->entries[i].value); +} + +int phm_find_boot_level(void *table, + uint32_t value, uint32_t *boot_level) +{ + int result = -EINVAL; + uint32_t i; + struct vi_dpm_table *dpm_table = (struct vi_dpm_table *)table; + + for (i = 0; i < dpm_table->count; i++) { + if (value == dpm_table->dpm_level[i].value) { + *boot_level = i; + result = 0; + } + } + + return result; +} + +int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *sclk) +{ + uint8_t entryId; + uint8_t voltageId; + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -EINVAL); + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ + for (entryId = 0; entryId < table_info->vdd_dep_on_sclk->count; entryId++) { + voltageId = table_info->vdd_dep_on_sclk->entries[entryId].vddInd; + if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id) + break; + } + + PP_ASSERT_WITH_CODE(entryId < table_info->vdd_dep_on_sclk->count, + "Can't find requested voltage id in vdd_dep_on_sclk table!", + return -EINVAL; + ); + + *sclk = table_info->vdd_dep_on_sclk->entries[entryId].clk; + + return 0; +} + +/** + * Initialize Dynamic State Adjustment Rule Settings + * + * @param hwmgr the address of the powerplay hardware manager. + */ +int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) +{ + uint32_t table_size; + struct phm_clock_voltage_dependency_table *table_clk_vlt; + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* initialize vddc_dep_on_dal_pwrl table */ + table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); + table_clk_vlt = (struct phm_clock_voltage_dependency_table *)kzalloc(table_size, GFP_KERNEL); + + if (NULL == table_clk_vlt) { + printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n"); + return -ENOMEM; + } else { + table_clk_vlt->count = 4; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; + table_clk_vlt->entries[1].v = 720; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; + table_clk_vlt->entries[2].v = 810; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; + table_clk_vlt->entries[3].v = 900; + pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + } + + return 0; +} + +int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) { + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + } + + if (NULL != hwmgr->backend) { + kfree(hwmgr->backend); + hwmgr->backend = NULL; + } + + return 0; +} + +uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask) +{ + uint32_t level = 0; + + while (0 == (mask & (1 << level))) + level++; + + return level; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h new file mode 100644 index 000000000000..c9e6c2d80ea6 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/hwmgr_ppt.h @@ -0,0 +1,105 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef PP_HWMGR_PPT_H +#define PP_HWMGR_PPT_H + +#include "hardwaremanager.h" +#include "smumgr.h" +#include "atom-types.h" + +struct phm_ppt_v1_clock_voltage_dependency_record { + uint32_t clk; + uint8_t vddInd; + uint16_t vdd_offset; + uint16_t vddc; + uint16_t vddgfx; + uint16_t vddci; + uint16_t mvdd; + uint8_t phases; + uint8_t cks_enable; + uint8_t cks_voffset; +}; + +typedef struct phm_ppt_v1_clock_voltage_dependency_record phm_ppt_v1_clock_voltage_dependency_record; + +struct phm_ppt_v1_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +typedef struct phm_ppt_v1_clock_voltage_dependency_table phm_ppt_v1_clock_voltage_dependency_table; + + +/* Multimedia Clock Voltage Dependency records and table */ +struct phm_ppt_v1_mm_clock_voltage_dependency_record { + uint32_t dclk; /* UVD D-clock */ + uint32_t vclk; /* UVD V-clock */ + uint32_t eclk; /* VCE clock */ + uint32_t aclk; /* ACP clock */ + uint32_t samclock; /* SAMU clock */ + uint8_t vddcInd; + uint16_t vddgfx_offset; + uint16_t vddc; + uint16_t vddgfx; + uint8_t phases; +}; +typedef struct phm_ppt_v1_mm_clock_voltage_dependency_record phm_ppt_v1_mm_clock_voltage_dependency_record; + +struct phm_ppt_v1_mm_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_mm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_mm_clock_voltage_dependency_table phm_ppt_v1_mm_clock_voltage_dependency_table; + +struct phm_ppt_v1_voltage_lookup_record { + uint16_t us_calculated; + uint16_t us_vdd; /* Base voltage */ + uint16_t us_cac_low; + uint16_t us_cac_mid; + uint16_t us_cac_high; +}; +typedef struct phm_ppt_v1_voltage_lookup_record phm_ppt_v1_voltage_lookup_record; + +struct phm_ppt_v1_voltage_lookup_table { + uint32_t count; + phm_ppt_v1_voltage_lookup_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_voltage_lookup_table phm_ppt_v1_voltage_lookup_table; + +/* PCIE records and Table */ + +struct phm_ppt_v1_pcie_record { + uint8_t gen_speed; + uint8_t lane_width; +}; +typedef struct phm_ppt_v1_pcie_record phm_ppt_v1_pcie_record; + +struct phm_ppt_v1_pcie_table { + uint32_t count; /* Number of entries. */ + phm_ppt_v1_pcie_record entries[1]; /* Dynamically allocate count entries. */ +}; +typedef struct phm_ppt_v1_pcie_table phm_ppt_v1_pcie_table; + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c new file mode 100644 index 000000000000..7b2d5000292d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pp_acpi.c @@ -0,0 +1,76 @@ +#include <linux/errno.h> +#include "linux/delay.h" +#include "hwmgr.h" +#include "amd_acpi.h" + +bool acpi_atcs_functions_supported(void *device, uint32_t index) +{ + int32_t result; + struct atcs_verify_interface output_buf = {0}; + + int32_t temp_buffer = 1; + + result = cgs_call_acpi_method(device, CGS_ACPI_METHOD_ATCS, + ATCS_FUNCTION_VERIFY_INTERFACE, + &temp_buffer, + &output_buf, + 1, + sizeof(temp_buffer), + sizeof(output_buf)); + + return result == 0 ? (output_buf.function_bits & (1 << (index - 1))) != 0 : false; +} + +int acpi_pcie_perf_request(void *device, uint8_t perf_req, bool advertise) +{ + struct atcs_pref_req_input atcs_input; + struct atcs_pref_req_output atcs_output; + u32 retry = 3; + int result; + struct cgs_system_info info = {0}; + + if (!acpi_atcs_functions_supported(device, ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST)) + return -EINVAL; + + info.size = sizeof(struct cgs_system_info); + info.info_id = CGS_SYSTEM_INFO_ADAPTER_BDF_ID; + result = cgs_query_system_info(device, &info); + if (result != 0) + return -EINVAL; + atcs_input.client_id = (uint16_t)info.value; + atcs_input.size = sizeof(struct atcs_pref_req_input); + atcs_input.valid_flags_mask = ATCS_VALID_FLAGS_MASK; + atcs_input.flags = ATCS_WAIT_FOR_COMPLETION; + if (advertise) + atcs_input.flags |= ATCS_ADVERTISE_CAPS; + atcs_input.req_type = ATCS_PCIE_LINK_SPEED; + atcs_input.perf_req = perf_req; + + atcs_output.size = sizeof(struct atcs_pref_req_input); + + while (retry--) { + result = cgs_call_acpi_method(device, + CGS_ACPI_METHOD_ATCS, + ATCS_FUNCTION_PCIE_PERFORMANCE_REQUEST, + &atcs_input, + &atcs_output, + 0, + sizeof(atcs_input), + sizeof(atcs_output)); + if (result != 0) + return -EIO; + + switch (atcs_output.ret_val) { + case ATCS_REQUEST_REFUSED: + default: + return -EINVAL; + case ATCS_REQUEST_COMPLETE: + return 0; + case ATCS_REQUEST_IN_PROGRESS: + udelay(10); + break; + } + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c new file mode 100644 index 000000000000..2a83a4af2904 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.c @@ -0,0 +1,1207 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> + +#include "ppatomctrl.h" +#include "atombios.h" +#include "cgs_common.h" +#include "pp_debug.h" +#include "ppevvmath.h" + +#define MEM_ID_MASK 0xff000000 +#define MEM_ID_SHIFT 24 +#define CLOCK_RANGE_MASK 0x00ffffff +#define CLOCK_RANGE_SHIFT 0 +#define LOW_NIBBLE_MASK 0xf +#define DATA_EQU_PREV 0 +#define DATA_FROM_TABLE 4 + +union voltage_object_info { + struct _ATOM_VOLTAGE_OBJECT_INFO v1; + struct _ATOM_VOLTAGE_OBJECT_INFO_V2 v2; + struct _ATOM_VOLTAGE_OBJECT_INFO_V3_1 v3; +}; + +static int atomctrl_retrieve_ac_timing( + uint8_t index, + ATOM_INIT_REG_BLOCK *reg_block, + pp_atomctrl_mc_reg_table *table) +{ + uint32_t i, j; + uint8_t tmem_id; + ATOM_MEMORY_SETTING_DATA_BLOCK *reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) + ((uint8_t *)reg_block + (2 * sizeof(uint16_t)) + le16_to_cpu(reg_block->usRegIndexTblSize)); + + uint8_t num_ranges = 0; + + while (*(uint32_t *)reg_data != END_OF_REG_DATA_BLOCK && + num_ranges < VBIOS_MAX_AC_TIMING_ENTRIES) { + tmem_id = (uint8_t)((*(uint32_t *)reg_data & MEM_ID_MASK) >> MEM_ID_SHIFT); + + if (index == tmem_id) { + table->mc_reg_table_entry[num_ranges].mclk_max = + (uint32_t)((*(uint32_t *)reg_data & CLOCK_RANGE_MASK) >> + CLOCK_RANGE_SHIFT); + + for (i = 0, j = 1; i < table->last; i++) { + if ((table->mc_reg_address[i].uc_pre_reg_data & + LOW_NIBBLE_MASK) == DATA_FROM_TABLE) { + table->mc_reg_table_entry[num_ranges].mc_data[i] = + (uint32_t)*((uint32_t *)reg_data + j); + j++; + } else if ((table->mc_reg_address[i].uc_pre_reg_data & + LOW_NIBBLE_MASK) == DATA_EQU_PREV) { + table->mc_reg_table_entry[num_ranges].mc_data[i] = + table->mc_reg_table_entry[num_ranges].mc_data[i-1]; + } + } + num_ranges++; + } + + reg_data = (ATOM_MEMORY_SETTING_DATA_BLOCK *) + ((uint8_t *)reg_data + le16_to_cpu(reg_block->usRegDataBlkSize)) ; + } + + PP_ASSERT_WITH_CODE((*(uint32_t *)reg_data == END_OF_REG_DATA_BLOCK), + "Invalid VramInfo table.", return -1); + table->num_entries = num_ranges; + + return 0; +} + +/** + * Get memory clock AC timing registers index from VBIOS table + * VBIOS set end of memory clock AC timing registers by ucPreRegDataLength bit6 = 1 + * @param reg_block the address ATOM_INIT_REG_BLOCK + * @param table the address of MCRegTable + * @return 0 + */ +static int atomctrl_set_mc_reg_address_table( + ATOM_INIT_REG_BLOCK *reg_block, + pp_atomctrl_mc_reg_table *table) +{ + uint8_t i = 0; + uint8_t num_entries = (uint8_t)((le16_to_cpu(reg_block->usRegIndexTblSize)) + / sizeof(ATOM_INIT_REG_INDEX_FORMAT)); + ATOM_INIT_REG_INDEX_FORMAT *format = ®_block->asRegIndexBuf[0]; + + num_entries--; /* subtract 1 data end mark entry */ + + PP_ASSERT_WITH_CODE((num_entries <= VBIOS_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + + /* ucPreRegDataLength bit6 = 1 is the end of memory clock AC timing registers */ + while ((!(format->ucPreRegDataLength & ACCESS_PLACEHOLDER)) && + (i < num_entries)) { + table->mc_reg_address[i].s1 = + (uint16_t)(le16_to_cpu(format->usRegIndex)); + table->mc_reg_address[i].uc_pre_reg_data = + format->ucPreRegDataLength; + + i++; + format = (ATOM_INIT_REG_INDEX_FORMAT *) + ((uint8_t *)format + sizeof(ATOM_INIT_REG_INDEX_FORMAT)); + } + + table->last = i; + return 0; +} + + +int atomctrl_initialize_mc_reg_table( + struct pp_hwmgr *hwmgr, + uint8_t module_index, + pp_atomctrl_mc_reg_table *table) +{ + ATOM_VRAM_INFO_HEADER_V2_1 *vram_info; + ATOM_INIT_REG_BLOCK *reg_block; + int result = 0; + u8 frev, crev; + u16 size; + + vram_info = (ATOM_VRAM_INFO_HEADER_V2_1 *) + cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, VRAM_Info), &size, &frev, &crev); + + if (module_index >= vram_info->ucNumOfVRAMModule) { + printk(KERN_ERR "[ powerplay ] Invalid VramInfo table."); + result = -1; + } else if (vram_info->sHeader.ucTableFormatRevision < 2) { + printk(KERN_ERR "[ powerplay ] Invalid VramInfo table."); + result = -1; + } + + if (0 == result) { + reg_block = (ATOM_INIT_REG_BLOCK *) + ((uint8_t *)vram_info + le16_to_cpu(vram_info->usMemClkPatchTblOffset)); + result = atomctrl_set_mc_reg_address_table(reg_block, table); + } + + if (0 == result) { + result = atomctrl_retrieve_ac_timing(module_index, + reg_block, table); + } + + return result; +} + +/** + * Set DRAM timings based on engine clock and memory clock. + */ +int atomctrl_set_engine_dram_timings_rv770( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock) +{ + SET_ENGINE_CLOCK_PS_ALLOCATION engine_clock_parameters; + + /* They are both in 10KHz Units. */ + engine_clock_parameters.ulTargetEngineClock = + (uint32_t) engine_clock & SET_CLOCK_FREQ_MASK; + engine_clock_parameters.ulTargetEngineClock |= + (COMPUTE_ENGINE_PLL_PARAM << 24); + + /* in 10 khz units.*/ + engine_clock_parameters.sReserved.ulClock = + (uint32_t) memory_clock & SET_CLOCK_FREQ_MASK; + return cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, DynamicMemorySettings), + &engine_clock_parameters); +} + +/** + * Private Function to get the PowerPlay Table Address. + * WARNING: The tabled returned by this function is in + * dynamically allocated memory. + * The caller has to release if by calling kfree. + */ +static ATOM_VOLTAGE_OBJECT_INFO *get_voltage_info_table(void *device) +{ + int index = GetIndexIntoMasterTable(DATA, VoltageObjectInfo); + u8 frev, crev; + u16 size; + union voltage_object_info *voltage_info; + + voltage_info = (union voltage_object_info *) + cgs_atom_get_data_table(device, index, + &size, &frev, &crev); + + if (voltage_info != NULL) + return (ATOM_VOLTAGE_OBJECT_INFO *) &(voltage_info->v3); + else + return NULL; +} + +static const ATOM_VOLTAGE_OBJECT_V3 *atomctrl_lookup_voltage_type_v3( + const ATOM_VOLTAGE_OBJECT_INFO_V3_1 * voltage_object_info_table, + uint8_t voltage_type, uint8_t voltage_mode) +{ + unsigned int size = le16_to_cpu(voltage_object_info_table->sHeader.usStructureSize); + unsigned int offset = offsetof(ATOM_VOLTAGE_OBJECT_INFO_V3_1, asVoltageObj[0]); + uint8_t *start = (uint8_t *)voltage_object_info_table; + + while (offset < size) { + const ATOM_VOLTAGE_OBJECT_V3 *voltage_object = + (const ATOM_VOLTAGE_OBJECT_V3 *)(start + offset); + + if (voltage_type == voltage_object->asGpioVoltageObj.sHeader.ucVoltageType && + voltage_mode == voltage_object->asGpioVoltageObj.sHeader.ucVoltageMode) + return voltage_object; + + offset += le16_to_cpu(voltage_object->asGpioVoltageObj.sHeader.usSize); + } + + return NULL; +} + +/** atomctrl_get_memory_pll_dividers_si(). + * + * @param hwmgr input parameter: pointer to HwMgr + * @param clock_value input parameter: memory clock + * @param dividers output parameter: memory PLL dividers + * @param strobe_mode input parameter: 1 for strobe mode, 0 for performance mode + */ +int atomctrl_get_memory_pll_dividers_si( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_memory_clock_param *mpll_param, + bool strobe_mode) +{ + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_1 mpll_parameters; + int result; + + mpll_parameters.ulClock = (uint32_t) clock_value; + mpll_parameters.ucInputFlag = (uint8_t)((strobe_mode) ? 1 : 0); + + result = cgs_atom_exec_cmd_table + (hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), + &mpll_parameters); + + if (0 == result) { + mpll_param->mpll_fb_divider.clk_frac = + mpll_parameters.ulFbDiv.usFbDivFrac; + mpll_param->mpll_fb_divider.cl_kf = + mpll_parameters.ulFbDiv.usFbDiv; + mpll_param->mpll_post_divider = + (uint32_t)mpll_parameters.ucPostDiv; + mpll_param->vco_mode = + (uint32_t)(mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_VCO_MODE_MASK); + mpll_param->yclk_sel = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_BYPASS_DQ_PLL) ? 1 : 0); + mpll_param->qdr = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_QDR_ENABLE) ? 1 : 0); + mpll_param->half_rate = + (uint32_t)((mpll_parameters.ucPllCntlFlag & + MPLL_CNTL_FLAG_AD_HALF_RATE) ? 1 : 0); + mpll_param->dll_speed = + (uint32_t)(mpll_parameters.ucDllSpeed); + mpll_param->bw_ctrl = + (uint32_t)(mpll_parameters.ucBWCntl); + } + + return result; +} + +/** atomctrl_get_memory_pll_dividers_vi(). + * + * @param hwmgr input parameter: pointer to HwMgr + * @param clock_value input parameter: memory clock + * @param dividers output parameter: memory PLL dividers + */ +int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, + uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param) +{ + COMPUTE_MEMORY_CLOCK_PARAM_PARAMETERS_V2_2 mpll_parameters; + int result; + + mpll_parameters.ulClock.ulClock = (uint32_t)clock_value; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryClockParam), + &mpll_parameters); + + if (!result) + mpll_param->mpll_post_divider = + (uint32_t)mpll_parameters.ulClock.ucPostDiv; + + return result; +} + +int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_kong *dividers) +{ + COMPUTE_MEMORY_ENGINE_PLL_PARAMETERS_V4 pll_parameters; + int result; + + pll_parameters.ulClock = clock_value; + + result = cgs_atom_exec_cmd_table + (hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + &pll_parameters); + + if (0 == result) { + dividers->pll_post_divider = pll_parameters.ucPostDiv; + dividers->real_clock = pll_parameters.ulClock; + } + + return result; +} + +int atomctrl_get_engine_pll_dividers_vi( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_vi *dividers) +{ + COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; + int result; + + pll_patameters.ulClock.ulClock = clock_value; + pll_patameters.ulClock.ucPostDiv = COMPUTE_GPUCLK_INPUT_FLAG_SCLK; + + result = cgs_atom_exec_cmd_table + (hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + &pll_patameters); + + if (0 == result) { + dividers->pll_post_divider = + pll_patameters.ulClock.ucPostDiv; + dividers->real_clock = + pll_patameters.ulClock.ulClock; + + dividers->ul_fb_div.ul_fb_div_frac = + pll_patameters.ulFbDiv.usFbDivFrac; + dividers->ul_fb_div.ul_fb_div = + pll_patameters.ulFbDiv.usFbDiv; + + dividers->uc_pll_ref_div = + pll_patameters.ucPllRefDiv; + dividers->uc_pll_post_div = + pll_patameters.ucPllPostDiv; + dividers->uc_pll_cntl_flag = + pll_patameters.ucPllCntlFlag; + } + + return result; +} + +int atomctrl_get_dfs_pll_dividers_vi( + struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_vi *dividers) +{ + COMPUTE_GPU_CLOCK_OUTPUT_PARAMETERS_V1_6 pll_patameters; + int result; + + pll_patameters.ulClock.ulClock = clock_value; + pll_patameters.ulClock.ucPostDiv = + COMPUTE_GPUCLK_INPUT_FLAG_DEFAULT_GPUCLK; + + result = cgs_atom_exec_cmd_table + (hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ComputeMemoryEnginePLL), + &pll_patameters); + + if (0 == result) { + dividers->pll_post_divider = + pll_patameters.ulClock.ucPostDiv; + dividers->real_clock = + pll_patameters.ulClock.ulClock; + + dividers->ul_fb_div.ul_fb_div_frac = + pll_patameters.ulFbDiv.usFbDivFrac; + dividers->ul_fb_div.ul_fb_div = + pll_patameters.ulFbDiv.usFbDiv; + + dividers->uc_pll_ref_div = + pll_patameters.ucPllRefDiv; + dividers->uc_pll_post_div = + pll_patameters.ucPllPostDiv; + dividers->uc_pll_cntl_flag = + pll_patameters.ucPllCntlFlag; + } + + return result; +} + +/** + * Get the reference clock in 10KHz + */ +uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr) +{ + ATOM_FIRMWARE_INFO *fw_info; + u8 frev, crev; + u16 size; + uint32_t clock; + + fw_info = (ATOM_FIRMWARE_INFO *) + cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if (fw_info == NULL) + clock = 2700; + else + clock = (uint32_t)(le16_to_cpu(fw_info->usReferenceClock)); + + return clock; +} + +/** + * Returns true if the given voltage type is controlled by GPIO pins. + * voltage_type is one of SET_VOLTAGE_TYPE_ASIC_VDDC, + * SET_VOLTAGE_TYPE_ASIC_MVDDC, SET_VOLTAGE_TYPE_ASIC_MVDDQ. + * voltage_mode is one of ATOM_SET_VOLTAGE, ATOM_SET_VOLTAGE_PHASE + */ +bool atomctrl_is_voltage_controled_by_gpio_v3( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint8_t voltage_mode) +{ + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->device); + bool ret; + + PP_ASSERT_WITH_CODE((NULL != voltage_info), + "Could not find Voltage Table in BIOS.", return false;); + + ret = (NULL != atomctrl_lookup_voltage_type_v3 + (voltage_info, voltage_type, voltage_mode)) ? true : false; + + return ret; +} + +int atomctrl_get_voltage_table_v3( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint8_t voltage_mode, + pp_atomctrl_voltage_table *voltage_table) +{ + ATOM_VOLTAGE_OBJECT_INFO_V3_1 *voltage_info = + (ATOM_VOLTAGE_OBJECT_INFO_V3_1 *)get_voltage_info_table(hwmgr->device); + const ATOM_VOLTAGE_OBJECT_V3 *voltage_object; + unsigned int i; + + PP_ASSERT_WITH_CODE((NULL != voltage_info), + "Could not find Voltage Table in BIOS.", return -1;); + + voltage_object = atomctrl_lookup_voltage_type_v3 + (voltage_info, voltage_type, voltage_mode); + + if (voltage_object == NULL) + return -1; + + PP_ASSERT_WITH_CODE( + (voltage_object->asGpioVoltageObj.ucGpioEntryNum <= + PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES), + "Too many voltage entries!", + return -1; + ); + + for (i = 0; i < voltage_object->asGpioVoltageObj.ucGpioEntryNum; i++) { + voltage_table->entries[i].value = + voltage_object->asGpioVoltageObj.asVolGpioLut[i].usVoltageValue; + voltage_table->entries[i].smio_low = + voltage_object->asGpioVoltageObj.asVolGpioLut[i].ulVoltageId; + } + + voltage_table->mask_low = + voltage_object->asGpioVoltageObj.ulGpioMaskVal; + voltage_table->count = + voltage_object->asGpioVoltageObj.ucGpioEntryNum; + voltage_table->phase_delay = + voltage_object->asGpioVoltageObj.ucPhaseDelay; + + return 0; +} + +static bool atomctrl_lookup_gpio_pin( + ATOM_GPIO_PIN_LUT * gpio_lookup_table, + const uint32_t pinId, + pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + unsigned int size = le16_to_cpu(gpio_lookup_table->sHeader.usStructureSize); + unsigned int offset = offsetof(ATOM_GPIO_PIN_LUT, asGPIO_Pin[0]); + uint8_t *start = (uint8_t *)gpio_lookup_table; + + while (offset < size) { + const ATOM_GPIO_PIN_ASSIGNMENT *pin_assignment = + (const ATOM_GPIO_PIN_ASSIGNMENT *)(start + offset); + + if (pinId == pin_assignment->ucGPIO_ID) { + gpio_pin_assignment->uc_gpio_pin_bit_shift = + pin_assignment->ucGpioPinBitShift; + gpio_pin_assignment->us_gpio_pin_aindex = + le16_to_cpu(pin_assignment->usGpioPin_AIndex); + return false; + } + + offset += offsetof(ATOM_GPIO_PIN_ASSIGNMENT, ucGPIO_ID) + 1; + } + + return true; +} + +/** + * Private Function to get the PowerPlay Table Address. + * WARNING: The tabled returned by this function is in + * dynamically allocated memory. + * The caller has to release if by calling kfree. + */ +static ATOM_GPIO_PIN_LUT *get_gpio_lookup_table(void *device) +{ + u8 frev, crev; + u16 size; + void *table_address; + + table_address = (ATOM_GPIO_PIN_LUT *) + cgs_atom_get_data_table(device, + GetIndexIntoMasterTable(DATA, GPIO_Pin_LUT), + &size, &frev, &crev); + + PP_ASSERT_WITH_CODE((NULL != table_address), + "Error retrieving BIOS Table Address!", return NULL;); + + return (ATOM_GPIO_PIN_LUT *)table_address; +} + +/** + * Returns 1 if the given pin id find in lookup table. + */ +bool atomctrl_get_pp_assign_pin( + struct pp_hwmgr *hwmgr, + const uint32_t pinId, + pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment) +{ + bool bRet = 0; + ATOM_GPIO_PIN_LUT *gpio_lookup_table = + get_gpio_lookup_table(hwmgr->device); + + PP_ASSERT_WITH_CODE((NULL != gpio_lookup_table), + "Could not find GPIO lookup Table in BIOS.", return -1); + + bRet = atomctrl_lookup_gpio_pin(gpio_lookup_table, pinId, + gpio_pin_assignment); + + return bRet; +} + +int atomctrl_calculate_voltage_evv_on_sclk( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint32_t sclk, + uint16_t virtual_voltage_Id, + uint16_t *voltage, + uint16_t dpm_level, + bool debug) +{ + ATOM_ASIC_PROFILING_INFO_V3_4 *getASICProfilingInfo; + + EFUSE_LINEAR_FUNC_PARAM sRO_fuse; + EFUSE_LINEAR_FUNC_PARAM sCACm_fuse; + EFUSE_LINEAR_FUNC_PARAM sCACb_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKt_Beta_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKv_m_fuse; + EFUSE_LOGISTIC_FUNC_PARAM sKv_b_fuse; + EFUSE_INPUT_PARAMETER sInput_FuseValues; + READ_EFUSE_VALUE_PARAMETER sOutput_FuseValues; + + uint32_t ul_RO_fused, ul_CACb_fused, ul_CACm_fused, ul_Kt_Beta_fused, ul_Kv_m_fused, ul_Kv_b_fused; + fInt fSM_A0, fSM_A1, fSM_A2, fSM_A3, fSM_A4, fSM_A5, fSM_A6, fSM_A7; + fInt fMargin_RO_a, fMargin_RO_b, fMargin_RO_c, fMargin_fixed, fMargin_FMAX_mean, fMargin_Plat_mean, fMargin_FMAX_sigma, fMargin_Plat_sigma, fMargin_DC_sigma; + fInt fLkg_FT, repeat; + fInt fMicro_FMAX, fMicro_CR, fSigma_FMAX, fSigma_CR, fSigma_DC, fDC_SCLK, fSquared_Sigma_DC, fSquared_Sigma_CR, fSquared_Sigma_FMAX; + fInt fRLL_LoadLine, fPowerDPMx, fDerateTDP, fVDDC_base, fA_Term, fC_Term, fB_Term, fRO_DC_margin; + fInt fRO_fused, fCACm_fused, fCACb_fused, fKv_m_fused, fKv_b_fused, fKt_Beta_fused, fFT_Lkg_V0NORM; + fInt fSclk_margin, fSclk, fEVV_V; + fInt fV_min, fV_max, fT_prod, fLKG_Factor, fT_FT, fV_FT, fV_x, fTDP_Power, fTDP_Power_right, fTDP_Power_left, fTDP_Current, fV_NL; + uint32_t ul_FT_Lkg_V0NORM; + fInt fLn_MaxDivMin, fMin, fAverage, fRange; + fInt fRoots[2]; + fInt fStepSize = GetScaledFraction(625, 100000); + + int result; + + getASICProfilingInfo = (ATOM_ASIC_PROFILING_INFO_V3_4 *) + cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, ASIC_ProfilingInfo), + NULL, NULL, NULL); + + if (!getASICProfilingInfo) + return -1; + + if(getASICProfilingInfo->asHeader.ucTableFormatRevision < 3 || + (getASICProfilingInfo->asHeader.ucTableFormatRevision == 3 && + getASICProfilingInfo->asHeader.ucTableContentRevision < 4)) + return -1; + + /*----------------------------------------------------------- + *GETTING MULTI-STEP PARAMETERS RELATED TO CURRENT DPM LEVEL + *----------------------------------------------------------- + */ + fRLL_LoadLine = Divide(getASICProfilingInfo->ulLoadLineSlop, 1000); + + switch (dpm_level) { + case 1: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm1); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM1, 1000); + break; + case 2: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm2); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM2, 1000); + break; + case 3: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm3); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM3, 1000); + break; + case 4: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm4); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM4, 1000); + break; + case 5: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm5); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM5, 1000); + break; + case 6: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm6); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM6, 1000); + break; + case 7: + fPowerDPMx = Convert_ULONG_ToFraction(getASICProfilingInfo->usPowerDpm7); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM7, 1000); + break; + default: + printk(KERN_ERR "DPM Level not supported\n"); + fPowerDPMx = Convert_ULONG_ToFraction(1); + fDerateTDP = GetScaledFraction(getASICProfilingInfo->ulTdpDerateDPM0, 1000); + } + + /*------------------------- + * DECODING FUSE VALUES + * ------------------------ + */ + /*Decode RO_Fused*/ + sRO_fuse = getASICProfilingInfo->sRoFuse; + + sInput_FuseValues.usEfuseIndex = sRO_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sRO_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sRO_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + /* Finally, the actual fuse value */ + ul_RO_fused = sOutput_FuseValues.ulEfuseValue; + fMin = GetScaledFraction(sRO_fuse.ulEfuseMin, 1); + fRange = GetScaledFraction(sRO_fuse.ulEfuseEncodeRange, 1); + fRO_fused = fDecodeLinearFuse(ul_RO_fused, fMin, fRange, sRO_fuse.ucEfuseLength); + + sCACm_fuse = getASICProfilingInfo->sCACm; + + sInput_FuseValues.usEfuseIndex = sCACm_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sCACm_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sCACm_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + ul_CACm_fused = sOutput_FuseValues.ulEfuseValue; + fMin = GetScaledFraction(sCACm_fuse.ulEfuseMin, 1000); + fRange = GetScaledFraction(sCACm_fuse.ulEfuseEncodeRange, 1000); + + fCACm_fused = fDecodeLinearFuse(ul_CACm_fused, fMin, fRange, sCACm_fuse.ucEfuseLength); + + sCACb_fuse = getASICProfilingInfo->sCACb; + + sInput_FuseValues.usEfuseIndex = sCACb_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sCACb_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sCACb_fuse.ucEfuseLength; + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + ul_CACb_fused = sOutput_FuseValues.ulEfuseValue; + fMin = GetScaledFraction(sCACb_fuse.ulEfuseMin, 1000); + fRange = GetScaledFraction(sCACb_fuse.ulEfuseEncodeRange, 1000); + + fCACb_fused = fDecodeLinearFuse(ul_CACb_fused, fMin, fRange, sCACb_fuse.ucEfuseLength); + + sKt_Beta_fuse = getASICProfilingInfo->sKt_b; + + sInput_FuseValues.usEfuseIndex = sKt_Beta_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKt_Beta_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKt_Beta_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + ul_Kt_Beta_fused = sOutput_FuseValues.ulEfuseValue; + fAverage = GetScaledFraction(sKt_Beta_fuse.ulEfuseEncodeAverage, 1000); + fRange = GetScaledFraction(sKt_Beta_fuse.ulEfuseEncodeRange, 1000); + + fKt_Beta_fused = fDecodeLogisticFuse(ul_Kt_Beta_fused, + fAverage, fRange, sKt_Beta_fuse.ucEfuseLength); + + sKv_m_fuse = getASICProfilingInfo->sKv_m; + + sInput_FuseValues.usEfuseIndex = sKv_m_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKv_m_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKv_m_fuse.ucEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + if (result) + return result; + + ul_Kv_m_fused = sOutput_FuseValues.ulEfuseValue; + fAverage = GetScaledFraction(sKv_m_fuse.ulEfuseEncodeAverage, 1000); + fRange = GetScaledFraction((sKv_m_fuse.ulEfuseEncodeRange & 0x7fffffff), 1000); + fRange = fMultiply(fRange, ConvertToFraction(-1)); + + fKv_m_fused = fDecodeLogisticFuse(ul_Kv_m_fused, + fAverage, fRange, sKv_m_fuse.ucEfuseLength); + + sKv_b_fuse = getASICProfilingInfo->sKv_b; + + sInput_FuseValues.usEfuseIndex = sKv_b_fuse.usEfuseIndex; + sInput_FuseValues.ucBitShift = sKv_b_fuse.ucEfuseBitLSB; + sInput_FuseValues.ucBitLength = sKv_b_fuse.ucEfuseLength; + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + ul_Kv_b_fused = sOutput_FuseValues.ulEfuseValue; + fAverage = GetScaledFraction(sKv_b_fuse.ulEfuseEncodeAverage, 1000); + fRange = GetScaledFraction(sKv_b_fuse.ulEfuseEncodeRange, 1000); + + fKv_b_fused = fDecodeLogisticFuse(ul_Kv_b_fused, + fAverage, fRange, sKv_b_fuse.ucEfuseLength); + + /* Decoding the Leakage - No special struct container */ + /* + * usLkgEuseIndex=56 + * ucLkgEfuseBitLSB=6 + * ucLkgEfuseLength=10 + * ulLkgEncodeLn_MaxDivMin=69077 + * ulLkgEncodeMax=1000000 + * ulLkgEncodeMin=1000 + * ulEfuseLogisticAlpha=13 + */ + + sInput_FuseValues.usEfuseIndex = getASICProfilingInfo->usLkgEuseIndex; + sInput_FuseValues.ucBitShift = getASICProfilingInfo->ucLkgEfuseBitLSB; + sInput_FuseValues.ucBitLength = getASICProfilingInfo->ucLkgEfuseLength; + + sOutput_FuseValues.sEfuse = sInput_FuseValues; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &sOutput_FuseValues); + + if (result) + return result; + + ul_FT_Lkg_V0NORM = sOutput_FuseValues.ulEfuseValue; + fLn_MaxDivMin = GetScaledFraction(getASICProfilingInfo->ulLkgEncodeLn_MaxDivMin, 10000); + fMin = GetScaledFraction(getASICProfilingInfo->ulLkgEncodeMin, 10000); + + fFT_Lkg_V0NORM = fDecodeLeakageID(ul_FT_Lkg_V0NORM, + fLn_MaxDivMin, fMin, getASICProfilingInfo->ucLkgEfuseLength); + fLkg_FT = fFT_Lkg_V0NORM; + + /*------------------------------------------- + * PART 2 - Grabbing all required values + *------------------------------------------- + */ + fSM_A0 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A0, 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A0_sign))); + fSM_A1 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A1, 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A1_sign))); + fSM_A2 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A2, 100000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A2_sign))); + fSM_A3 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A3, 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A3_sign))); + fSM_A4 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A4, 1000000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A4_sign))); + fSM_A5 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A5, 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A5_sign))); + fSM_A6 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A6, 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A6_sign))); + fSM_A7 = fMultiply(GetScaledFraction(getASICProfilingInfo->ulSM_A7, 1000), + ConvertToFraction(uPow(-1, getASICProfilingInfo->ucSM_A7_sign))); + + fMargin_RO_a = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_a); + fMargin_RO_b = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_b); + fMargin_RO_c = ConvertToFraction(getASICProfilingInfo->ulMargin_RO_c); + + fMargin_fixed = ConvertToFraction(getASICProfilingInfo->ulMargin_fixed); + + fMargin_FMAX_mean = GetScaledFraction( + getASICProfilingInfo->ulMargin_Fmax_mean, 10000); + fMargin_Plat_mean = GetScaledFraction( + getASICProfilingInfo->ulMargin_plat_mean, 10000); + fMargin_FMAX_sigma = GetScaledFraction( + getASICProfilingInfo->ulMargin_Fmax_sigma, 10000); + fMargin_Plat_sigma = GetScaledFraction( + getASICProfilingInfo->ulMargin_plat_sigma, 10000); + + fMargin_DC_sigma = GetScaledFraction( + getASICProfilingInfo->ulMargin_DC_sigma, 100); + fMargin_DC_sigma = fDivide(fMargin_DC_sigma, ConvertToFraction(1000)); + + fCACm_fused = fDivide(fCACm_fused, ConvertToFraction(100)); + fCACb_fused = fDivide(fCACb_fused, ConvertToFraction(100)); + fKt_Beta_fused = fDivide(fKt_Beta_fused, ConvertToFraction(100)); + fKv_m_fused = fNegate(fDivide(fKv_m_fused, ConvertToFraction(100))); + fKv_b_fused = fDivide(fKv_b_fused, ConvertToFraction(10)); + + fSclk = GetScaledFraction(sclk, 100); + + fV_max = fDivide(GetScaledFraction( + getASICProfilingInfo->ulMaxVddc, 1000), ConvertToFraction(4)); + fT_prod = GetScaledFraction(getASICProfilingInfo->ulBoardCoreTemp, 10); + fLKG_Factor = GetScaledFraction(getASICProfilingInfo->ulEvvLkgFactor, 100); + fT_FT = GetScaledFraction(getASICProfilingInfo->ulLeakageTemp, 10); + fV_FT = fDivide(GetScaledFraction( + getASICProfilingInfo->ulLeakageVoltage, 1000), ConvertToFraction(4)); + fV_min = fDivide(GetScaledFraction( + getASICProfilingInfo->ulMinVddc, 1000), ConvertToFraction(4)); + + /*----------------------- + * PART 3 + *----------------------- + */ + + fA_Term = fAdd(fMargin_RO_a, fAdd(fMultiply(fSM_A4,fSclk), fSM_A5)); + fB_Term = fAdd(fAdd(fMultiply(fSM_A2, fSclk), fSM_A6), fMargin_RO_b); + fC_Term = fAdd(fMargin_RO_c, + fAdd(fMultiply(fSM_A0,fLkg_FT), + fAdd(fMultiply(fSM_A1, fMultiply(fLkg_FT,fSclk)), + fAdd(fMultiply(fSM_A3, fSclk), + fSubtract(fSM_A7,fRO_fused))))); + + fVDDC_base = fSubtract(fRO_fused, + fSubtract(fMargin_RO_c, + fSubtract(fSM_A3, fMultiply(fSM_A1, fSclk)))); + fVDDC_base = fDivide(fVDDC_base, fAdd(fMultiply(fSM_A0,fSclk), fSM_A2)); + + repeat = fSubtract(fVDDC_base, + fDivide(fMargin_DC_sigma, ConvertToFraction(1000))); + + fRO_DC_margin = fAdd(fMultiply(fMargin_RO_a, + fGetSquare(repeat)), + fAdd(fMultiply(fMargin_RO_b, repeat), + fMargin_RO_c)); + + fDC_SCLK = fSubtract(fRO_fused, + fSubtract(fRO_DC_margin, + fSubtract(fSM_A3, + fMultiply(fSM_A2, repeat)))); + fDC_SCLK = fDivide(fDC_SCLK, fAdd(fMultiply(fSM_A0,repeat), fSM_A1)); + + fSigma_DC = fSubtract(fSclk, fDC_SCLK); + + fMicro_FMAX = fMultiply(fSclk, fMargin_FMAX_mean); + fMicro_CR = fMultiply(fSclk, fMargin_Plat_mean); + fSigma_FMAX = fMultiply(fSclk, fMargin_FMAX_sigma); + fSigma_CR = fMultiply(fSclk, fMargin_Plat_sigma); + + fSquared_Sigma_DC = fGetSquare(fSigma_DC); + fSquared_Sigma_CR = fGetSquare(fSigma_CR); + fSquared_Sigma_FMAX = fGetSquare(fSigma_FMAX); + + fSclk_margin = fAdd(fMicro_FMAX, + fAdd(fMicro_CR, + fAdd(fMargin_fixed, + fSqrt(fAdd(fSquared_Sigma_FMAX, + fAdd(fSquared_Sigma_DC, fSquared_Sigma_CR)))))); + /* + fA_Term = fSM_A4 * (fSclk + fSclk_margin) + fSM_A5; + fB_Term = fSM_A2 * (fSclk + fSclk_margin) + fSM_A6; + fC_Term = fRO_DC_margin + fSM_A0 * fLkg_FT + fSM_A1 * fLkg_FT * (fSclk + fSclk_margin) + fSM_A3 * (fSclk + fSclk_margin) + fSM_A7 - fRO_fused; + */ + + fA_Term = fAdd(fMultiply(fSM_A4, fAdd(fSclk, fSclk_margin)), fSM_A5); + fB_Term = fAdd(fMultiply(fSM_A2, fAdd(fSclk, fSclk_margin)), fSM_A6); + fC_Term = fAdd(fRO_DC_margin, + fAdd(fMultiply(fSM_A0, fLkg_FT), + fAdd(fMultiply(fMultiply(fSM_A1, fLkg_FT), + fAdd(fSclk, fSclk_margin)), + fAdd(fMultiply(fSM_A3, + fAdd(fSclk, fSclk_margin)), + fSubtract(fSM_A7, fRO_fused))))); + + SolveQuadracticEqn(fA_Term, fB_Term, fC_Term, fRoots); + + if (GreaterThan(fRoots[0], fRoots[1])) + fEVV_V = fRoots[1]; + else + fEVV_V = fRoots[0]; + + if (GreaterThan(fV_min, fEVV_V)) + fEVV_V = fV_min; + else if (GreaterThan(fEVV_V, fV_max)) + fEVV_V = fSubtract(fV_max, fStepSize); + + fEVV_V = fRoundUpByStepSize(fEVV_V, fStepSize, 0); + + /*----------------- + * PART 4 + *----------------- + */ + + fV_x = fV_min; + + while (GreaterThan(fAdd(fV_max, fStepSize), fV_x)) { + fTDP_Power_left = fMultiply(fMultiply(fMultiply(fAdd( + fMultiply(fCACm_fused, fV_x), fCACb_fused), fSclk), + fGetSquare(fV_x)), fDerateTDP); + + fTDP_Power_right = fMultiply(fFT_Lkg_V0NORM, fMultiply(fLKG_Factor, + fMultiply(fExponential(fMultiply(fAdd(fMultiply(fKv_m_fused, + fT_prod), fKv_b_fused), fV_x)), fV_x))); + fTDP_Power_right = fMultiply(fTDP_Power_right, fExponential(fMultiply( + fKt_Beta_fused, fT_prod))); + fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( + fAdd(fMultiply(fKv_m_fused, fT_prod), fKv_b_fused), fV_FT))); + fTDP_Power_right = fDivide(fTDP_Power_right, fExponential(fMultiply( + fKt_Beta_fused, fT_FT))); + + fTDP_Power = fAdd(fTDP_Power_left, fTDP_Power_right); + + fTDP_Current = fDivide(fTDP_Power, fV_x); + + fV_NL = fAdd(fV_x, fDivide(fMultiply(fTDP_Current, fRLL_LoadLine), + ConvertToFraction(10))); + + fV_NL = fRoundUpByStepSize(fV_NL, fStepSize, 0); + + if (GreaterThan(fV_max, fV_NL) && + (GreaterThan(fV_NL,fEVV_V) || + Equal(fV_NL, fEVV_V))) { + fV_NL = fMultiply(fV_NL, ConvertToFraction(1000)); + + *voltage = (uint16_t)fV_NL.partial.real; + break; + } else + fV_x = fAdd(fV_x, fStepSize); + } + + return result; +} + +/** atomctrl_get_voltage_evv_on_sclk gets voltage via call to ATOM COMMAND table. + * @param hwmgr input: pointer to hwManager + * @param voltage_type input: type of EVV voltage VDDC or VDDGFX + * @param sclk input: in 10Khz unit. DPM state SCLK frequency + * which is define in PPTable SCLK/VDDC dependence + * table associated with this virtual_voltage_Id + * @param virtual_voltage_Id input: voltage id which match per voltage DPM state: 0xff01, 0xff02.. 0xff08 + * @param voltage output: real voltage level in unit of mv + */ +int atomctrl_get_voltage_evv_on_sclk( + struct pp_hwmgr *hwmgr, + uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, + uint16_t *voltage) +{ + int result; + GET_VOLTAGE_INFO_INPUT_PARAMETER_V1_2 get_voltage_info_param_space; + + get_voltage_info_param_space.ucVoltageType = + voltage_type; + get_voltage_info_param_space.ucVoltageMode = + ATOM_GET_VOLTAGE_EVV_VOLTAGE; + get_voltage_info_param_space.usVoltageLevel = + virtual_voltage_Id; + get_voltage_info_param_space.ulSCLKFreq = + sclk; + + result = cgs_atom_exec_cmd_table(hwmgr->device, + GetIndexIntoMasterTable(COMMAND, GetVoltageInfo), + &get_voltage_info_param_space); + + if (0 != result) + return result; + + *voltage = ((GET_EVV_VOLTAGE_INFO_OUTPUT_PARAMETER_V1_2 *) + (&get_voltage_info_param_space))->usVoltageLevel; + + return result; +} + +/** + * Get the mpll reference clock in 10KHz + */ +uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr) +{ + ATOM_COMMON_TABLE_HEADER *fw_info; + uint32_t clock; + u8 frev, crev; + u16 size; + + fw_info = (ATOM_COMMON_TABLE_HEADER *) + cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if (fw_info == NULL) + clock = 2700; + else { + if ((fw_info->ucTableFormatRevision == 2) && + (le16_to_cpu(fw_info->usStructureSize) >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) { + ATOM_FIRMWARE_INFO_V2_1 *fwInfo_2_1 = + (ATOM_FIRMWARE_INFO_V2_1 *)fw_info; + clock = (uint32_t)(le16_to_cpu(fwInfo_2_1->usMemoryReferenceClock)); + } else { + ATOM_FIRMWARE_INFO *fwInfo_0_0 = + (ATOM_FIRMWARE_INFO *)fw_info; + clock = (uint32_t)(le16_to_cpu(fwInfo_0_0->usReferenceClock)); + } + } + + return clock; +} + +/** + * Get the asic internal spread spectrum table + */ +static ATOM_ASIC_INTERNAL_SS_INFO *asic_internal_ss_get_ss_table(void *device) +{ + ATOM_ASIC_INTERNAL_SS_INFO *table = NULL; + u8 frev, crev; + u16 size; + + table = (ATOM_ASIC_INTERNAL_SS_INFO *) + cgs_atom_get_data_table(device, + GetIndexIntoMasterTable(DATA, ASIC_InternalSS_Info), + &size, &frev, &crev); + + return table; +} + +/** + * Get the asic internal spread spectrum assignment + */ +static int asic_internal_ss_get_ss_asignment(struct pp_hwmgr *hwmgr, + const uint8_t clockSource, + const uint32_t clockSpeed, + pp_atomctrl_internal_ss_info *ssEntry) +{ + ATOM_ASIC_INTERNAL_SS_INFO *table; + ATOM_ASIC_SS_ASSIGNMENT *ssInfo; + int entry_found = 0; + + memset(ssEntry, 0x00, sizeof(pp_atomctrl_internal_ss_info)); + + table = asic_internal_ss_get_ss_table(hwmgr->device); + + if (NULL == table) + return -1; + + ssInfo = &table->asSpreadSpectrum[0]; + + while (((uint8_t *)ssInfo - (uint8_t *)table) < + le16_to_cpu(table->sHeader.usStructureSize)) { + if ((clockSource == ssInfo->ucClockIndication) && + ((uint32_t)clockSpeed <= le32_to_cpu(ssInfo->ulTargetClockRange))) { + entry_found = 1; + break; + } + + ssInfo = (ATOM_ASIC_SS_ASSIGNMENT *)((uint8_t *)ssInfo + + sizeof(ATOM_ASIC_SS_ASSIGNMENT)); + } + + if (entry_found) { + ssEntry->speed_spectrum_percentage = + ssInfo->usSpreadSpectrumPercentage; + ssEntry->speed_spectrum_rate = ssInfo->usSpreadRateInKhz; + + if (((GET_DATA_TABLE_MAJOR_REVISION(table) == 2) && + (GET_DATA_TABLE_MINOR_REVISION(table) >= 2)) || + (GET_DATA_TABLE_MAJOR_REVISION(table) == 3)) { + ssEntry->speed_spectrum_rate /= 100; + } + + switch (ssInfo->ucSpreadSpectrumMode) { + case 0: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_down; + break; + case 1: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_center; + break; + default: + ssEntry->speed_spectrum_mode = + pp_atomctrl_spread_spectrum_mode_down; + break; + } + } + + return entry_found ? 0 : 1; +} + +/** + * Get the memory clock spread spectrum info + */ +int atomctrl_get_memory_clock_spread_spectrum( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + pp_atomctrl_internal_ss_info *ssInfo) +{ + return asic_internal_ss_get_ss_asignment(hwmgr, + ASIC_INTERNAL_MEMORY_SS, memory_clock, ssInfo); +} +/** + * Get the engine clock spread spectrum info + */ +int atomctrl_get_engine_clock_spread_spectrum( + struct pp_hwmgr *hwmgr, + const uint32_t engine_clock, + pp_atomctrl_internal_ss_info *ssInfo) +{ + return asic_internal_ss_get_ss_asignment(hwmgr, + ASIC_INTERNAL_ENGINE_SS, engine_clock, ssInfo); +} + +int atomctrl_read_efuse(void *device, uint16_t start_index, + uint16_t end_index, uint32_t mask, uint32_t *efuse) +{ + int result; + READ_EFUSE_VALUE_PARAMETER efuse_param; + + efuse_param.sEfuse.usEfuseIndex = (start_index / 32) * 4; + efuse_param.sEfuse.ucBitShift = (uint8_t) + (start_index - ((start_index / 32) * 32)); + efuse_param.sEfuse.ucBitLength = (uint8_t) + ((end_index - start_index) + 1); + + result = cgs_atom_exec_cmd_table(device, + GetIndexIntoMasterTable(COMMAND, ReadEfuseValue), + &efuse_param); + if (!result) + *efuse = efuse_param.ulEfuseValue & mask; + + return result; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h new file mode 100644 index 000000000000..627420b80a5f --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppatomctrl.h @@ -0,0 +1,246 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef PP_ATOMVOLTAGECTRL_H +#define PP_ATOMVOLTAGECTRL_H + +#include "hwmgr.h" + +#define MEM_TYPE_GDDR5 0x50 +#define MEM_TYPE_GDDR4 0x40 +#define MEM_TYPE_GDDR3 0x30 +#define MEM_TYPE_DDR2 0x20 +#define MEM_TYPE_GDDR1 0x10 +#define MEM_TYPE_DDR3 0xb0 +#define MEM_TYPE_MASK 0xF0 + + +/* As returned from PowerConnectorDetectionTable. */ +#define PP_ATOM_POWER_BUDGET_DISABLE_OVERDRIVE 0x80 +#define PP_ATOM_POWER_BUDGET_SHOW_WARNING 0x40 +#define PP_ATOM_POWER_BUDGET_SHOW_WAIVER 0x20 +#define PP_ATOM_POWER_POWER_BUDGET_BEHAVIOUR 0x0F + +/* New functions for Evergreen and beyond. */ +#define PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES 32 + +struct pp_atomctrl_clock_dividers { + uint32_t pll_post_divider; + uint32_t pll_feedback_divider; + uint32_t pll_ref_divider; + bool enable_post_divider; +}; + +typedef struct pp_atomctrl_clock_dividers pp_atomctrl_clock_dividers; + +union pp_atomctrl_tcipll_fb_divider { + struct { + uint32_t ul_fb_div_frac : 14; + uint32_t ul_fb_div : 12; + uint32_t un_used : 6; + }; + uint32_t ul_fb_divider; +}; + +typedef union pp_atomctrl_tcipll_fb_divider pp_atomctrl_tcipll_fb_divider; + +struct pp_atomctrl_clock_dividers_rv730 { + uint32_t pll_post_divider; + pp_atomctrl_tcipll_fb_divider mpll_feedback_divider; + uint32_t pll_ref_divider; + bool enable_post_divider; + bool enable_dithen; + uint32_t vco_mode; +}; +typedef struct pp_atomctrl_clock_dividers_rv730 pp_atomctrl_clock_dividers_rv730; + + +struct pp_atomctrl_clock_dividers_kong { + uint32_t pll_post_divider; + uint32_t real_clock; +}; +typedef struct pp_atomctrl_clock_dividers_kong pp_atomctrl_clock_dividers_kong; + +struct pp_atomctrl_clock_dividers_ci { + uint32_t pll_post_divider; /* post divider value */ + uint32_t real_clock; + pp_atomctrl_tcipll_fb_divider ul_fb_div; /* Output Parameter: PLL FB divider */ + uint8_t uc_pll_ref_div; /* Output Parameter: PLL ref divider */ + uint8_t uc_pll_post_div; /* Output Parameter: PLL post divider */ + uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ +}; +typedef struct pp_atomctrl_clock_dividers_ci pp_atomctrl_clock_dividers_ci; + +struct pp_atomctrl_clock_dividers_vi { + uint32_t pll_post_divider; /* post divider value */ + uint32_t real_clock; + pp_atomctrl_tcipll_fb_divider ul_fb_div; /*Output Parameter: PLL FB divider */ + uint8_t uc_pll_ref_div; /*Output Parameter: PLL ref divider */ + uint8_t uc_pll_post_div; /*Output Parameter: PLL post divider */ + uint8_t uc_pll_cntl_flag; /*Output Flags: control flag */ +}; +typedef struct pp_atomctrl_clock_dividers_vi pp_atomctrl_clock_dividers_vi; + +union pp_atomctrl_s_mpll_fb_divider { + struct { + uint32_t cl_kf : 12; + uint32_t clk_frac : 12; + uint32_t un_used : 8; + }; + uint32_t ul_fb_divider; +}; +typedef union pp_atomctrl_s_mpll_fb_divider pp_atomctrl_s_mpll_fb_divider; + +enum pp_atomctrl_spread_spectrum_mode { + pp_atomctrl_spread_spectrum_mode_down = 0, + pp_atomctrl_spread_spectrum_mode_center +}; +typedef enum pp_atomctrl_spread_spectrum_mode pp_atomctrl_spread_spectrum_mode; + +struct pp_atomctrl_memory_clock_param { + pp_atomctrl_s_mpll_fb_divider mpll_fb_divider; + uint32_t mpll_post_divider; + uint32_t bw_ctrl; + uint32_t dll_speed; + uint32_t vco_mode; + uint32_t yclk_sel; + uint32_t qdr; + uint32_t half_rate; +}; +typedef struct pp_atomctrl_memory_clock_param pp_atomctrl_memory_clock_param; + +struct pp_atomctrl_internal_ss_info { + uint32_t speed_spectrum_percentage; /* in 1/100 percentage */ + uint32_t speed_spectrum_rate; /* in KHz */ + pp_atomctrl_spread_spectrum_mode speed_spectrum_mode; +}; +typedef struct pp_atomctrl_internal_ss_info pp_atomctrl_internal_ss_info; + +#ifndef NUMBER_OF_M3ARB_PARAMS +#define NUMBER_OF_M3ARB_PARAMS 3 +#endif + +#ifndef NUMBER_OF_M3ARB_PARAM_SETS +#define NUMBER_OF_M3ARB_PARAM_SETS 10 +#endif + +struct pp_atomctrl_kong_system_info { + uint32_t ul_bootup_uma_clock; /* in 10kHz unit */ + uint16_t us_max_nb_voltage; /* high NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ + uint16_t us_min_nb_voltage; /* low NB voltage, calculated using current VDDNB (D24F2xDC) and VDDNB offset fuse; */ + uint16_t us_bootup_nb_voltage; /* boot up NB voltage */ + uint8_t uc_htc_tmp_lmt; /* bit [22:16] of D24F3x64 Hardware Thermal Control (HTC) Register, may not be needed, TBD */ + uint8_t uc_tj_offset; /* bit [28:22] of D24F3xE4 Thermtrip Status Register,may not be needed, TBD */ + /* 0: default 1: uvd 2: fs-3d */ + uint32_t ul_csr_m3_srb_cntl[NUMBER_OF_M3ARB_PARAM_SETS][NUMBER_OF_M3ARB_PARAMS];/* arrays with values for CSR M3 arbiter for default */ +}; +typedef struct pp_atomctrl_kong_system_info pp_atomctrl_kong_system_info; + +struct pp_atomctrl_memory_info { + uint8_t memory_vendor; + uint8_t memory_type; +}; +typedef struct pp_atomctrl_memory_info pp_atomctrl_memory_info; + +#define MAX_AC_TIMING_ENTRIES 16 + +struct pp_atomctrl_memory_clock_range_table { + uint8_t num_entries; + uint8_t rsv[3]; + + uint32_t mclk[MAX_AC_TIMING_ENTRIES]; +}; +typedef struct pp_atomctrl_memory_clock_range_table pp_atomctrl_memory_clock_range_table; + +struct pp_atomctrl_voltage_table_entry { + uint16_t value; + uint32_t smio_low; +}; + +typedef struct pp_atomctrl_voltage_table_entry pp_atomctrl_voltage_table_entry; + +struct pp_atomctrl_voltage_table { + uint32_t count; + uint32_t mask_low; + uint32_t phase_delay; /* Used for ATOM_GPIO_VOLTAGE_OBJECT_V3 and later */ + pp_atomctrl_voltage_table_entry entries[PP_ATOMCTRL_MAX_VOLTAGE_ENTRIES]; +}; + +typedef struct pp_atomctrl_voltage_table pp_atomctrl_voltage_table; + +#define VBIOS_MC_REGISTER_ARRAY_SIZE 32 +#define VBIOS_MAX_AC_TIMING_ENTRIES 20 + +struct pp_atomctrl_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[VBIOS_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct pp_atomctrl_mc_reg_entry pp_atomctrl_mc_reg_entry; + +struct pp_atomctrl_mc_register_address { + uint16_t s1; + uint8_t uc_pre_reg_data; +}; + +typedef struct pp_atomctrl_mc_register_address pp_atomctrl_mc_register_address; + +struct pp_atomctrl_mc_reg_table { + uint8_t last; /* number of registers */ + uint8_t num_entries; /* number of AC timing entries */ + pp_atomctrl_mc_reg_entry mc_reg_table_entry[VBIOS_MAX_AC_TIMING_ENTRIES]; + pp_atomctrl_mc_register_address mc_reg_address[VBIOS_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct pp_atomctrl_mc_reg_table pp_atomctrl_mc_reg_table; + +struct pp_atomctrl_gpio_pin_assignment { + uint16_t us_gpio_pin_aindex; + uint8_t uc_gpio_pin_bit_shift; +}; +typedef struct pp_atomctrl_gpio_pin_assignment pp_atomctrl_gpio_pin_assignment; + +extern bool atomctrl_get_pp_assign_pin(struct pp_hwmgr *hwmgr, const uint32_t pinId, pp_atomctrl_gpio_pin_assignment *gpio_pin_assignment); +extern int atomctrl_get_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage); +extern uint32_t atomctrl_get_mpll_reference_clock(struct pp_hwmgr *hwmgr); +extern int atomctrl_get_memory_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t memory_clock, pp_atomctrl_internal_ss_info *ssInfo); +extern int atomctrl_get_engine_clock_spread_spectrum(struct pp_hwmgr *hwmgr, const uint32_t engine_clock, pp_atomctrl_internal_ss_info *ssInfo); +extern int atomctrl_initialize_mc_reg_table(struct pp_hwmgr *hwmgr, uint8_t module_index, pp_atomctrl_mc_reg_table *table); +extern int atomctrl_set_engine_dram_timings_rv770(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint32_t memory_clock); +extern uint32_t atomctrl_get_reference_clock(struct pp_hwmgr *hwmgr); +extern int atomctrl_get_memory_pll_dividers_si(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param, bool strobe_mode); +extern int atomctrl_get_engine_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); +extern int atomctrl_get_dfs_pll_dividers_vi(struct pp_hwmgr *hwmgr, uint32_t clock_value, pp_atomctrl_clock_dividers_vi *dividers); +extern bool atomctrl_is_voltage_controled_by_gpio_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode); +extern int atomctrl_get_voltage_table_v3(struct pp_hwmgr *hwmgr, uint8_t voltage_type, uint8_t voltage_mode, pp_atomctrl_voltage_table *voltage_table); +extern int atomctrl_get_memory_pll_dividers_vi(struct pp_hwmgr *hwmgr, + uint32_t clock_value, pp_atomctrl_memory_clock_param *mpll_param); +extern int atomctrl_get_engine_pll_dividers_kong(struct pp_hwmgr *hwmgr, + uint32_t clock_value, + pp_atomctrl_clock_dividers_kong *dividers); +extern int atomctrl_read_efuse(void *device, uint16_t start_index, + uint16_t end_index, uint32_t mask, uint32_t *efuse); +extern int atomctrl_calculate_voltage_evv_on_sclk(struct pp_hwmgr *hwmgr, uint8_t voltage_type, + uint32_t sclk, uint16_t virtual_voltage_Id, uint16_t *voltage, uint16_t dpm_level, bool debug); + + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h b/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h new file mode 100644 index 000000000000..42f2423cddea --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/ppevvmath.h @@ -0,0 +1,617 @@ +/* + * Copyright 2015 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. + * + */ +#include <asm/div64.h> + +#define SHIFT_AMOUNT 16 /* We multiply all original integers with 2^SHIFT_AMOUNT to get the fInt representation */ + +#define PRECISION 5 /* Change this value to change the number of decimal places in the final output - 5 is a good default */ + +#define SHIFTED_2 (2 << SHIFT_AMOUNT) +#define MAX (1 << (SHIFT_AMOUNT - 1)) - 1 /* 32767 - Might change in the future */ + +/* ------------------------------------------------------------------------------- + * NEW TYPE - fINT + * ------------------------------------------------------------------------------- + * A variable of type fInt can be accessed in 3 ways using the dot (.) operator + * fInt A; + * A.full => The full number as it is. Generally not easy to read + * A.partial.real => Only the integer portion + * A.partial.decimal => Only the fractional portion + */ +typedef union _fInt { + int full; + struct _partial { + unsigned int decimal: SHIFT_AMOUNT; /*Needs to always be unsigned*/ + int real: 32 - SHIFT_AMOUNT; + } partial; +} fInt; + +/* ------------------------------------------------------------------------------- + * Function Declarations + * ------------------------------------------------------------------------------- + */ +fInt ConvertToFraction(int); /* Use this to convert an INT to a FINT */ +fInt Convert_ULONG_ToFraction(uint32_t); /* Use this to convert an uint32_t to a FINT */ +fInt GetScaledFraction(int, int); /* Use this to convert an INT to a FINT after scaling it by a factor */ +int ConvertBackToInteger(fInt); /* Convert a FINT back to an INT that is scaled by 1000 (i.e. last 3 digits are the decimal digits) */ + +fInt fNegate(fInt); /* Returns -1 * input fInt value */ +fInt fAdd (fInt, fInt); /* Returns the sum of two fInt numbers */ +fInt fSubtract (fInt A, fInt B); /* Returns A-B - Sometimes easier than Adding negative numbers */ +fInt fMultiply (fInt, fInt); /* Returns the product of two fInt numbers */ +fInt fDivide (fInt A, fInt B); /* Returns A/B */ +fInt fGetSquare(fInt); /* Returns the square of a fInt number */ +fInt fSqrt(fInt); /* Returns the Square Root of a fInt number */ + +int uAbs(int); /* Returns the Absolute value of the Int */ +fInt fAbs(fInt); /* Returns the Absolute value of the fInt */ +int uPow(int base, int exponent); /* Returns base^exponent an INT */ + +void SolveQuadracticEqn(fInt, fInt, fInt, fInt[]); /* Returns the 2 roots via the array */ +bool Equal(fInt, fInt); /* Returns true if two fInts are equal to each other */ +bool GreaterThan(fInt A, fInt B); /* Returns true if A > B */ + +fInt fExponential(fInt exponent); /* Can be used to calculate e^exponent */ +fInt fNaturalLog(fInt value); /* Can be used to calculate ln(value) */ + +/* Fuse decoding functions + * ------------------------------------------------------------------------------------- + */ +fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength); +fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength); +fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength); + +/* Internal Support Functions - Use these ONLY for testing or adding to internal functions + * ------------------------------------------------------------------------------------- + * Some of the following functions take two INTs as their input - This is unsafe for a variety of reasons. + */ +fInt Add (int, int); /* Add two INTs and return Sum as FINT */ +fInt Multiply (int, int); /* Multiply two INTs and return Product as FINT */ +fInt Divide (int, int); /* You get the idea... */ +fInt fNegate(fInt); + +int uGetScaledDecimal (fInt); /* Internal function */ +int GetReal (fInt A); /* Internal function */ + +/* Future Additions and Incomplete Functions + * ------------------------------------------------------------------------------------- + */ +int GetRoundedValue(fInt); /* Incomplete function - Useful only when Precision is lacking */ + /* Let us say we have 2.126 but can only handle 2 decimal points. We could */ + /* either chop of 6 and keep 2.12 or use this function to get 2.13, which is more accurate */ + +/* ------------------------------------------------------------------------------------- + * TROUBLESHOOTING INFORMATION + * ------------------------------------------------------------------------------------- + * 1) ConvertToFraction - InputOutOfRangeException: Only accepts numbers smaller than MAX (default: 32767) + * 2) fAdd - OutputOutOfRangeException: Output bigger than MAX (default: 32767) + * 3) fMultiply - OutputOutOfRangeException: + * 4) fGetSquare - OutputOutOfRangeException: + * 5) fDivide - DivideByZeroException + * 6) fSqrt - NegativeSquareRootException: Input cannot be a negative number + */ + +/* ------------------------------------------------------------------------------------- + * START OF CODE + * ------------------------------------------------------------------------------------- + */ +fInt fExponential(fInt exponent) /*Can be used to calculate e^exponent*/ +{ + uint32_t i; + bool bNegated = false; + + fInt fPositiveOne = ConvertToFraction(1); + fInt fZERO = ConvertToFraction(0); + + fInt lower_bound = Divide(78, 10000); + fInt solution = fPositiveOne; /*Starting off with baseline of 1 */ + fInt error_term; + + uint32_t k_array[11] = {55452, 27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; + uint32_t expk_array[11] = {2560000, 160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; + + if (GreaterThan(fZERO, exponent)) { + exponent = fNegate(exponent); + bNegated = true; + } + + while (GreaterThan(exponent, lower_bound)) { + for (i = 0; i < 11; i++) { + if (GreaterThan(exponent, GetScaledFraction(k_array[i], 10000))) { + exponent = fSubtract(exponent, GetScaledFraction(k_array[i], 10000)); + solution = fMultiply(solution, GetScaledFraction(expk_array[i], 10000)); + } + } + } + + error_term = fAdd(fPositiveOne, exponent); + + solution = fMultiply(solution, error_term); + + if (bNegated) + solution = fDivide(fPositiveOne, solution); + + return solution; +} + +fInt fNaturalLog(fInt value) +{ + uint32_t i; + fInt upper_bound = Divide(8, 1000); + fInt fNegativeOne = ConvertToFraction(-1); + fInt solution = ConvertToFraction(0); /*Starting off with baseline of 0 */ + fInt error_term; + + uint32_t k_array[10] = {160000, 40000, 20000, 15000, 12500, 11250, 10625, 10313, 10156, 10078}; + uint32_t logk_array[10] = {27726, 13863, 6931, 4055, 2231, 1178, 606, 308, 155, 78}; + + while (GreaterThan(fAdd(value, fNegativeOne), upper_bound)) { + for (i = 0; i < 10; i++) { + if (GreaterThan(value, GetScaledFraction(k_array[i], 10000))) { + value = fDivide(value, GetScaledFraction(k_array[i], 10000)); + solution = fAdd(solution, GetScaledFraction(logk_array[i], 10000)); + } + } + } + + error_term = fAdd(fNegativeOne, value); + + return (fAdd(solution, error_term)); +} + +fInt fDecodeLinearFuse(uint32_t fuse_value, fInt f_min, fInt f_range, uint32_t bitlength) +{ + fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fInt f_decoded_value; + + f_decoded_value = fDivide(f_fuse_value, f_bit_max_value); + f_decoded_value = fMultiply(f_decoded_value, f_range); + f_decoded_value = fAdd(f_decoded_value, f_min); + + return f_decoded_value; +} + + +fInt fDecodeLogisticFuse(uint32_t fuse_value, fInt f_average, fInt f_range, uint32_t bitlength) +{ + fInt f_fuse_value = Convert_ULONG_ToFraction(fuse_value); + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fInt f_CONSTANT_NEG13 = ConvertToFraction(-13); + fInt f_CONSTANT1 = ConvertToFraction(1); + + fInt f_decoded_value; + + f_decoded_value = fSubtract(fDivide(f_bit_max_value, f_fuse_value), f_CONSTANT1); + f_decoded_value = fNaturalLog(f_decoded_value); + f_decoded_value = fMultiply(f_decoded_value, fDivide(f_range, f_CONSTANT_NEG13)); + f_decoded_value = fAdd(f_decoded_value, f_average); + + return f_decoded_value; +} + +fInt fDecodeLeakageID (uint32_t leakageID_fuse, fInt ln_max_div_min, fInt f_min, uint32_t bitlength) +{ + fInt fLeakage; + fInt f_bit_max_value = Convert_ULONG_ToFraction((uPow(2, bitlength)) - 1); + + fLeakage = fMultiply(ln_max_div_min, Convert_ULONG_ToFraction(leakageID_fuse)); + fLeakage = fDivide(fLeakage, f_bit_max_value); + fLeakage = fExponential(fLeakage); + fLeakage = fMultiply(fLeakage, f_min); + + return fLeakage; +} + +fInt ConvertToFraction(int X) /*Add all range checking here. Is it possible to make fInt a private declaration? */ +{ + fInt temp; + + if (X <= MAX) + temp.full = (X << SHIFT_AMOUNT); + else + temp.full = 0; + + return temp; +} + +fInt fNegate(fInt X) +{ + fInt CONSTANT_NEGONE = ConvertToFraction(-1); + return (fMultiply(X, CONSTANT_NEGONE)); +} + +fInt Convert_ULONG_ToFraction(uint32_t X) +{ + fInt temp; + + if (X <= MAX) + temp.full = (X << SHIFT_AMOUNT); + else + temp.full = 0; + + return temp; +} + +fInt GetScaledFraction(int X, int factor) +{ + int times_shifted, factor_shifted; + bool bNEGATED; + fInt fValue; + + times_shifted = 0; + factor_shifted = 0; + bNEGATED = false; + + if (X < 0) { + X = -1*X; + bNEGATED = true; + } + + if (factor < 0) { + factor = -1*factor; + + bNEGATED = !bNEGATED; /*If bNEGATED = true due to X < 0, this will cover the case of negative cancelling negative */ + } + + if ((X > MAX) || factor > MAX) { + if ((X/factor) <= MAX) { + while (X > MAX) { + X = X >> 1; + times_shifted++; + } + + while (factor > MAX) { + factor = factor >> 1; + factor_shifted++; + } + } else { + fValue.full = 0; + return fValue; + } + } + + if (factor == 1) + return (ConvertToFraction(X)); + + fValue = fDivide(ConvertToFraction(X * uPow(-1, bNEGATED)), ConvertToFraction(factor)); + + fValue.full = fValue.full << times_shifted; + fValue.full = fValue.full >> factor_shifted; + + return fValue; +} + +/* Addition using two fInts */ +fInt fAdd (fInt X, fInt Y) +{ + fInt Sum; + + Sum.full = X.full + Y.full; + + return Sum; +} + +/* Addition using two fInts */ +fInt fSubtract (fInt X, fInt Y) +{ + fInt Difference; + + Difference.full = X.full - Y.full; + + return Difference; +} + +bool Equal(fInt A, fInt B) +{ + if (A.full == B.full) + return true; + else + return false; +} + +bool GreaterThan(fInt A, fInt B) +{ + if (A.full > B.full) + return true; + else + return false; +} + +fInt fMultiply (fInt X, fInt Y) /* Uses 64-bit integers (int64_t) */ +{ + fInt Product; + int64_t tempProduct; + bool X_LessThanOne, Y_LessThanOne; + + X_LessThanOne = (X.partial.real == 0 && X.partial.decimal != 0 && X.full >= 0); + Y_LessThanOne = (Y.partial.real == 0 && Y.partial.decimal != 0 && Y.full >= 0); + + /*The following is for a very specific common case: Non-zero number with ONLY fractional portion*/ + /* TEMPORARILY DISABLED - CAN BE USED TO IMPROVE PRECISION + + if (X_LessThanOne && Y_LessThanOne) { + Product.full = X.full * Y.full; + return Product + }*/ + + tempProduct = ((int64_t)X.full) * ((int64_t)Y.full); /*Q(16,16)*Q(16,16) = Q(32, 32) - Might become a negative number! */ + tempProduct = tempProduct >> 16; /*Remove lagging 16 bits - Will lose some precision from decimal; */ + Product.full = (int)tempProduct; /*The int64_t will lose the leading 16 bits that were part of the integer portion */ + + return Product; +} + +fInt fDivide (fInt X, fInt Y) +{ + fInt fZERO, fQuotient; + int64_t longlongX, longlongY; + + fZERO = ConvertToFraction(0); + + if (Equal(Y, fZERO)) + return fZERO; + + longlongX = (int64_t)X.full; + longlongY = (int64_t)Y.full; + + longlongX = longlongX << 16; /*Q(16,16) -> Q(32,32) */ + + do_div(longlongX, longlongY); /*Q(32,32) divided by Q(16,16) = Q(16,16) Back to original format */ + + fQuotient.full = (int)longlongX; + return fQuotient; +} + +int ConvertBackToInteger (fInt A) /*THIS is the function that will be used to check with the Golden settings table*/ +{ + fInt fullNumber, scaledDecimal, scaledReal; + + scaledReal.full = GetReal(A) * uPow(10, PRECISION-1); /* DOUBLE CHECK THISSSS!!! */ + + scaledDecimal.full = uGetScaledDecimal(A); + + fullNumber = fAdd(scaledDecimal,scaledReal); + + return fullNumber.full; +} + +fInt fGetSquare(fInt A) +{ + return fMultiply(A,A); +} + +/* x_new = x_old - (x_old^2 - C) / (2 * x_old) */ +fInt fSqrt(fInt num) +{ + fInt F_divide_Fprime, Fprime; + fInt test; + fInt twoShifted; + int seed, counter, error; + fInt x_new, x_old, C, y; + + fInt fZERO = ConvertToFraction(0); + /* (0 > num) is the same as (num < 0), i.e., num is negative */ + if (GreaterThan(fZERO, num) || Equal(fZERO, num)) + return fZERO; + + C = num; + + if (num.partial.real > 3000) + seed = 60; + else if (num.partial.real > 1000) + seed = 30; + else if (num.partial.real > 100) + seed = 10; + else + seed = 2; + + counter = 0; + + if (Equal(num, fZERO)) /*Square Root of Zero is zero */ + return fZERO; + + twoShifted = ConvertToFraction(2); + x_new = ConvertToFraction(seed); + + do { + counter++; + + x_old.full = x_new.full; + + test = fGetSquare(x_old); /*1.75*1.75 is reverting back to 1 when shifted down */ + y = fSubtract(test, C); /*y = f(x) = x^2 - C; */ + + Fprime = fMultiply(twoShifted, x_old); + F_divide_Fprime = fDivide(y, Fprime); + + x_new = fSubtract(x_old, F_divide_Fprime); + + error = ConvertBackToInteger(x_new) - ConvertBackToInteger(x_old); + + if (counter > 20) /*20 is already way too many iterations. If we dont have an answer by then, we never will*/ + return x_new; + + } while (uAbs(error) > 0); + + return (x_new); +} + +void SolveQuadracticEqn(fInt A, fInt B, fInt C, fInt Roots[]) +{ + fInt* pRoots = &Roots[0]; + fInt temp, root_first, root_second; + fInt f_CONSTANT10, f_CONSTANT100; + + f_CONSTANT100 = ConvertToFraction(100); + f_CONSTANT10 = ConvertToFraction(10); + + while(GreaterThan(A, f_CONSTANT100) || GreaterThan(B, f_CONSTANT100) || GreaterThan(C, f_CONSTANT100)) { + A = fDivide(A, f_CONSTANT10); + B = fDivide(B, f_CONSTANT10); + C = fDivide(C, f_CONSTANT10); + } + + temp = fMultiply(ConvertToFraction(4), A); /* root = 4*A */ + temp = fMultiply(temp, C); /* root = 4*A*C */ + temp = fSubtract(fGetSquare(B), temp); /* root = b^2 - 4AC */ + temp = fSqrt(temp); /*root = Sqrt (b^2 - 4AC); */ + + root_first = fSubtract(fNegate(B), temp); /* b - Sqrt(b^2 - 4AC) */ + root_second = fAdd(fNegate(B), temp); /* b + Sqrt(b^2 - 4AC) */ + + root_first = fDivide(root_first, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ + root_first = fDivide(root_first, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ + + root_second = fDivide(root_second, ConvertToFraction(2)); /* [b +- Sqrt(b^2 - 4AC)]/[2] */ + root_second = fDivide(root_second, A); /*[b +- Sqrt(b^2 - 4AC)]/[2*A] */ + + *(pRoots + 0) = root_first; + *(pRoots + 1) = root_second; +} + +/* ----------------------------------------------------------------------------- + * SUPPORT FUNCTIONS + * ----------------------------------------------------------------------------- + */ + +/* Addition using two normal ints - Temporary - Use only for testing purposes?. */ +fInt Add (int X, int Y) +{ + fInt A, B, Sum; + + A.full = (X << SHIFT_AMOUNT); + B.full = (Y << SHIFT_AMOUNT); + + Sum.full = A.full + B.full; + + return Sum; +} + +/* Conversion Functions */ +int GetReal (fInt A) +{ + return (A.full >> SHIFT_AMOUNT); +} + +/* Temporarily Disabled */ +int GetRoundedValue(fInt A) /*For now, round the 3rd decimal place */ +{ + /* ROUNDING TEMPORARLY DISABLED + int temp = A.full; + + int decimal_cutoff, decimal_mask = 0x000001FF; + + decimal_cutoff = temp & decimal_mask; + + + if (decimal_cutoff > 0x147) { + temp += 673; + }*/ + + return ConvertBackToInteger(A)/10000; /*Temporary - in case this was used somewhere else */ +} + +fInt Multiply (int X, int Y) +{ + fInt A, B, Product; + + A.full = X << SHIFT_AMOUNT; + B.full = Y << SHIFT_AMOUNT; + + Product = fMultiply(A, B); + + return Product; +} +fInt Divide (int X, int Y) +{ + fInt A, B, Quotient; + + A.full = X << SHIFT_AMOUNT; + B.full = Y << SHIFT_AMOUNT; + + Quotient = fDivide(A, B); + + return Quotient; +} + +int uGetScaledDecimal (fInt A) /*Converts the fractional portion to whole integers - Costly function */ +{ + int dec[PRECISION]; + int i, scaledDecimal = 0, tmp = A.partial.decimal; + + for (i = 0; i < PRECISION; i++) { + dec[i] = tmp / (1 << SHIFT_AMOUNT); + + tmp = tmp - ((1 << SHIFT_AMOUNT)*dec[i]); + + tmp *= 10; + + scaledDecimal = scaledDecimal + dec[i]*uPow(10, PRECISION - 1 -i); + } + + return scaledDecimal; +} + +int uPow(int base, int power) +{ + if (power == 0) + return 1; + else + return (base)*uPow(base, power - 1); +} + +fInt fAbs(fInt A) +{ + if (A.partial.real < 0) + return (fMultiply(A, ConvertToFraction(-1))); + else + return A; +} + +int uAbs(int X) +{ + if (X < 0) + return (X * -1); + else + return X; +} + +fInt fRoundUpByStepSize(fInt A, fInt fStepSize, bool error_term) +{ + fInt solution; + + solution = fDivide(A, fStepSize); + solution.partial.decimal = 0; /*All fractional digits changes to 0 */ + + if (error_term) + solution.partial.real += 1; /*Error term of 1 added */ + + solution = fMultiply(solution, fStepSize); + solution = fAdd(solution, fStepSize); + + return solution; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c new file mode 100644 index 000000000000..186496a34cbe --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.c @@ -0,0 +1,64 @@ +/* + * Copyright 2015 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. + * + */ + +#include <linux/types.h> +#include "atom-types.h" +#include "atombios.h" +#include "pppcielanes.h" + +/** \file + * Functions related to PCIe lane changes. + */ + +/* For converting from number of lanes to lane bits. */ +static const unsigned char pp_r600_encode_lanes[] = { + 0, /* 0 Not Supported */ + 1, /* 1 Lane */ + 2, /* 2 Lanes */ + 0, /* 3 Not Supported */ + 3, /* 4 Lanes */ + 0, /* 5 Not Supported */ + 0, /* 6 Not Supported */ + 0, /* 7 Not Supported */ + 4, /* 8 Lanes */ + 0, /* 9 Not Supported */ + 0, /* 10 Not Supported */ + 0, /* 11 Not Supported */ + 5, /* 12 Lanes (Not actually supported) */ + 0, /* 13 Not Supported */ + 0, /* 14 Not Supported */ + 0, /* 15 Not Supported */ + 6 /* 16 Lanes */ +}; + +static const unsigned char pp_r600_decoded_lanes[8] = { 16, 1, 2, 4, 8, 12, 16, }; + +uint8_t encode_pcie_lane_width(uint32_t num_lanes) +{ + return pp_r600_encode_lanes[num_lanes]; +} + +uint8_t decode_pcie_lane_width(uint32_t num_lanes) +{ + return pp_r600_decoded_lanes[num_lanes]; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h new file mode 100644 index 000000000000..70b163b35570 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/pppcielanes.h @@ -0,0 +1,31 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef PP_PCIELANES_H +#define PP_PCIELANES_H + +extern uint8_t encode_pcie_lane_width(uint32_t num_lanes); +extern uint8_t decode_pcie_lane_width(uint32_t num_lanes); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c new file mode 100644 index 000000000000..1d385f473776 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.c @@ -0,0 +1,1679 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> + +#include "processpptables.h" +#include <atom-types.h> +#include <atombios.h> +#include "pp_debug.h" +#include "pptable.h" +#include "power_state.h" +#include "hwmgr.h" +#include "hardwaremanager.h" + + +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2 12 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3 14 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4 16 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5 18 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6 20 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7 22 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8 24 +#define SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V9 26 + +#define NUM_BITS_CLOCK_INFO_ARRAY_INDEX 6 + +static uint16_t get_vce_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t vce_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V2) + vce_table_offset = le16_to_cpu(extended_header->usVCETableOffset); + } + } + + return vce_table_offset; +} + +static uint16_t get_vce_clock_info_array_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + + return 0; +} + +static uint16_t get_vce_clock_info_array_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, + powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const VCEClockInfoArray *p = (const VCEClockInfoArray *) + (((unsigned long) powerplay_table) + table_offset); + table_size = sizeof(uint8_t) + p->ucNumEntries * sizeof(VCEClockInfo); + } + + return table_size; +} + +static uint16_t get_vce_clock_voltage_limit_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_info_array_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + get_vce_clock_info_array_size(hwmgr, + powerplay_table); + + return 0; +} + +static uint16_t get_vce_clock_voltage_limit_table_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *)(((unsigned long) powerplay_table) + table_offset); + + table_size = sizeof(uint8_t) + ptable->numEntries * sizeof(ATOM_PPLIB_VCE_Clock_Voltage_Limit_Record); + } + return table_size; +} + +static uint16_t get_vce_state_table_offset(struct pp_hwmgr *hwmgr, const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + + if (table_offset > 0) + return table_offset + get_vce_clock_voltage_limit_table_size(hwmgr, powerplay_table); + + return 0; +} + +static const ATOM_PPLIB_VCE_State_Table *get_vce_state_table( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_vce_state_table_offset(hwmgr, powerplay_table); + + if (table_offset > 0) + return (const ATOM_PPLIB_VCE_State_Table *)(((unsigned long) powerplay_table) + table_offset); + + return NULL; +} + +static uint16_t get_uvd_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t uvd_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V3) + uvd_table_offset = le16_to_cpu(extended_header->usUVDTableOffset); + } + } + return uvd_table_offset; +} + +static uint16_t get_uvd_clock_info_array_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + return 0; +} + +static uint16_t get_uvd_clock_info_array_size(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, + powerplay_table); + uint16_t table_size = 0; + + if (table_offset > 0) { + const UVDClockInfoArray *p = (const UVDClockInfoArray *) + (((unsigned long) powerplay_table) + + table_offset); + table_size = sizeof(UCHAR) + + p->ucNumEntries * sizeof(UVDClockInfo); + } + + return table_size; +} + +static uint16_t get_uvd_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_uvd_clock_info_array_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + + get_uvd_clock_info_array_size(hwmgr, powerplay_table); + + return 0; +} + +static uint16_t get_samu_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t samu_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *extended_header = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V4) + samu_table_offset = le16_to_cpu(extended_header->usSAMUTableOffset); + } + } + + return samu_table_offset; +} + +static uint16_t get_samu_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t table_offset = get_samu_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) + return table_offset + 1; + + return 0; +} + +static uint16_t get_acp_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t acp_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V6) + acp_table_offset = le16_to_cpu(pExtendedHeader->usACPTableOffset); + } + } + + return acp_table_offset; +} + +static uint16_t get_acp_clock_voltage_limit_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t tableOffset = get_acp_table_offset(hwmgr, powerplay_table); + + if (tableOffset > 0) + return tableOffset + 1; + + return 0; +} + +static uint16_t get_cacp_tdp_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t cacTdpTableOffset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V7) + cacTdpTableOffset = le16_to_cpu(pExtendedHeader->usPowerTuneTableOffset); + } + } + + return cacTdpTableOffset; +} + +static int get_cac_tdp_table(struct pp_hwmgr *hwmgr, + struct phm_cac_tdp_table **ptable, + const ATOM_PowerTune_Table *table, + uint16_t us_maximum_power_delivery_limit) +{ + unsigned long table_size; + struct phm_cac_tdp_table *tdp_table; + + table_size = sizeof(unsigned long) + sizeof(struct phm_cac_tdp_table); + + tdp_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == tdp_table) + return -ENOMEM; + + tdp_table->usTDP = le16_to_cpu(table->usTDP); + tdp_table->usConfigurableTDP = le16_to_cpu(table->usConfigurableTDP); + tdp_table->usTDC = le16_to_cpu(table->usTDC); + tdp_table->usBatteryPowerLimit = le16_to_cpu(table->usBatteryPowerLimit); + tdp_table->usSmallPowerLimit = le16_to_cpu(table->usSmallPowerLimit); + tdp_table->usLowCACLeakage = le16_to_cpu(table->usLowCACLeakage); + tdp_table->usHighCACLeakage = le16_to_cpu(table->usHighCACLeakage); + tdp_table->usMaximumPowerDeliveryLimit = us_maximum_power_delivery_limit; + + *ptable = tdp_table; + + return 0; +} + +static uint16_t get_sclk_vdd_gfx_table_offset(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t sclk_vdd_gfx_table_offset = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) { + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + if (powerplay_table3->usExtendendedHeaderOffset > 0) { + const ATOM_PPLIB_EXTENDEDHEADER *pExtendedHeader = + (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table3) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + if (le16_to_cpu(pExtendedHeader->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V8) + sclk_vdd_gfx_table_offset = + le16_to_cpu(pExtendedHeader->usSclkVddgfxTableOffset); + } + } + + return sclk_vdd_gfx_table_offset; +} + +static uint16_t get_sclk_vdd_gfx_clock_voltage_dependency_table_offset( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + uint16_t tableOffset = get_sclk_vdd_gfx_table_offset(hwmgr, powerplay_table); + + if (tableOffset > 0) + return tableOffset; + + return 0; +} + + +static int get_clock_voltage_dependency_table(struct pp_hwmgr *hwmgr, + struct phm_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_Clock_Voltage_Dependency_Table *table) +{ + + unsigned long table_size, i; + struct phm_clock_voltage_dependency_table *dep_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_clock_voltage_dependency_table) + * table->ucNumEntries; + + dep_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == dep_table) + return -ENOMEM; + + dep_table->count = (unsigned long)table->ucNumEntries; + + for (i = 0; i < dep_table->count; i++) { + dep_table->entries[i].clk = + ((unsigned long)table->entries[i].ucClockHigh << 16) | + le16_to_cpu(table->entries[i].usClockLow); + dep_table->entries[i].v = + (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + } + + *ptable = dep_table; + + return 0; +} + +static int get_valid_clk(struct pp_hwmgr *hwmgr, + struct phm_clock_array **ptable, + const struct phm_clock_voltage_dependency_table *table) +{ + unsigned long table_size, i; + struct phm_clock_array *clock_table; + + table_size = sizeof(unsigned long) + sizeof(unsigned long) * table->count; + clock_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == clock_table) + return -ENOMEM; + + clock_table->count = (unsigned long)table->count; + + for (i = 0; i < clock_table->count; i++) + clock_table->values[i] = (unsigned long)table->entries[i].clk; + + *ptable = clock_table; + + return 0; +} + +static int get_clock_voltage_limit(struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + const ATOM_PPLIB_Clock_Voltage_Limit_Table *table) +{ + limits->sclk = ((unsigned long)table->entries[0].ucSclkHigh << 16) | + le16_to_cpu(table->entries[0].usSclkLow); + limits->mclk = ((unsigned long)table->entries[0].ucMclkHigh << 16) | + le16_to_cpu(table->entries[0].usMclkLow); + limits->vddc = (unsigned long)le16_to_cpu(table->entries[0].usVddc); + limits->vddci = (unsigned long)le16_to_cpu(table->entries[0].usVddci); + + return 0; +} + + +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable, + enum phm_platform_caps cap) +{ + if (enable) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + +static int set_platform_caps(struct pp_hwmgr *hwmgr, + unsigned long powerplay_caps) +{ + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L0s), + PHM_PlatformCaps_EnableASPML0s + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_ASPM_L1), + PHM_PlatformCaps_EnableASPML1 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACKBIAS), + PHM_PlatformCaps_EnableBackbias + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY), + PHM_PlatformCaps_GeminiPrimary + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_STEPVDDC), + PHM_PlatformCaps_StepVddc + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VOLTAGECONTROL), + PHM_PlatformCaps_EnableVoltageControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL), + PHM_PlatformCaps_EnableSideportControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1), + PHM_PlatformCaps_TurnOffPll_ASPML1 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_HTLINKCONTROL), + PHM_PlatformCaps_EnableHTLinkControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_MVDDCONTROL), + PHM_PlatformCaps_EnableMVDDControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VDDCI_CONTROL), + PHM_PlatformCaps_ControlVDDCI + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REGULATOR_HOT), + PHM_PlatformCaps_RegulatorHot + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_GOTO_BOOT_ON_ALERT), + PHM_PlatformCaps_BootStateOnAlert + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DONT_WAIT_FOR_VBLANK_ON_ALERT), + PHM_PlatformCaps_DontWaitForVBlankOnAlert + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_NEW_CAC_VOLTAGE), + PHM_PlatformCaps_NewCACVoltage + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_REVERT_GPIO5_POLARITY), + PHM_PlatformCaps_RevertGPIO5Polarity + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17), + PHM_PlatformCaps_Thermal2GPIO17 + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_VRHOT_GPIO_CONFIGURABLE), + PHM_PlatformCaps_VRHotGPIOConfigurable + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_TEMP_INVERSION), + PHM_PlatformCaps_TempInversion + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_EVV), + PHM_PlatformCaps_EVV + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), + PHM_PlatformCaps_LoadPostProductionFirmware + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_PP_PLATFORM_CAP_DISABLE_USING_ACTUAL_TEMPERATURE_FOR_POWER_CALC), + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc + ); + + return 0; +} + +static PP_StateClassificationFlags make_classification_flags( + struct pp_hwmgr *hwmgr, + USHORT classification, + USHORT classification2) +{ + PP_StateClassificationFlags result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & + ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_3DPERFORMANCE) + result |= PP_StateClassificationFlag_3DPerformance; + + + if (classification & ATOM_PPLIB_CLASSIFICATION_OVERDRIVETEMPLATE) + result |= PP_StateClassificationFlag_ACOverdriveTemplate; + + if (classification & ATOM_PPLIB_CLASSIFICATION_UVDSTATE) + result |= PP_StateClassificationFlag_Uvd; + + if (classification & ATOM_PPLIB_CLASSIFICATION_HDSTATE) + result |= PP_StateClassificationFlag_UvdHD; + + if (classification & ATOM_PPLIB_CLASSIFICATION_SDSTATE) + result |= PP_StateClassificationFlag_UvdSD; + + if (classification & ATOM_PPLIB_CLASSIFICATION_HD2STATE) + result |= PP_StateClassificationFlag_HD2; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_ULV) + result |= PP_StateClassificationFlag_ULV; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_MVC) + result |= PP_StateClassificationFlag_UvdMVC; + + return result; +} + +static int init_non_clock_fields(struct pp_hwmgr *hwmgr, + struct pp_power_state *ps, + uint8_t version, + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info) { + unsigned long rrr_index; + unsigned long tmp; + + ps->classification.ui_label = (le16_to_cpu(pnon_clock_info->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + ps->classification.flags = make_classification_flags(hwmgr, + le16_to_cpu(pnon_clock_info->usClassification), + le16_to_cpu(pnon_clock_info->usClassification2)); + + ps->classification.temporary_state = false; + ps->classification.to_be_deleted = false; + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SINGLE_DISPLAY_ONLY; + + ps->validation.singleDisplayOnly = (0 != tmp); + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_DISALLOW_ON_DC; + + ps->validation.disallowOnDC = (0 != tmp); + + ps->pcie.lanes = ((le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_PCIE_LINK_WIDTH_MASK) >> + ATOM_PPLIB_PCIE_LINK_WIDTH_SHIFT) + 1; + + ps->pcie.lanes = 0; + + ps->display.disableFrameModulation = false; + + rrr_index = (le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK) >> + ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT; + + if (rrr_index != ATOM_PPLIB_LIMITED_REFRESHRATE_UNLIMITED) { + static const uint8_t look_up[(ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_MASK >> ATOM_PPLIB_LIMITED_REFRESHRATE_VALUE_SHIFT) + 1] = \ + { 0, 50, 0 }; + + ps->display.refreshrateSource = PP_RefreshrateSource_Explicit; + ps->display.explicitRefreshrate = look_up[rrr_index]; + ps->display.limitRefreshrate = true; + + if (ps->display.explicitRefreshrate == 0) + ps->display.limitRefreshrate = false; + } else + ps->display.limitRefreshrate = false; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_ENABLE_VARIBRIGHT; + + ps->display.enableVariBright = (0 != tmp); + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SWSTATE_MEMORY_DLL_OFF; + + ps->memory.dllOff = (0 != tmp); + + ps->memory.m3arb = (uint8_t)(le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_M3ARB_MASK) >> ATOM_PPLIB_M3ARB_SHIFT; + + ps->temperatures.min = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * + pnon_clock_info->ucMinTemperature; + + ps->temperatures.max = PP_TEMPERATURE_UNITS_PER_CENTIGRADES * + pnon_clock_info->ucMaxTemperature; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SOFTWARE_DISABLE_LOADBALANCING; + + ps->software.disableLoadBalancing = tmp; + + tmp = le32_to_cpu(pnon_clock_info->ulCapsAndSettings) & + ATOM_PPLIB_SOFTWARE_ENABLE_SLEEP_FOR_TIMESTAMPS; + + ps->software.enableSleepForTimestamps = (0 != tmp); + + ps->validation.supportedPowerLevels = pnon_clock_info->ucRequiredPower; + + if (ATOM_PPLIB_NONCLOCKINFO_VER1 < version) { + ps->uvd_clocks.VCLK = pnon_clock_info->ulVCLK; + ps->uvd_clocks.DCLK = pnon_clock_info->ulDCLK; + } else { + ps->uvd_clocks.VCLK = 0; + ps->uvd_clocks.DCLK = 0; + } + + return 0; +} + +static ULONG size_of_entry_v2(ULONG num_dpm_levels) +{ + return (sizeof(UCHAR) + sizeof(UCHAR) + + (num_dpm_levels * sizeof(UCHAR))); +} + +static const ATOM_PPLIB_STATE_V2 *get_state_entry_v2( + const StateArray * pstate_arrays, + ULONG entry_index) +{ + ULONG i; + const ATOM_PPLIB_STATE_V2 *pstate; + + pstate = pstate_arrays->states; + if (entry_index <= pstate_arrays->ucNumEntries) { + for (i = 0; i < entry_index; i++) + pstate = (ATOM_PPLIB_STATE_V2 *)( + (unsigned long)pstate + + size_of_entry_v2(pstate->ucNumDPMLevels)); + } + return pstate; +} + + +static const ATOM_PPLIB_POWERPLAYTABLE *get_powerplay_table( + struct pp_hwmgr *hwmgr) +{ + const void *table_addr = NULL; + uint8_t frev, crev; + uint16_t size; + + table_addr = cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, PowerPlayInfo), + &size, &frev, &crev); + + hwmgr->soft_pp_table = table_addr; + + return (const ATOM_PPLIB_POWERPLAYTABLE *)table_addr; +} + + +int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, + unsigned long *num_of_entries) +{ + const StateArray *pstate_arrays; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + + if (powerplay_table == NULL) + return -1; + + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + *num_of_entries = (unsigned long)(pstate_arrays->ucNumEntries); + } else + *num_of_entries = (unsigned long)(powerplay_table->ucNumStates); + + return 0; +} + +int pp_tables_get_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, + struct pp_power_state *ps, + pp_tables_hw_clock_info_callback func) +{ + int i; + const StateArray *pstate_arrays; + const ATOM_PPLIB_STATE_V2 *pstate_entry_v2; + const ATOM_PPLIB_NONCLOCK_INFO *pnon_clock_info; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + int result = 0; + int res = 0; + + const ClockInfoArray *pclock_arrays; + + const NonClockInfoArray *pnon_clock_arrays; + + const ATOM_PPLIB_STATE *pstate_entry; + + if (powerplay_table == NULL) + return -1; + + ps->classification.bios_index = entry_index; + + if (powerplay_table->sHeader.ucTableFormatRevision >= 6) { + pstate_arrays = (StateArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + if (entry_index > pstate_arrays->ucNumEntries) + return -1; + + pstate_entry_v2 = get_state_entry_v2(pstate_arrays, entry_index); + pclock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usClockInfoArrayOffset)); + + pnon_clock_arrays = (NonClockInfoArray *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset)); + + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)(pnon_clock_arrays->nonClockInfo) + + (pstate_entry_v2->nonClockInfoIndex * pnon_clock_arrays->ucEntrySize)); + + result = init_non_clock_fields(hwmgr, ps, pnon_clock_arrays->ucEntrySize, pnon_clock_info); + + for (i = 0; i < pstate_entry_v2->ucNumDPMLevels; i++) { + const void *pclock_info = (const void *)( + (unsigned long)(pclock_arrays->clockInfo) + + (pstate_entry_v2->clockInfoIndex[i] * pclock_arrays->ucEntrySize)); + res = func(hwmgr, &ps->hardware, i, pclock_info); + if ((0 == result) && (0 != res)) + result = res; + } + } else { + if (entry_index > powerplay_table->ucNumStates) + return -1; + + pstate_entry = (ATOM_PPLIB_STATE *)((unsigned long)powerplay_table + powerplay_table->usStateArrayOffset + + entry_index * powerplay_table->ucStateEntrySize); + + pnon_clock_info = (ATOM_PPLIB_NONCLOCK_INFO *)((unsigned long)powerplay_table + + le16_to_cpu(powerplay_table->usNonClockInfoArrayOffset) + + pstate_entry->ucNonClockStateIndex * + powerplay_table->ucNonClockSize); + + result = init_non_clock_fields(hwmgr, ps, + powerplay_table->ucNonClockSize, + pnon_clock_info); + + for (i = 0; i < powerplay_table->ucStateEntrySize-1; i++) { + const void *pclock_info = (const void *)((unsigned long)powerplay_table + + le16_to_cpu(powerplay_table->usClockInfoArrayOffset) + + pstate_entry->ucClockStateIndices[i] * + powerplay_table->ucClockInfoSize); + + int res = func(hwmgr, &ps->hardware, i, pclock_info); + + if ((0 == result) && (0 != res)) + result = res; + } + } + + if ((0 == result) && + (0 != (ps->classification.flags & PP_StateClassificationFlag_Boot))) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(ps->hardware)); + + return result; +} + + + +static int init_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table +) +{ + return 0; +} + + +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + return 0; +} + +static int init_overdrive_limits_V1_4(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, + const ATOM_FIRMWARE_INFO_V1_4 *fw_info) +{ + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le32_to_cpu(fw_info->ulASICMaxEngineClock); + + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le32_to_cpu(fw_info->ulASICMaxMemoryClock); + + hwmgr->platform_descriptor.maxOverdriveVDDC = + le32_to_cpu(fw_info->ul3DAccelerationEngineClock) & 0x7FF; + + hwmgr->platform_descriptor.minOverdriveVDDC = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + + hwmgr->platform_descriptor.maxOverdriveVDDC = + le16_to_cpu(fw_info->usBootUpVDDCVoltage); + + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + return 0; +} + +static int init_overdrive_limits_V2_1(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table, + const ATOM_FIRMWARE_INFO_V2_1 *fw_info) +{ + const ATOM_PPLIB_POWERPLAYTABLE3 *powerplay_table3; + const ATOM_PPLIB_EXTENDEDHEADER *header; + + if (le16_to_cpu(powerplay_table->usTableSize) < + sizeof(ATOM_PPLIB_POWERPLAYTABLE3)) + return 0; + + powerplay_table3 = (const ATOM_PPLIB_POWERPLAYTABLE3 *)powerplay_table; + + if (0 == powerplay_table3->usExtendendedHeaderOffset) + return 0; + + header = (ATOM_PPLIB_EXTENDEDHEADER *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table3->usExtendendedHeaderOffset)); + + hwmgr->platform_descriptor.overdriveLimit.engineClock = le32_to_cpu(header->ulMaxEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = le32_to_cpu(header->ulMaxMemoryClock); + + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + return 0; +} + +static int init_overdrive_limits(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + int result; + uint8_t frev, crev; + uint16_t size; + + const ATOM_COMMON_TABLE_HEADER *fw_info = NULL; + + hwmgr->platform_descriptor.overdriveLimit.engineClock = 0; + hwmgr->platform_descriptor.overdriveLimit.memoryClock = 0; + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + + /* We assume here that fw_info is unchanged if this call fails.*/ + fw_info = cgs_atom_get_data_table(hwmgr->device, + GetIndexIntoMasterTable(DATA, FirmwareInfo), + &size, &frev, &crev); + + if ((fw_info->ucTableFormatRevision == 1) + && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V1_4))) + result = init_overdrive_limits_V1_4(hwmgr, + powerplay_table, + (const ATOM_FIRMWARE_INFO_V1_4 *)fw_info); + + else if ((fw_info->ucTableFormatRevision == 2) + && (fw_info->usStructureSize >= sizeof(ATOM_FIRMWARE_INFO_V2_1))) + result = init_overdrive_limits_V2_1(hwmgr, + powerplay_table, + (const ATOM_FIRMWARE_INFO_V2_1 *)fw_info); + + if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 + && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0 + && !phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_OverdriveDisabledByPowerBudget)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ACOverdriveSupport); + + return result; +} + +static int get_uvd_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_uvd_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *table, + const UVDClockInfoArray *array) +{ + unsigned long table_size, i; + struct phm_uvd_clock_voltage_dependency_table *uvd_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_uvd_clock_voltage_dependency_table) * + table->numEntries; + + uvd_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == uvd_table) + return -ENOMEM; + + uvd_table->count = table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + const UVDClockInfo *entry = + &array->entries[table->entries[i].ucUVDClockInfoIndex]; + uvd_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + uvd_table->entries[i].vclk = ((unsigned long)entry->ucVClkHigh << 16) + | le16_to_cpu(entry->usVClkLow); + uvd_table->entries[i].dclk = ((unsigned long)entry->ucDClkHigh << 16) + | le16_to_cpu(entry->usDClkLow); + } + + *ptable = uvd_table; + + return 0; +} + +static int get_vce_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_vce_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table, + const VCEClockInfoArray *array) +{ + unsigned long table_size, i; + struct phm_vce_clock_voltage_dependency_table *vce_table = NULL; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_vce_clock_voltage_dependency_table) + * table->numEntries; + + vce_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == vce_table) + return -ENOMEM; + + vce_table->count = table->numEntries; + for (i = 0; i < table->numEntries; i++) { + const VCEClockInfo *entry = &array->entries[table->entries[i].ucVCEClockInfoIndex]; + + vce_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + vce_table->entries[i].evclk = ((unsigned long)entry->ucEVClkHigh << 16) + | le16_to_cpu(entry->usEVClkLow); + vce_table->entries[i].ecclk = ((unsigned long)entry->ucECClkHigh << 16) + | le16_to_cpu(entry->usECClkLow); + } + + *ptable = vce_table; + + return 0; +} + +static int get_samu_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_samu_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *table) +{ + unsigned long table_size, i; + struct phm_samu_clock_voltage_dependency_table *samu_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_samu_clock_voltage_dependency_table) * + table->numEntries; + + samu_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == samu_table) + return -ENOMEM; + + samu_table->count = table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + samu_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + samu_table->entries[i].samclk = ((unsigned long)table->entries[i].ucSAMClockHigh << 16) + | le16_to_cpu(table->entries[i].usSAMClockLow); + } + + *ptable = samu_table; + + return 0; +} + +static int get_acp_clock_voltage_limit_table(struct pp_hwmgr *hwmgr, + struct phm_acp_clock_voltage_dependency_table **ptable, + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *table) +{ + unsigned table_size, i; + struct phm_acp_clock_voltage_dependency_table *acp_table; + + table_size = sizeof(unsigned long) + + sizeof(struct phm_acp_clock_voltage_dependency_table) * + table->numEntries; + + acp_table = kzalloc(table_size, GFP_KERNEL); + if (NULL == acp_table) + return -ENOMEM; + + acp_table->count = (unsigned long)table->numEntries; + + for (i = 0; i < table->numEntries; i++) { + acp_table->entries[i].v = (unsigned long)le16_to_cpu(table->entries[i].usVoltage); + acp_table->entries[i].acpclk = ((unsigned long)table->entries[i].ucACPClockHigh << 16) + | le16_to_cpu(table->entries[i].usACPClockLow); + } + + *ptable = acp_table; + + return 0; +} + +static int init_clock_voltage_dependency(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + ATOM_PPLIB_Clock_Voltage_Dependency_Table *table; + ATOM_PPLIB_Clock_Voltage_Limit_Table *limit_table; + int result = 0; + + uint16_t vce_clock_info_array_offset; + uint16_t uvd_clock_info_array_offset; + uint16_t table_offset; + + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; + hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; + hwmgr->dyn_state.ppm_parameter_table = NULL; + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; + + vce_clock_info_array_offset = get_vce_clock_info_array_offset( + hwmgr, powerplay_table); + table_offset = get_vce_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + if (vce_clock_info_array_offset > 0 && table_offset > 0) { + const VCEClockInfoArray *array = (const VCEClockInfoArray *) + (((unsigned long) powerplay_table) + + vce_clock_info_array_offset); + const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *table = + (const ATOM_PPLIB_VCE_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_vce_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.vce_clock_voltage_dependency_table, + table, array); + } + + uvd_clock_info_array_offset = get_uvd_clock_info_array_offset(hwmgr, powerplay_table); + table_offset = get_uvd_clock_voltage_limit_table_offset(hwmgr, powerplay_table); + + if (uvd_clock_info_array_offset > 0 && table_offset > 0) { + const UVDClockInfoArray *array = (const UVDClockInfoArray *) + (((unsigned long) powerplay_table) + + uvd_clock_info_array_offset); + const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_UVD_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_uvd_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.uvd_clock_voltage_dependency_table, ptable, array); + } + + table_offset = get_samu_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_SAMClk_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_samu_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.samu_clock_voltage_dependency_table, ptable); + } + + table_offset = get_acp_clock_voltage_limit_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *ptable = + (const ATOM_PPLIB_ACPClk_Voltage_Limit_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_acp_clock_voltage_limit_table(hwmgr, + &hwmgr->dyn_state.acp_clock_voltage_dependency_table, ptable); + } + + table_offset = get_cacp_tdp_table_offset(hwmgr, powerplay_table); + if (table_offset > 0) { + UCHAR rev_id = *(UCHAR *)(((unsigned long)powerplay_table) + table_offset); + + if (rev_id > 0) { + const ATOM_PPLIB_POWERTUNE_Table_V1 *tune_table = + (const ATOM_PPLIB_POWERTUNE_Table_V1 *) + (((unsigned long) powerplay_table) + table_offset); + result = get_cac_tdp_table(hwmgr, &hwmgr->dyn_state.cac_dtp_table, + &tune_table->power_tune_table, + le16_to_cpu(tune_table->usMaximumPowerDeliveryLimit)); + hwmgr->dyn_state.cac_dtp_table->usDefaultTargetOperatingTemp = + le16_to_cpu(tune_table->usTjMax); + } else { + const ATOM_PPLIB_POWERTUNE_Table *tune_table = + (const ATOM_PPLIB_POWERTUNE_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_cac_tdp_table(hwmgr, + &hwmgr->dyn_state.cac_dtp_table, + &tune_table->power_tune_table, 255); + } + } + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; + if (0 != powerplay_table4->usVddcDependencyOnSCLKOffset) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + powerplay_table4->usVddcDependencyOnSCLKOffset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddc_dependency_on_sclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usVddciDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + powerplay_table4->usVddciDependencyOnMCLKOffset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddci_dependency_on_mclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usVddcDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + powerplay_table4->usVddcDependencyOnMCLKOffset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vddc_dependency_on_mclk, table); + } + + if (result == 0 && (0 != powerplay_table4->usMaxClockVoltageOnDCOffset)) { + limit_table = (ATOM_PPLIB_Clock_Voltage_Limit_Table *) + (((unsigned long) powerplay_table4) + + powerplay_table4->usMaxClockVoltageOnDCOffset); + result = get_clock_voltage_limit(hwmgr, + &hwmgr->dyn_state.max_clock_voltage_on_dc, limit_table); + } + + if (result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) && + (0 != hwmgr->dyn_state.vddc_dependency_on_mclk->count)) + result = get_valid_clk(hwmgr, &hwmgr->dyn_state.valid_mclk_values, + hwmgr->dyn_state.vddc_dependency_on_mclk); + + if(result == 0 && (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) && + (0 != hwmgr->dyn_state.vddc_dependency_on_sclk->count)) + result = get_valid_clk(hwmgr, + &hwmgr->dyn_state.valid_sclk_values, + hwmgr->dyn_state.vddc_dependency_on_sclk); + + if (result == 0 && (0 != powerplay_table4->usMvddDependencyOnMCLKOffset)) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table4) + + powerplay_table4->usMvddDependencyOnMCLKOffset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.mvdd_dependency_on_mclk, table); + } + } + + table_offset = get_sclk_vdd_gfx_clock_voltage_dependency_table_offset(hwmgr, + powerplay_table); + + if (table_offset > 0) { + table = (ATOM_PPLIB_Clock_Voltage_Dependency_Table *) + (((unsigned long) powerplay_table) + table_offset); + result = get_clock_voltage_dependency_table(hwmgr, + &hwmgr->dyn_state.vdd_gfx_dependency_on_sclk, table); + } + + return result; +} + +static int get_cac_leakage_table(struct pp_hwmgr *hwmgr, + struct phm_cac_leakage_table **ptable, + const ATOM_PPLIB_CAC_Leakage_Table *table) +{ + struct phm_cac_leakage_table *cac_leakage_table; + unsigned long table_size, i; + + table_size = sizeof(ULONG) + + (sizeof(struct phm_cac_leakage_table) * table->ucNumEntries); + + cac_leakage_table = kzalloc(table_size, GFP_KERNEL); + + cac_leakage_table->count = (ULONG)table->ucNumEntries; + + for (i = 0; i < cac_leakage_table->count; i++) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EVV)) { + cac_leakage_table->entries[i].Vddc1 = le16_to_cpu(table->entries[i].usVddc1); + cac_leakage_table->entries[i].Vddc2 = le16_to_cpu(table->entries[i].usVddc2); + cac_leakage_table->entries[i].Vddc3 = le16_to_cpu(table->entries[i].usVddc3); + } else { + cac_leakage_table->entries[i].Vddc = le16_to_cpu(table->entries[i].usVddc); + cac_leakage_table->entries[i].Leakage = le32_to_cpu(table->entries[i].ulLeakageValue); + } + } + + *ptable = cac_leakage_table; + + return 0; +} + +static int get_platform_power_management_table(struct pp_hwmgr *hwmgr, + ATOM_PPLIB_PPM_Table *atom_ppm_table) +{ + struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_PPLIB_PPM_Table), GFP_KERNEL); + + if (NULL == ptr) + return -ENOMEM; + + ptr->ppm_design = atom_ppm_table->ucPpmDesign; + ptr->cpu_core_number = le16_to_cpu(atom_ppm_table->usCpuCoreNumber); + ptr->platform_tdp = le32_to_cpu(atom_ppm_table->ulPlatformTDP); + ptr->small_ac_platform_tdp = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDP); + ptr->platform_tdc = le32_to_cpu(atom_ppm_table->ulPlatformTDC); + ptr->small_ac_platform_tdc = le32_to_cpu(atom_ppm_table->ulSmallACPlatformTDC); + ptr->apu_tdp = le32_to_cpu(atom_ppm_table->ulApuTDP); + ptr->dgpu_tdp = le32_to_cpu(atom_ppm_table->ulDGpuTDP); + ptr->dgpu_ulv_power = le32_to_cpu(atom_ppm_table->ulDGpuUlvPower); + ptr->tj_max = le32_to_cpu(atom_ppm_table->ulTjmax); + hwmgr->dyn_state.ppm_parameter_table = ptr; + + return 0; +} + +static int init_dpm2_parameters(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + int result = 0; + + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE5)) { + const ATOM_PPLIB_POWERPLAYTABLE5 *ptable5 = + (const ATOM_PPLIB_POWERPLAYTABLE5 *)powerplay_table; + const ATOM_PPLIB_POWERPLAYTABLE4 *ptable4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *) + (&ptable5->basicTable4); + const ATOM_PPLIB_POWERPLAYTABLE3 *ptable3 = + (const ATOM_PPLIB_POWERPLAYTABLE3 *) + (&ptable4->basicTable3); + const ATOM_PPLIB_EXTENDEDHEADER *extended_header; + uint16_t table_offset; + ATOM_PPLIB_PPM_Table *atom_ppm_table; + + hwmgr->platform_descriptor.TDPLimit = le32_to_cpu(ptable5->ulTDPLimit); + hwmgr->platform_descriptor.nearTDPLimit = le32_to_cpu(ptable5->ulNearTDPLimit); + + hwmgr->platform_descriptor.TDPODLimit = le16_to_cpu(ptable5->usTDPODLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + hwmgr->platform_descriptor.nearTDPLimitAdjusted = le32_to_cpu(ptable5->ulNearTDPLimit); + + if (hwmgr->platform_descriptor.TDPODLimit != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + + hwmgr->platform_descriptor.SQRampingThreshold = le32_to_cpu(ptable5->ulSQRampingThreshold); + + hwmgr->platform_descriptor.CACLeakage = le32_to_cpu(ptable5->ulCACLeakage); + + hwmgr->dyn_state.cac_leakage_table = NULL; + + if (0 != ptable5->usCACLeakageTableOffset) { + const ATOM_PPLIB_CAC_Leakage_Table *pCAC_leakage_table = + (ATOM_PPLIB_CAC_Leakage_Table *)(((unsigned long)ptable5) + + le16_to_cpu(ptable5->usCACLeakageTableOffset)); + result = get_cac_leakage_table(hwmgr, + &hwmgr->dyn_state.cac_leakage_table, pCAC_leakage_table); + } + + hwmgr->platform_descriptor.LoadLineSlope = le16_to_cpu(ptable5->usLoadLineSlope); + + hwmgr->dyn_state.ppm_parameter_table = NULL; + + if (0 != ptable3->usExtendendedHeaderOffset) { + extended_header = (const ATOM_PPLIB_EXTENDEDHEADER *) + (((unsigned long)powerplay_table) + + le16_to_cpu(ptable3->usExtendendedHeaderOffset)); + if ((extended_header->usPPMTableOffset > 0) && + le16_to_cpu(extended_header->usSize) >= + SIZE_OF_ATOM_PPLIB_EXTENDEDHEADER_V5) { + table_offset = le16_to_cpu(extended_header->usPPMTableOffset); + atom_ppm_table = (ATOM_PPLIB_PPM_Table *) + (((unsigned long)powerplay_table) + table_offset); + if (0 == get_platform_power_management_table(hwmgr, atom_ppm_table)) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnablePlatformPowerManagement); + } + } + } + return result; +} + +static int init_phase_shedding_table(struct pp_hwmgr *hwmgr, + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table) +{ + if (le16_to_cpu(powerplay_table->usTableSize) >= + sizeof(ATOM_PPLIB_POWERPLAYTABLE4)) { + const ATOM_PPLIB_POWERPLAYTABLE4 *powerplay_table4 = + (const ATOM_PPLIB_POWERPLAYTABLE4 *)powerplay_table; + + if (0 != powerplay_table4->usVddcPhaseShedLimitsTableOffset) { + const ATOM_PPLIB_PhaseSheddingLimits_Table *ptable = + (ATOM_PPLIB_PhaseSheddingLimits_Table *) + (((unsigned long)powerplay_table4) + + le16_to_cpu(powerplay_table4->usVddcPhaseShedLimitsTableOffset)); + struct phm_phase_shedding_limits_table *table; + unsigned long size, i; + + + size = sizeof(unsigned long) + + (sizeof(struct phm_phase_shedding_limits_table) * + ptable->ucNumEntries); + + table = kzalloc(size, GFP_KERNEL); + + table->count = (unsigned long)ptable->ucNumEntries; + + for (i = 0; i < table->count; i++) { + table->entries[i].Voltage = (unsigned long)le16_to_cpu(ptable->entries[i].usVoltage); + table->entries[i].Sclk = ((unsigned long)ptable->entries[i].ucSclkHigh << 16) + | le16_to_cpu(ptable->entries[i].usSclkLow); + table->entries[i].Mclk = ((unsigned long)ptable->entries[i].ucMclkHigh << 16) + | le16_to_cpu(ptable->entries[i].usMclkLow); + } + hwmgr->dyn_state.vddc_phase_shed_limits_table = table; + } + } + + return 0; +} + +int get_number_of_vce_state_table_entries( + struct pp_hwmgr *hwmgr) +{ + const ATOM_PPLIB_POWERPLAYTABLE *table = + get_powerplay_table(hwmgr); + const ATOM_PPLIB_VCE_State_Table *vce_table = + get_vce_state_table(hwmgr, table); + + if (vce_table > 0) + return vce_table->numEntries; + + return 0; +} + +int get_vce_state_table_entry(struct pp_hwmgr *hwmgr, + unsigned long i, + struct PP_VCEState *vce_state, + void **clock_info, + unsigned long *flag) +{ + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table = get_powerplay_table(hwmgr); + + const ATOM_PPLIB_VCE_State_Table *vce_state_table = get_vce_state_table(hwmgr, powerplay_table); + + unsigned short vce_clock_info_array_offset = get_vce_clock_info_array_offset(hwmgr, powerplay_table); + + const VCEClockInfoArray *vce_clock_info_array = (const VCEClockInfoArray *)(((unsigned long) powerplay_table) + vce_clock_info_array_offset); + + const ClockInfoArray *clock_arrays = (ClockInfoArray *)(((unsigned long)powerplay_table) + powerplay_table->usClockInfoArrayOffset); + + const ATOM_PPLIB_VCE_State_Record *record = &vce_state_table->entries[i]; + + const VCEClockInfo *vce_clock_info = &vce_clock_info_array->entries[record->ucVCEClockInfoIndex]; + + unsigned long clockInfoIndex = record->ucClockInfoIndex & 0x3F; + + *flag = (record->ucClockInfoIndex >> NUM_BITS_CLOCK_INFO_ARRAY_INDEX); + + vce_state->evclk = ((uint32_t)vce_clock_info->ucEVClkHigh << 16) | vce_clock_info->usEVClkLow; + vce_state->ecclk = ((uint32_t)vce_clock_info->ucECClkHigh << 16) | vce_clock_info->usECClkLow; + + *clock_info = (void *)((unsigned long)(clock_arrays->clockInfo) + (clockInfoIndex * clock_arrays->ucEntrySize)); + + return 0; +} + + +static int pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result; + const ATOM_PPLIB_POWERPLAYTABLE *powerplay_table; + + hwmgr->need_pp_table_upload = true; + + powerplay_table = get_powerplay_table(hwmgr); + + result = init_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_overdrive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_overdrive_limits failed", return result); + + result = init_clock_voltage_dependency(hwmgr, + powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_clock_voltage_dependency failed", return result); + + result = init_dpm2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm2_parameters failed", return result); + + result = init_phase_shedding_table(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_phase_shedding_table failed", return result); + + return result; +} + +static int pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->soft_pp_table) { + kfree(hwmgr->soft_pp_table); + hwmgr->soft_pp_table = NULL; + } + + if (NULL != hwmgr->dyn_state.vddc_dependency_on_sclk) { + kfree(hwmgr->dyn_state.vddc_dependency_on_sclk); + hwmgr->dyn_state.vddc_dependency_on_sclk = NULL; + } + + if (NULL != hwmgr->dyn_state.vddci_dependency_on_mclk) { + kfree(hwmgr->dyn_state.vddci_dependency_on_mclk); + hwmgr->dyn_state.vddci_dependency_on_mclk = NULL; + } + + if (NULL != hwmgr->dyn_state.vddc_dependency_on_mclk) { + kfree(hwmgr->dyn_state.vddc_dependency_on_mclk); + hwmgr->dyn_state.vddc_dependency_on_mclk = NULL; + } + + if (NULL != hwmgr->dyn_state.mvdd_dependency_on_mclk) { + kfree(hwmgr->dyn_state.mvdd_dependency_on_mclk); + hwmgr->dyn_state.mvdd_dependency_on_mclk = NULL; + } + + if (NULL != hwmgr->dyn_state.valid_mclk_values) { + kfree(hwmgr->dyn_state.valid_mclk_values); + hwmgr->dyn_state.valid_mclk_values = NULL; + } + + if (NULL != hwmgr->dyn_state.valid_sclk_values) { + kfree(hwmgr->dyn_state.valid_sclk_values); + hwmgr->dyn_state.valid_sclk_values = NULL; + } + + if (NULL != hwmgr->dyn_state.cac_leakage_table) { + kfree(hwmgr->dyn_state.cac_leakage_table); + hwmgr->dyn_state.cac_leakage_table = NULL; + } + + if (NULL != hwmgr->dyn_state.vddc_phase_shed_limits_table) { + kfree(hwmgr->dyn_state.vddc_phase_shed_limits_table); + hwmgr->dyn_state.vddc_phase_shed_limits_table = NULL; + } + + if (NULL != hwmgr->dyn_state.vce_clock_voltage_dependency_table) { + kfree(hwmgr->dyn_state.vce_clock_voltage_dependency_table); + hwmgr->dyn_state.vce_clock_voltage_dependency_table = NULL; + } + + if (NULL != hwmgr->dyn_state.uvd_clock_voltage_dependency_table) { + kfree(hwmgr->dyn_state.uvd_clock_voltage_dependency_table); + hwmgr->dyn_state.uvd_clock_voltage_dependency_table = NULL; + } + + if (NULL != hwmgr->dyn_state.samu_clock_voltage_dependency_table) { + kfree(hwmgr->dyn_state.samu_clock_voltage_dependency_table); + hwmgr->dyn_state.samu_clock_voltage_dependency_table = NULL; + } + + if (NULL != hwmgr->dyn_state.acp_clock_voltage_dependency_table) { + kfree(hwmgr->dyn_state.acp_clock_voltage_dependency_table); + hwmgr->dyn_state.acp_clock_voltage_dependency_table = NULL; + } + + if (NULL != hwmgr->dyn_state.cac_dtp_table) { + kfree(hwmgr->dyn_state.cac_dtp_table); + hwmgr->dyn_state.cac_dtp_table = NULL; + } + + if (NULL != hwmgr->dyn_state.ppm_parameter_table) { + kfree(hwmgr->dyn_state.ppm_parameter_table); + hwmgr->dyn_state.ppm_parameter_table = NULL; + } + + if (NULL != hwmgr->dyn_state.vdd_gfx_dependency_on_sclk) { + kfree(hwmgr->dyn_state.vdd_gfx_dependency_on_sclk); + hwmgr->dyn_state.vdd_gfx_dependency_on_sclk = NULL; + } + + if (NULL != hwmgr->dyn_state.vq_budgeting_table) { + kfree(hwmgr->dyn_state.vq_budgeting_table); + hwmgr->dyn_state.vq_budgeting_table = NULL; + } + + return 0; +} + +const struct pp_table_func pptable_funcs = { + .pptable_init = pp_tables_initialize, + .pptable_fini = pp_tables_uninitialize, + .pptable_get_number_of_vce_state_table_entries = + get_number_of_vce_state_table_entries, + .pptable_get_vce_state_table_entry = + get_vce_state_table_entry, +}; + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h new file mode 100644 index 000000000000..30434802417e --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/processpptables.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 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. + * Interface Functions related to the BIOS PowerPlay Tables. + * + */ + +#ifndef PROCESSPPTABLES_H +#define PROCESSPPTABLES_H + +struct pp_hwmgr; +struct pp_power_state; +struct pp_hw_power_state; + +extern const struct pp_table_func pptable_funcs; + +typedef int (*pp_tables_hw_clock_info_callback)(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps, + unsigned int index, + const void *clock_info); + +int pp_tables_get_num_of_entries(struct pp_hwmgr *hwmgr, + unsigned long *num_of_entries); + +int pp_tables_get_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, + struct pp_power_state *ps, + pp_tables_hw_clock_info_callback func); + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c new file mode 100644 index 000000000000..e58d038a997b --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.c @@ -0,0 +1,350 @@ +/* + * Copyright 2015 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. + * + */ + +#include "hwmgr.h" +#include "tonga_clockpowergating.h" +#include "tonga_ppsmc.h" +#include "tonga_hwmgr.h" + +int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_uvd_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_UVDPowerOFF); + return 0; +} + +int tonga_phm_powerup_uvd(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_uvd_power_gating(hwmgr)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UVDDynamicPowerGating)) { + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_UVDPowerON, 1); + } else { + return smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_UVDPowerON, 0); + } + } + + return 0; +} + +int tonga_phm_powerdown_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_vce_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_VCEPowerOFF); + return 0; +} + +int tonga_phm_powerup_vce(struct pp_hwmgr *hwmgr) +{ + if (phm_cf_want_vce_power_gating(hwmgr)) + return smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_VCEPowerON); + return 0; +} + +int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating) +{ + int ret = 0; + + switch (block) { + case PHM_AsicBlock_UVD_MVC: + case PHM_AsicBlock_UVD: + case PHM_AsicBlock_UVD_HD: + case PHM_AsicBlock_UVD_SD: + if (gating == PHM_ClockGateSetting_StaticOff) + ret = tonga_phm_powerdown_uvd(hwmgr); + else + ret = tonga_phm_powerup_uvd(hwmgr); + break; + case PHM_AsicBlock_GFX: + default: + break; + } + + return ret; +} + +int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = false; + data->vce_power_gated = false; + + tonga_phm_powerup_uvd(hwmgr); + tonga_phm_powerup_vce(hwmgr); + + return 0; +} + +int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (data->uvd_power_gated == bgate) + return 0; + + data->uvd_power_gated = bgate; + + if (bgate) { + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + tonga_update_uvd_dpm(hwmgr, true); + tonga_phm_powerdown_uvd(hwmgr); + } else { + tonga_phm_powerup_uvd(hwmgr); + cgs_set_powergating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_UNGATE); + cgs_set_clockgating_state(hwmgr->device, + AMD_IP_BLOCK_TYPE_UVD, + AMD_PG_STATE_GATE); + + tonga_update_uvd_dpm(hwmgr, false); + } + + return 0; +} + +int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct phm_set_power_state_input states; + const struct pp_power_state *pcurrent; + struct pp_power_state *requested; + + pcurrent = hwmgr->current_ps; + requested = hwmgr->request_ps; + + states.pcurrent_state = &(pcurrent->hardware); + states.pnew_state = &(requested->hardware); + + if (phm_cf_want_vce_power_gating(hwmgr)) { + if (data->vce_power_gated != bgate) { + if (bgate) { + cgs_set_clockgating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_CG_STATE_UNGATE); + cgs_set_powergating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + tonga_enable_disable_vce_dpm(hwmgr, false); + data->vce_power_gated = true; + } else { + tonga_phm_powerup_vce(hwmgr); + data->vce_power_gated = false; + cgs_set_powergating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_UNGATE); + cgs_set_clockgating_state( + hwmgr->device, + AMD_IP_BLOCK_TYPE_VCE, + AMD_PG_STATE_GATE); + + tonga_update_vce_dpm(hwmgr, &states); + tonga_enable_disable_vce_dpm(hwmgr, true); + return 0; + } + } + } else { + tonga_update_vce_dpm(hwmgr, &states); + tonga_enable_disable_vce_dpm(hwmgr, true); + return 0; + } + + if (!data->vce_power_gated) + tonga_update_vce_dpm(hwmgr, &states); + + return 0; +} + +int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, + const uint32_t *msg_id) +{ + PPSMC_Msg msg; + uint32_t value; + + switch ((*msg_id & PP_GROUP_MASK) >> PP_GROUP_SHIFT) { + case PP_GROUP_GFX: + switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { + case PP_BLOCK_GFX_CG: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_CGCG_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_GFX_CGLS_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + case PP_BLOCK_GFX_MG: + /* For GFX MGCG, there are three different ones; + * CPF, RLC, and all others. CPF MGCG will not be used for Tonga. + * For GFX MGLS, Tonga will not support it. + * */ + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = (CG_RLC_MGCG_MASK | CG_GFX_OTHERS_MGCG_MASK); + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + default: + return -1; + } + break; + + case PP_GROUP_SYS: + switch ((*msg_id & PP_BLOCK_MASK) >> PP_BLOCK_SHIFT) { + case PP_BLOCK_SYS_BIF: + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_BIF_MGLS_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + case PP_BLOCK_SYS_MC: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_MC_MGCG_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_MC_MGLS_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + + } + break; + + case PP_BLOCK_SYS_HDP: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_HDP_MGCG_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + + value = CG_SYS_HDP_MGLS_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + case PP_BLOCK_SYS_SDMA: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_SDMA_MGCG_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + + if (PP_STATE_SUPPORT_LS & *msg_id) { + msg = (*msg_id & PP_STATE_MASK) & PP_STATE_LS + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + + value = CG_SYS_SDMA_MGLS_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + case PP_BLOCK_SYS_ROM: + if (PP_STATE_SUPPORT_CG & *msg_id) { + msg = ((*msg_id & PP_STATE_MASK) & PP_STATE_CG) + ? PPSMC_MSG_EnableClockGatingFeature + : PPSMC_MSG_DisableClockGatingFeature; + value = CG_SYS_ROM_MASK; + + if (0 != smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, msg, value)) + return -1; + } + break; + + default: + return -1; + + } + break; + + default: + return -1; + + } + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h new file mode 100644 index 000000000000..8bc38cb17b7f --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_clockpowergating.h @@ -0,0 +1,36 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _TONGA_CLOCK_POWER_GATING_H_ +#define _TONGA_CLOCK_POWER_GATING_H_ + +#include "tonga_hwmgr.h" +#include "pp_asicblocks.h" + +extern int tonga_phm_set_asic_block_gating(struct pp_hwmgr *hwmgr, enum PHM_AsicBlock block, enum PHM_ClockGateSetting gating); +extern int tonga_phm_powergate_vce(struct pp_hwmgr *hwmgr, bool bgate); +extern int tonga_phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool bgate); +extern int tonga_phm_powerdown_uvd(struct pp_hwmgr *hwmgr); +extern int tonga_phm_disable_clock_power_gating(struct pp_hwmgr *hwmgr); +extern int tonga_phm_update_clock_gatings(struct pp_hwmgr *hwmgr, const uint32_t *msg_id); +#endif /* _TONGA_CLOCK_POWER_GATING_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h new file mode 100644 index 000000000000..080d69d77f04 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_dyn_defaults.h @@ -0,0 +1,107 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef TONGA_DYN_DEFAULTS_H +#define TONGA_DYN_DEFAULTS_H + + +/** \file + * Volcanic Islands Dynamic default parameters. + */ + +enum TONGAdpm_TrendDetection { + TONGAdpm_TrendDetection_AUTO, + TONGAdpm_TrendDetection_UP, + TONGAdpm_TrendDetection_DOWN +}; +typedef enum TONGAdpm_TrendDetection TONGAdpm_TrendDetection; + +/* Bit vector representing same fields as hardware register. */ +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT0 0x3FFFC102 /* CP_Gfx_busy */ +/* HDP_busy */ +/* IH_busy */ +/* DRM_busy */ +/* DRMDMA_busy */ +/* UVD_busy */ +/* VCE_busy */ +/* ACP_busy */ +/* SAMU_busy */ +/* AVP_busy */ +/* SDMA enabled */ +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT1 0x000400 /* FE_Gfx_busy - Intended for primary usage. Rest are for flexibility. */ +/* SH_Gfx_busy */ +/* RB_Gfx_busy */ +/* VCE_busy */ + +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT2 0xC00080 /* SH_Gfx_busy - Intended for primary usage. Rest are for flexibility. */ +/* FE_Gfx_busy */ +/* RB_Gfx_busy */ +/* ACP_busy */ + +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT3 0xC00200 /* RB_Gfx_busy - Intended for primary usage. Rest are for flexibility. */ +/* FE_Gfx_busy */ +/* SH_Gfx_busy */ +/* UVD_busy */ + +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT4 0xC01680 /* UVD_busy */ +/* VCE_busy */ +/* ACP_busy */ +/* SAMU_busy */ + +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT5 0xC00033 /* GFX, HDP, DRMDMA */ +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT6 0xC00033 /* GFX, HDP, DRMDMA */ +#define PPTONGA_VOTINGRIGHTSCLIENTS_DFLT7 0x3FFFC000 /* GFX, HDP, DRMDMA */ + + +/* thermal protection counter (units).*/ +#define PPTONGA_THERMALPROTECTCOUNTER_DFLT 0x200 /* ~19us */ + +/* static screen threshold unit */ +#define PPTONGA_STATICSCREENTHRESHOLDUNIT_DFLT 0 + +/* static screen threshold */ +#define PPTONGA_STATICSCREENTHRESHOLD_DFLT 0x00C8 + +/* gfx idle clock stop threshold */ +#define PPTONGA_GFXIDLECLOCKSTOPTHRESHOLD_DFLT 0x200 /* ~19us with static screen threshold unit of 0 */ + +/* Fixed reference divider to use when building baby stepping tables. */ +#define PPTONGA_REFERENCEDIVIDER_DFLT 4 + +/* + * ULV voltage change delay time + * Used to be delay_vreg in N.I. split for S.I. + * Using N.I. delay_vreg value as default + * ReferenceClock = 2700 + * VoltageResponseTime = 1000 + * VDDCDelayTime = (VoltageResponseTime * ReferenceClock) / 1600 = 1687 + */ + +#define PPTONGA_ULVVOLTAGECHANGEDELAY_DFLT 1687 + +#define PPTONGA_CGULVPARAMETER_DFLT 0x00040035 +#define PPTONGA_CGULVCONTROL_DFLT 0x00007450 +#define PPTONGA_TARGETACTIVITY_DFLT 30 /*30% */ +#define PPTONGA_MCLK_TARGETACTIVITY_DFLT 10 /*10% */ + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c new file mode 100644 index 000000000000..3cb5d041b3cf --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.c @@ -0,0 +1,6069 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> +#include "linux/delay.h" +#include "pp_acpi.h" +#include "hwmgr.h" +#include <atombios.h> +#include "tonga_hwmgr.h" +#include "pptable.h" +#include "processpptables.h" +#include "tonga_processpptables.h" +#include "tonga_pptable.h" +#include "pp_debug.h" +#include "tonga_ppsmc.h" +#include "cgs_common.h" +#include "pppcielanes.h" +#include "tonga_dyn_defaults.h" +#include "smumgr.h" +#include "tonga_smumgr.h" +#include "tonga_clockpowergating.h" +#include "tonga_thermal.h" + +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" + +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" + +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" + +#include "cgs_linux.h" +#include "eventmgr.h" +#include "amd_pcie_helpers.h" + +#define MC_CG_ARB_FREQ_F0 0x0a +#define MC_CG_ARB_FREQ_F1 0x0b +#define MC_CG_ARB_FREQ_F2 0x0c +#define MC_CG_ARB_FREQ_F3 0x0d + +#define MC_CG_SEQ_DRAMCONF_S0 0x05 +#define MC_CG_SEQ_DRAMCONF_S1 0x06 +#define MC_CG_SEQ_YCLK_SUSPEND 0x04 +#define MC_CG_SEQ_YCLK_RESUME 0x0a + +#define PCIE_BUS_CLK 10000 +#define TCLK (PCIE_BUS_CLK / 10) + +#define SMC_RAM_END 0x40000 +#define SMC_CG_IND_START 0xc0030000 +#define SMC_CG_IND_END 0xc0040000 /* First byte after SMC_CG_IND*/ + +#define VOLTAGE_SCALE 4 +#define VOLTAGE_VID_OFFSET_SCALE1 625 +#define VOLTAGE_VID_OFFSET_SCALE2 100 + +#define VDDC_VDDCI_DELTA 200 +#define VDDC_VDDGFX_DELTA 300 + +#define MC_SEQ_MISC0_GDDR5_SHIFT 28 +#define MC_SEQ_MISC0_GDDR5_MASK 0xf0000000 +#define MC_SEQ_MISC0_GDDR5_VALUE 5 + +typedef uint32_t PECI_RegistryValue; + +/* [2.5%,~2.5%] Clock stretched is multiple of 2.5% vs not and [Fmin, Fmax, LDO_REFSEL, USE_FOR_LOW_FREQ] */ +uint16_t PP_ClockStretcherLookupTable[2][4] = { + {600, 1050, 3, 0}, + {600, 1050, 6, 1} }; + +/* [FF, SS] type, [] 4 voltage ranges, and [Floor Freq, Boundary Freq, VID min , VID max] */ +uint32_t PP_ClockStretcherDDTTable[2][4][4] = { + { {265, 529, 120, 128}, {325, 650, 96, 119}, {430, 860, 32, 95}, {0, 0, 0, 31} }, + { {275, 550, 104, 112}, {319, 638, 96, 103}, {360, 720, 64, 95}, {384, 768, 32, 63} } }; + +/* [Use_For_Low_freq] value, [0%, 5%, 10%, 7.14%, 14.28%, 20%] (coming from PWR_CKS_CNTL.stretch_amount reg spec) */ +uint8_t PP_ClockStretchAmountConversion[2][6] = { + {0, 1, 3, 2, 4, 5}, + {0, 2, 4, 5, 6, 5} }; + +/* Values for the CG_THERMAL_CTRL::DPM_EVENT_SRC field. */ +enum DPM_EVENT_SRC { + DPM_EVENT_SRC_ANALOG = 0, /* Internal analog trip point */ + DPM_EVENT_SRC_EXTERNAL = 1, /* External (GPIO 17) signal */ + DPM_EVENT_SRC_DIGITAL = 2, /* Internal digital trip point (DIG_THERM_DPM) */ + DPM_EVENT_SRC_ANALOG_OR_EXTERNAL = 3, /* Internal analog or external */ + DPM_EVENT_SRC_DIGITAL_OR_EXTERNAL = 4 /* Internal digital or external */ +}; +typedef enum DPM_EVENT_SRC DPM_EVENT_SRC; + +const unsigned long PhwTonga_Magic = (unsigned long)(PHM_VIslands_Magic); + +struct tonga_power_state *cast_phw_tonga_power_state( + struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (struct tonga_power_state *)hw_ps; +} + +const struct tonga_power_state *cast_const_phw_tonga_power_state( + const struct pp_hw_power_state *hw_ps) +{ + PP_ASSERT_WITH_CODE((PhwTonga_Magic == hw_ps->magic), + "Invalid Powerstate Type!", + return NULL;); + + return (const struct tonga_power_state *)hw_ps; +} + +int tonga_add_voltage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *look_up_table, + phm_ppt_v1_voltage_lookup_record *record) +{ + uint32_t i; + PP_ASSERT_WITH_CODE((NULL != look_up_table), + "Lookup Table empty.", return -1;); + PP_ASSERT_WITH_CODE((0 != look_up_table->count), + "Lookup Table empty.", return -1;); + PP_ASSERT_WITH_CODE((SMU72_MAX_LEVELS_VDDGFX >= look_up_table->count), + "Lookup Table is full.", return -1;); + + /* This is to avoid entering duplicate calculated records. */ + for (i = 0; i < look_up_table->count; i++) { + if (look_up_table->entries[i].us_vdd == record->us_vdd) { + if (look_up_table->entries[i].us_calculated == 1) + return 0; + else + break; + } + } + + look_up_table->entries[i].us_calculated = 1; + look_up_table->entries[i].us_vdd = record->us_vdd; + look_up_table->entries[i].us_cac_low = record->us_cac_low; + look_up_table->entries[i].us_cac_mid = record->us_cac_mid; + look_up_table->entries[i].us_cac_high = record->us_cac_high; + /* Only increment the count when we're appending, not replacing duplicate entry. */ + if (i == look_up_table->count) + look_up_table->count++; + + return 0; +} + +int tonga_notify_smc_display_change(struct pp_hwmgr *hwmgr, bool has_display) +{ + PPSMC_Msg msg = has_display? (PPSMC_Msg)PPSMC_HasDisplay : (PPSMC_Msg)PPSMC_NoDisplay; + + return (smum_send_msg_to_smc(hwmgr->smumgr, msg) == 0) ? 0 : -1; +} + +uint8_t tonga_get_voltage_id(pp_atomctrl_voltage_table *voltage_table, + uint32_t voltage) +{ + uint8_t count = (uint8_t) (voltage_table->count); + uint8_t i = 0; + + PP_ASSERT_WITH_CODE((NULL != voltage_table), + "Voltage Table empty.", return 0;); + PP_ASSERT_WITH_CODE((0 != count), + "Voltage Table empty.", return 0;); + + for (i = 0; i < count; i++) { + /* find first voltage bigger than requested */ + if (voltage_table->entries[i].value >= voltage) + return i; + } + + /* voltage is bigger than max voltage in the table */ + return i - 1; +} + +/** + * @brief PhwTonga_GetVoltageOrder + * Returns index of requested voltage record in lookup(table) + * @param hwmgr - pointer to hardware manager + * @param lookupTable - lookup list to search in + * @param voltage - voltage to look for + * @return 0 on success + */ +uint8_t tonga_get_voltage_index(phm_ppt_v1_voltage_lookup_table *look_up_table, + uint16_t voltage) +{ + uint8_t count = (uint8_t) (look_up_table->count); + uint8_t i; + + PP_ASSERT_WITH_CODE((NULL != look_up_table), "Lookup Table empty.", return 0;); + PP_ASSERT_WITH_CODE((0 != count), "Lookup Table empty.", return 0;); + + for (i = 0; i < count; i++) { + /* find first voltage equal or bigger than requested */ + if (look_up_table->entries[i].us_vdd >= voltage) + return i; + } + + /* voltage is bigger than max voltage in the table */ + return i-1; +} + +bool tonga_is_dpm_running(struct pp_hwmgr *hwmgr) +{ + /* + * We return the status of Voltage Control instead of checking SCLK/MCLK DPM + * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM, + * whereas voltage control is a fundemental change that will not be disabled + */ + + return (0 == PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + FEATURE_STATUS, VOLTAGE_CONTROLLER_ON) ? 1 : 0); +} + +/** + * Re-generate the DPM level mask value + * @param hwmgr the address of the hardware manager + */ +static uint32_t tonga_get_dpm_level_enable_mask_value( + struct tonga_single_dpm_table * dpm_table) +{ + uint32_t i; + uint32_t mask_value = 0; + + for (i = dpm_table->count; i > 0; i--) { + mask_value = mask_value << 1; + + if (dpm_table->dpm_levels[i-1].enabled) + mask_value |= 0x1; + else + mask_value &= 0xFFFFFFFE; + } + return mask_value; +} + +/** + * Retrieve DPM default values from registry (if available) + * + * @param hwmgr the address of the powerplay hardware manager. + */ +void tonga_initialize_dpm_defaults(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + phw_tonga_ulv_parm *ulv = &(data->ulv); + uint32_t tmp; + + ulv->ch_ulv_parameter = PPTONGA_CGULVPARAMETER_DFLT; + data->voting_rights_clients0 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT0; + data->voting_rights_clients1 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT1; + data->voting_rights_clients2 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT2; + data->voting_rights_clients3 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT3; + data->voting_rights_clients4 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT4; + data->voting_rights_clients5 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT5; + data->voting_rights_clients6 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT6; + data->voting_rights_clients7 = PPTONGA_VOTINGRIGHTSCLIENTS_DFLT7; + + data->static_screen_threshold_unit = PPTONGA_STATICSCREENTHRESHOLDUNIT_DFLT; + data->static_screen_threshold = PPTONGA_STATICSCREENTHRESHOLD_DFLT; + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ABM); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_NonABMSupportInPPLib); + + tmp = 0; + if (tmp == 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicACTiming); + + tmp = 0; + if (0 != tmp) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableMemoryTransition); + + data->mclk_strobe_mode_threshold = 40000; + data->mclk_stutter_mode_threshold = 30000; + data->mclk_edc_enable_threshold = 40000; + data->mclk_edc_wr_enable_threshold = 40000; + + tmp = 0; + if (tmp != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableMCLS); + + data->pcie_gen_performance.max = PP_PCIEGen1; + data->pcie_gen_performance.min = PP_PCIEGen3; + data->pcie_gen_power_saving.max = PP_PCIEGen1; + data->pcie_gen_power_saving.min = PP_PCIEGen3; + + data->pcie_lane_performance.max = 0; + data->pcie_lane_performance.min = 16; + data->pcie_lane_power_saving.max = 0; + data->pcie_lane_power_saving.min = 16; + + tmp = 0; + + if (tmp) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicUVDState); + +} + +int tonga_update_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + int result = 0; + uint32_t low_sclk_interrupt_threshold = 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SclkThrottleLowNotification) + && (hwmgr->gfx_arbiter.sclk_threshold != data->low_sclk_interrupt_threshold)) { + data->low_sclk_interrupt_threshold = hwmgr->gfx_arbiter.sclk_threshold; + low_sclk_interrupt_threshold = data->low_sclk_interrupt_threshold; + + CONVERT_FROM_HOST_TO_SMC_UL(low_sclk_interrupt_threshold); + + result = tonga_copy_bytes_to_smc( + hwmgr->smumgr, + data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, + LowSclkInterruptThreshold), + (uint8_t *)&low_sclk_interrupt_threshold, + sizeof(uint32_t), + data->sram_end + ); + } + + return result; +} + +/** + * Find SCLK value that is associated with specified virtual_voltage_Id. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param virtual_voltage_Id voltageId to look for. + * @param sclk output value . + * @return always 0 if success and 2 if association not found + */ +static int tonga_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, uint32_t *sclk) +{ + uint8_t entryId; + uint8_t voltageId; + struct phm_ppt_v1_information *pptable_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + PP_ASSERT_WITH_CODE(lookup_table->count != 0, "Lookup table is empty", return -1); + + /* search for leakage voltage ID 0xff01 ~ 0xff08 and sckl */ + for (entryId = 0; entryId < pptable_info->vdd_dep_on_sclk->count; entryId++) { + voltageId = pptable_info->vdd_dep_on_sclk->entries[entryId].vddInd; + if (lookup_table->entries[voltageId].us_vdd == virtual_voltage_id) + break; + } + + PP_ASSERT_WITH_CODE(entryId < pptable_info->vdd_dep_on_sclk->count, + "Can't find requested voltage id in vdd_dep_on_sclk table!", + return -1; + ); + + *sclk = pptable_info->vdd_dep_on_sclk->entries[entryId].clk; + + return 0; +} + +/** + * Get Leakage VDDC based on leakage ID. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return 2 if vddgfx returned is greater than 2V or if BIOS + */ +int tonga_get_evv_voltage(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; + uint16_t virtual_voltage_id; + uint16_t vddc = 0; + uint16_t vddgfx = 0; + uint16_t i, j; + uint32_t sclk = 0; + + /* retrieve voltage for leakage ID (0xff01 + i) */ + for (i = 0; i < TONGA_MAX_LEAKAGE_COUNT; i++) { + virtual_voltage_id = ATOM_VIRTUAL_VOLTAGE_ID0 + i; + + /* in split mode we should have only vddgfx EVV leakages */ + if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) { + if (0 == tonga_get_sclk_for_voltage_evv(hwmgr, + pptable_info->vddgfx_lookup_table, virtual_voltage_id, &sclk)) { + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + for (j = 1; j < sclk_table->count; j++) { + if (sclk_table->entries[j].clk == sclk && + sclk_table->entries[j].cks_enable == 0) { + sclk += 5000; + break; + } + } + } + PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk + (hwmgr, VOLTAGE_TYPE_VDDGFX, sclk, + virtual_voltage_id, &vddgfx), + "Error retrieving EVV voltage value!", continue); + + /* need to make sure vddgfx is less than 2v or else, it could burn the ASIC. */ + PP_ASSERT_WITH_CODE((vddgfx < 2000 && vddgfx != 0), "Invalid VDDGFX value!", return -1); + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddgfx != 0 && vddgfx != virtual_voltage_id) { + data->vddcgfx_leakage.actual_voltage[data->vddcgfx_leakage.count] = vddgfx; + data->vddcgfx_leakage.leakage_id[data->vddcgfx_leakage.count] = virtual_voltage_id; + data->vddcgfx_leakage.count++; + } + } + } else { + /* in merged mode we have only vddc EVV leakages */ + if (0 == tonga_get_sclk_for_voltage_evv(hwmgr, + pptable_info->vddc_lookup_table, + virtual_voltage_id, &sclk)) { + PP_ASSERT_WITH_CODE(0 == atomctrl_get_voltage_evv_on_sclk + (hwmgr, VOLTAGE_TYPE_VDDC, sclk, + virtual_voltage_id, &vddc), + "Error retrieving EVV voltage value!", continue); + + /* need to make sure vddc is less than 2v or else, it could burn the ASIC. */ + if (vddc > 2000) + printk(KERN_ERR "[ powerplay ] Invalid VDDC value! \n"); + + /* the voltage should not be zero nor equal to leakage ID */ + if (vddc != 0 && vddc != virtual_voltage_id) { + data->vddc_leakage.actual_voltage[data->vddc_leakage.count] = vddc; + data->vddc_leakage.leakage_id[data->vddc_leakage.count] = virtual_voltage_id; + data->vddc_leakage.count++; + } + } + } + } + + return 0; +} + +int tonga_enable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* enable SCLK dpm */ + if (0 == data->sclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_DPM_Enable)), + "Failed to enable SCLK DPM during DPM Start Function!", + return -1); + } + + /* enable MCLK dpm */ + if (0 == data->mclk_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_Enable)), + "Failed to enable MCLK DPM during DPM Start Function!", + return -1); + + PHM_WRITE_FIELD(hwmgr->device, MC_SEQ_CNTL_3, CAC_EN, 0x1); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC0_CNTL, 0x05);/* CH0,1 read */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC1_CNTL, 0x05);/* CH2,3 read */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_CPL_CNTL, 0x100005);/*Read */ + + udelay(10); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC0_CNTL, 0x400005);/* CH0,1 write */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_MC1_CNTL, 0x400005);/* CH2,3 write */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixLCAC_CPL_CNTL, 0x500005);/* write */ + + } + + return 0; +} + +int tonga_start_dpm(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* enable general power management */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 1); + /* enable sclk deep sleep */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 1); + + /* prepare for PCIE DPM */ + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + + offsetof(SMU72_SoftRegisters, VoltageChangeTimeout), 0x1000); + + PHM_WRITE_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__PCIE, SWRST_COMMAND_1, RESETLC, 0x0); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_Voltage_Cntl_Enable)), + "Failed to enable voltage DPM during DPM Start Function!", + return -1); + + if (0 != tonga_enable_sclk_mclk_dpm(hwmgr)) { + PP_ASSERT_WITH_CODE(0, "Failed to enable Sclk DPM and Mclk DPM!", return -1); + } + + /* enable PCIE dpm */ + if (0 == data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_Enable)), + "Failed to enable pcie DPM during DPM Start Function!", + return -1 + ); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition)) { + smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_EnableACDCGPIOInterrupt); + } + + return 0; +} + +int tonga_disable_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* disable SCLK dpm */ + if (0 == data->sclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + PP_ASSERT_WITH_CODE( + (0 == tonga_is_dpm_running(hwmgr)), + "Trying to Disable SCLK DPM when DPM is disabled", + return -1 + ); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_DPM_Disable)), + "Failed to disable SCLK DPM during DPM stop Function!", + return -1); + } + + /* disable MCLK dpm */ + if (0 == data->mclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */ + PP_ASSERT_WITH_CODE( + (0 == tonga_is_dpm_running(hwmgr)), + "Trying to Disable MCLK DPM when DPM is disabled", + return -1 + ); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_Disable)), + "Failed to Disable MCLK DPM during DPM stop Function!", + return -1); + } + + return 0; +} + +int tonga_stop_dpm(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, GLOBAL_PWRMGT_EN, 0); + /* disable sclk deep sleep*/ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, DYNAMIC_PM_EN, 0); + + /* disable PCIE dpm */ + if (0 == data->pcie_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + PP_ASSERT_WITH_CODE( + (0 == tonga_is_dpm_running(hwmgr)), + "Trying to Disable PCIE DPM when DPM is disabled", + return -1 + ); + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_Disable)), + "Failed to disable pcie DPM during DPM stop Function!", + return -1); + } + + if (0 != tonga_disable_sclk_mclk_dpm(hwmgr)) + PP_ASSERT_WITH_CODE(0, "Failed to disable Sclk DPM and Mclk DPM!", return -1); + + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + PP_ASSERT_WITH_CODE( + (0 == tonga_is_dpm_running(hwmgr)), + "Trying to Disable Voltage CNTL when DPM is disabled", + return -1 + ); + + PP_ASSERT_WITH_CODE( + (0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_Voltage_Cntl_Disable)), + "Failed to disable voltage DPM during DPM stop Function!", + return -1); + + return 0; +} + +int tonga_enable_sclk_control(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, SCLK_PWRMGT_CNTL, SCLK_PWRMGT_OFF, 0); + + return 0; +} + +/** + * Send a message to the SMC and return a parameter + * + * @param hwmgr: the address of the powerplay hardware manager. + * @param msg: the message to send. + * @param parameter: pointer to the received parameter + * @return The response that came from the SMC. + */ +PPSMC_Result tonga_send_msg_to_smc_return_parameter( + struct pp_hwmgr *hwmgr, + PPSMC_Msg msg, + uint32_t *parameter) +{ + int result; + + result = smum_send_msg_to_smc(hwmgr->smumgr, msg); + + if ((0 == result) && parameter) { + *parameter = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + } + + return result; +} + +/** + * force DPM power State + * + * @param hwmgr: the address of the powerplay hardware manager. + * @param n : DPM level + * @return The response that came from the SMC. + */ +int tonga_dpm_force_state(struct pp_hwmgr *hwmgr, uint32_t n) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t level_mask = 1 << n; + + /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */ + PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr), + "Trying to force SCLK when DPM is disabled", return -1;); + if (0 == data->sclk_dpm_key_disabled) + return (0 == smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + (PPSMC_Msg)(PPSMC_MSG_SCLKDPM_SetEnabledMask), + level_mask) ? 0 : 1); + + return 0; +} + +/** + * force DPM power State + * + * @param hwmgr: the address of the powerplay hardware manager. + * @param n : DPM level + * @return The response that came from the SMC. + */ +int tonga_dpm_force_state_mclk(struct pp_hwmgr *hwmgr, uint32_t n) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t level_mask = 1 << n; + + /* Checking if DPM is running. If we discover hang because of this, we should skip this message. */ + PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr), + "Trying to Force MCLK when DPM is disabled", return -1;); + if (0 == data->mclk_dpm_key_disabled) + return (0 == smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + (PPSMC_Msg)(PPSMC_MSG_MCLKDPM_SetEnabledMask), + level_mask) ? 0 : 1); + + return 0; +} + +/** + * force DPM power State + * + * @param hwmgr: the address of the powerplay hardware manager. + * @param n : DPM level + * @return The response that came from the SMC. + */ +int tonga_dpm_force_state_pcie(struct pp_hwmgr *hwmgr, uint32_t n) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + PP_ASSERT_WITH_CODE(0 == tonga_is_dpm_running(hwmgr), + "Trying to Force PCIE level when DPM is disabled", return -1;); + if (0 == data->pcie_dpm_key_disabled) + return (0 == smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + (PPSMC_Msg)(PPSMC_MSG_PCIeDPM_ForceLevel), + n) ? 0 : 1); + + return 0; +} + +/** + * Set the initial state by calling SMC to switch to this state directly + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_set_boot_state(struct pp_hwmgr *hwmgr) +{ + /* + * SMC only stores one state that SW will ask to switch too, + * so we switch the the just uploaded one + */ + return (0 == tonga_disable_sclk_mclk_dpm(hwmgr)) ? 0 : 1; +} + +/** + * Get the location of various tables inside the FW image. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_process_firmware_header(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct tonga_smumgr *tonga_smu = (struct tonga_smumgr *)(hwmgr->smumgr->backend); + + uint32_t tmp; + int result; + bool error = 0; + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, DpmTable), + &tmp, data->sram_end); + + if (0 == result) { + data->dpm_table_start = tmp; + } + + error |= (0 != result); + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, SoftRegisters), + &tmp, data->sram_end); + + if (0 == result) { + data->soft_regs_start = tmp; + tonga_smu->ulSoftRegsStart = tmp; + } + + error |= (0 != result); + + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcRegisterTable), + &tmp, data->sram_end); + + if (0 == result) { + data->mc_reg_table_start = tmp; + } + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, FanTable), + &tmp, data->sram_end); + + if (0 == result) { + data->fan_table_start = tmp; + } + + error |= (0 != result); + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, mcArbDramTimingTable), + &tmp, data->sram_end); + + if (0 == result) { + data->arb_table_start = tmp; + } + + error |= (0 != result); + + + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + SMU72_FIRMWARE_HEADER_LOCATION + + offsetof(SMU72_Firmware_Header, Version), + &tmp, data->sram_end); + + if (0 == result) { + hwmgr->microcode_version_info.SMC = tmp; + } + + error |= (0 != result); + + return error ? 1 : 0; +} + +/** + * Read clock related registers. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_read_clock_registers(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + data->clock_registers.vCG_SPLL_FUNC_CNTL = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL); + data->clock_registers.vCG_SPLL_FUNC_CNTL_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_2); + data->clock_registers.vCG_SPLL_FUNC_CNTL_3 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_3); + data->clock_registers.vCG_SPLL_FUNC_CNTL_4 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_FUNC_CNTL_4); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM); + data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2 = + cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_SPLL_SPREAD_SPECTRUM_2); + data->clock_registers.vDLL_CNTL = + cgs_read_register(hwmgr->device, mmDLL_CNTL); + data->clock_registers.vMCLK_PWRMGT_CNTL = + cgs_read_register(hwmgr->device, mmMCLK_PWRMGT_CNTL); + data->clock_registers.vMPLL_AD_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_AD_FUNC_CNTL); + data->clock_registers.vMPLL_DQ_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_DQ_FUNC_CNTL); + data->clock_registers.vMPLL_FUNC_CNTL = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL); + data->clock_registers.vMPLL_FUNC_CNTL_1 = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_1); + data->clock_registers.vMPLL_FUNC_CNTL_2 = + cgs_read_register(hwmgr->device, mmMPLL_FUNC_CNTL_2); + data->clock_registers.vMPLL_SS1 = + cgs_read_register(hwmgr->device, mmMPLL_SS1); + data->clock_registers.vMPLL_SS2 = + cgs_read_register(hwmgr->device, mmMPLL_SS2); + + return 0; +} + +/** + * Find out if memory is GDDR5. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_get_memory_type(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t temp; + + temp = cgs_read_register(hwmgr->device, mmMC_SEQ_MISC0); + + data->is_memory_GDDR5 = (MC_SEQ_MISC0_GDDR5_VALUE == + ((temp & MC_SEQ_MISC0_GDDR5_MASK) >> + MC_SEQ_MISC0_GDDR5_SHIFT)); + + return 0; +} + +/** + * Enables Dynamic Power Management by SMC + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_enable_acpi_power_management(struct pp_hwmgr *hwmgr) +{ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, STATIC_PM_EN, 1); + + return 0; +} + +/** + * Initialize PowerGating States for different engines + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_init_power_gate_state(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + data->uvd_power_gated = 0; + data->vce_power_gated = 0; + data->samu_power_gated = 0; + data->acp_power_gated = 0; + data->pg_acp_init = 1; + + return 0; +} + +/** + * Checks if DPM is enabled + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_check_for_dpm_running(struct pp_hwmgr *hwmgr) +{ + /* + * We return the status of Voltage Control instead of checking SCLK/MCLK DPM + * because we may have test scenarios that need us intentionly disable SCLK/MCLK DPM, + * whereas voltage control is a fundemental change that will not be disabled + */ + return (0 == tonga_is_dpm_running(hwmgr) ? 0 : 1); +} + +/** + * Checks if DPM is stopped + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_check_for_dpm_stopped(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + if (0 != tonga_is_dpm_running(hwmgr)) { + /* If HW Virtualization is enabled, dpm_table_start will not have a valid value */ + if (!data->dpm_table_start) { + return 1; + } + } + + return 0; +} + +/** + * Remove repeated voltage values and create table with unique values. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param voltage_table the pointer to changing voltage table + * @return 1 in success + */ + +static int tonga_trim_voltage_table(struct pp_hwmgr *hwmgr, + pp_atomctrl_voltage_table *voltage_table) +{ + uint32_t table_size, i, j; + uint16_t vvalue; + bool bVoltageFound = 0; + pp_atomctrl_voltage_table *table; + + PP_ASSERT_WITH_CODE((NULL != voltage_table), "Voltage Table empty.", return -1;); + table_size = sizeof(pp_atomctrl_voltage_table); + table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -ENOMEM; + + memset(table, 0x00, table_size); + table->mask_low = voltage_table->mask_low; + table->phase_delay = voltage_table->phase_delay; + + for (i = 0; i < voltage_table->count; i++) { + vvalue = voltage_table->entries[i].value; + bVoltageFound = 0; + + for (j = 0; j < table->count; j++) { + if (vvalue == table->entries[j].value) { + bVoltageFound = 1; + break; + } + } + + if (!bVoltageFound) { + table->entries[table->count].value = vvalue; + table->entries[table->count].smio_low = + voltage_table->entries[i].smio_low; + table->count++; + } + } + + memcpy(table, voltage_table, sizeof(pp_atomctrl_voltage_table)); + + kfree(table); + + return 0; +} + +static int tonga_get_svi2_vdd_ci_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *voltage_dependency_table) +{ + uint32_t i; + int result; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + pp_atomctrl_voltage_table *vddci_voltage_table = &(data->vddci_voltage_table); + + PP_ASSERT_WITH_CODE((0 != voltage_dependency_table->count), + "Voltage Dependency Table empty.", return -1;); + + vddci_voltage_table->mask_low = 0; + vddci_voltage_table->phase_delay = 0; + vddci_voltage_table->count = voltage_dependency_table->count; + + for (i = 0; i < voltage_dependency_table->count; i++) { + vddci_voltage_table->entries[i].value = + voltage_dependency_table->entries[i].vddci; + vddci_voltage_table->entries[i].smio_low = 0; + } + + result = tonga_trim_voltage_table(hwmgr, vddci_voltage_table); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to trim VDDCI table.", return result;); + + return 0; +} + + + +static int tonga_get_svi2_vdd_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *look_up_table, + pp_atomctrl_voltage_table *voltage_table) +{ + uint8_t i = 0; + + PP_ASSERT_WITH_CODE((0 != look_up_table->count), + "Voltage Lookup Table empty.", return -1;); + + voltage_table->mask_low = 0; + voltage_table->phase_delay = 0; + + voltage_table->count = look_up_table->count; + + for (i = 0; i < voltage_table->count; i++) { + voltage_table->entries[i].value = look_up_table->entries[i].us_vdd; + voltage_table->entries[i].smio_low = 0; + } + + return 0; +} + +/* + * -------------------------------------------------------- Voltage Tables -------------------------------------------------------------------------- + * If the voltage table would be bigger than what will fit into the state table on the SMC keep only the higher entries. + */ + +static void tonga_trim_voltage_table_to_fit_state_table( + struct pp_hwmgr *hwmgr, + uint32_t max_voltage_steps, + pp_atomctrl_voltage_table *voltage_table) +{ + unsigned int i, diff; + + if (voltage_table->count <= max_voltage_steps) { + return; + } + + diff = voltage_table->count - max_voltage_steps; + + for (i = 0; i < max_voltage_steps; i++) { + voltage_table->entries[i] = voltage_table->entries[i + diff]; + } + + voltage_table->count = max_voltage_steps; + + return; +} + +/** + * Create Voltage Tables. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_construct_voltage_tables(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result; + + /* MVDD has only GPIO voltage control */ + if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT, &(data->mvdd_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve MVDD table.", return result;); + } + + if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) { + /* GPIO voltage */ + result = atomctrl_get_voltage_table_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT, &(data->vddci_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve VDDCI table.", return result;); + } else if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) { + /* SVI2 voltage */ + result = tonga_get_svi2_vdd_ci_voltage_table(hwmgr, + pptable_info->vdd_dep_on_mclk); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDCI table from dependancy table.", return result;); + } + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + /* VDDGFX has only SVI2 voltage control */ + result = tonga_get_svi2_vdd_voltage_table(hwmgr, + pptable_info->vddgfx_lookup_table, &(data->vddgfx_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDGFX table from lookup table.", return result;); + } + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + /* VDDC has only SVI2 voltage control */ + result = tonga_get_svi2_vdd_voltage_table(hwmgr, + pptable_info->vddc_lookup_table, &(data->vddc_voltage_table)); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to retrieve SVI2 VDDC table from lookup table.", return result;); + } + + PP_ASSERT_WITH_CODE( + (data->vddc_voltage_table.count <= (SMU72_MAX_LEVELS_VDDC)), + "Too many voltage values for VDDC. Trimming to fit state table.", + tonga_trim_voltage_table_to_fit_state_table(hwmgr, + SMU72_MAX_LEVELS_VDDC, &(data->vddc_voltage_table)); + ); + + PP_ASSERT_WITH_CODE( + (data->vddgfx_voltage_table.count <= (SMU72_MAX_LEVELS_VDDGFX)), + "Too many voltage values for VDDGFX. Trimming to fit state table.", + tonga_trim_voltage_table_to_fit_state_table(hwmgr, + SMU72_MAX_LEVELS_VDDGFX, &(data->vddgfx_voltage_table)); + ); + + PP_ASSERT_WITH_CODE( + (data->vddci_voltage_table.count <= (SMU72_MAX_LEVELS_VDDCI)), + "Too many voltage values for VDDCI. Trimming to fit state table.", + tonga_trim_voltage_table_to_fit_state_table(hwmgr, + SMU72_MAX_LEVELS_VDDCI, &(data->vddci_voltage_table)); + ); + + PP_ASSERT_WITH_CODE( + (data->mvdd_voltage_table.count <= (SMU72_MAX_LEVELS_MVDD)), + "Too many voltage values for MVDD. Trimming to fit state table.", + tonga_trim_voltage_table_to_fit_state_table(hwmgr, + SMU72_MAX_LEVELS_MVDD, &(data->mvdd_voltage_table)); + ); + + return 0; +} + +/** + * Vddc table preparation for SMC. + * + * @param hwmgr the address of the hardware manager + * @param table the SMC DPM table structure to be populated + * @return always 0 + */ +static int tonga_populate_smc_vddc_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + table->VddcLevelCount = data->vddc_voltage_table.count; + for (count = 0; count < table->VddcLevelCount; count++) { + table->VddcTable[count] = + PP_HOST_TO_SMC_US(data->vddc_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddcLevelCount); + } + return 0; +} + +/** + * VddGfx table preparation for SMC. + * + * @param hwmgr the address of the hardware manager + * @param table the SMC DPM table structure to be populated + * @return always 0 + */ +static int tonga_populate_smc_vdd_gfx_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + unsigned int count; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + table->VddGfxLevelCount = data->vddgfx_voltage_table.count; + for (count = 0; count < data->vddgfx_voltage_table.count; count++) { + table->VddGfxTable[count] = + PP_HOST_TO_SMC_US(data->vddgfx_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->VddGfxLevelCount); + } + return 0; +} + +/** + * Vddci table preparation for SMC. + * + * @param *hwmgr The address of the hardware manager. + * @param *table The SMC DPM table structure to be populated. + * @return 0 + */ +static int tonga_populate_smc_vdd_ci_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t count; + + table->VddciLevelCount = data->vddci_voltage_table.count; + for (count = 0; count < table->VddciLevelCount; count++) { + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) { + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) { + table->SmioTable1.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level. */ + table->SmioTable1.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->vddci_voltage_table.entries[count].smio_low; + table->VddciTable[count] = + PP_HOST_TO_SMC_US(data->vddci_voltage_table.entries[count].value * VOLTAGE_SCALE); + } + } + + table->SmioMask1 = data->vddci_voltage_table.mask_low; + CONVERT_FROM_HOST_TO_SMC_UL(table->VddciLevelCount); + + return 0; +} + +/** + * Mvdd table preparation for SMC. + * + * @param *hwmgr The address of the hardware manager. + * @param *table The SMC DPM table structure to be populated. + * @return 0 + */ +static int tonga_populate_smc_mvdd_table(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t count; + + if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + table->MvddLevelCount = data->mvdd_voltage_table.count; + for (count = 0; count < table->MvddLevelCount; count++) { + table->SmioTable2.Pattern[count].Voltage = + PP_HOST_TO_SMC_US(data->mvdd_voltage_table.entries[count].value * VOLTAGE_SCALE); + /* Index into DpmTable.Smio. Drive bits from Smio entry to get this voltage level.*/ + table->SmioTable2.Pattern[count].Smio = + (uint8_t) count; + table->Smio[count] |= + data->mvdd_voltage_table.entries[count].smio_low; + } + table->SmioMask2 = data->vddci_voltage_table.mask_low; + + CONVERT_FROM_HOST_TO_SMC_UL(table->MvddLevelCount); + } + + return 0; +} + +/** + * Convert a voltage value in mv unit to VID number required by SMU firmware + */ +static uint8_t convert_to_vid(uint16_t vddc) +{ + return (uint8_t) ((6200 - (vddc * VOLTAGE_SCALE)) / 25); +} + + +/** + * Preparation of vddc and vddgfx CAC tables for SMC. + * + * @param hwmgr the address of the hardware manager + * @param table the SMC DPM table structure to be populated + * @return always 0 + */ +static int tonga_populate_cac_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + uint32_t count; + uint8_t index; + int result = 0; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table = pptable_info->vddgfx_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table = pptable_info->vddc_lookup_table; + + /* pTables is already swapped, so in order to use the value from it, we need to swap it back. */ + uint32_t vddcLevelCount = PP_SMC_TO_HOST_UL(table->VddcLevelCount); + uint32_t vddgfxLevelCount = PP_SMC_TO_HOST_UL(table->VddGfxLevelCount); + + for (count = 0; count < vddcLevelCount; count++) { + /* We are populating vddc CAC data to BapmVddc table in split and merged mode */ + index = tonga_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddcVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddcVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddcVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + + if ((data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2)) { + /* We are populating vddgfx CAC data to BapmVddgfx table in split mode */ + for (count = 0; count < vddgfxLevelCount; count++) { + index = tonga_get_voltage_index(vddgfx_lookup_table, + data->vddgfx_voltage_table.entries[count].value); + table->BapmVddGfxVidLoSidd[count] = + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_low); + table->BapmVddGfxVidHiSidd[count] = + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_mid); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddgfx_lookup_table->entries[index].us_cac_high); + } + } else { + for (count = 0; count < vddcLevelCount; count++) { + index = tonga_get_voltage_index(vddc_lookup_table, + data->vddc_voltage_table.entries[count].value); + table->BapmVddGfxVidLoSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_low); + table->BapmVddGfxVidHiSidd[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_mid); + table->BapmVddGfxVidHiSidd2[count] = + convert_to_vid(vddc_lookup_table->entries[index].us_cac_high); + } + } + + return result; +} + + +/** + * Preparation of voltage tables for SMC. + * + * @param hwmgr the address of the hardware manager + * @param table the SMC DPM table structure to be populated + * @return always 0 + */ + +int tonga_populate_smc_voltage_tables(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result; + + result = tonga_populate_smc_vddc_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDC voltage table to SMC", return -1); + + result = tonga_populate_smc_vdd_ci_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDCI voltage table to SMC", return -1); + + result = tonga_populate_smc_vdd_gfx_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate VDDGFX voltage table to SMC", return -1); + + result = tonga_populate_smc_mvdd_table(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate MVDD voltage table to SMC", return -1); + + result = tonga_populate_cac_tables(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "can not populate CAC voltage tables to SMC", return -1); + + return 0; +} + +/** + * Populates the SMC VRConfig field in DPM table. + * + * @param hwmgr the address of the hardware manager + * @param table the SMC DPM table structure to be populated + * @return always 0 + */ +static int tonga_populate_vr_config(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint16_t config; + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_gfx_control) { + /* Splitted mode */ + config = VR_SVI2_PLANE_1; + table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); + + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_2; + table->VRConfig |= config; + } else { + printk(KERN_ERR "[ powerplay ] VDDC and VDDGFX should be both on SVI2 control in splitted mode! \n"); + } + } else { + /* Merged mode */ + config = VR_MERGED_WITH_VDDC; + table->VRConfig |= (config<<VRCONF_VDDGFX_SHIFT); + + /* Set Vddc Voltage Controller */ + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->voltage_control) { + config = VR_SVI2_PLANE_1; + table->VRConfig |= config; + } else { + printk(KERN_ERR "[ powerplay ] VDDC should be on SVI2 control in merged mode! \n"); + } + } + + /* Set Vddci Voltage Controller */ + if (TONGA_VOLTAGE_CONTROL_BY_SVID2 == data->vdd_ci_control) { + config = VR_SVI2_PLANE_2; /* only in merged mode */ + table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); + } else if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->vdd_ci_control) { + config = VR_SMIO_PATTERN_1; + table->VRConfig |= (config<<VRCONF_VDDCI_SHIFT); + } + + /* Set Mvdd Voltage Controller */ + if (TONGA_VOLTAGE_CONTROL_BY_GPIO == data->mvdd_control) { + config = VR_SMIO_PATTERN_2; + table->VRConfig |= (config<<VRCONF_MVDD_SHIFT); + } + + return 0; +} + +static int tonga_get_dependecy_volt_by_clk(struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table *allowed_clock_voltage_table, + uint32_t clock, SMU_VoltageLevel *voltage, uint32_t *mvdd) +{ + uint32_t i = 0; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + /* clock - voltage dependency table is empty table */ + if (allowed_clock_voltage_table->count == 0) + return -1; + + for (i = 0; i < allowed_clock_voltage_table->count; i++) { + /* find first sclk bigger than request */ + if (allowed_clock_voltage_table->entries[i].clk >= clock) { + voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i].vddgfx); + + voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i].vddc); + + if (allowed_clock_voltage_table->entries[i].vddci) { + voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i].vddci); + } else { + voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i].vddc - data->vddc_vddci_delta); + } + + if (allowed_clock_voltage_table->entries[i].mvdd) { + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i].mvdd; + } + + voltage->Phases = 1; + return 0; + } + } + + /* sclk is bigger than max sclk in the dependence table */ + voltage->VddGfx = tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddgfx); + voltage->Vddc = tonga_get_voltage_index(pptable_info->vddc_lookup_table, + allowed_clock_voltage_table->entries[i-1].vddc); + + if (allowed_clock_voltage_table->entries[i-1].vddci) { + voltage->Vddci = tonga_get_voltage_id(&data->vddci_voltage_table, + allowed_clock_voltage_table->entries[i-1].vddci); + } + if (allowed_clock_voltage_table->entries[i-1].mvdd) { + *mvdd = (uint32_t) allowed_clock_voltage_table->entries[i-1].mvdd; + } + + return 0; +} + +/** + * Call SMC to reset S0/S1 to S1 and Reset SMIO to initial value + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_reset_to_default(struct pp_hwmgr *hwmgr) +{ + return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_ResetToDefaults) == 0) ? 0 : 1; +} + +int tonga_populate_memory_timing_parameters( + struct pp_hwmgr *hwmgr, + uint32_t engine_clock, + uint32_t memory_clock, + struct SMU72_Discrete_MCArbDramTimingTableEntry *arb_regs + ) +{ + uint32_t dramTiming; + uint32_t dramTiming2; + uint32_t burstTime; + int result; + + result = atomctrl_set_engine_dram_timings_rv770(hwmgr, + engine_clock, memory_clock); + + PP_ASSERT_WITH_CODE(result == 0, + "Error calling VBIOS to set DRAM_TIMING.", return result); + + dramTiming = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + dramTiming2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burstTime = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + + arb_regs->McArbDramTiming = PP_HOST_TO_SMC_UL(dramTiming); + arb_regs->McArbDramTiming2 = PP_HOST_TO_SMC_UL(dramTiming2); + arb_regs->McArbBurstTime = (uint8_t)burstTime; + + return 0; +} + +/** + * Setup parameters for the MC ARB. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + * This function is to be called from the SetPowerState table. + */ +int tonga_program_memory_timing_parameters(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + int result = 0; + SMU72_Discrete_MCArbDramTimingTable arb_regs; + uint32_t i, j; + + memset(&arb_regs, 0x00, sizeof(SMU72_Discrete_MCArbDramTimingTable)); + + for (i = 0; i < data->dpm_table.sclk_table.count; i++) { + for (j = 0; j < data->dpm_table.mclk_table.count; j++) { + result = tonga_populate_memory_timing_parameters + (hwmgr, data->dpm_table.sclk_table.dpm_levels[i].value, + data->dpm_table.mclk_table.dpm_levels[j].value, + &arb_regs.entries[i][j]); + + if (0 != result) { + break; + } + } + } + + if (0 == result) { + result = tonga_copy_bytes_to_smc( + hwmgr->smumgr, + data->arb_table_start, + (uint8_t *)&arb_regs, + sizeof(SMU72_Discrete_MCArbDramTimingTable), + data->sram_end + ); + } + + return result; +} + +static int tonga_populate_smc_link_level(struct pp_hwmgr *hwmgr, SMU72_Discrete_DpmTable *table) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct tonga_dpm_table *dpm_table = &data->dpm_table; + uint32_t i; + + /* Index (dpm_table->pcie_speed_table.count) is reserved for PCIE boot level. */ + for (i = 0; i <= dpm_table->pcie_speed_table.count; i++) { + table->LinkLevel[i].PcieGenSpeed = + (uint8_t)dpm_table->pcie_speed_table.dpm_levels[i].value; + table->LinkLevel[i].PcieLaneCount = + (uint8_t)encode_pcie_lane_width(dpm_table->pcie_speed_table.dpm_levels[i].param1); + table->LinkLevel[i].EnabledForActivity = + 1; + table->LinkLevel[i].SPC = + (uint8_t)(data->pcie_spc_cap & 0xff); + table->LinkLevel[i].DownThreshold = + PP_HOST_TO_SMC_UL(5); + table->LinkLevel[i].UpThreshold = + PP_HOST_TO_SMC_UL(30); + } + + data->smc_state_table.LinkLevelCount = + (uint8_t)dpm_table->pcie_speed_table.count; + data->dpm_level_enable_mask.pcie_dpm_enable_mask = + tonga_get_dpm_level_enable_mask_value(&dpm_table->pcie_speed_table); + + return 0; +} + +static int tonga_populate_smc_uvd_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + table->UvdLevelCount = (uint8_t) (mm_table->count); + table->UvdBootLevel = 0; + + for (count = 0; count < table->UvdLevelCount; count++) { + table->UvdLevel[count].VclkFrequency = mm_table->entries[count].vclk; + table->UvdLevel[count].DclkFrequency = mm_table->entries[count].dclk; + table->UvdLevel[count].MinVoltage.Vddc = + tonga_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->UvdLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ? + tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->UvdLevel[count].MinVoltage.Vddci = + tonga_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - data->vddc_vddci_delta); + table->UvdLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].VclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Vclk clock", return result); + + table->UvdLevel[count].VclkDivider = (uint8_t)dividers.pll_post_divider; + + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->UvdLevel[count].DclkFrequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for Dclk clock", return result); + + table->UvdLevel[count].DclkDivider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].VclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->UvdLevel[count].DclkFrequency); + //CONVERT_FROM_HOST_TO_SMC_UL((uint32_t)table->UvdLevel[count].MinVoltage); + } + + return result; + +} + +static int tonga_populate_smc_vce_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + table->VceLevelCount = (uint8_t) (mm_table->count); + table->VceBootLevel = 0; + + for (count = 0; count < table->VceLevelCount; count++) { + table->VceLevel[count].Frequency = + mm_table->entries[count].eclk; + table->VceLevel[count].MinVoltage.Vddc = + tonga_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->VceLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ? + tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->VceLevel[count].MinVoltage.Vddci = + tonga_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - data->vddc_vddci_delta); + table->VceLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->VceLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for VCE engine clock", return result); + + table->VceLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->VceLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_smc_acp_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + table->AcpLevelCount = (uint8_t) (mm_table->count); + table->AcpBootLevel = 0; + + for (count = 0; count < table->AcpLevelCount; count++) { + table->AcpLevel[count].Frequency = + pptable_info->mm_dep_table->entries[count].aclk; + table->AcpLevel[count].MinVoltage.Vddc = + tonga_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->AcpLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ? + tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->AcpLevel[count].MinVoltage.Vddci = + tonga_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - data->vddc_vddci_delta); + table->AcpLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->AcpLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for engine clock", return result); + + table->AcpLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->AcpLevel[count].Frequency); + } + + return result; +} + +static int tonga_populate_smc_samu_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + uint8_t count; + pp_atomctrl_clock_dividers_vi dividers; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + table->SamuBootLevel = 0; + table->SamuLevelCount = (uint8_t) (mm_table->count); + + for (count = 0; count < table->SamuLevelCount; count++) { + /* not sure whether we need evclk or not */ + table->SamuLevel[count].Frequency = + pptable_info->mm_dep_table->entries[count].samclock; + table->SamuLevel[count].MinVoltage.Vddc = + tonga_get_voltage_index(pptable_info->vddc_lookup_table, + mm_table->entries[count].vddc); + table->SamuLevel[count].MinVoltage.VddGfx = + (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) ? + tonga_get_voltage_index(pptable_info->vddgfx_lookup_table, + mm_table->entries[count].vddgfx) : 0; + table->SamuLevel[count].MinVoltage.Vddci = + tonga_get_voltage_id(&data->vddci_voltage_table, + mm_table->entries[count].vddc - data->vddc_vddci_delta); + table->SamuLevel[count].MinVoltage.Phases = 1; + + /* retrieve divider value for VBIOS */ + result = atomctrl_get_dfs_pll_dividers_vi(hwmgr, + table->SamuLevel[count].Frequency, ÷rs); + PP_ASSERT_WITH_CODE((0 == result), + "can not find divide id for samu clock", return result); + + table->SamuLevel[count].Divider = (uint8_t)dividers.pll_post_divider; + + CONVERT_FROM_HOST_TO_SMC_UL(table->SamuLevel[count].Frequency); + } + + return result; +} + +/** + * Populates the SMC MCLK structure using the provided memory clock + * + * @param hwmgr the address of the hardware manager + * @param memory_clock the memory clock to use to populate the structure + * @param sclk the SMC SCLK structure to be populated + */ +static int tonga_calculate_mclk_params( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *mclk, + bool strobe_mode, + bool dllStateOn + ) +{ + const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + uint32_t mpll_ad_func_cntl = data->clock_registers.vMPLL_AD_FUNC_CNTL; + uint32_t mpll_dq_func_cntl = data->clock_registers.vMPLL_DQ_FUNC_CNTL; + uint32_t mpll_func_cntl = data->clock_registers.vMPLL_FUNC_CNTL; + uint32_t mpll_func_cntl_1 = data->clock_registers.vMPLL_FUNC_CNTL_1; + uint32_t mpll_func_cntl_2 = data->clock_registers.vMPLL_FUNC_CNTL_2; + uint32_t mpll_ss1 = data->clock_registers.vMPLL_SS1; + uint32_t mpll_ss2 = data->clock_registers.vMPLL_SS2; + + pp_atomctrl_memory_clock_param mpll_param; + int result; + + result = atomctrl_get_memory_pll_dividers_si(hwmgr, + memory_clock, &mpll_param, strobe_mode); + PP_ASSERT_WITH_CODE(0 == result, + "Error retrieving Memory Clock Parameters from VBIOS.", return result); + + /* MPLL_FUNC_CNTL setup*/ + mpll_func_cntl = PHM_SET_FIELD(mpll_func_cntl, MPLL_FUNC_CNTL, BWCTRL, mpll_param.bw_ctrl); + + /* MPLL_FUNC_CNTL_1 setup*/ + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKF, mpll_param.mpll_fb_divider.cl_kf); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, CLKFRAC, mpll_param.mpll_fb_divider.clk_frac); + mpll_func_cntl_1 = PHM_SET_FIELD(mpll_func_cntl_1, + MPLL_FUNC_CNTL_1, VCO_MODE, mpll_param.vco_mode); + + /* MPLL_AD_FUNC_CNTL setup*/ + mpll_ad_func_cntl = PHM_SET_FIELD(mpll_ad_func_cntl, + MPLL_AD_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + + if (data->is_memory_GDDR5) { + /* MPLL_DQ_FUNC_CNTL setup*/ + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_SEL, mpll_param.yclk_sel); + mpll_dq_func_cntl = PHM_SET_FIELD(mpll_dq_func_cntl, + MPLL_DQ_FUNC_CNTL, YCLK_POST_DIV, mpll_param.mpll_post_divider); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MemorySpreadSpectrumSupport)) { + /* + ************************************ + Fref = Reference Frequency + NF = Feedback divider ratio + NR = Reference divider ratio + Fnom = Nominal VCO output frequency = Fref * NF / NR + Fs = Spreading Rate + D = Percentage down-spread / 2 + Fint = Reference input frequency to PFD = Fref / NR + NS = Spreading rate divider ratio = int(Fint / (2 * Fs)) + CLKS = NS - 1 = ISS_STEP_NUM[11:0] + NV = D * Fs / Fnom * 4 * ((Fnom/Fref * NR) ^ 2) + CLKV = 65536 * NV = ISS_STEP_SIZE[25:0] + ************************************* + */ + pp_atomctrl_internal_ss_info ss_info; + uint32_t freq_nom; + uint32_t tmp; + uint32_t reference_clock = atomctrl_get_mpll_reference_clock(hwmgr); + + /* for GDDR5 for all modes and DDR3 */ + if (1 == mpll_param.qdr) + freq_nom = memory_clock * 4 * (1 << mpll_param.mpll_post_divider); + else + freq_nom = memory_clock * 2 * (1 << mpll_param.mpll_post_divider); + + /* tmp = (freq_nom / reference_clock * reference_divider) ^ 2 Note: S.I. reference_divider = 1*/ + tmp = (freq_nom / reference_clock); + tmp = tmp * tmp; + + if (0 == atomctrl_get_memory_clock_spread_spectrum(hwmgr, freq_nom, &ss_info)) { + /* ss_info.speed_spectrum_percentage -- in unit of 0.01% */ + /* ss.Info.speed_spectrum_rate -- in unit of khz */ + /* CLKS = reference_clock / (2 * speed_spectrum_rate * reference_divider) * 10 */ + /* = reference_clock * 5 / speed_spectrum_rate */ + uint32_t clks = reference_clock * 5 / ss_info.speed_spectrum_rate; + + /* CLKV = 65536 * speed_spectrum_percentage / 2 * spreadSpecrumRate / freq_nom * 4 / 100000 * ((freq_nom / reference_clock) ^ 2) */ + /* = 131 * speed_spectrum_percentage * speed_spectrum_rate / 100 * ((freq_nom / reference_clock) ^ 2) / freq_nom */ + uint32_t clkv = + (uint32_t)((((131 * ss_info.speed_spectrum_percentage * + ss_info.speed_spectrum_rate) / 100) * tmp) / freq_nom); + + mpll_ss1 = PHM_SET_FIELD(mpll_ss1, MPLL_SS1, CLKV, clkv); + mpll_ss2 = PHM_SET_FIELD(mpll_ss2, MPLL_SS2, CLKS, clks); + } + } + + /* MCLK_PWRMGT_CNTL setup */ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, DLL_SPEED, mpll_param.dll_speed); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, dllStateOn); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, dllStateOn); + + + /* Save the result data to outpupt memory level structure */ + mclk->MclkFrequency = memory_clock; + mclk->MpllFuncCntl = mpll_func_cntl; + mclk->MpllFuncCntl_1 = mpll_func_cntl_1; + mclk->MpllFuncCntl_2 = mpll_func_cntl_2; + mclk->MpllAdFuncCntl = mpll_ad_func_cntl; + mclk->MpllDqFuncCntl = mpll_dq_func_cntl; + mclk->MclkPwrmgtCntl = mclk_pwrmgt_cntl; + mclk->DllCntl = dll_cntl; + mclk->MpllSs1 = mpll_ss1; + mclk->MpllSs2 = mpll_ss2; + + return 0; +} + +static uint8_t tonga_get_mclk_frequency_ratio(uint32_t memory_clock, + bool strobe_mode) +{ + uint8_t mc_para_index; + + if (strobe_mode) { + if (memory_clock < 12500) { + mc_para_index = 0x00; + } else if (memory_clock > 47500) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 2500); + } + } else { + if (memory_clock < 65000) { + mc_para_index = 0x00; + } else if (memory_clock > 135000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 60000) / 5000); + } + } + + return mc_para_index; +} + +static uint8_t tonga_get_ddr3_mclk_frequency_ratio(uint32_t memory_clock) +{ + uint8_t mc_para_index; + + if (memory_clock < 10000) { + mc_para_index = 0; + } else if (memory_clock >= 80000) { + mc_para_index = 0x0f; + } else { + mc_para_index = (uint8_t)((memory_clock - 10000) / 5000 + 1); + } + + return mc_para_index; +} + +static int tonga_populate_single_memory_level( + struct pp_hwmgr *hwmgr, + uint32_t memory_clock, + SMU72_Discrete_MemoryLevel *memory_level + ) +{ + uint32_t minMvdd = 0; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + int result = 0; + bool dllStateOn; + struct cgs_display_info info = {0}; + + + if (NULL != pptable_info->vdd_dep_on_mclk) { + result = tonga_get_dependecy_volt_by_clk(hwmgr, + pptable_info->vdd_dep_on_mclk, memory_clock, &memory_level->MinVoltage, &minMvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find MinVddc voltage value from memory VDDC voltage dependency table", return result); + } + + if (data->mvdd_control == TONGA_VOLTAGE_CONTROL_NONE) { + memory_level->MinMvdd = data->vbios_boot_state.mvdd_bootup_value; + } else { + memory_level->MinMvdd = minMvdd; + } + memory_level->EnabledForThrottle = 1; + memory_level->EnabledForActivity = 0; + memory_level->UpHyst = 0; + memory_level->DownHyst = 100; + memory_level->VoltageDownHyst = 0; + + /* Indicates maximum activity level for this performance level.*/ + memory_level->ActivityLevel = (uint16_t)data->mclk_activity_target; + memory_level->StutterEnable = 0; + memory_level->StrobeEnable = 0; + memory_level->EdcReadEnable = 0; + memory_level->EdcWriteEnable = 0; + memory_level->RttEnable = 0; + + /* default set to low watermark. Highest level will be set to high later.*/ + memory_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + cgs_get_active_displays_info(hwmgr->device, &info); + data->display_timing.num_existing_displays = info.display_count; + + if ((data->mclk_stutter_mode_threshold != 0) && + (memory_clock <= data->mclk_stutter_mode_threshold) && + (data->is_uvd_enabled == 0) +#if defined(LINUX) + && (PHM_READ_FIELD(hwmgr->device, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE) & 0x1) + && (data->display_timing.num_existing_displays <= 2) + && (data->display_timing.num_existing_displays != 0) +#endif + ) + memory_level->StutterEnable = 1; + + /* decide strobe mode*/ + memory_level->StrobeEnable = (data->mclk_strobe_mode_threshold != 0) && + (memory_clock <= data->mclk_strobe_mode_threshold); + + /* decide EDC mode and memory clock ratio*/ + if (data->is_memory_GDDR5) { + memory_level->StrobeRatio = tonga_get_mclk_frequency_ratio(memory_clock, + memory_level->StrobeEnable); + + if ((data->mclk_edc_enable_threshold != 0) && + (memory_clock > data->mclk_edc_enable_threshold)) { + memory_level->EdcReadEnable = 1; + } + + if ((data->mclk_edc_wr_enable_threshold != 0) && + (memory_clock > data->mclk_edc_wr_enable_threshold)) { + memory_level->EdcWriteEnable = 1; + } + + if (memory_level->StrobeEnable) { + if (tonga_get_mclk_frequency_ratio(memory_clock, 1) >= + ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC7) >> 16) & 0xf)) { + dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } else { + dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC6) >> 1) & 0x1) ? 1 : 0; + } + + } else { + dllStateOn = data->dll_defaule_on; + } + } else { + memory_level->StrobeRatio = + tonga_get_ddr3_mclk_frequency_ratio(memory_clock); + dllStateOn = ((cgs_read_register(hwmgr->device, mmMC_SEQ_MISC5) >> 1) & 0x1) ? 1 : 0; + } + + result = tonga_calculate_mclk_params(hwmgr, + memory_clock, memory_level, memory_level->StrobeEnable, dllStateOn); + + if (0 == result) { + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MinMvdd); + /* MCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkFrequency); + /* Indicates maximum activity level for this performance level.*/ + CONVERT_FROM_HOST_TO_SMC_US(memory_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllFuncCntl_2); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllAdFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllDqFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MclkPwrmgtCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->DllCntl); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs1); + CONVERT_FROM_HOST_TO_SMC_UL(memory_level->MpllSs2); + } + + return result; +} + +/** + * Populates the SMC MVDD structure using the provided memory clock. + * + * @param hwmgr the address of the hardware manager + * @param mclk the MCLK value to be used in the decision if MVDD should be high or low. + * @param voltage the SMC VOLTAGE structure to be populated + */ +int tonga_populate_mvdd_value(struct pp_hwmgr *hwmgr, uint32_t mclk, SMIO_Pattern *smio_pattern) +{ + const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i = 0; + + if (TONGA_VOLTAGE_CONTROL_NONE != data->mvdd_control) { + /* find mvdd value which clock is more than request */ + for (i = 0; i < pptable_info->vdd_dep_on_mclk->count; i++) { + if (mclk <= pptable_info->vdd_dep_on_mclk->entries[i].clk) { + /* Always round to higher voltage. */ + smio_pattern->Voltage = data->mvdd_voltage_table.entries[i].value; + break; + } + } + + PP_ASSERT_WITH_CODE(i < pptable_info->vdd_dep_on_mclk->count, + "MVDD Voltage is outside the supported range.", return -1); + + } else { + return -1; + } + + return 0; +} + + +static int tonga_populate_smv_acpi_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + SMIO_Pattern voltage_level; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_2 = data->clock_registers.vCG_SPLL_FUNC_CNTL_2; + uint32_t dll_cntl = data->clock_registers.vDLL_CNTL; + uint32_t mclk_pwrmgt_cntl = data->clock_registers.vMCLK_PWRMGT_CNTL; + + /* The ACPI state should not do DPM on DC (or ever).*/ + table->ACPILevel.Flags &= ~PPSMC_SWSTATE_FLAG_DC; + + table->ACPILevel.MinVoltage = data->smc_state_table.GraphicsLevel[0].MinVoltage; + + /* assign zero for now*/ + table->ACPILevel.SclkFrequency = atomctrl_get_reference_clock(hwmgr); + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, + table->ACPILevel.SclkFrequency, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* divider ID for required SCLK*/ + table->ACPILevel.SclkDid = (uint8_t)dividers.pll_post_divider; + table->ACPILevel.DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + table->ACPILevel.DeepSleepDivId = 0; + + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PWRON, 0); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_RESET, 1); + spll_func_cntl_2 = PHM_SET_FIELD(spll_func_cntl_2, + CG_SPLL_FUNC_CNTL_2, SCLK_MUX_SEL, 4); + + table->ACPILevel.CgSpllFuncCntl = spll_func_cntl; + table->ACPILevel.CgSpllFuncCntl2 = spll_func_cntl_2; + table->ACPILevel.CgSpllFuncCntl3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + table->ACPILevel.CgSpllFuncCntl4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + table->ACPILevel.SpllSpreadSpectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + table->ACPILevel.SpllSpreadSpectrum2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + table->ACPILevel.CcPwrDynRm = 0; + table->ACPILevel.CcPwrDynRm1 = 0; + + + /* For various features to be enabled/disabled while this level is active.*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.Flags); + /* SCLK frequency in units of 10KHz*/ + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(table->ACPILevel.CcPwrDynRm1); + + /* table->MemoryACPILevel.MinVddcPhases = table->ACPILevel.MinVddcPhases;*/ + table->MemoryACPILevel.MinVoltage = data->smc_state_table.MemoryLevel[0].MinVoltage; + + /* CONVERT_FROM_HOST_TO_SMC_UL(table->MemoryACPILevel.MinVoltage);*/ + + if (0 == tonga_populate_mvdd_value(hwmgr, 0, &voltage_level)) + table->MemoryACPILevel.MinMvdd = + PP_HOST_TO_SMC_UL(voltage_level.Voltage * VOLTAGE_SCALE); + else + table->MemoryACPILevel.MinMvdd = 0; + + /* Force reset on DLL*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_RESET, 0x1); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_RESET, 0x1); + + /* Disable DLL in ACPIState*/ + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK0_PDNB, 0); + mclk_pwrmgt_cntl = PHM_SET_FIELD(mclk_pwrmgt_cntl, + MCLK_PWRMGT_CNTL, MRDCK1_PDNB, 0); + + /* Enable DLL bypass signal*/ + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK0_BYPASS, 0); + dll_cntl = PHM_SET_FIELD(dll_cntl, + DLL_CNTL, MRDCK1_BYPASS, 0); + + table->MemoryACPILevel.DllCntl = + PP_HOST_TO_SMC_UL(dll_cntl); + table->MemoryACPILevel.MclkPwrmgtCntl = + PP_HOST_TO_SMC_UL(mclk_pwrmgt_cntl); + table->MemoryACPILevel.MpllAdFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_AD_FUNC_CNTL); + table->MemoryACPILevel.MpllDqFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_DQ_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL); + table->MemoryACPILevel.MpllFuncCntl_1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_1); + table->MemoryACPILevel.MpllFuncCntl_2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_FUNC_CNTL_2); + table->MemoryACPILevel.MpllSs1 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS1); + table->MemoryACPILevel.MpllSs2 = + PP_HOST_TO_SMC_UL(data->clock_registers.vMPLL_SS2); + + table->MemoryACPILevel.EnabledForThrottle = 0; + table->MemoryACPILevel.EnabledForActivity = 0; + table->MemoryACPILevel.UpHyst = 0; + table->MemoryACPILevel.DownHyst = 100; + table->MemoryACPILevel.VoltageDownHyst = 0; + /* Indicates maximum activity level for this performance level.*/ + table->MemoryACPILevel.ActivityLevel = PP_HOST_TO_SMC_US((uint16_t)data->mclk_activity_target); + + table->MemoryACPILevel.StutterEnable = 0; + table->MemoryACPILevel.StrobeEnable = 0; + table->MemoryACPILevel.EdcReadEnable = 0; + table->MemoryACPILevel.EdcWriteEnable = 0; + table->MemoryACPILevel.RttEnable = 0; + + return result; +} + +static int tonga_find_boot_level(struct tonga_single_dpm_table *table, uint32_t value, uint32_t *boot_level) +{ + int result = 0; + uint32_t i; + + for (i = 0; i < table->count; i++) { + if (value == table->dpm_levels[i].value) { + *boot_level = i; + result = 0; + } + } + return result; +} + +static int tonga_populate_smc_boot_level(struct pp_hwmgr *hwmgr, + SMU72_Discrete_DpmTable *table) +{ + int result = 0; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + table->GraphicsBootLevel = 0; /* 0 == DPM[0] (low), etc. */ + table->MemoryBootLevel = 0; /* 0 == DPM[0] (low), etc. */ + + /* find boot level from dpm table*/ + result = tonga_find_boot_level(&(data->dpm_table.sclk_table), + data->vbios_boot_state.sclk_bootup_value, + (uint32_t *)&(data->smc_state_table.GraphicsBootLevel)); + + if (0 != result) { + data->smc_state_table.GraphicsBootLevel = 0; + printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \ + in dependency table. Using Graphics DPM level 0!"); + result = 0; + } + + result = tonga_find_boot_level(&(data->dpm_table.mclk_table), + data->vbios_boot_state.mclk_bootup_value, + (uint32_t *)&(data->smc_state_table.MemoryBootLevel)); + + if (0 != result) { + data->smc_state_table.MemoryBootLevel = 0; + printk(KERN_ERR "[ powerplay ] VBIOS did not find boot engine clock value \ + in dependency table. Using Memory DPM level 0!"); + result = 0; + } + + table->BootVoltage.Vddc = + tonga_get_voltage_id(&(data->vddc_voltage_table), + data->vbios_boot_state.vddc_bootup_value); + table->BootVoltage.VddGfx = + tonga_get_voltage_id(&(data->vddgfx_voltage_table), + data->vbios_boot_state.vddgfx_bootup_value); + table->BootVoltage.Vddci = + tonga_get_voltage_id(&(data->vddci_voltage_table), + data->vbios_boot_state.vddci_bootup_value); + table->BootMVdd = data->vbios_boot_state.mvdd_bootup_value; + + CONVERT_FROM_HOST_TO_SMC_US(table->BootMVdd); + + return result; +} + + +/** + * Calculates the SCLK dividers using the provided engine clock + * + * @param hwmgr the address of the hardware manager + * @param engine_clock the engine clock to use to populate the structure + * @param sclk the SMC SCLK structure to be populated + */ +int tonga_calculate_sclk_params(struct pp_hwmgr *hwmgr, + uint32_t engine_clock, SMU72_Discrete_GraphicsLevel *sclk) +{ + const tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + pp_atomctrl_clock_dividers_vi dividers; + uint32_t spll_func_cntl = data->clock_registers.vCG_SPLL_FUNC_CNTL; + uint32_t spll_func_cntl_3 = data->clock_registers.vCG_SPLL_FUNC_CNTL_3; + uint32_t spll_func_cntl_4 = data->clock_registers.vCG_SPLL_FUNC_CNTL_4; + uint32_t cg_spll_spread_spectrum = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM; + uint32_t cg_spll_spread_spectrum_2 = data->clock_registers.vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t reference_clock; + uint32_t reference_divider; + uint32_t fbdiv; + int result; + + /* get the engine clock dividers for this clock value*/ + result = atomctrl_get_engine_pll_dividers_vi(hwmgr, engine_clock, ÷rs); + + PP_ASSERT_WITH_CODE(result == 0, + "Error retrieving Engine Clock dividers from VBIOS.", return result); + + /* To get FBDIV we need to multiply this by 16384 and divide it by Fref.*/ + reference_clock = atomctrl_get_reference_clock(hwmgr); + + reference_divider = 1 + dividers.uc_pll_ref_div; + + /* low 14 bits is fraction and high 12 bits is divider*/ + fbdiv = dividers.ul_fb_div.ul_fb_divider & 0x3FFFFFF; + + /* SPLL_FUNC_CNTL setup*/ + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_REF_DIV, dividers.uc_pll_ref_div); + spll_func_cntl = PHM_SET_FIELD(spll_func_cntl, + CG_SPLL_FUNC_CNTL, SPLL_PDIV_A, dividers.uc_pll_post_div); + + /* SPLL_FUNC_CNTL_3 setup*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_FB_DIV, fbdiv); + + /* set to use fractional accumulation*/ + spll_func_cntl_3 = PHM_SET_FIELD(spll_func_cntl_3, + CG_SPLL_FUNC_CNTL_3, SPLL_DITHEN, 1); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EngineSpreadSpectrumSupport)) { + pp_atomctrl_internal_ss_info ss_info; + + uint32_t vcoFreq = engine_clock * dividers.uc_pll_post_div; + if (0 == atomctrl_get_engine_clock_spread_spectrum(hwmgr, vcoFreq, &ss_info)) { + /* + * ss_info.speed_spectrum_percentage -- in unit of 0.01% + * ss_info.speed_spectrum_rate -- in unit of khz + */ + /* clks = reference_clock * 10 / (REFDIV + 1) / speed_spectrum_rate / 2 */ + uint32_t clkS = reference_clock * 5 / (reference_divider * ss_info.speed_spectrum_rate); + + /* clkv = 2 * D * fbdiv / NS */ + uint32_t clkV = 4 * ss_info.speed_spectrum_percentage * fbdiv / (clkS * 10000); + + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, CLKS, clkS); + cg_spll_spread_spectrum = + PHM_SET_FIELD(cg_spll_spread_spectrum, CG_SPLL_SPREAD_SPECTRUM, SSEN, 1); + cg_spll_spread_spectrum_2 = + PHM_SET_FIELD(cg_spll_spread_spectrum_2, CG_SPLL_SPREAD_SPECTRUM_2, CLKV, clkV); + } + } + + sclk->SclkFrequency = engine_clock; + sclk->CgSpllFuncCntl3 = spll_func_cntl_3; + sclk->CgSpllFuncCntl4 = spll_func_cntl_4; + sclk->SpllSpreadSpectrum = cg_spll_spread_spectrum; + sclk->SpllSpreadSpectrum2 = cg_spll_spread_spectrum_2; + sclk->SclkDid = (uint8_t)dividers.pll_post_divider; + + return 0; +} + +/** + * Populates single SMC SCLK structure using the provided engine clock + * + * @param hwmgr the address of the hardware manager + * @param engine_clock the engine clock to use to populate the structure + * @param sclk the SMC SCLK structure to be populated + */ +static int tonga_populate_single_graphic_level(struct pp_hwmgr *hwmgr, uint32_t engine_clock, uint16_t sclk_activity_level_threshold, SMU72_Discrete_GraphicsLevel *graphic_level) +{ + int result; + uint32_t threshold; + uint32_t mvdd; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + result = tonga_calculate_sclk_params(hwmgr, engine_clock, graphic_level); + + + /* populate graphics levels*/ + result = tonga_get_dependecy_volt_by_clk(hwmgr, + pptable_info->vdd_dep_on_sclk, engine_clock, + &graphic_level->MinVoltage, &mvdd); + PP_ASSERT_WITH_CODE((0 == result), + "can not find VDDC voltage value for VDDC \ + engine clock dependency table", return result); + + /* SCLK frequency in units of 10KHz*/ + graphic_level->SclkFrequency = engine_clock; + + /* Indicates maximum activity level for this performance level. 50% for now*/ + graphic_level->ActivityLevel = sclk_activity_level_threshold; + + graphic_level->CcPwrDynRm = 0; + graphic_level->CcPwrDynRm1 = 0; + /* this level can be used if activity is high enough.*/ + graphic_level->EnabledForActivity = 0; + /* this level can be used for throttling.*/ + graphic_level->EnabledForThrottle = 1; + graphic_level->UpHyst = 0; + graphic_level->DownHyst = 0; + graphic_level->VoltageDownHyst = 0; + graphic_level->PowerThrottle = 0; + + threshold = engine_clock * data->fast_watemark_threshold / 100; +/* + *get the DAL clock. do it in funture. + PECI_GetMinClockSettings(hwmgr->peci, &minClocks); + data->display_timing.min_clock_insr = minClocks.engineClockInSR; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) + { + graphic_level->DeepSleepDivId = PhwTonga_GetSleepDividerIdFromClock(hwmgr, engine_clock, minClocks.engineClockInSR); + } +*/ + + /* Default to slow, highest DPM level will be set to PPSMC_DISPLAY_WATERMARK_LOW later.*/ + graphic_level->DisplayWatermark = PPSMC_DISPLAY_WATERMARK_LOW; + + if (0 == result) { + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVoltage);*/ + /* CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->MinVddcPhases);*/ + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SclkFrequency); + CONVERT_FROM_HOST_TO_SMC_US(graphic_level->ActivityLevel); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl3); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CgSpllFuncCntl4); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->SpllSpreadSpectrum2); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm); + CONVERT_FROM_HOST_TO_SMC_UL(graphic_level->CcPwrDynRm1); + } + + return result; +} + +/** + * Populates all SMC SCLK levels' structure based on the trimmed allowed dpm engine clock states + * + * @param hwmgr the address of the hardware manager + */ +static int tonga_populate_all_graphic_levels(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + struct tonga_dpm_table *dpm_table = &data->dpm_table; + phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; + uint8_t pcie_entry_count = (uint8_t) data->dpm_table.pcie_speed_table.count; + int result = 0; + uint32_t level_array_adress = data->dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, GraphicsLevel); + uint32_t level_array_size = sizeof(SMU72_Discrete_GraphicsLevel) * + SMU72_MAX_LEVELS_GRAPHICS; /* 64 -> long; 32 -> int*/ + SMU72_Discrete_GraphicsLevel *levels = data->smc_state_table.GraphicsLevel; + uint32_t i, maxEntry; + uint8_t highest_pcie_level_enabled = 0, lowest_pcie_level_enabled = 0, mid_pcie_level_enabled = 0, count = 0; + PECI_RegistryValue reg_value; + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->sclk_table.count; i++) { + result = tonga_populate_single_graphic_level(hwmgr, + dpm_table->sclk_table.dpm_levels[i].value, + (uint16_t)data->activity_target[i], + &(data->smc_state_table.GraphicsLevel[i])); + + if (0 != result) + return result; + + /* Making sure only DPM level 0-1 have Deep Sleep Div ID populated. */ + if (i > 1) + data->smc_state_table.GraphicsLevel[i].DeepSleepDivId = 0; + + if (0 == i) { + reg_value = 0; + if (reg_value != 0) + data->smc_state_table.GraphicsLevel[0].UpHyst = (uint8_t)reg_value; + } + + if (1 == i) { + reg_value = 0; + if (reg_value != 0) + data->smc_state_table.GraphicsLevel[1].UpHyst = (uint8_t)reg_value; + } + } + + /* Only enable level 0 for now. */ + data->smc_state_table.GraphicsLevel[0].EnabledForActivity = 1; + + /* set highest level watermark to high */ + if (dpm_table->sclk_table.count > 1) + data->smc_state_table.GraphicsLevel[dpm_table->sclk_table.count-1].DisplayWatermark = + PPSMC_DISPLAY_WATERMARK_HIGH; + + data->smc_state_table.GraphicsDpmLevelCount = + (uint8_t)dpm_table->sclk_table.count; + data->dpm_level_enable_mask.sclk_dpm_enable_mask = + tonga_get_dpm_level_enable_mask_value(&dpm_table->sclk_table); + + if (pcie_table != NULL) { + PP_ASSERT_WITH_CODE((pcie_entry_count >= 1), + "There must be 1 or more PCIE levels defined in PPTable.", return -1); + maxEntry = pcie_entry_count - 1; /* for indexing, we need to decrement by 1.*/ + for (i = 0; i < dpm_table->sclk_table.count; i++) { + data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = + (uint8_t) ((i < maxEntry) ? i : maxEntry); + } + } else { + if (0 == data->dpm_level_enable_mask.pcie_dpm_enable_mask) + printk(KERN_ERR "[ powerplay ] Pcie Dpm Enablemask is 0!"); + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(highest_pcie_level_enabled+1))) != 0)) { + highest_pcie_level_enabled++; + } + + while (data->dpm_level_enable_mask.pcie_dpm_enable_mask && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<lowest_pcie_level_enabled)) == 0)) { + lowest_pcie_level_enabled++; + } + + while ((count < highest_pcie_level_enabled) && + ((data->dpm_level_enable_mask.pcie_dpm_enable_mask & + (1<<(lowest_pcie_level_enabled+1+count))) == 0)) { + count++; + } + mid_pcie_level_enabled = (lowest_pcie_level_enabled+1+count) < highest_pcie_level_enabled ? + (lowest_pcie_level_enabled+1+count) : highest_pcie_level_enabled; + + + /* set pcieDpmLevel to highest_pcie_level_enabled*/ + for (i = 2; i < dpm_table->sclk_table.count; i++) { + data->smc_state_table.GraphicsLevel[i].pcieDpmLevel = highest_pcie_level_enabled; + } + + /* set pcieDpmLevel to lowest_pcie_level_enabled*/ + data->smc_state_table.GraphicsLevel[0].pcieDpmLevel = lowest_pcie_level_enabled; + + /* set pcieDpmLevel to mid_pcie_level_enabled*/ + data->smc_state_table.GraphicsLevel[1].pcieDpmLevel = mid_pcie_level_enabled; + } + /* level count will send to smc once at init smc table and never change*/ + result = tonga_copy_bytes_to_smc(hwmgr->smumgr, level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end); + + if (0 != result) + return result; + + return 0; +} + +/** + * Populates all SMC MCLK levels' structure based on the trimmed allowed dpm memory clock states + * + * @param hwmgr the address of the hardware manager + */ + +static int tonga_populate_all_memory_levels(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct tonga_dpm_table *dpm_table = &data->dpm_table; + int result; + /* populate MCLK dpm table to SMU7 */ + uint32_t level_array_adress = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, MemoryLevel); + uint32_t level_array_size = sizeof(SMU72_Discrete_MemoryLevel) * SMU72_MAX_LEVELS_MEMORY; + SMU72_Discrete_MemoryLevel *levels = data->smc_state_table.MemoryLevel; + uint32_t i; + + memset(levels, 0x00, level_array_size); + + for (i = 0; i < dpm_table->mclk_table.count; i++) { + PP_ASSERT_WITH_CODE((0 != dpm_table->mclk_table.dpm_levels[i].value), + "can not populate memory level as memory clock is zero", return -1); + result = tonga_populate_single_memory_level(hwmgr, dpm_table->mclk_table.dpm_levels[i].value, + &(data->smc_state_table.MemoryLevel[i])); + if (0 != result) { + return result; + } + } + + /* Only enable level 0 for now.*/ + data->smc_state_table.MemoryLevel[0].EnabledForActivity = 1; + + /* + * in order to prevent MC activity from stutter mode to push DPM up. + * the UVD change complements this by putting the MCLK in a higher state + * by default such that we are not effected by up threshold or and MCLK DPM latency. + */ + data->smc_state_table.MemoryLevel[0].ActivityLevel = 0x1F; + CONVERT_FROM_HOST_TO_SMC_US(data->smc_state_table.MemoryLevel[0].ActivityLevel); + + data->smc_state_table.MemoryDpmLevelCount = (uint8_t)dpm_table->mclk_table.count; + data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&dpm_table->mclk_table); + /* set highest level watermark to high*/ + data->smc_state_table.MemoryLevel[dpm_table->mclk_table.count-1].DisplayWatermark = PPSMC_DISPLAY_WATERMARK_HIGH; + + /* level count will send to smc once at init smc table and never change*/ + result = tonga_copy_bytes_to_smc(hwmgr->smumgr, + level_array_adress, (uint8_t *)levels, (uint32_t)level_array_size, data->sram_end); + + if (0 != result) { + return result; + } + + return 0; +} + +struct TONGA_DLL_SPEED_SETTING { + uint16_t Min; /* Minimum Data Rate*/ + uint16_t Max; /* Maximum Data Rate*/ + uint32_t dll_speed; /* The desired DLL_SPEED setting*/ +}; + +static int tonga_populate_clock_stretcher_data_table(struct pp_hwmgr *hwmgr) +{ + return 0; +} + +/* ---------------------------------------- ULV related functions ----------------------------------------------------*/ + + +static int tonga_reset_single_dpm_table( + struct pp_hwmgr *hwmgr, + struct tonga_single_dpm_table *dpm_table, + uint32_t count) +{ + uint32_t i; + if (!(count <= MAX_REGULAR_DPM_NUMBER)) + printk(KERN_ERR "[ powerplay ] Fatal error, can not set up single DPM \ + table entries to exceed max number! \n"); + + dpm_table->count = count; + for (i = 0; i < MAX_REGULAR_DPM_NUMBER; i++) { + dpm_table->dpm_levels[i].enabled = 0; + } + + return 0; +} + +static void tonga_setup_pcie_table_entry( + struct tonga_single_dpm_table *dpm_table, + uint32_t index, uint32_t pcie_gen, + uint32_t pcie_lanes) +{ + dpm_table->dpm_levels[index].value = pcie_gen; + dpm_table->dpm_levels[index].param1 = pcie_lanes; + dpm_table->dpm_levels[index].enabled = 1; +} + +static int tonga_setup_default_pcie_tables(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_pcie_table *pcie_table = pptable_info->pcie_table; + uint32_t i, maxEntry; + + if (data->use_pcie_performance_levels && !data->use_pcie_power_saving_levels) { + data->pcie_gen_power_saving = data->pcie_gen_performance; + data->pcie_lane_power_saving = data->pcie_lane_performance; + } else if (!data->use_pcie_performance_levels && data->use_pcie_power_saving_levels) { + data->pcie_gen_performance = data->pcie_gen_power_saving; + data->pcie_lane_performance = data->pcie_lane_power_saving; + } + + tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.pcie_speed_table, SMU72_MAX_LEVELS_LINK); + + if (pcie_table != NULL) { + /* + * maxEntry is used to make sure we reserve one PCIE level for boot level (fix for A+A PSPP issue). + * If PCIE table from PPTable have ULV entry + 8 entries, then ignore the last entry. + */ + maxEntry = (SMU72_MAX_LEVELS_LINK < pcie_table->count) ? + SMU72_MAX_LEVELS_LINK : pcie_table->count; + for (i = 1; i < maxEntry; i++) { + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, i-1, + get_pcie_gen_support(data->pcie_gen_cap, pcie_table->entries[i].gen_speed), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + } + data->dpm_table.pcie_speed_table.count = maxEntry - 1; + } else { + /* Hardcode Pcie Table */ + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 0, + get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 1, + get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 2, + get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 3, + get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 4, + get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, 5, + get_pcie_gen_support(data->pcie_gen_cap, PP_Max_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + data->dpm_table.pcie_speed_table.count = 6; + } + /* Populate last level for boot PCIE level, but do not increment count. */ + tonga_setup_pcie_table_entry(&data->dpm_table.pcie_speed_table, + data->dpm_table.pcie_speed_table.count, + get_pcie_gen_support(data->pcie_gen_cap, PP_Min_PCIEGen), + get_pcie_lane_support(data->pcie_lane_cap, PP_Max_PCIELane)); + + return 0; + +} + +/* + * This function is to initalize all DPM state tables for SMU7 based on the dependency table. + * Dynamic state patching function will then trim these state tables to the allowed range based + * on the power policy or external client requests, such as UVD request, etc. + */ +static int tonga_setup_default_dpm_tables(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint32_t i; + + phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_sclk_table = + pptable_info->vdd_dep_on_sclk; + phm_ppt_v1_clock_voltage_dependency_table *allowed_vdd_mclk_table = + pptable_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL, + "SCLK dependency table is missing. This table is mandatory", return -1); + PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table->count >= 1, + "SCLK dependency table has to have is missing. This table is mandatory", return -1); + + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, + "MCLK dependency table is missing. This table is mandatory", return -1); + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table->count >= 1, + "VMCLK dependency table has to have is missing. This table is mandatory", return -1); + + /* clear the state table to reset everything to default */ + memset(&(data->dpm_table), 0x00, sizeof(data->dpm_table)); + tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.sclk_table, SMU72_MAX_LEVELS_GRAPHICS); + tonga_reset_single_dpm_table(hwmgr, &data->dpm_table.mclk_table, SMU72_MAX_LEVELS_MEMORY); + /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.VddcTable, SMU72_MAX_LEVELS_VDDC); */ + /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_gfx_table, SMU72_MAX_LEVELS_VDDGFX);*/ + /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.vdd_ci_table, SMU72_MAX_LEVELS_VDDCI);*/ + /* tonga_reset_single_dpm_table(hwmgr, &tonga_hwmgr->dpm_table.mvdd_table, SMU72_MAX_LEVELS_MVDD);*/ + + PP_ASSERT_WITH_CODE(allowed_vdd_sclk_table != NULL, + "SCLK dependency table is missing. This table is mandatory", return -1); + /* Initialize Sclk DPM table based on allow Sclk values*/ + data->dpm_table.sclk_table.count = 0; + + for (i = 0; i < allowed_vdd_sclk_table->count; i++) { + if (i == 0 || data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count-1].value != + allowed_vdd_sclk_table->entries[i].clk) { + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].value = + allowed_vdd_sclk_table->entries[i].clk; + data->dpm_table.sclk_table.dpm_levels[data->dpm_table.sclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; to do */ + data->dpm_table.sclk_table.count++; + } + } + + PP_ASSERT_WITH_CODE(allowed_vdd_mclk_table != NULL, + "MCLK dependency table is missing. This table is mandatory", return -1); + /* Initialize Mclk DPM table based on allow Mclk values */ + data->dpm_table.mclk_table.count = 0; + for (i = 0; i < allowed_vdd_mclk_table->count; i++) { + if (i == 0 || data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count-1].value != + allowed_vdd_mclk_table->entries[i].clk) { + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].value = + allowed_vdd_mclk_table->entries[i].clk; + data->dpm_table.mclk_table.dpm_levels[data->dpm_table.mclk_table.count].enabled = 1; /*(i==0) ? 1 : 0; */ + data->dpm_table.mclk_table.count++; + } + } + + /* Initialize Vddc DPM table based on allow Vddc values. And populate corresponding std values. */ + for (i = 0; i < allowed_vdd_sclk_table->count; i++) { + data->dpm_table.vddc_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddc; + /* tonga_hwmgr->dpm_table.VddcTable.dpm_levels[i].param1 = stdVoltageTable->entries[i].Leakage; */ + /* param1 is for corresponding std voltage */ + data->dpm_table.vddc_table.dpm_levels[i].enabled = 1; + } + data->dpm_table.vddc_table.count = allowed_vdd_sclk_table->count; + + if (NULL != allowed_vdd_mclk_table) { + /* Initialize Vddci DPM table based on allow Mclk values */ + for (i = 0; i < allowed_vdd_mclk_table->count; i++) { + data->dpm_table.vdd_ci_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].vddci; + data->dpm_table.vdd_ci_table.dpm_levels[i].enabled = 1; + data->dpm_table.mvdd_table.dpm_levels[i].value = allowed_vdd_mclk_table->entries[i].mvdd; + data->dpm_table.mvdd_table.dpm_levels[i].enabled = 1; + } + data->dpm_table.vdd_ci_table.count = allowed_vdd_mclk_table->count; + data->dpm_table.mvdd_table.count = allowed_vdd_mclk_table->count; + } + + /* setup PCIE gen speed levels*/ + tonga_setup_default_pcie_tables(hwmgr); + + /* save a copy of the default DPM table*/ + memcpy(&(data->golden_dpm_table), &(data->dpm_table), sizeof(struct tonga_dpm_table)); + + return 0; +} + +int tonga_populate_smc_initial_state(struct pp_hwmgr *hwmgr, + const struct tonga_power_state *bootState) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + uint8_t count, level; + + count = (uint8_t) (pptable_info->vdd_dep_on_sclk->count); + for (level = 0; level < count; level++) { + if (pptable_info->vdd_dep_on_sclk->entries[level].clk >= + bootState->performance_levels[0].engine_clock) { + data->smc_state_table.GraphicsBootLevel = level; + break; + } + } + + count = (uint8_t) (pptable_info->vdd_dep_on_mclk->count); + for (level = 0; level < count; level++) { + if (pptable_info->vdd_dep_on_mclk->entries[level].clk >= + bootState->performance_levels[0].memory_clock) { + data->smc_state_table.MemoryBootLevel = level; + break; + } + } + + return 0; +} + +/** + * Initializes the SMC table and uploads it + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pInput the pointer to input data (PowerState) + * @return always 0 + */ +int tonga_init_smc_table(struct pp_hwmgr *hwmgr) +{ + int result; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + SMU72_Discrete_DpmTable *table = &(data->smc_state_table); + const phw_tonga_ulv_parm *ulv = &(data->ulv); + uint8_t i; + PECI_RegistryValue reg_value; + pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; + + result = tonga_setup_default_dpm_tables(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to setup default DPM tables!", return result;); + memset(&(data->smc_state_table), 0x00, sizeof(data->smc_state_table)); + if (TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control) { + tonga_populate_smc_voltage_tables(hwmgr, table); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition)) { + table->SystemFlags |= PPSMC_SYSTEMFLAG_GPIO_DC; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_StepVddc)) { + table->SystemFlags |= PPSMC_SYSTEMFLAG_STEPVDDC; + } + + if (data->is_memory_GDDR5) { + table->SystemFlags |= PPSMC_SYSTEMFLAG_GDDR5; + } + + i = PHM_READ_FIELD(hwmgr->device, CC_MC_MAX_CHANNEL, NOOFCHAN); + + if (i == 1 || i == 0) { + table->SystemFlags |= PPSMC_SYSTEMFLAG_12CHANNEL; + } + + if (ulv->ulv_supported && pptable_info->us_ulv_voltage_offset) { + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ULV state!", return result;); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_ULV_PARAMETER, ulv->ch_ulv_parameter); + } + + result = tonga_populate_smc_link_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Link Level!", return result;); + + result = tonga_populate_all_graphic_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Graphics Level!", return result;); + + result = tonga_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Memory Level!", return result;); + + result = tonga_populate_smv_acpi_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACPI Level!", return result;); + + result = tonga_populate_smc_vce_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize VCE Level!", return result;); + + result = tonga_populate_smc_acp_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize ACP Level!", return result;); + + result = tonga_populate_smc_samu_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize SAMU Level!", return result;); + + /* Since only the initial state is completely set up at this point (the other states are just copies of the boot state) we only */ + /* need to populate the ARB settings for the initial state. */ + result = tonga_program_memory_timing_parameters(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to Write ARB settings for the initial state.", return result;); + + result = tonga_populate_smc_uvd_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize UVD Level!", return result;); + + result = tonga_populate_smc_boot_level(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize Boot Level!", return result;); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher)) { + result = tonga_populate_clock_stretcher_data_table(hwmgr); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate Clock Stretcher Data Table!", return result;); + } + table->GraphicsVoltageChangeEnable = 1; + table->GraphicsThermThrottleEnable = 1; + table->GraphicsInterval = 1; + table->VoltageInterval = 1; + table->ThermalInterval = 1; + table->TemperatureLimitHigh = + pptable_info->cac_dtp_table->usTargetOperatingTemp * + TONGA_Q88_FORMAT_CONVERSION_UNIT; + table->TemperatureLimitLow = + (pptable_info->cac_dtp_table->usTargetOperatingTemp - 1) * + TONGA_Q88_FORMAT_CONVERSION_UNIT; + table->MemoryVoltageChangeEnable = 1; + table->MemoryInterval = 1; + table->VoltageResponseTime = 0; + table->PhaseResponseTime = 0; + table->MemoryThermThrottleEnable = 1; + + /* + * Cail reads current link status and reports it as cap (we cannot change this due to some previous issues we had) + * SMC drops the link status to lowest level after enabling DPM by PowerPlay. After pnp or toggling CF, driver gets reloaded again + * but this time Cail reads current link status which was set to low by SMC and reports it as cap to powerplay + * To avoid it, we set PCIeBootLinkLevel to highest dpm level + */ + PP_ASSERT_WITH_CODE((1 <= data->dpm_table.pcie_speed_table.count), + "There must be 1 or more PCIE levels defined in PPTable.", + return -1); + + table->PCIeBootLinkLevel = (uint8_t) (data->dpm_table.pcie_speed_table.count); + + table->PCIeGenInterval = 1; + + result = tonga_populate_vr_config(hwmgr, table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to populate VRConfig setting!", return result); + + table->ThermGpio = 17; + table->SclkStepSize = 0x4000; + + reg_value = 0; + if ((0 == reg_value) && + (0 == atomctrl_get_pp_assign_pin(hwmgr, + VDDC_VRHOT_GPIO_PINID, &gpio_pin_assignment))) { + table->VRHotGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } else { + table->VRHotGpio = TONGA_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot); + } + + /* ACDC Switch GPIO */ + reg_value = 0; + if ((0 == reg_value) && + (0 == atomctrl_get_pp_assign_pin(hwmgr, + PP_AC_DC_SWITCH_GPIO_PINID, &gpio_pin_assignment))) { + table->AcDcGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } else { + table->AcDcGpio = TONGA_UNUSED_GPIO_PIN; + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + } + + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + + reg_value = 0; + if (1 == reg_value) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_AutomaticDCTransition); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_Falcon_QuickTransition); + } + + reg_value = 0; + if ((0 == reg_value) && + (0 == atomctrl_get_pp_assign_pin(hwmgr, + THERMAL_INT_OUTPUT_GPIO_PINID, &gpio_pin_assignment))) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = gpio_pin_assignment.uc_gpio_pin_bit_shift; + + table->ThermOutPolarity = + (0 == (cgs_read_register(hwmgr->device, mmGPIOPAD_A) & + (1 << gpio_pin_assignment.uc_gpio_pin_bit_shift))) ? 1:0; + + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_ONLY; + + /* if required, combine VRHot/PCC with thermal out GPIO*/ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_RegulatorHot) && + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_CombinePCCWithThermalSignal)){ + table->ThermOutMode = SMU7_THERM_OUT_MODE_THERM_VRHOT; + } + } else { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ThermalOutGPIO); + + table->ThermOutGpio = 17; + table->ThermOutPolarity = 1; + table->ThermOutMode = SMU7_THERM_OUT_MODE_DISABLE; + } + + for (i = 0; i < SMU72_MAX_ENTRIES_SMIO; i++) { + table->Smio[i] = PP_HOST_TO_SMC_UL(table->Smio[i]); + } + CONVERT_FROM_HOST_TO_SMC_UL(table->SystemFlags); + CONVERT_FROM_HOST_TO_SMC_UL(table->VRConfig); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask1); + CONVERT_FROM_HOST_TO_SMC_UL(table->SmioMask2); + CONVERT_FROM_HOST_TO_SMC_UL(table->SclkStepSize); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitHigh); + CONVERT_FROM_HOST_TO_SMC_US(table->TemperatureLimitLow); + CONVERT_FROM_HOST_TO_SMC_US(table->VoltageResponseTime); + CONVERT_FROM_HOST_TO_SMC_US(table->PhaseResponseTime); + + /* Upload all dpm data to SMC memory.(dpm level, dpm level count etc) */ + result = tonga_copy_bytes_to_smc(hwmgr->smumgr, data->dpm_table_start + + offsetof(SMU72_Discrete_DpmTable, SystemFlags), + (uint8_t *)&(table->SystemFlags), + sizeof(SMU72_Discrete_DpmTable)-3 * sizeof(SMU72_PIDController), + data->sram_end); + + PP_ASSERT_WITH_CODE(0 == result, + "Failed to upload dpm data to SMC memory!", return result;); + + return result; +} + +/* Look up the voltaged based on DAL's requested level. and then send the requested VDDC voltage to SMC*/ +static void tonga_apply_dal_minimum_voltage_request(struct pp_hwmgr *hwmgr) +{ + return; +} + +int tonga_upload_dpm_level_enable_mask(struct pp_hwmgr *hwmgr) +{ + PPSMC_Result result; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* Apply minimum voltage based on DAL's request level */ + tonga_apply_dal_minimum_voltage_request(hwmgr); + + if (0 == data->sclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + if (0 != tonga_is_dpm_running(hwmgr)) + printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n"); + + if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + result = smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + (PPSMC_Msg)PPSMC_MSG_SCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == result), + "Set Sclk Dpm enable Mask failed", return -1); + } + } + + if (0 == data->mclk_dpm_key_disabled) { + /* Checking if DPM is running. If we discover hang because of this, we should skip this message.*/ + if (0 != tonga_is_dpm_running(hwmgr)) + printk(KERN_ERR "[ powerplay ] Trying to set Enable Mask when DPM is disabled \n"); + + if (0 != data->dpm_level_enable_mask.mclk_dpm_enable_mask) { + result = smum_send_msg_to_smc_with_parameter( + hwmgr->smumgr, + (PPSMC_Msg)PPSMC_MSG_MCLKDPM_SetEnabledMask, + data->dpm_level_enable_mask.mclk_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == result), + "Set Mclk Dpm enable Mask failed", return -1); + } + } + + return 0; +} + + +int tonga_force_dpm_highest(struct pp_hwmgr *hwmgr) +{ + uint32_t level, tmp; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + if (0 == data->pcie_dpm_key_disabled) { + /* PCIE */ + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) { + level = 0; + tmp = data->dpm_level_enable_mask.pcie_dpm_enable_mask; + while (tmp >>= 1) + level++ ; + + if (0 != level) { + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)), + "force highest pcie dpm state failed!", return -1); + } + } + } + + if (0 == data->sclk_dpm_key_disabled) { + /* SCLK */ + if (data->dpm_level_enable_mask.sclk_dpm_enable_mask != 0) { + level = 0; + tmp = data->dpm_level_enable_mask.sclk_dpm_enable_mask; + while (tmp >>= 1) + level++ ; + + if (0 != level) { + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)), + "force highest sclk dpm state failed!", return -1); + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level) + printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \ + Curr_Sclk_Index does not match the level \n"); + + } + } + } + + if (0 == data->mclk_dpm_key_disabled) { + /* MCLK */ + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) { + level = 0; + tmp = data->dpm_level_enable_mask.mclk_dpm_enable_mask; + while (tmp >>= 1) + level++ ; + + if (0 != level) { + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)), + "force highest mclk dpm state failed!", return -1); + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level) + printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \ + Curr_Mclk_Index does not match the level \n"); + } + } + } + + return 0; +} + +/** + * Find the MC microcode version and store it in the HwMgr struct + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_get_mc_microcode_version (struct pp_hwmgr *hwmgr) +{ + cgs_write_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_INDEX, 0x9F); + + hwmgr->microcode_version_info.MC = cgs_read_register(hwmgr->device, mmMC_SEQ_IO_DEBUG_DATA); + + return 0; +} + +/** + * Initialize Dynamic State Adjustment Rule Settings + * + * @param hwmgr the address of the powerplay hardware manager. + */ +int tonga_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr) +{ + uint32_t table_size; + struct phm_clock_voltage_dependency_table *table_clk_vlt; + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + hwmgr->dyn_state.mclk_sclk_ratio = 4; + hwmgr->dyn_state.sclk_mclk_delta = 15000; /* 150 MHz */ + hwmgr->dyn_state.vddc_vddci_delta = 200; /* 200mV */ + + /* initialize vddc_dep_on_dal_pwrl table */ + table_size = sizeof(uint32_t) + 4 * sizeof(struct phm_clock_voltage_dependency_record); + table_clk_vlt = (struct phm_clock_voltage_dependency_table *)kzalloc(table_size, GFP_KERNEL); + + if (NULL == table_clk_vlt) { + printk(KERN_ERR "[ powerplay ] Can not allocate space for vddc_dep_on_dal_pwrl! \n"); + return -ENOMEM; + } else { + table_clk_vlt->count = 4; + table_clk_vlt->entries[0].clk = PP_DAL_POWERLEVEL_ULTRALOW; + table_clk_vlt->entries[0].v = 0; + table_clk_vlt->entries[1].clk = PP_DAL_POWERLEVEL_LOW; + table_clk_vlt->entries[1].v = 720; + table_clk_vlt->entries[2].clk = PP_DAL_POWERLEVEL_NOMINAL; + table_clk_vlt->entries[2].v = 810; + table_clk_vlt->entries[3].clk = PP_DAL_POWERLEVEL_PERFORMANCE; + table_clk_vlt->entries[3].v = 900; + pptable_info->vddc_dep_on_dal_pwrl = table_clk_vlt; + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = table_clk_vlt; + } + + return 0; +} + +static int tonga_set_private_var_based_on_pptale(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + phm_ppt_v1_clock_voltage_dependency_table *allowed_sclk_vdd_table = + pptable_info->vdd_dep_on_sclk; + phm_ppt_v1_clock_voltage_dependency_table *allowed_mclk_vdd_table = + pptable_info->vdd_dep_on_mclk; + + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table != NULL, + "VDD dependency on SCLK table is missing. \ + This table is mandatory", return -1); + PP_ASSERT_WITH_CODE(allowed_sclk_vdd_table->count >= 1, + "VDD dependency on SCLK table has to have is missing. \ + This table is mandatory", return -1); + + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table != NULL, + "VDD dependency on MCLK table is missing. \ + This table is mandatory", return -1); + PP_ASSERT_WITH_CODE(allowed_mclk_vdd_table->count >= 1, + "VDD dependency on MCLK table has to have is missing. \ + This table is mandatory", return -1); + + data->min_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[0].vddc; + data->max_vddc_in_pp_table = (uint16_t)allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + + pptable_info->max_clock_voltage_on_ac.sclk = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].clk; + pptable_info->max_clock_voltage_on_ac.mclk = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].clk; + pptable_info->max_clock_voltage_on_ac.vddc = + allowed_sclk_vdd_table->entries[allowed_sclk_vdd_table->count - 1].vddc; + pptable_info->max_clock_voltage_on_ac.vddci = + allowed_mclk_vdd_table->entries[allowed_mclk_vdd_table->count - 1].vddci; + + hwmgr->dyn_state.max_clock_voltage_on_ac.sclk = + pptable_info->max_clock_voltage_on_ac.sclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.mclk = + pptable_info->max_clock_voltage_on_ac.mclk; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddc = + pptable_info->max_clock_voltage_on_ac.vddc; + hwmgr->dyn_state.max_clock_voltage_on_ac.vddci = + pptable_info->max_clock_voltage_on_ac.vddci; + + return 0; +} + +int tonga_unforce_dpm_levels(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + int result = 1; + + PP_ASSERT_WITH_CODE (0 == tonga_is_dpm_running(hwmgr), + "Trying to Unforce DPM when DPM is disabled. Returning without sending SMC message.", + return result); + + if (0 == data->pcie_dpm_key_disabled) { + PP_ASSERT_WITH_CODE((0 == smum_send_msg_to_smc( + hwmgr->smumgr, + PPSMC_MSG_PCIeDPM_UnForceLevel)), + "unforce pcie level failed!", + return -1); + } + + result = tonga_upload_dpm_level_enable_mask(hwmgr); + + return result; +} + +static uint32_t tonga_get_lowest_enable_level( + struct pp_hwmgr *hwmgr, uint32_t level_mask) +{ + uint32_t level = 0; + + while (0 == (level_mask & (1 << level))) + level++; + + return level; +} + +static int tonga_force_dpm_lowest(struct pp_hwmgr *hwmgr) +{ + uint32_t level; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + if (0 == data->pcie_dpm_key_disabled) { + /* PCIE */ + if (data->dpm_level_enable_mask.pcie_dpm_enable_mask != 0) { + level = tonga_get_lowest_enable_level(hwmgr, + data->dpm_level_enable_mask.pcie_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_pcie(hwmgr, level)), + "force lowest pcie dpm state failed!", return -1); + } + } + + if (0 == data->sclk_dpm_key_disabled) { + /* SCLK */ + if (0 != data->dpm_level_enable_mask.sclk_dpm_enable_mask) { + level = tonga_get_lowest_enable_level(hwmgr, + data->dpm_level_enable_mask.sclk_dpm_enable_mask); + + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state(hwmgr, level)), + "force sclk dpm state failed!", return -1); + + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, TARGET_AND_CURRENT_PROFILE_INDEX, CURR_SCLK_INDEX) != level) + printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \ + Curr_Sclk_Index does not match the level \n"); + } + } + + if (0 == data->mclk_dpm_key_disabled) { + /* MCLK */ + if (data->dpm_level_enable_mask.mclk_dpm_enable_mask != 0) { + level = tonga_get_lowest_enable_level(hwmgr, + data->dpm_level_enable_mask.mclk_dpm_enable_mask); + PP_ASSERT_WITH_CODE((0 == tonga_dpm_force_state_mclk(hwmgr, level)), + "force lowest mclk dpm state failed!", return -1); + if (PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + TARGET_AND_CURRENT_PROFILE_INDEX, CURR_MCLK_INDEX) != level) + printk(KERN_ERR "[ powerplay ] Target_and_current_Profile_Index. \ + Curr_Mclk_Index does not match the level \n"); + } + } + + return 0; +} + +static int tonga_patch_voltage_dependency_tables_with_lookup_table(struct pp_hwmgr *hwmgr) +{ + uint8_t entryId; + uint8_t voltageId; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk; + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) { + for (entryId = 0; entryId < sclk_table->count; ++entryId) { + voltageId = sclk_table->entries[entryId].vddInd; + sclk_table->entries[entryId].vddgfx = + pptable_info->vddgfx_lookup_table->entries[voltageId].us_vdd; + } + } else { + for (entryId = 0; entryId < sclk_table->count; ++entryId) { + voltageId = sclk_table->entries[entryId].vddInd; + sclk_table->entries[entryId].vddc = + pptable_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + } + + for (entryId = 0; entryId < mclk_table->count; ++entryId) { + voltageId = mclk_table->entries[entryId].vddInd; + mclk_table->entries[entryId].vddc = + pptable_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + + for (entryId = 0; entryId < mm_table->count; ++entryId) { + voltageId = mm_table->entries[entryId].vddcInd; + mm_table->entries[entryId].vddc = + pptable_info->vddc_lookup_table->entries[voltageId].us_vdd; + } + + return 0; + +} + +static int tonga_calc_voltage_dependency_tables(struct pp_hwmgr *hwmgr) +{ + uint8_t entryId; + phm_ppt_v1_voltage_lookup_record v_record; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + phm_ppt_v1_clock_voltage_dependency_table *sclk_table = pptable_info->vdd_dep_on_sclk; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table = pptable_info->vdd_dep_on_mclk; + + if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) { + for (entryId = 0; entryId < sclk_table->count; ++entryId) { + if (sclk_table->entries[entryId].vdd_offset & (1 << 15)) + v_record.us_vdd = sclk_table->entries[entryId].vddgfx + + sclk_table->entries[entryId].vdd_offset - 0xFFFF; + else + v_record.us_vdd = sclk_table->entries[entryId].vddgfx + + sclk_table->entries[entryId].vdd_offset; + + sclk_table->entries[entryId].vddc = + v_record.us_cac_low = v_record.us_cac_mid = + v_record.us_cac_high = v_record.us_vdd; + + tonga_add_voltage(hwmgr, pptable_info->vddc_lookup_table, &v_record); + } + + for (entryId = 0; entryId < mclk_table->count; ++entryId) { + if (mclk_table->entries[entryId].vdd_offset & (1 << 15)) + v_record.us_vdd = mclk_table->entries[entryId].vddc + + mclk_table->entries[entryId].vdd_offset - 0xFFFF; + else + v_record.us_vdd = mclk_table->entries[entryId].vddc + + mclk_table->entries[entryId].vdd_offset; + + mclk_table->entries[entryId].vddgfx = v_record.us_cac_low = + v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; + tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); + } + } + + return 0; + +} + +static int tonga_calc_mm_voltage_dependency_table(struct pp_hwmgr *hwmgr) +{ + uint32_t entryId; + phm_ppt_v1_voltage_lookup_record v_record; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table = pptable_info->mm_dep_table; + + if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) { + for (entryId = 0; entryId < mm_table->count; entryId++) { + if (mm_table->entries[entryId].vddgfx_offset & (1 << 15)) + v_record.us_vdd = mm_table->entries[entryId].vddc + + mm_table->entries[entryId].vddgfx_offset - 0xFFFF; + else + v_record.us_vdd = mm_table->entries[entryId].vddc + + mm_table->entries[entryId].vddgfx_offset; + + /* Add the calculated VDDGFX to the VDDGFX lookup table */ + mm_table->entries[entryId].vddgfx = v_record.us_cac_low = + v_record.us_cac_mid = v_record.us_cac_high = v_record.us_vdd; + tonga_add_voltage(hwmgr, pptable_info->vddgfx_lookup_table, &v_record); + } + } + return 0; +} + + +/** + * Change virtual leakage voltage to actual value. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to changing voltage + * @param pointer to leakage table + */ +static void tonga_patch_with_vdd_leakage(struct pp_hwmgr *hwmgr, + uint16_t *voltage, phw_tonga_leakage_voltage *pLeakageTable) +{ + uint32_t leakage_index; + + /* search for leakage voltage ID 0xff01 ~ 0xff08 */ + for (leakage_index = 0; leakage_index < pLeakageTable->count; leakage_index++) { + /* if this voltage matches a leakage voltage ID */ + /* patch with actual leakage voltage */ + if (pLeakageTable->leakage_id[leakage_index] == *voltage) { + *voltage = pLeakageTable->actual_voltage[leakage_index]; + break; + } + } + + if (*voltage > ATOM_VIRTUAL_VOLTAGE_ID0) + printk(KERN_ERR "[ powerplay ] Voltage value looks like a Leakage ID but it's not patched \n"); +} + +/** + * Patch voltage lookup table by EVV leakages. + * + * @param hwmgr the address of the powerplay hardware manager. + * @param pointer to voltage lookup table + * @param pointer to leakage table + * @return always 0 + */ +static int tonga_patch_lookup_table_with_leakage(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table, + phw_tonga_leakage_voltage *pLeakageTable) +{ + uint32_t i; + + for (i = 0; i < lookup_table->count; i++) { + tonga_patch_with_vdd_leakage(hwmgr, + &lookup_table->entries[i].us_vdd, pLeakageTable); + } + + return 0; +} + +static int tonga_patch_clock_voltage_lomits_with_vddc_leakage(struct pp_hwmgr *hwmgr, + phw_tonga_leakage_voltage *pLeakageTable, uint16_t *Vddc) +{ + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddc, pLeakageTable); + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + pptable_info->max_clock_voltage_on_dc.vddc; + + return 0; +} + +static int tonga_patch_clock_voltage_limits_with_vddgfx_leakage( + struct pp_hwmgr *hwmgr, phw_tonga_leakage_voltage *pLeakageTable, + uint16_t *Vddgfx) +{ + tonga_patch_with_vdd_leakage(hwmgr, (uint16_t *)Vddgfx, pLeakageTable); + return 0; +} + +int tonga_sort_lookup_table(struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table *lookup_table) +{ + uint32_t table_size, i, j; + phm_ppt_v1_voltage_lookup_record tmp_voltage_lookup_record; + table_size = lookup_table->count; + + PP_ASSERT_WITH_CODE(0 != lookup_table->count, + "Lookup table is empty", return -1); + + /* Sorting voltages */ + for (i = 0; i < table_size - 1; i++) { + for (j = i + 1; j > 0; j--) { + if (lookup_table->entries[j].us_vdd < lookup_table->entries[j-1].us_vdd) { + tmp_voltage_lookup_record = lookup_table->entries[j-1]; + lookup_table->entries[j-1] = lookup_table->entries[j]; + lookup_table->entries[j] = tmp_voltage_lookup_record; + } + } + } + + return 0; +} + +static int tonga_complete_dependency_tables(struct pp_hwmgr *hwmgr) +{ + int result = 0; + int tmp_result; + tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (data->vdd_gfx_control == TONGA_VOLTAGE_CONTROL_BY_SVID2) { + tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr, + pptable_info->vddgfx_lookup_table, &(data->vddcgfx_leakage)); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_patch_clock_voltage_limits_with_vddgfx_leakage(hwmgr, + &(data->vddcgfx_leakage), &pptable_info->max_clock_voltage_on_dc.vddgfx); + if (tmp_result != 0) + result = tmp_result; + } else { + tmp_result = tonga_patch_lookup_table_with_leakage(hwmgr, + pptable_info->vddc_lookup_table, &(data->vddc_leakage)); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_patch_clock_voltage_lomits_with_vddc_leakage(hwmgr, + &(data->vddc_leakage), &pptable_info->max_clock_voltage_on_dc.vddc); + if (tmp_result != 0) + result = tmp_result; + } + + tmp_result = tonga_patch_voltage_dependency_tables_with_lookup_table(hwmgr); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_calc_voltage_dependency_tables(hwmgr); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_calc_mm_voltage_dependency_table(hwmgr); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddgfx_lookup_table); + if (tmp_result != 0) + result = tmp_result; + + tmp_result = tonga_sort_lookup_table(hwmgr, pptable_info->vddc_lookup_table); + if (tmp_result != 0) + result = tmp_result; + + return result; +} + +int tonga_init_sclk_threshold(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + data->low_sclk_interrupt_threshold = 0; + + return 0; +} + +int tonga_setup_asic_task(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = tonga_read_clock_registers(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to read clock registers!", result = tmp_result); + + tmp_result = tonga_get_memory_type(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get memory type!", result = tmp_result); + + tmp_result = tonga_enable_acpi_power_management(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable ACPI power management!", result = tmp_result); + + tmp_result = tonga_init_power_gate_state(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init power gate state!", result = tmp_result); + + tmp_result = tonga_get_mc_microcode_version(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to get MC microcode version!", result = tmp_result); + + tmp_result = tonga_init_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to init sclk threshold!", result = tmp_result); + + return result; +} + +/** + * Enable voltage control + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_enable_voltage_control(struct pp_hwmgr *hwmgr) +{ + /* enable voltage control */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, GENERAL_PWRMGT, VOLT_PWRMGT_EN, 1); + + return 0; +} + +/** + * Checks if we want to support voltage control + * + * @param hwmgr the address of the powerplay hardware manager. + */ +bool cf_tonga_voltage_control(const struct pp_hwmgr *hwmgr) +{ + const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + return(TONGA_VOLTAGE_CONTROL_NONE != data->voltage_control); +} + +/*---------------------------MC----------------------------*/ + +uint8_t tonga_get_memory_modile_index(struct pp_hwmgr *hwmgr) +{ + return (uint8_t) (0xFF & (cgs_read_register(hwmgr->device, mmBIOS_SCRATCH_4) >> 16)); +} + +bool tonga_check_s0_mc_reg_index(uint16_t inReg, uint16_t *outReg) +{ + bool result = 1; + + switch (inReg) { + case mmMC_SEQ_RAS_TIMING: + *outReg = mmMC_SEQ_RAS_TIMING_LP; + break; + + case mmMC_SEQ_DLL_STBY: + *outReg = mmMC_SEQ_DLL_STBY_LP; + break; + + case mmMC_SEQ_G5PDX_CMD0: + *outReg = mmMC_SEQ_G5PDX_CMD0_LP; + break; + + case mmMC_SEQ_G5PDX_CMD1: + *outReg = mmMC_SEQ_G5PDX_CMD1_LP; + break; + + case mmMC_SEQ_G5PDX_CTRL: + *outReg = mmMC_SEQ_G5PDX_CTRL_LP; + break; + + case mmMC_SEQ_CAS_TIMING: + *outReg = mmMC_SEQ_CAS_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING: + *outReg = mmMC_SEQ_MISC_TIMING_LP; + break; + + case mmMC_SEQ_MISC_TIMING2: + *outReg = mmMC_SEQ_MISC_TIMING2_LP; + break; + + case mmMC_SEQ_PMG_DVS_CMD: + *outReg = mmMC_SEQ_PMG_DVS_CMD_LP; + break; + + case mmMC_SEQ_PMG_DVS_CTL: + *outReg = mmMC_SEQ_PMG_DVS_CTL_LP; + break; + + case mmMC_SEQ_RD_CTL_D0: + *outReg = mmMC_SEQ_RD_CTL_D0_LP; + break; + + case mmMC_SEQ_RD_CTL_D1: + *outReg = mmMC_SEQ_RD_CTL_D1_LP; + break; + + case mmMC_SEQ_WR_CTL_D0: + *outReg = mmMC_SEQ_WR_CTL_D0_LP; + break; + + case mmMC_SEQ_WR_CTL_D1: + *outReg = mmMC_SEQ_WR_CTL_D1_LP; + break; + + case mmMC_PMG_CMD_EMRS: + *outReg = mmMC_SEQ_PMG_CMD_EMRS_LP; + break; + + case mmMC_PMG_CMD_MRS: + *outReg = mmMC_SEQ_PMG_CMD_MRS_LP; + break; + + case mmMC_PMG_CMD_MRS1: + *outReg = mmMC_SEQ_PMG_CMD_MRS1_LP; + break; + + case mmMC_SEQ_PMG_TIMING: + *outReg = mmMC_SEQ_PMG_TIMING_LP; + break; + + case mmMC_PMG_CMD_MRS2: + *outReg = mmMC_SEQ_PMG_CMD_MRS2_LP; + break; + + case mmMC_SEQ_WR_CTL_2: + *outReg = mmMC_SEQ_WR_CTL_2_LP; + break; + + default: + result = 0; + break; + } + + return result; +} + +int tonga_set_s0_mc_reg_index(phw_tonga_mc_reg_table *table) +{ + uint32_t i; + uint16_t address; + + for (i = 0; i < table->last; i++) { + table->mc_reg_address[i].s0 = + tonga_check_s0_mc_reg_index(table->mc_reg_address[i].s1, &address) + ? address : table->mc_reg_address[i].s1; + } + return 0; +} + +int tonga_copy_vbios_smc_reg_table(const pp_atomctrl_mc_reg_table *table, phw_tonga_mc_reg_table *ni_table) +{ + uint8_t i, j; + + PP_ASSERT_WITH_CODE((table->last <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + PP_ASSERT_WITH_CODE((table->num_entries <= MAX_AC_TIMING_ENTRIES), + "Invalid VramInfo table.", return -1); + + for (i = 0; i < table->last; i++) { + ni_table->mc_reg_address[i].s1 = table->mc_reg_address[i].s1; + } + ni_table->last = table->last; + + for (i = 0; i < table->num_entries; i++) { + ni_table->mc_reg_table_entry[i].mclk_max = + table->mc_reg_table_entry[i].mclk_max; + for (j = 0; j < table->last; j++) { + ni_table->mc_reg_table_entry[i].mc_data[j] = + table->mc_reg_table_entry[i].mc_data[j]; + } + } + ni_table->num_entries = table->num_entries; + + return 0; +} + +/** + * VBIOS omits some information to reduce size, we need to recover them here. + * 1. when we see mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to mmMC_PMG_CMD_EMRS /_LP[15:0]. + * Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0] + * 2. when we see mmMC_SEQ_RESERVE_M, bit[15:0] EMRS2, need to be write to mmMC_PMG_CMD_MRS1/_LP[15:0]. + * 3. need to set these data for each clock range + * + * @param hwmgr the address of the powerplay hardware manager. + * @param table the address of MCRegTable + * @return always 0 + */ +int tonga_set_mc_special_registers(struct pp_hwmgr *hwmgr, phw_tonga_mc_reg_table *table) +{ + uint8_t i, j, k; + uint32_t temp_reg; + const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + for (i = 0, j = table->last; i < table->last; i++) { + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + switch (table->mc_reg_address[i].s1) { + /* + * mmMC_SEQ_MISC1, bit[31:16] EMRS1, need to be write to mmMC_PMG_CMD_EMRS /_LP[15:0]. + * Bit[15:0] MRS, need to be update mmMC_PMG_CMD_MRS/_LP[15:0] + */ + case mmMC_SEQ_MISC1: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_EMRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_EMRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + ((temp_reg & 0xffff0000)) | + ((table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16); + } + j++; + PP_ASSERT_WITH_CODE((j < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + + if (!data->is_memory_GDDR5) { + table->mc_reg_table_entry[k].mc_data[j] |= 0x100; + } + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + + if (!data->is_memory_GDDR5) { + table->mc_reg_address[j].s1 = mmMC_PMG_AUTO_CMD; + table->mc_reg_address[j].s0 = mmMC_PMG_AUTO_CMD; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (table->mc_reg_table_entry[k].mc_data[i] & 0xffff0000) >> 16; + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + } + + break; + + case mmMC_SEQ_RESERVE_M: + temp_reg = cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1); + table->mc_reg_address[j].s1 = mmMC_PMG_CMD_MRS1; + table->mc_reg_address[j].s0 = mmMC_SEQ_PMG_CMD_MRS1_LP; + for (k = 0; k < table->num_entries; k++) { + table->mc_reg_table_entry[k].mc_data[j] = + (temp_reg & 0xffff0000) | + (table->mc_reg_table_entry[k].mc_data[i] & 0x0000ffff); + } + j++; + PP_ASSERT_WITH_CODE((j <= SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE), + "Invalid VramInfo table.", return -1); + break; + + default: + break; + } + + } + + table->last = j; + + return 0; +} + +int tonga_set_valid_flag(phw_tonga_mc_reg_table *table) +{ + uint8_t i, j; + for (i = 0; i < table->last; i++) { + for (j = 1; j < table->num_entries; j++) { + if (table->mc_reg_table_entry[j-1].mc_data[i] != + table->mc_reg_table_entry[j].mc_data[i]) { + table->validflag |= (1<<i); + break; + } + } + } + + return 0; +} + +int tonga_initialize_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + pp_atomctrl_mc_reg_table *table; + phw_tonga_mc_reg_table *ni_table = &data->tonga_mc_reg_table; + uint8_t module_index = tonga_get_memory_modile_index(hwmgr); + + table = kzalloc(sizeof(pp_atomctrl_mc_reg_table), GFP_KERNEL); + + if (NULL == table) + return -1; + + /* Program additional LP registers that are no longer programmed by VBIOS */ + cgs_write_register(hwmgr->device, mmMC_SEQ_RAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_CAS_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_CAS_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_DLL_STBY_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_DLL_STBY)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CMD1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_G5PDX_CTRL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CMD)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_DVS_CTL)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_MISC_TIMING2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_EMRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_EMRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS1_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D0)); + cgs_write_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_RD_CTL_D1)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_TIMING_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_PMG_TIMING)); + cgs_write_register(hwmgr->device, mmMC_SEQ_PMG_CMD_MRS2_LP, cgs_read_register(hwmgr->device, mmMC_PMG_CMD_MRS2)); + cgs_write_register(hwmgr->device, mmMC_SEQ_WR_CTL_2_LP, cgs_read_register(hwmgr->device, mmMC_SEQ_WR_CTL_2)); + + memset(table, 0x00, sizeof(pp_atomctrl_mc_reg_table)); + + result = atomctrl_initialize_mc_reg_table(hwmgr, module_index, table); + + if (0 == result) + result = tonga_copy_vbios_smc_reg_table(table, ni_table); + + if (0 == result) { + tonga_set_s0_mc_reg_index(ni_table); + result = tonga_set_mc_special_registers(hwmgr, ni_table); + } + + if (0 == result) + tonga_set_valid_flag(ni_table); + + kfree(table); + return result; +} + +/* +* Copy one arb setting to another and then switch the active set. +* arbFreqSrc and arbFreqDest is one of the MC_CG_ARB_FREQ_Fx constants. +*/ +int tonga_copy_and_switch_arb_sets(struct pp_hwmgr *hwmgr, + uint32_t arbFreqSrc, uint32_t arbFreqDest) +{ + uint32_t mc_arb_dram_timing; + uint32_t mc_arb_dram_timing2; + uint32_t burst_time; + uint32_t mc_cg_config; + + switch (arbFreqSrc) { + case MC_CG_ARB_FREQ_F0: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0); + break; + + case MC_CG_ARB_FREQ_F1: + mc_arb_dram_timing = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1); + mc_arb_dram_timing2 = cgs_read_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1); + burst_time = PHM_READ_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1); + break; + + default: + return -1; + } + + switch (arbFreqDest) { + case MC_CG_ARB_FREQ_F0: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE0, burst_time); + break; + + case MC_CG_ARB_FREQ_F1: + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING_1, mc_arb_dram_timing); + cgs_write_register(hwmgr->device, mmMC_ARB_DRAM_TIMING2_1, mc_arb_dram_timing2); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_BURST_TIME, STATE1, burst_time); + break; + + default: + return -1; + } + + mc_cg_config = cgs_read_register(hwmgr->device, mmMC_CG_CONFIG); + mc_cg_config |= 0x0000000F; + cgs_write_register(hwmgr->device, mmMC_CG_CONFIG, mc_cg_config); + PHM_WRITE_FIELD(hwmgr->device, MC_ARB_CG, CG_ARB_REQ, arbFreqDest); + + return 0; +} + +/** + * Initial switch from ARB F0->F1 + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + * This function is to be called from the SetPowerState table. + */ +int tonga_initial_switch_from_arb_f0_to_f1(struct pp_hwmgr *hwmgr) +{ + return tonga_copy_and_switch_arb_sets(hwmgr, MC_CG_ARB_FREQ_F0, MC_CG_ARB_FREQ_F1); +} + +/** + * Initialize the ARB DRAM timing table's index field. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_init_arb_table_index(struct pp_hwmgr *hwmgr) +{ + const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t tmp; + int result; + + /* + * This is a read-modify-write on the first byte of the ARB table. + * The first byte in the SMU72_Discrete_MCArbDramTimingTable structure is the field 'current'. + * This solution is ugly, but we never write the whole table only individual fields in it. + * In reality this field should not be in that structure but in a soft register. + */ + result = tonga_read_smc_sram_dword(hwmgr->smumgr, + data->arb_table_start, &tmp, data->sram_end); + + if (0 != result) + return result; + + tmp &= 0x00FFFFFF; + tmp |= ((uint32_t)MC_CG_ARB_FREQ_F1) << 24; + + return tonga_write_smc_sram_dword(hwmgr->smumgr, + data->arb_table_start, tmp, data->sram_end); +} + +int tonga_populate_mc_reg_address(struct pp_hwmgr *hwmgr, SMU72_Discrete_MCRegisters *mc_reg_table) +{ + const struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + uint32_t i, j; + + for (i = 0, j = 0; j < data->tonga_mc_reg_table.last; j++) { + if (data->tonga_mc_reg_table.validflag & 1<<j) { + PP_ASSERT_WITH_CODE(i < SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE, + "Index of mc_reg_table->address[] array out of boundary", return -1); + mc_reg_table->address[i].s0 = + PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s0); + mc_reg_table->address[i].s1 = + PP_HOST_TO_SMC_US(data->tonga_mc_reg_table.mc_reg_address[j].s1); + i++; + } + } + + mc_reg_table->last = (uint8_t)i; + + return 0; +} + +/*convert register values from driver to SMC format */ +void tonga_convert_mc_registers( + const phw_tonga_mc_reg_entry * pEntry, + SMU72_Discrete_MCRegisterSet *pData, + uint32_t numEntries, uint32_t validflag) +{ + uint32_t i, j; + + for (i = 0, j = 0; j < numEntries; j++) { + if (validflag & 1<<j) { + pData->value[i] = PP_HOST_TO_SMC_UL(pEntry->mc_data[j]); + i++; + } + } +} + +/* find the entry in the memory range table, then populate the value to SMC's tonga_mc_reg_table */ +int tonga_convert_mc_reg_table_entry_to_smc( + struct pp_hwmgr *hwmgr, + const uint32_t memory_clock, + SMU72_Discrete_MCRegisterSet *mc_reg_table_data + ) +{ + const tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t i = 0; + + for (i = 0; i < data->tonga_mc_reg_table.num_entries; i++) { + if (memory_clock <= + data->tonga_mc_reg_table.mc_reg_table_entry[i].mclk_max) { + break; + } + } + + if ((i == data->tonga_mc_reg_table.num_entries) && (i > 0)) + --i; + + tonga_convert_mc_registers(&data->tonga_mc_reg_table.mc_reg_table_entry[i], + mc_reg_table_data, data->tonga_mc_reg_table.last, data->tonga_mc_reg_table.validflag); + + return 0; +} + +int tonga_convert_mc_reg_table_to_smc(struct pp_hwmgr *hwmgr, + SMU72_Discrete_MCRegisters *mc_reg_table) +{ + int result = 0; + tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + int res; + uint32_t i; + + for (i = 0; i < data->dpm_table.mclk_table.count; i++) { + res = tonga_convert_mc_reg_table_entry_to_smc( + hwmgr, + data->dpm_table.mclk_table.dpm_levels[i].value, + &mc_reg_table->data[i] + ); + + if (0 != res) + result = res; + } + + return result; +} + +int tonga_populate_initial_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + int result; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + memset(&data->mc_reg_table, 0x00, sizeof(SMU72_Discrete_MCRegisters)); + result = tonga_populate_mc_reg_address(hwmgr, &(data->mc_reg_table)); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for the MC register addresses!", return result;); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &data->mc_reg_table); + PP_ASSERT_WITH_CODE(0 == result, + "Failed to initialize MCRegTable for driver state!", return result;); + + return tonga_copy_bytes_to_smc(hwmgr->smumgr, data->mc_reg_table_start, + (uint8_t *)&data->mc_reg_table, sizeof(SMU72_Discrete_MCRegisters), data->sram_end); +} + +/** + * Programs static screed detection parameters + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_program_static_screen_threshold_parameters(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* Set static screen threshold unit*/ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD_UNIT, + data->static_screen_threshold_unit); + /* Set static screen threshold*/ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__SMC, CG_STATIC_SCREEN_PARAMETER, STATIC_SCREEN_THRESHOLD, + data->static_screen_threshold); + + return 0; +} + +/** + * Setup display gap for glitch free memory clock switching. + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_enable_display_gap(struct pp_hwmgr *hwmgr) +{ + uint32_t display_gap = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); + + display_gap = PHM_SET_FIELD(display_gap, + CG_DISPLAY_GAP_CNTL, DISP_GAP, DISPLAY_GAP_IGNORE); + + display_gap = PHM_SET_FIELD(display_gap, + CG_DISPLAY_GAP_CNTL, DISP_GAP_MCHG, DISPLAY_GAP_VBLANK); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_DISPLAY_GAP_CNTL, display_gap); + + return 0; +} + +/** + * Programs activity state transition voting clients + * + * @param hwmgr the address of the powerplay hardware manager. + * @return always 0 + */ +int tonga_program_voting_clients(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data = (tonga_hwmgr *)(hwmgr->backend); + + /* Clear reset for voting clients before enabling DPM */ + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_SCLK_CNT, 0); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + SCLK_PWRMGT_CNTL, RESET_BUSY_CNT, 0); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_0, data->voting_rights_clients0); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_1, data->voting_rights_clients1); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_2, data->voting_rights_clients2); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_3, data->voting_rights_clients3); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_4, data->voting_rights_clients4); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_5, data->voting_rights_clients5); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_6, data->voting_rights_clients6); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCG_FREQ_TRAN_VOTING_7, data->voting_rights_clients7); + + return 0; +} + + +int tonga_enable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = tonga_check_for_dpm_stopped(hwmgr); + + if (cf_tonga_voltage_control(hwmgr)) { + tmp_result = tonga_enable_voltage_control(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable voltage control!", result = tmp_result); + + tmp_result = tonga_construct_voltage_tables(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to contruct voltage tables!", result = tmp_result); + } + + tmp_result = tonga_initialize_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize MC reg table!", result = tmp_result); + + tmp_result = tonga_program_static_screen_threshold_parameters(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program static screen threshold parameters!", result = tmp_result); + + tmp_result = tonga_enable_display_gap(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable display gap!", result = tmp_result); + + tmp_result = tonga_program_voting_clients(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to program voting clients!", result = tmp_result); + + tmp_result = tonga_process_firmware_header(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to process firmware header!", result = tmp_result); + + tmp_result = tonga_initial_switch_from_arb_f0_to_f1(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize switch from ArbF0 to F1!", result = tmp_result); + + tmp_result = tonga_init_smc_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize SMC table!", result = tmp_result); + + tmp_result = tonga_init_arb_table_index(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to initialize ARB table index!", result = tmp_result); + + tmp_result = tonga_populate_initial_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to populate initialize MC Reg table!", result = tmp_result); + + tmp_result = tonga_notify_smc_display_change(hwmgr, false); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to notify no display!", result = tmp_result); + + /* enable SCLK control */ + tmp_result = tonga_enable_sclk_control(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to enable SCLK control!", result = tmp_result); + + /* enable DPM */ + tmp_result = tonga_start_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to start DPM!", result = tmp_result); + + return result; +} + +int tonga_disable_dpm_tasks(struct pp_hwmgr *hwmgr) +{ + int tmp_result, result = 0; + + tmp_result = tonga_check_for_dpm_running(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "SMC is still running!", return 0); + + tmp_result = tonga_stop_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to stop DPM!", result = tmp_result); + + tmp_result = tonga_reset_to_default(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), + "Failed to reset to default!", result = tmp_result); + + return result; +} + +int tonga_reset_asic_tasks(struct pp_hwmgr *hwmgr) +{ + int result; + + result = tonga_set_boot_state(hwmgr); + if (0 != result) + printk(KERN_ERR "[ powerplay ] Failed to reset asic via set boot state! \n"); + + return result; +} + +int tonga_hwmgr_backend_fini(struct pp_hwmgr *hwmgr) +{ + if (NULL != hwmgr->dyn_state.vddc_dep_on_dal_pwrl) { + kfree(hwmgr->dyn_state.vddc_dep_on_dal_pwrl); + hwmgr->dyn_state.vddc_dep_on_dal_pwrl = NULL; + } + + if (NULL != hwmgr->backend) { + kfree(hwmgr->backend); + hwmgr->backend = NULL; + } + + return 0; +} + +/** + * Initializes the Volcanic Islands Hardware Manager + * + * @param hwmgr the address of the powerplay hardware manager. + * @return 1 if success; otherwise appropriate error code. + */ +int tonga_hwmgr_backend_init(struct pp_hwmgr *hwmgr) +{ + int result = 0; + SMU72_Discrete_DpmTable *table = NULL; + tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + pp_atomctrl_gpio_pin_assignment gpio_pin_assignment; + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + phw_tonga_ulv_parm *ulv; + + PP_ASSERT_WITH_CODE((NULL != hwmgr), + "Invalid Parameter!", return -1;); + + data->dll_defaule_on = 0; + data->sram_end = SMC_RAM_END; + + data->activity_target[0] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[1] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[2] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[3] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[4] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[5] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[6] = PPTONGA_TARGETACTIVITY_DFLT; + data->activity_target[7] = PPTONGA_TARGETACTIVITY_DFLT; + + data->vddc_vddci_delta = VDDC_VDDCI_DELTA; + data->vddc_vddgfx_delta = VDDC_VDDGFX_DELTA; + data->mclk_activity_target = PPTONGA_MCLK_TARGETACTIVITY_DFLT; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableVoltageIsland); + + data->sclk_dpm_key_disabled = 0; + data->mclk_dpm_key_disabled = 0; + data->pcie_dpm_key_disabled = 0; + data->pcc_monitor_enabled = 0; + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_UnTabledHardwareInterface); + + data->gpio_debug = 0; + data->engine_clock_data = 0; + data->memory_clock_data = 0; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DynamicPatchPowerState); + + /* need to set voltage control types before EVV patching*/ + data->voltage_control = TONGA_VOLTAGE_CONTROL_NONE; + data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_NONE; + data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_NONE; + data->mvdd_control = TONGA_VOLTAGE_CONTROL_NONE; + + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDC, VOLTAGE_OBJ_SVID2)) { + data->voltage_control = TONGA_VOLTAGE_CONTROL_BY_SVID2; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDGFX)) { + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDGFX, VOLTAGE_OBJ_SVID2)) { + data->vdd_gfx_control = TONGA_VOLTAGE_CONTROL_BY_SVID2; + } + } + + if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_gfx_control) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDGFX); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl)) { + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_MVDDC, VOLTAGE_OBJ_GPIO_LUT)) { + data->mvdd_control = TONGA_VOLTAGE_CONTROL_BY_GPIO; + } + } + + if (TONGA_VOLTAGE_CONTROL_NONE == data->mvdd_control) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableMVDDControl); + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI)) { + if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_GPIO_LUT)) + data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_GPIO; + else if (atomctrl_is_voltage_controled_by_gpio_v3(hwmgr, + VOLTAGE_TYPE_VDDCI, VOLTAGE_OBJ_SVID2)) + data->vdd_ci_control = TONGA_VOLTAGE_CONTROL_BY_SVID2; + } + + if (TONGA_VOLTAGE_CONTROL_NONE == data->vdd_ci_control) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ControlVDDCI); + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_TablelessHardwareInterface); + + if (pptable_info->cac_dtp_table->usClockStretchAmount != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ClockStretcher); + + /* Initializes DPM default values*/ + tonga_initialize_dpm_defaults(hwmgr); + + /* Get leakage voltage based on leakage ID.*/ + PP_ASSERT_WITH_CODE((0 == tonga_get_evv_voltage(hwmgr)), + "Get EVV Voltage Failed. Abort Driver loading!", return -1); + + tonga_complete_dependency_tables(hwmgr); + + /* Parse pptable data read from VBIOS*/ + tonga_set_private_var_based_on_pptale(hwmgr); + + /* ULV Support*/ + ulv = &(data->ulv); + ulv->ulv_supported = 0; + + /* Initalize Dynamic State Adjustment Rule Settings*/ + result = tonga_initializa_dynamic_state_adjustment_rule_settings(hwmgr); + if (result) + printk(KERN_ERR "[ powerplay ] tonga_initializa_dynamic_state_adjustment_rule_settings failed!\n"); + data->uvd_enabled = 0; + + table = &(data->smc_state_table); + + /* + * if ucGPIO_ID=VDDC_PCC_GPIO_PINID in GPIO_LUTable, + * Peak Current Control feature is enabled and we should program PCC HW register + */ + if (0 == atomctrl_get_pp_assign_pin(hwmgr, VDDC_PCC_GPIO_PINID, &gpio_pin_assignment)) { + uint32_t temp_reg = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__SMC, ixCNB_PWRMGT_CNTL); + + switch (gpio_pin_assignment.uc_gpio_pin_bit_shift) { + case 0: + temp_reg = PHM_SET_FIELD(temp_reg, + CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x1); + break; + case 1: + temp_reg = PHM_SET_FIELD(temp_reg, + CNB_PWRMGT_CNTL, GNB_SLOW_MODE, 0x2); + break; + case 2: + temp_reg = PHM_SET_FIELD(temp_reg, + CNB_PWRMGT_CNTL, GNB_SLOW, 0x1); + break; + case 3: + temp_reg = PHM_SET_FIELD(temp_reg, + CNB_PWRMGT_CNTL, FORCE_NB_PS1, 0x1); + break; + case 4: + temp_reg = PHM_SET_FIELD(temp_reg, + CNB_PWRMGT_CNTL, DPM_ENABLED, 0x1); + break; + default: + printk(KERN_ERR "[ powerplay ] Failed to setup PCC HW register! \ + Wrong GPIO assigned for VDDC_PCC_GPIO_PINID! \n"); + break; + } + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, + ixCNB_PWRMGT_CNTL, temp_reg); + } + + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnableSMU7ThermalManagement); + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_SMU7); + + data->vddc_phase_shed_control = 0; + + if (0 == result) { + struct cgs_system_info sys_info = {0}; + + data->is_tlu_enabled = 0; + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels = + TONGA_MAX_HARDWARE_POWERLEVELS; + hwmgr->platform_descriptor.hardwarePerformanceLevels = 2; + hwmgr->platform_descriptor.minimumClocksReductionPercentage = 50; + + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_GEN_INFO; + result = cgs_query_system_info(hwmgr->device, &sys_info); + if (result) + data->pcie_gen_cap = 0x30007; + else + data->pcie_gen_cap = (uint32_t)sys_info.value; + if (data->pcie_gen_cap & CAIL_PCIE_LINK_SPEED_SUPPORT_GEN3) + data->pcie_spc_cap = 20; + sys_info.size = sizeof(struct cgs_system_info); + sys_info.info_id = CGS_SYSTEM_INFO_PCIE_MLW; + result = cgs_query_system_info(hwmgr->device, &sys_info); + if (result) + data->pcie_lane_cap = 0x2f0000; + else + data->pcie_lane_cap = (uint32_t)sys_info.value; + } else { + /* Ignore return value in here, we are cleaning up a mess. */ + tonga_hwmgr_backend_fini(hwmgr); + } + + return result; +} + +static int tonga_force_dpm_level(struct pp_hwmgr *hwmgr, + enum amd_dpm_forced_level level) +{ + int ret = 0; + + switch (level) { + case AMD_DPM_FORCED_LEVEL_HIGH: + ret = tonga_force_dpm_highest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_LOW: + ret = tonga_force_dpm_lowest(hwmgr); + if (ret) + return ret; + break; + case AMD_DPM_FORCED_LEVEL_AUTO: + ret = tonga_unforce_dpm_levels(hwmgr); + if (ret) + return ret; + break; + default: + break; + } + + hwmgr->dpm_level = level; + return ret; +} + +static int tonga_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps) +{ + struct tonga_power_state *tonga_ps = + cast_phw_tonga_power_state(&prequest_ps->hardware); + + uint32_t sclk; + uint32_t mclk; + struct PP_Clocks minimum_clocks = {0}; + bool disable_mclk_switching; + bool disable_mclk_switching_for_frame_lock; + struct cgs_display_info info = {0}; + const struct phm_clock_and_voltage_limits *max_limits; + uint32_t i; + tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + int32_t count; + int32_t stable_pstate_sclk = 0, stable_pstate_mclk = 0; + + data->battery_state = (PP_StateUILabel_Battery == prequest_ps->classification.ui_label); + + PP_ASSERT_WITH_CODE(tonga_ps->performance_level_count == 2, + "VI should always have 2 performance levels", + ); + + max_limits = (PP_PowerSource_AC == hwmgr->power_source) ? + &(hwmgr->dyn_state.max_clock_voltage_on_ac) : + &(hwmgr->dyn_state.max_clock_voltage_on_dc); + + if (PP_PowerSource_DC == hwmgr->power_source) { + for (i = 0; i < tonga_ps->performance_level_count; i++) { + if (tonga_ps->performance_levels[i].memory_clock > max_limits->mclk) + tonga_ps->performance_levels[i].memory_clock = max_limits->mclk; + if (tonga_ps->performance_levels[i].engine_clock > max_limits->sclk) + tonga_ps->performance_levels[i].engine_clock = max_limits->sclk; + } + } + + tonga_ps->vce_clocks.EVCLK = hwmgr->vce_arbiter.evclk; + tonga_ps->vce_clocks.ECCLK = hwmgr->vce_arbiter.ecclk; + + tonga_ps->acp_clk = hwmgr->acp_arbiter.acpclk; + + cgs_get_active_displays_info(hwmgr->device, &info); + + /*TO DO result = PHM_CheckVBlankTime(hwmgr, &vblankTooShort);*/ + + /* TO DO GetMinClockSettings(hwmgr->pPECI, &minimum_clocks); */ + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) { + + max_limits = &(hwmgr->dyn_state.max_clock_voltage_on_ac); + stable_pstate_sclk = (max_limits->sclk * 75) / 100; + + for (count = pptable_info->vdd_dep_on_sclk->count-1; count >= 0; count--) { + if (stable_pstate_sclk >= pptable_info->vdd_dep_on_sclk->entries[count].clk) { + stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[count].clk; + break; + } + } + + if (count < 0) + stable_pstate_sclk = pptable_info->vdd_dep_on_sclk->entries[0].clk; + + stable_pstate_mclk = max_limits->mclk; + + minimum_clocks.engineClock = stable_pstate_sclk; + minimum_clocks.memoryClock = stable_pstate_mclk; + } + + if (minimum_clocks.engineClock < hwmgr->gfx_arbiter.sclk) + minimum_clocks.engineClock = hwmgr->gfx_arbiter.sclk; + + if (minimum_clocks.memoryClock < hwmgr->gfx_arbiter.mclk) + minimum_clocks.memoryClock = hwmgr->gfx_arbiter.mclk; + + tonga_ps->sclk_threshold = hwmgr->gfx_arbiter.sclk_threshold; + + if (0 != hwmgr->gfx_arbiter.sclk_over_drive) { + PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.sclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.engineClock), + "Overdrive sclk exceeds limit", + hwmgr->gfx_arbiter.sclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.engineClock); + + if (hwmgr->gfx_arbiter.sclk_over_drive >= hwmgr->gfx_arbiter.sclk) + tonga_ps->performance_levels[1].engine_clock = hwmgr->gfx_arbiter.sclk_over_drive; + } + + if (0 != hwmgr->gfx_arbiter.mclk_over_drive) { + PP_ASSERT_WITH_CODE((hwmgr->gfx_arbiter.mclk_over_drive <= hwmgr->platform_descriptor.overdriveLimit.memoryClock), + "Overdrive mclk exceeds limit", + hwmgr->gfx_arbiter.mclk_over_drive = hwmgr->platform_descriptor.overdriveLimit.memoryClock); + + if (hwmgr->gfx_arbiter.mclk_over_drive >= hwmgr->gfx_arbiter.mclk) + tonga_ps->performance_levels[1].memory_clock = hwmgr->gfx_arbiter.mclk_over_drive; + } + + disable_mclk_switching_for_frame_lock = phm_cap_enabled( + hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock); + + disable_mclk_switching = (1 < info.display_count) || + disable_mclk_switching_for_frame_lock; + + sclk = tonga_ps->performance_levels[0].engine_clock; + mclk = tonga_ps->performance_levels[0].memory_clock; + + if (disable_mclk_switching) + mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count - 1].memory_clock; + + if (sclk < minimum_clocks.engineClock) + sclk = (minimum_clocks.engineClock > max_limits->sclk) ? max_limits->sclk : minimum_clocks.engineClock; + + if (mclk < minimum_clocks.memoryClock) + mclk = (minimum_clocks.memoryClock > max_limits->mclk) ? max_limits->mclk : minimum_clocks.memoryClock; + + tonga_ps->performance_levels[0].engine_clock = sclk; + tonga_ps->performance_levels[0].memory_clock = mclk; + + tonga_ps->performance_levels[1].engine_clock = + (tonga_ps->performance_levels[1].engine_clock >= tonga_ps->performance_levels[0].engine_clock) ? + tonga_ps->performance_levels[1].engine_clock : + tonga_ps->performance_levels[0].engine_clock; + + if (disable_mclk_switching) { + if (mclk < tonga_ps->performance_levels[1].memory_clock) + mclk = tonga_ps->performance_levels[1].memory_clock; + + tonga_ps->performance_levels[0].memory_clock = mclk; + tonga_ps->performance_levels[1].memory_clock = mclk; + } else { + if (tonga_ps->performance_levels[1].memory_clock < tonga_ps->performance_levels[0].memory_clock) + tonga_ps->performance_levels[1].memory_clock = tonga_ps->performance_levels[0].memory_clock; + } + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) { + for (i=0; i < tonga_ps->performance_level_count; i++) { + tonga_ps->performance_levels[i].engine_clock = stable_pstate_sclk; + tonga_ps->performance_levels[i].memory_clock = stable_pstate_mclk; + tonga_ps->performance_levels[i].pcie_gen = data->pcie_gen_performance.max; + tonga_ps->performance_levels[i].pcie_lane = data->pcie_gen_performance.max; + } + } + + return 0; +} + +int tonga_get_power_state_size(struct pp_hwmgr *hwmgr) +{ + return sizeof(struct tonga_power_state); +} + +static int tonga_dpm_get_mclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct tonga_power_state *tonga_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + tonga_ps = cast_phw_tonga_power_state(&ps->hardware); + + if (low) + return tonga_ps->performance_levels[0].memory_clock; + else + return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock; +} + +static int tonga_dpm_get_sclk(struct pp_hwmgr *hwmgr, bool low) +{ + struct pp_power_state *ps; + struct tonga_power_state *tonga_ps; + + if (hwmgr == NULL) + return -EINVAL; + + ps = hwmgr->request_ps; + + if (ps == NULL) + return -EINVAL; + + tonga_ps = cast_phw_tonga_power_state(&ps->hardware); + + if (low) + return tonga_ps->performance_levels[0].engine_clock; + else + return tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock; +} + +static uint16_t tonga_get_current_pcie_speed( + struct pp_hwmgr *hwmgr) +{ + uint32_t speed_cntl = 0; + + speed_cntl = cgs_read_ind_register(hwmgr->device, + CGS_IND_REG__PCIE, + ixPCIE_LC_SPEED_CNTL); + return((uint16_t)PHM_GET_FIELD(speed_cntl, + PCIE_LC_SPEED_CNTL, LC_CURRENT_DATA_RATE)); +} + +static int tonga_get_current_pcie_lane_number( + struct pp_hwmgr *hwmgr) +{ + uint32_t link_width; + + link_width = PHM_READ_INDIRECT_FIELD(hwmgr->device, + CGS_IND_REG__PCIE, + PCIE_LC_LINK_WIDTH_CNTL, + LC_LINK_WIDTH_RD); + + PP_ASSERT_WITH_CODE((7 >= link_width), + "Invalid PCIe lane width!", return 0); + + return decode_pcie_lane_width(link_width); +} + +static int tonga_dpm_patch_boot_state(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_power_state *ps = (struct tonga_power_state *)hw_ps; + ATOM_FIRMWARE_INFO_V2_2 *fw_info; + uint16_t size; + uint8_t frev, crev; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + + /* First retrieve the Boot clocks and VDDC from the firmware info table. + * We assume here that fw_info is unchanged if this call fails. + */ + fw_info = (ATOM_FIRMWARE_INFO_V2_2 *)cgs_atom_get_data_table( + hwmgr->device, index, + &size, &frev, &crev); + if (!fw_info) + /* During a test, there is no firmware info table. */ + return 0; + + /* Patch the state. */ + data->vbios_boot_state.sclk_bootup_value = le32_to_cpu(fw_info->ulDefaultEngineClock); + data->vbios_boot_state.mclk_bootup_value = le32_to_cpu(fw_info->ulDefaultMemoryClock); + data->vbios_boot_state.mvdd_bootup_value = le16_to_cpu(fw_info->usBootUpMVDDCVoltage); + data->vbios_boot_state.vddc_bootup_value = le16_to_cpu(fw_info->usBootUpVDDCVoltage); + data->vbios_boot_state.vddci_bootup_value = le16_to_cpu(fw_info->usBootUpVDDCIVoltage); + data->vbios_boot_state.pcie_gen_bootup_value = tonga_get_current_pcie_speed(hwmgr); + data->vbios_boot_state.pcie_lane_bootup_value = + (uint16_t)tonga_get_current_pcie_lane_number(hwmgr); + + /* set boot power state */ + ps->performance_levels[0].memory_clock = data->vbios_boot_state.mclk_bootup_value; + ps->performance_levels[0].engine_clock = data->vbios_boot_state.sclk_bootup_value; + ps->performance_levels[0].pcie_gen = data->vbios_boot_state.pcie_gen_bootup_value; + ps->performance_levels[0].pcie_lane = data->vbios_boot_state.pcie_lane_bootup_value; + + return 0; +} + +static int tonga_get_pp_table_entry_callback_func(struct pp_hwmgr *hwmgr, + void *state, struct pp_power_state *power_state, + void *pp_table, uint32_t classification_flag) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + struct tonga_power_state *tonga_ps = + (struct tonga_power_state *)(&(power_state->hardware)); + + struct tonga_performance_level *performance_level; + + ATOM_Tonga_State *state_entry = (ATOM_Tonga_State *)state; + + ATOM_Tonga_POWERPLAYTABLE *powerplay_table = + (ATOM_Tonga_POWERPLAYTABLE *)pp_table; + + ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = + (ATOM_Tonga_SCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + + ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (ATOM_Tonga_MCLK_Dependency_Table *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + + /* The following fields are not initialized here: id orderedList allStatesList */ + power_state->classification.ui_label = + (le16_to_cpu(state_entry->usClassification) & + ATOM_PPLIB_CLASSIFICATION_UI_MASK) >> + ATOM_PPLIB_CLASSIFICATION_UI_SHIFT; + power_state->classification.flags = classification_flag; + /* NOTE: There is a classification2 flag in BIOS that is not being used right now */ + + power_state->classification.temporary_state = false; + power_state->classification.to_be_deleted = false; + + power_state->validation.disallowOnDC = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_DISALLOW_ON_DC)); + + power_state->pcie.lanes = 0; + + power_state->display.disableFrameModulation = false; + power_state->display.limitRefreshrate = false; + power_state->display.enableVariBright = + (0 != (le32_to_cpu(state_entry->ulCapsAndSettings) & ATOM_Tonga_ENABLE_VARIBRIGHT)); + + power_state->validation.supportedPowerLevels = 0; + power_state->uvd_clocks.VCLK = 0; + power_state->uvd_clocks.DCLK = 0; + power_state->temperatures.min = 0; + power_state->temperatures.max = 0; + + performance_level = &(tonga_ps->performance_levels + [tonga_ps->performance_level_count++]); + + PP_ASSERT_WITH_CODE( + (tonga_ps->performance_level_count < SMU72_MAX_LEVELS_GRAPHICS), + "Performance levels exceeds SMC limit!", + return -1); + + PP_ASSERT_WITH_CODE( + (tonga_ps->performance_level_count <= + hwmgr->platform_descriptor.hardwareActivityPerformanceLevels), + "Performance levels exceeds Driver limit!", + return -1); + + /* Performance levels are arranged from low to high. */ + performance_level->memory_clock = + le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexLow].ulMclk); + + performance_level->engine_clock = + le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexLow].ulSclk); + + performance_level->pcie_gen = get_pcie_gen_support( + data->pcie_gen_cap, + state_entry->ucPCIEGenLow); + + performance_level->pcie_lane = get_pcie_lane_support( + data->pcie_lane_cap, + state_entry->ucPCIELaneHigh); + + performance_level = + &(tonga_ps->performance_levels[tonga_ps->performance_level_count++]); + + performance_level->memory_clock = + le32_to_cpu(mclk_dep_table->entries[state_entry->ucMemoryClockIndexHigh].ulMclk); + + performance_level->engine_clock = + le32_to_cpu(sclk_dep_table->entries[state_entry->ucEngineClockIndexHigh].ulSclk); + + performance_level->pcie_gen = get_pcie_gen_support( + data->pcie_gen_cap, + state_entry->ucPCIEGenHigh); + + performance_level->pcie_lane = get_pcie_lane_support( + data->pcie_lane_cap, + state_entry->ucPCIELaneHigh); + + return 0; +} + +static int tonga_get_pp_table_entry(struct pp_hwmgr *hwmgr, + unsigned long entry_index, struct pp_power_state *ps) +{ + int result; + struct tonga_power_state *tonga_ps; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + struct phm_ppt_v1_information *table_info = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + struct phm_ppt_v1_clock_voltage_dependency_table *dep_mclk_table = + table_info->vdd_dep_on_mclk; + + ps->hardware.magic = PhwTonga_Magic; + + tonga_ps = cast_phw_tonga_power_state(&(ps->hardware)); + + result = tonga_get_powerplay_table_entry(hwmgr, entry_index, ps, + tonga_get_pp_table_entry_callback_func); + + /* This is the earliest time we have all the dependency table and the VBIOS boot state + * as PP_Tables_GetPowerPlayTableEntry retrieves the VBIOS boot state + * if there is only one VDDCI/MCLK level, check if it's the same as VBIOS boot state + */ + if (dep_mclk_table != NULL && dep_mclk_table->count == 1) { + if (dep_mclk_table->entries[0].clk != + data->vbios_boot_state.mclk_bootup_value) + printk(KERN_ERR "Single MCLK entry VDDCI/MCLK dependency table " + "does not match VBIOS boot MCLK level"); + if (dep_mclk_table->entries[0].vddci != + data->vbios_boot_state.vddci_bootup_value) + printk(KERN_ERR "Single VDDCI entry VDDCI/MCLK dependency table " + "does not match VBIOS boot VDDCI level"); + } + + /* set DC compatible flag if this state supports DC */ + if (!ps->validation.disallowOnDC) + tonga_ps->dc_compatible = true; + + if (ps->classification.flags & PP_StateClassificationFlag_ACPI) + data->acpi_pcie_gen = tonga_ps->performance_levels[0].pcie_gen; + else if (ps->classification.flags & PP_StateClassificationFlag_Boot) { + if (data->bacos.best_match == 0xffff) { + /* For V.I. use boot state as base BACO state */ + data->bacos.best_match = PP_StateClassificationFlag_Boot; + data->bacos.performance_level = tonga_ps->performance_levels[0]; + } + } + + tonga_ps->uvd_clocks.VCLK = ps->uvd_clocks.VCLK; + tonga_ps->uvd_clocks.DCLK = ps->uvd_clocks.DCLK; + + if (!result) { + uint32_t i; + + switch (ps->classification.ui_label) { + case PP_StateUILabel_Performance: + data->use_pcie_performance_levels = true; + + for (i = 0; i < tonga_ps->performance_level_count; i++) { + if (data->pcie_gen_performance.max < + tonga_ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.max = + tonga_ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_performance.min > + tonga_ps->performance_levels[i].pcie_gen) + data->pcie_gen_performance.min = + tonga_ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_performance.max < + tonga_ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.max = + tonga_ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_performance.min > + tonga_ps->performance_levels[i].pcie_lane) + data->pcie_lane_performance.min = + tonga_ps->performance_levels[i].pcie_lane; + } + break; + case PP_StateUILabel_Battery: + data->use_pcie_power_saving_levels = true; + + for (i = 0; i < tonga_ps->performance_level_count; i++) { + if (data->pcie_gen_power_saving.max < + tonga_ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.max = + tonga_ps->performance_levels[i].pcie_gen; + + if (data->pcie_gen_power_saving.min > + tonga_ps->performance_levels[i].pcie_gen) + data->pcie_gen_power_saving.min = + tonga_ps->performance_levels[i].pcie_gen; + + if (data->pcie_lane_power_saving.max < + tonga_ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.max = + tonga_ps->performance_levels[i].pcie_lane; + + if (data->pcie_lane_power_saving.min > + tonga_ps->performance_levels[i].pcie_lane) + data->pcie_lane_power_saving.min = + tonga_ps->performance_levels[i].pcie_lane; + } + break; + default: + break; + } + } + return 0; +} + +static void +tonga_print_current_perforce_level(struct pp_hwmgr *hwmgr, struct seq_file *m) +{ + uint32_t sclk, mclk, active_percent; + uint32_t offset; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetSclkFrequency)); + + sclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + + smum_send_msg_to_smc(hwmgr->smumgr, (PPSMC_Msg)(PPSMC_MSG_API_GetMclkFrequency)); + + mclk = cgs_read_register(hwmgr->device, mmSMC_MSG_ARG_0); + seq_printf(m, "\n [ mclk ]: %u MHz\n\n [ sclk ]: %u MHz\n", mclk/100, sclk/100); + + + offset = data->soft_regs_start + offsetof(SMU72_SoftRegisters, AverageGraphicsActivity); + active_percent = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, offset); + active_percent += 80; + active_percent >>= 8; + + seq_printf(m, "\n [GPU load]: %u%%\n\n", active_percent > 100 ? 100 : active_percent); + +} + +static int tonga_find_dpm_states_clocks_in_dpm_table(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state); + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_single_dpm_table *psclk_table = &(data->dpm_table.sclk_table); + uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock; + struct tonga_single_dpm_table *pmclk_table = &(data->dpm_table.mclk_table); + uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock; + struct PP_Clocks min_clocks = {0}; + uint32_t i; + struct cgs_display_info info = {0}; + + data->need_update_smu7_dpm_table = 0; + + for (i = 0; i < psclk_table->count; i++) { + if (sclk == psclk_table->dpm_levels[i].value) + break; + } + + if (i >= psclk_table->count) + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_SCLK; + else { + /* TODO: Check SCLK in DAL's minimum clocks in case DeepSleep divider update is required.*/ + if(data->display_timing.min_clock_insr != min_clocks.engineClockInSR) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_SCLK; + } + + for (i=0; i < pmclk_table->count; i++) { + if (mclk == pmclk_table->dpm_levels[i].value) + break; + } + + if (i >= pmclk_table->count) + data->need_update_smu7_dpm_table |= DPMTABLE_OD_UPDATE_MCLK; + + cgs_get_active_displays_info(hwmgr->device, &info); + + if (data->display_timing.num_existing_displays != info.display_count) + data->need_update_smu7_dpm_table |= DPMTABLE_UPDATE_MCLK; + + return 0; +} + +static uint16_t tonga_get_maximum_link_speed(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_ps) +{ + uint32_t i; + uint32_t sclk, max_sclk = 0; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + struct tonga_dpm_table *pdpm_table = &data->dpm_table; + + for (i = 0; i < hw_ps->performance_level_count; i++) { + sclk = hw_ps->performance_levels[i].engine_clock; + if (max_sclk < sclk) + max_sclk = sclk; + } + + for (i = 0; i < pdpm_table->sclk_table.count; i++) { + if (pdpm_table->sclk_table.dpm_levels[i].value == max_sclk) + return (uint16_t) ((i >= pdpm_table->pcie_speed_table.count) ? + pdpm_table->pcie_speed_table.dpm_levels[pdpm_table->pcie_speed_table.count-1].value : + pdpm_table->pcie_speed_table.dpm_levels[i].value); + } + + return 0; +} + +static int tonga_request_link_speed_change_before_state_change(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state); + const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state); + + uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_nps); + uint16_t current_link_speed; + + if (data->force_pcie_gen == PP_PCIEGenInvalid) + current_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_cps); + else + current_link_speed = data->force_pcie_gen; + + data->force_pcie_gen = PP_PCIEGenInvalid; + data->pspp_notify_required = false; + if (target_link_speed > current_link_speed) { + switch(target_link_speed) { + case PP_PCIEGen3: + if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN3, false)) + break; + data->force_pcie_gen = PP_PCIEGen2; + if (current_link_speed == PP_PCIEGen2) + break; + case PP_PCIEGen2: + if (0 == acpi_pcie_perf_request(hwmgr->device, PCIE_PERF_REQ_GEN2, false)) + break; + default: + data->force_pcie_gen = tonga_get_current_pcie_speed(hwmgr); + break; + } + } else { + if (target_link_speed < current_link_speed) + data->pspp_notify_required = true; + } + + return 0; +} + +static int tonga_freeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + PP_ASSERT_WITH_CODE( + true == tonga_is_dpm_running(hwmgr), + "Trying to freeze SCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE( + 0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_FreezeLevel), + "Failed to freeze SCLK DPM during FreezeSclkMclkDPM Function!", + return -1); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + DPMTABLE_OD_UPDATE_MCLK)) { + PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr), + "Trying to freeze MCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE( + 0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_MCLKDPM_FreezeLevel), + "Failed to freeze MCLK DPM during FreezeSclkMclkDPM Function!", + return -1); + } + + return 0; +} + +static int tonga_populate_and_upload_sclk_mclk_dpm_levels(struct pp_hwmgr *hwmgr, const void *input) +{ + int result = 0; + + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state); + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t sclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].engine_clock; + uint32_t mclk = tonga_ps->performance_levels[tonga_ps->performance_level_count-1].memory_clock; + struct tonga_dpm_table *pdpm_table = &data->dpm_table; + + struct tonga_dpm_table *pgolden_dpm_table = &data->golden_dpm_table; + uint32_t dpm_count, clock_percent; + uint32_t i; + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_SCLK) { + pdpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value = sclk; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) { + /* Need to do calculation based on the golden DPM table + * as the Heatmap GPU Clock axis is also based on the default values + */ + PP_ASSERT_WITH_CODE( + (pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value != 0), + "Divide by 0!", + return -1); + dpm_count = pdpm_table->sclk_table.count < 2 ? 0 : pdpm_table->sclk_table.count-2; + for (i = dpm_count; i > 1; i--) { + if (sclk > pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value) { + clock_percent = ((sclk - pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value)*100) / + pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value; + + pdpm_table->sclk_table.dpm_levels[i].value = + pgolden_dpm_table->sclk_table.dpm_levels[i].value + + (pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100; + + } else if (pgolden_dpm_table->sclk_table.dpm_levels[pdpm_table->sclk_table.count-1].value > sclk) { + clock_percent = ((pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value - sclk)*100) / + pgolden_dpm_table->sclk_table.dpm_levels[pgolden_dpm_table->sclk_table.count-1].value; + + pdpm_table->sclk_table.dpm_levels[i].value = + pgolden_dpm_table->sclk_table.dpm_levels[i].value - + (pgolden_dpm_table->sclk_table.dpm_levels[i].value * clock_percent)/100; + } else + pdpm_table->sclk_table.dpm_levels[i].value = + pgolden_dpm_table->sclk_table.dpm_levels[i].value; + } + } + } + + if (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK) { + pdpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value = mclk; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinACSupport) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_OD6PlusinDCSupport)) { + + PP_ASSERT_WITH_CODE( + (pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value != 0), + "Divide by 0!", + return -1); + dpm_count = pdpm_table->mclk_table.count < 2? 0 : pdpm_table->mclk_table.count-2; + for (i = dpm_count; i > 1; i--) { + if (mclk > pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value) { + clock_percent = ((mclk - pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value)*100) / + pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value; + + pdpm_table->mclk_table.dpm_levels[i].value = + pgolden_dpm_table->mclk_table.dpm_levels[i].value + + (pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100; + + } else if (pgolden_dpm_table->mclk_table.dpm_levels[pdpm_table->mclk_table.count-1].value > mclk) { + clock_percent = ((pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value - mclk)*100) / + pgolden_dpm_table->mclk_table.dpm_levels[pgolden_dpm_table->mclk_table.count-1].value; + + pdpm_table->mclk_table.dpm_levels[i].value = + pgolden_dpm_table->mclk_table.dpm_levels[i].value - + (pgolden_dpm_table->mclk_table.dpm_levels[i].value * clock_percent)/100; + } else + pdpm_table->mclk_table.dpm_levels[i].value = pgolden_dpm_table->mclk_table.dpm_levels[i].value; + } + } + } + + if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK)) { + result = tonga_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate SCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + if (data->need_update_smu7_dpm_table & (DPMTABLE_OD_UPDATE_MCLK + DPMTABLE_UPDATE_MCLK)) { + /*populate MCLK dpm table to SMU7 */ + result = tonga_populate_all_memory_levels(hwmgr); + PP_ASSERT_WITH_CODE((0 == result), + "Failed to populate MCLK during PopulateNewDPMClocksStates Function!", + return result); + } + + return result; +} + +static int tonga_trim_single_dpm_states(struct pp_hwmgr *hwmgr, + struct tonga_single_dpm_table * pdpm_table, + uint32_t low_limit, uint32_t high_limit) +{ + uint32_t i; + + for (i = 0; i < pdpm_table->count; i++) { + if ((pdpm_table->dpm_levels[i].value < low_limit) || + (pdpm_table->dpm_levels[i].value > high_limit)) + pdpm_table->dpm_levels[i].enabled = false; + else + pdpm_table->dpm_levels[i].enabled = true; + } + return 0; +} + +static int tonga_trim_dpm_states(struct pp_hwmgr *hwmgr, const struct tonga_power_state *hw_state) +{ + int result = 0; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t high_limit_count; + + PP_ASSERT_WITH_CODE((hw_state->performance_level_count >= 1), + "power state did not have any performance level", + return -1); + + high_limit_count = (1 == hw_state->performance_level_count) ? 0: 1; + + tonga_trim_single_dpm_states(hwmgr, + &(data->dpm_table.sclk_table), + hw_state->performance_levels[0].engine_clock, + hw_state->performance_levels[high_limit_count].engine_clock); + + tonga_trim_single_dpm_states(hwmgr, + &(data->dpm_table.mclk_table), + hw_state->performance_levels[0].memory_clock, + hw_state->performance_levels[high_limit_count].memory_clock); + + return result; +} + +static int tonga_generate_dpm_level_enable_mask(struct pp_hwmgr *hwmgr, const void *input) +{ + int result; + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state); + + + result = tonga_trim_dpm_states(hwmgr, tonga_ps); + if (0 != result) + return result; + + data->dpm_level_enable_mask.sclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.sclk_table); + data->dpm_level_enable_mask.mclk_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.mclk_table); + data->last_mclk_dpm_enable_mask = data->dpm_level_enable_mask.mclk_dpm_enable_mask; + if (data->uvd_enabled) + data->dpm_level_enable_mask.mclk_dpm_enable_mask &= 0xFFFFFFFE; + + data->dpm_level_enable_mask.pcie_dpm_enable_mask = tonga_get_dpm_level_enable_mask_value(&data->dpm_table.pcie_speed_table); + + return 0; +} + +int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + (PPSMC_Msg)PPSMC_MSG_VCEDPM_Enable : + (PPSMC_Msg)PPSMC_MSG_VCEDPM_Disable); +} + +int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable) +{ + return smum_send_msg_to_smc(hwmgr->smumgr, enable ? + (PPSMC_Msg)PPSMC_MSG_UVDDPM_Enable : + (PPSMC_Msg)PPSMC_MSG_UVDDPM_Disable); +} + +int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *ptable_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (!bgate) { + data->smc_state_table.UvdBootLevel = (uint8_t) (ptable_information->mm_dep_table->count - 1); + mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, UvdBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0x00FFFFFF; + mm_boot_level_value |= data->smc_state_table.UvdBootLevel << 24; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_UVDDPM) || + phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_UVDDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.UvdBootLevel)); + } + + return tonga_enable_disable_uvd_dpm(hwmgr, !bgate); +} + +int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + const struct tonga_power_state *tonga_nps = cast_const_phw_tonga_power_state(states->pnew_state); + const struct tonga_power_state *tonga_cps = cast_const_phw_tonga_power_state(states->pcurrent_state); + + uint32_t mm_boot_level_offset, mm_boot_level_value; + struct phm_ppt_v1_information *pptable_info = (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (tonga_nps->vce_clocks.EVCLK > 0 && (tonga_cps == NULL || tonga_cps->vce_clocks.EVCLK == 0)) { + data->smc_state_table.VceBootLevel = (uint8_t) (pptable_info->mm_dep_table->count - 1); + + mm_boot_level_offset = data->dpm_table_start + offsetof(SMU72_Discrete_DpmTable, VceBootLevel); + mm_boot_level_offset /= 4; + mm_boot_level_offset *= 4; + mm_boot_level_value = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset); + mm_boot_level_value &= 0xFF00FFFF; + mm_boot_level_value |= data->smc_state_table.VceBootLevel << 16; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, mm_boot_level_offset, mm_boot_level_value); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_StablePState)) + smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, + PPSMC_MSG_VCEDPM_SetEnabledMask, + (uint32_t)(1 << data->smc_state_table.VceBootLevel)); + + tonga_enable_disable_vce_dpm(hwmgr, true); + } else if (tonga_nps->vce_clocks.EVCLK == 0 && tonga_cps != NULL && tonga_cps->vce_clocks.EVCLK > 0) + tonga_enable_disable_vce_dpm(hwmgr, false); + + return 0; +} + +static int tonga_update_and_upload_mc_reg_table(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + uint32_t address; + int32_t result; + + if (0 == (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) + return 0; + + + memset(&data->mc_reg_table, 0, sizeof(SMU72_Discrete_MCRegisters)); + + result = tonga_convert_mc_reg_table_to_smc(hwmgr, &(data->mc_reg_table)); + + if(result != 0) + return result; + + + address = data->mc_reg_table_start + (uint32_t)offsetof(SMU72_Discrete_MCRegisters, data[0]); + + return tonga_copy_bytes_to_smc(hwmgr->smumgr, address, + (uint8_t *)&data->mc_reg_table.data[0], + sizeof(SMU72_Discrete_MCRegisterSet) * data->dpm_table.mclk_table.count, + data->sram_end); +} + +static int tonga_program_memory_timing_parameters_conditionally(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_OD_UPDATE_MCLK)) + return tonga_program_memory_timing_parameters(hwmgr); + + return 0; +} + +static int tonga_unfreeze_sclk_mclk_dpm(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + + if (0 == data->need_update_smu7_dpm_table) + return 0; + + if ((0 == data->sclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & + (DPMTABLE_OD_UPDATE_SCLK + DPMTABLE_UPDATE_SCLK))) { + + PP_ASSERT_WITH_CODE(true == tonga_is_dpm_running(hwmgr), + "Trying to Unfreeze SCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE( + 0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_UnfreezeLevel), + "Failed to unfreeze SCLK DPM during UnFreezeSclkMclkDPM Function!", + return -1); + } + + if ((0 == data->mclk_dpm_key_disabled) && + (data->need_update_smu7_dpm_table & DPMTABLE_OD_UPDATE_MCLK)) { + + PP_ASSERT_WITH_CODE( + true == tonga_is_dpm_running(hwmgr), + "Trying to Unfreeze MCLK DPM when DPM is disabled", + ); + PP_ASSERT_WITH_CODE( + 0 == smum_send_msg_to_smc(hwmgr->smumgr, + PPSMC_MSG_SCLKDPM_UnfreezeLevel), + "Failed to unfreeze MCLK DPM during UnFreezeSclkMclkDPM Function!", + return -1); + } + + data->need_update_smu7_dpm_table = 0; + + return 0; +} + +static int tonga_notify_link_speed_change_after_state_change(struct pp_hwmgr *hwmgr, const void *input) +{ + const struct phm_set_power_state_input *states = (const struct phm_set_power_state_input *)input; + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + const struct tonga_power_state *tonga_ps = cast_const_phw_tonga_power_state(states->pnew_state); + uint16_t target_link_speed = tonga_get_maximum_link_speed(hwmgr, tonga_ps); + uint8_t request; + + if (data->pspp_notify_required || + data->pcie_performance_request) { + if (target_link_speed == PP_PCIEGen3) + request = PCIE_PERF_REQ_GEN3; + else if (target_link_speed == PP_PCIEGen2) + request = PCIE_PERF_REQ_GEN2; + else + request = PCIE_PERF_REQ_GEN1; + + if(request == PCIE_PERF_REQ_GEN1 && tonga_get_current_pcie_speed(hwmgr) > 0) { + data->pcie_performance_request = false; + return 0; + } + + if (0 != acpi_pcie_perf_request(hwmgr->device, request, false)) { + if (PP_PCIEGen2 == target_link_speed) + printk("PSPP request to switch to Gen2 from Gen3 Failed!"); + else + printk("PSPP request to switch to Gen1 from Gen2 Failed!"); + } + } + + data->pcie_performance_request = false; + return 0; +} + +static int tonga_set_power_state_tasks(struct pp_hwmgr *hwmgr, const void *input) +{ + int tmp_result, result = 0; + + tmp_result = tonga_find_dpm_states_clocks_in_dpm_table(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to find DPM states clocks in DPM table!", result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = tonga_request_link_speed_change_before_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to request link speed change before state change!", result = tmp_result); + } + + tmp_result = tonga_freeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to freeze SCLK MCLK DPM!", result = tmp_result); + + tmp_result = tonga_populate_and_upload_sclk_mclk_dpm_levels(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to populate and upload SCLK MCLK DPM levels!", result = tmp_result); + + tmp_result = tonga_generate_dpm_level_enable_mask(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to generate DPM level enabled mask!", result = tmp_result); + + tmp_result = tonga_update_vce_dpm(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update VCE DPM!", result = tmp_result); + + tmp_result = tonga_update_sclk_threshold(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to update SCLK threshold!", result = tmp_result); + + tmp_result = tonga_update_and_upload_mc_reg_table(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload MC reg table!", result = tmp_result); + + tmp_result = tonga_program_memory_timing_parameters_conditionally(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to program memory timing parameters!", result = tmp_result); + + tmp_result = tonga_unfreeze_sclk_mclk_dpm(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to unfreeze SCLK MCLK DPM!", result = tmp_result); + + tmp_result = tonga_upload_dpm_level_enable_mask(hwmgr); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to upload DPM level enabled mask!", result = tmp_result); + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_PCIEPerformanceRequest)) { + tmp_result = tonga_notify_link_speed_change_after_state_change(hwmgr, input); + PP_ASSERT_WITH_CODE((0 == tmp_result), "Failed to notify link speed change after state change!", result = tmp_result); + } + + return result; +} + +/** +* Set maximum target operating fan output PWM +* +* @param pHwMgr: the address of the powerplay hardware manager. +* @param usMaxFanPwm: max operating fan PWM in percents +* @return The response that came from the SMC. +*/ +static int tonga_set_max_fan_pwm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm) +{ + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM = us_max_fan_pwm; + + if (phm_is_hw_access_blocked(hwmgr)) + return 0; + + return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanPwmMax, us_max_fan_pwm) ? 0 : -EINVAL); +} + +int tonga_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr) +{ + uint32_t num_active_displays = 0; + struct cgs_display_info info = {0}; + info.mode_info = NULL; + + cgs_get_active_displays_info(hwmgr->device, &info); + + num_active_displays = info.display_count; + + if (num_active_displays > 1) /* to do && (pHwMgr->pPECI->displayConfiguration.bMultiMonitorInSync != TRUE)) */ + tonga_notify_smc_display_change(hwmgr, false); + else + tonga_notify_smc_display_change(hwmgr, true); + + return 0; +} + +/** +* Programs the display gap +* +* @param hwmgr the address of the powerplay hardware manager. +* @return always OK +*/ +int tonga_program_display_gap(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + uint32_t num_active_displays = 0; + uint32_t display_gap = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL); + uint32_t display_gap2; + uint32_t pre_vbi_time_in_us; + uint32_t frame_time_in_us; + uint32_t ref_clock; + uint32_t refresh_rate = 0; + struct cgs_display_info info = {0}; + struct cgs_mode_info mode_info; + + info.mode_info = &mode_info; + + cgs_get_active_displays_info(hwmgr->device, &info); + num_active_displays = info.display_count; + + display_gap = PHM_SET_FIELD(display_gap, CG_DISPLAY_GAP_CNTL, DISP_GAP, (num_active_displays > 0)? DISPLAY_GAP_VBLANK_OR_WM : DISPLAY_GAP_IGNORE); + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL, display_gap); + + ref_clock = mode_info.ref_clock; + refresh_rate = mode_info.refresh_rate; + + if(0 == refresh_rate) + refresh_rate = 60; + + frame_time_in_us = 1000000 / refresh_rate; + + pre_vbi_time_in_us = frame_time_in_us - 200 - mode_info.vblank_time_us; + display_gap2 = pre_vbi_time_in_us * (ref_clock / 100); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_DISPLAY_GAP_CNTL2, display_gap2); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, PreVBlankGap), 0x64); + + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, data->soft_regs_start + offsetof(SMU72_SoftRegisters, VBlankTimeout), (frame_time_in_us - pre_vbi_time_in_us)); + + if (num_active_displays == 1) + tonga_notify_smc_display_change(hwmgr, true); + + return 0; +} + +int tonga_display_configuration_changed_task(struct pp_hwmgr *hwmgr) +{ + + tonga_program_display_gap(hwmgr); + + /* to do PhwTonga_CacUpdateDisplayConfiguration(pHwMgr); */ + return 0; +} + +/** +* Set maximum target operating fan output RPM +* +* @param pHwMgr: the address of the powerplay hardware manager. +* @param usMaxFanRpm: max operating fan RPM value. +* @return The response that came from the SMC. +*/ +static int tonga_set_max_fan_rpm_output(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm) +{ + hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM = us_max_fan_pwm; + + if (phm_is_hw_access_blocked(hwmgr)) + return 0; + + return (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanRpmMax, us_max_fan_pwm) ? 0 : -EINVAL); +} + +uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr) +{ + uint32_t reference_clock; + uint32_t tc; + uint32_t divide; + + ATOM_FIRMWARE_INFO *fw_info; + uint16_t size; + uint8_t frev, crev; + int index = GetIndexIntoMasterTable(DATA, FirmwareInfo); + + tc = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL_2, MUX_TCLK_TO_XCLK); + + if (tc) + return TCLK; + + fw_info = (ATOM_FIRMWARE_INFO *)cgs_atom_get_data_table(hwmgr->device, index, + &size, &frev, &crev); + + if (!fw_info) + return 0; + + reference_clock = le16_to_cpu(fw_info->usMinPixelClockPLL_Output); + + divide = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_CLKPIN_CNTL, XTALIN_DIVIDE); + + if (0 != divide) + return reference_clock / 4; + + return reference_clock; +} + +int tonga_dpm_set_interrupt_state(void *private_data, + unsigned src_id, unsigned type, + int enabled) +{ + uint32_t cg_thermal_int; + struct pp_hwmgr *hwmgr = ((struct pp_eventmgr *)private_data)->hwmgr; + + if (hwmgr == NULL) + return -EINVAL; + + switch (type) { + case AMD_THERMAL_IRQ_LOW_TO_HIGH: + if (enabled) { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } else { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTH_MASK_MASK; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } + break; + + case AMD_THERMAL_IRQ_HIGH_TO_LOW: + if (enabled) { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int |= CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } else { + cg_thermal_int = cgs_read_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT); + cg_thermal_int &= ~CG_THERMAL_INT_CTRL__THERM_INTL_MASK_MASK; + cgs_write_ind_register(hwmgr->device, CGS_IND_REG__SMC, ixCG_THERMAL_INT, cg_thermal_int); + } + break; + default: + break; + } + return 0; +} + +int tonga_register_internal_thermal_interrupt(struct pp_hwmgr *hwmgr, + const void *thermal_interrupt_info) +{ + int result; + const struct pp_interrupt_registration_info *info = + (const struct pp_interrupt_registration_info *)thermal_interrupt_info; + + if (info == NULL) + return -EINVAL; + + result = cgs_add_irq_source(hwmgr->device, 230, AMD_THERMAL_IRQ_LAST, + tonga_dpm_set_interrupt_state, + info->call_back, info->context); + + if (result) + return -EINVAL; + + result = cgs_add_irq_source(hwmgr->device, 231, AMD_THERMAL_IRQ_LAST, + tonga_dpm_set_interrupt_state, + info->call_back, info->context); + + if (result) + return -EINVAL; + + return 0; +} + +bool tonga_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + bool is_update_required = false; + struct cgs_display_info info = {0,0,NULL}; + + cgs_get_active_displays_info(hwmgr->device, &info); + + if (data->display_timing.num_existing_displays != info.display_count) + is_update_required = true; +/* TO DO NEED TO GET DEEP SLEEP CLOCK FROM DAL + if (phm_cap_enabled(hwmgr->hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_SclkDeepSleep)) { + cgs_get_min_clock_settings(hwmgr->device, &min_clocks); + if(min_clocks.engineClockInSR != data->display_timing.minClockInSR) + is_update_required = true; +*/ + return is_update_required; +} + +static inline bool tonga_are_power_levels_equal(const struct tonga_performance_level *pl1, + const struct tonga_performance_level *pl2) +{ + return ((pl1->memory_clock == pl2->memory_clock) && + (pl1->engine_clock == pl2->engine_clock) && + (pl1->pcie_gen == pl2->pcie_gen) && + (pl1->pcie_lane == pl2->pcie_lane)); +} + +int tonga_check_states_equal(struct pp_hwmgr *hwmgr, const struct pp_hw_power_state *pstate1, const struct pp_hw_power_state *pstate2, bool *equal) +{ + const struct tonga_power_state *psa = cast_const_phw_tonga_power_state(pstate1); + const struct tonga_power_state *psb = cast_const_phw_tonga_power_state(pstate2); + int i; + + if (pstate1 == NULL || pstate2 == NULL || equal == NULL) + return -EINVAL; + + /* If the two states don't even have the same number of performance levels they cannot be the same state. */ + if (psa->performance_level_count != psb->performance_level_count) { + *equal = false; + return 0; + } + + for (i = 0; i < psa->performance_level_count; i++) { + if (!tonga_are_power_levels_equal(&(psa->performance_levels[i]), &(psb->performance_levels[i]))) { + /* If we have found even one performance level pair that is different the states are different. */ + *equal = false; + return 0; + } + } + + /* If all performance levels are the same try to use the UVD clocks to break the tie.*/ + *equal = ((psa->uvd_clocks.VCLK == psb->uvd_clocks.VCLK) && (psa->uvd_clocks.DCLK == psb->uvd_clocks.DCLK)); + *equal &= ((psa->vce_clocks.EVCLK == psb->vce_clocks.EVCLK) && (psa->vce_clocks.ECCLK == psb->vce_clocks.ECCLK)); + *equal &= (psa->sclk_threshold == psb->sclk_threshold); + *equal &= (psa->acp_clk == psb->acp_clk); + + return 0; +} + +static int tonga_set_fan_control_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + if (mode) { + /* stop auto-manage */ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl)) + tonga_fan_ctrl_stop_smc_fan_control(hwmgr); + tonga_fan_ctrl_set_static_mode(hwmgr, mode); + } else + /* restart auto-manage */ + tonga_fan_ctrl_reset_fan_speed_to_default(hwmgr); + + return 0; +} + +static int tonga_get_fan_control_mode(struct pp_hwmgr *hwmgr) +{ + if (hwmgr->fan_ctrl_is_in_default_mode) + return hwmgr->fan_ctrl_default_mode; + else + return PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_FDO_CTRL2, FDO_PWM_MODE); +} + +static const struct pp_hwmgr_func tonga_hwmgr_funcs = { + .backend_init = &tonga_hwmgr_backend_init, + .backend_fini = &tonga_hwmgr_backend_fini, + .asic_setup = &tonga_setup_asic_task, + .dynamic_state_management_enable = &tonga_enable_dpm_tasks, + .apply_state_adjust_rules = tonga_apply_state_adjust_rules, + .force_dpm_level = &tonga_force_dpm_level, + .power_state_set = tonga_set_power_state_tasks, + .get_power_state_size = tonga_get_power_state_size, + .get_mclk = tonga_dpm_get_mclk, + .get_sclk = tonga_dpm_get_sclk, + .patch_boot_state = tonga_dpm_patch_boot_state, + .get_pp_table_entry = tonga_get_pp_table_entry, + .get_num_of_pp_table_entries = tonga_get_number_of_powerplay_table_entries, + .print_current_perforce_level = tonga_print_current_perforce_level, + .powerdown_uvd = tonga_phm_powerdown_uvd, + .powergate_uvd = tonga_phm_powergate_uvd, + .powergate_vce = tonga_phm_powergate_vce, + .disable_clock_power_gating = tonga_phm_disable_clock_power_gating, + .notify_smc_display_config_after_ps_adjustment = tonga_notify_smc_display_config_after_ps_adjustment, + .display_config_changed = tonga_display_configuration_changed_task, + .set_max_fan_pwm_output = tonga_set_max_fan_pwm_output, + .set_max_fan_rpm_output = tonga_set_max_fan_rpm_output, + .get_temperature = tonga_thermal_get_temperature, + .stop_thermal_controller = tonga_thermal_stop_thermal_controller, + .get_fan_speed_info = tonga_fan_ctrl_get_fan_speed_info, + .get_fan_speed_percent = tonga_fan_ctrl_get_fan_speed_percent, + .set_fan_speed_percent = tonga_fan_ctrl_set_fan_speed_percent, + .reset_fan_speed_to_default = tonga_fan_ctrl_reset_fan_speed_to_default, + .get_fan_speed_rpm = tonga_fan_ctrl_get_fan_speed_rpm, + .set_fan_speed_rpm = tonga_fan_ctrl_set_fan_speed_rpm, + .uninitialize_thermal_controller = tonga_thermal_ctrl_uninitialize_thermal_controller, + .register_internal_thermal_interrupt = tonga_register_internal_thermal_interrupt, + .check_smc_update_required_for_display_configuration = tonga_check_smc_update_required_for_display_configuration, + .check_states_equal = tonga_check_states_equal, + .set_fan_control_mode = tonga_set_fan_control_mode, + .get_fan_control_mode = tonga_get_fan_control_mode, +}; + +int tonga_hwmgr_init(struct pp_hwmgr *hwmgr) +{ + tonga_hwmgr *data; + + data = kzalloc (sizeof(tonga_hwmgr), GFP_KERNEL); + if (data == NULL) + return -ENOMEM; + memset(data, 0x00, sizeof(tonga_hwmgr)); + + hwmgr->backend = data; + hwmgr->hwmgr_func = &tonga_hwmgr_funcs; + hwmgr->pptable_func = &tonga_pptable_funcs; + pp_tonga_thermal_initialize(hwmgr); + return 0; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h new file mode 100644 index 000000000000..49168d262ccc --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_hwmgr.h @@ -0,0 +1,408 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef TONGA_HWMGR_H +#define TONGA_HWMGR_H + +#include "hwmgr.h" +#include "smu72_discrete.h" +#include "ppatomctrl.h" +#include "ppinterrupt.h" +#include "tonga_powertune.h" + +#define TONGA_MAX_HARDWARE_POWERLEVELS 2 +#define TONGA_DYNCLK_NUMBER_OF_TREND_COEFFICIENTS 15 + +struct tonga_performance_level { + uint32_t memory_clock; + uint32_t engine_clock; + uint16_t pcie_gen; + uint16_t pcie_lane; +}; + +struct _phw_tonga_bacos { + uint32_t best_match; + uint32_t baco_flags; + struct tonga_performance_level performance_level; +}; +typedef struct _phw_tonga_bacos phw_tonga_bacos; + +struct _phw_tonga_uvd_clocks { + uint32_t VCLK; + uint32_t DCLK; +}; + +typedef struct _phw_tonga_uvd_clocks phw_tonga_uvd_clocks; + +struct _phw_tonga_vce_clocks { + uint32_t EVCLK; + uint32_t ECCLK; +}; + +typedef struct _phw_tonga_vce_clocks phw_tonga_vce_clocks; + +struct tonga_power_state { + uint32_t magic; + phw_tonga_uvd_clocks uvd_clocks; + phw_tonga_vce_clocks vce_clocks; + uint32_t sam_clk; + uint32_t acp_clk; + uint16_t performance_level_count; + bool dc_compatible; + uint32_t sclk_threshold; + struct tonga_performance_level performance_levels[TONGA_MAX_HARDWARE_POWERLEVELS]; +}; + +struct _phw_tonga_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; +typedef struct _phw_tonga_dpm_level phw_tonga_dpm_level; + +#define TONGA_MAX_DEEPSLEEP_DIVIDER_ID 5 +#define MAX_REGULAR_DPM_NUMBER 8 +#define TONGA_MINIMUM_ENGINE_CLOCK 2500 + +struct tonga_single_dpm_table { + uint32_t count; + phw_tonga_dpm_level dpm_levels[MAX_REGULAR_DPM_NUMBER]; +}; + +struct tonga_dpm_table { + struct tonga_single_dpm_table sclk_table; + struct tonga_single_dpm_table mclk_table; + struct tonga_single_dpm_table pcie_speed_table; + struct tonga_single_dpm_table vddc_table; + struct tonga_single_dpm_table vdd_gfx_table; + struct tonga_single_dpm_table vdd_ci_table; + struct tonga_single_dpm_table mvdd_table; +}; +typedef struct _phw_tonga_dpm_table phw_tonga_dpm_table; + + +struct _phw_tonga_clock_regisiters { + uint32_t vCG_SPLL_FUNC_CNTL; + uint32_t vCG_SPLL_FUNC_CNTL_2; + uint32_t vCG_SPLL_FUNC_CNTL_3; + uint32_t vCG_SPLL_FUNC_CNTL_4; + uint32_t vCG_SPLL_SPREAD_SPECTRUM; + uint32_t vCG_SPLL_SPREAD_SPECTRUM_2; + uint32_t vDLL_CNTL; + uint32_t vMCLK_PWRMGT_CNTL; + uint32_t vMPLL_AD_FUNC_CNTL; + uint32_t vMPLL_DQ_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL; + uint32_t vMPLL_FUNC_CNTL_1; + uint32_t vMPLL_FUNC_CNTL_2; + uint32_t vMPLL_SS1; + uint32_t vMPLL_SS2; +}; +typedef struct _phw_tonga_clock_regisiters phw_tonga_clock_registers; + +struct _phw_tonga_voltage_smio_registers { + uint32_t vs0_vid_lower_smio_cntl; +}; +typedef struct _phw_tonga_voltage_smio_registers phw_tonga_voltage_smio_registers; + + +struct _phw_tonga_mc_reg_entry { + uint32_t mclk_max; + uint32_t mc_data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct _phw_tonga_mc_reg_entry phw_tonga_mc_reg_entry; + +struct _phw_tonga_mc_reg_table { + uint8_t last; /* number of registers*/ + uint8_t num_entries; /* number of entries in mc_reg_table_entry used*/ + uint16_t validflag; /* indicate the corresponding register is valid or not. 1: valid, 0: invalid. bit0->address[0], bit1->address[1], etc.*/ + phw_tonga_mc_reg_entry mc_reg_table_entry[MAX_AC_TIMING_ENTRIES]; + SMU72_Discrete_MCRegisterAddress mc_reg_address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; +typedef struct _phw_tonga_mc_reg_table phw_tonga_mc_reg_table; + +#define DISABLE_MC_LOADMICROCODE 1 +#define DISABLE_MC_CFGPROGRAMMING 2 + +/*Ultra Low Voltage parameter structure */ +struct _phw_tonga_ulv_parm{ + bool ulv_supported; + uint32_t ch_ulv_parameter; + uint32_t ulv_volt_change_delay; + struct tonga_performance_level ulv_power_level; +}; +typedef struct _phw_tonga_ulv_parm phw_tonga_ulv_parm; + +#define TONGA_MAX_LEAKAGE_COUNT 8 + +struct _phw_tonga_leakage_voltage { + uint16_t count; + uint16_t leakage_id[TONGA_MAX_LEAKAGE_COUNT]; + uint16_t actual_voltage[TONGA_MAX_LEAKAGE_COUNT]; +}; +typedef struct _phw_tonga_leakage_voltage phw_tonga_leakage_voltage; + +struct _phw_tonga_display_timing { + uint32_t min_clock_insr; + uint32_t num_existing_displays; +}; +typedef struct _phw_tonga_display_timing phw_tonga_display_timing; + +struct _phw_tonga_dpmlevel_enable_mask { + uint32_t uvd_dpm_enable_mask; + uint32_t vce_dpm_enable_mask; + uint32_t acp_dpm_enable_mask; + uint32_t samu_dpm_enable_mask; + uint32_t sclk_dpm_enable_mask; + uint32_t mclk_dpm_enable_mask; + uint32_t pcie_dpm_enable_mask; +}; +typedef struct _phw_tonga_dpmlevel_enable_mask phw_tonga_dpmlevel_enable_mask; + +struct _phw_tonga_pcie_perf_range { + uint16_t max; + uint16_t min; +}; +typedef struct _phw_tonga_pcie_perf_range phw_tonga_pcie_perf_range; + +struct _phw_tonga_vbios_boot_state { + uint16_t mvdd_bootup_value; + uint16_t vddc_bootup_value; + uint16_t vddci_bootup_value; + uint16_t vddgfx_bootup_value; + uint32_t sclk_bootup_value; + uint32_t mclk_bootup_value; + uint16_t pcie_gen_bootup_value; + uint16_t pcie_lane_bootup_value; +}; +typedef struct _phw_tonga_vbios_boot_state phw_tonga_vbios_boot_state; + +#define DPMTABLE_OD_UPDATE_SCLK 0x00000001 +#define DPMTABLE_OD_UPDATE_MCLK 0x00000002 +#define DPMTABLE_UPDATE_SCLK 0x00000004 +#define DPMTABLE_UPDATE_MCLK 0x00000008 + +/* We need to review which fields are needed. */ +/* This is mostly a copy of the RV7xx/Evergreen structure which is close, but not identical to the N.Islands one. */ +struct tonga_hwmgr { + struct tonga_dpm_table dpm_table; + struct tonga_dpm_table golden_dpm_table; + + uint32_t voting_rights_clients0; + uint32_t voting_rights_clients1; + uint32_t voting_rights_clients2; + uint32_t voting_rights_clients3; + uint32_t voting_rights_clients4; + uint32_t voting_rights_clients5; + uint32_t voting_rights_clients6; + uint32_t voting_rights_clients7; + uint32_t static_screen_threshold_unit; + uint32_t static_screen_threshold; + uint32_t voltage_control; + uint32_t vdd_gfx_control; + + uint32_t vddc_vddci_delta; + uint32_t vddc_vddgfx_delta; + + struct pp_interrupt_registration_info internal_high_thermal_interrupt_info; + struct pp_interrupt_registration_info internal_low_thermal_interrupt_info; + struct pp_interrupt_registration_info smc_to_host_interrupt_info; + uint32_t active_auto_throttle_sources; + + struct pp_interrupt_registration_info external_throttle_interrupt; + irq_handler_func_t external_throttle_callback; + void *external_throttle_context; + + struct pp_interrupt_registration_info ctf_interrupt_info; + irq_handler_func_t ctf_callback; + void *ctf_context; + + phw_tonga_clock_registers clock_registers; + phw_tonga_voltage_smio_registers voltage_smio_registers; + + bool is_memory_GDDR5; + uint16_t acpi_vddc; + bool pspp_notify_required; /* Flag to indicate if PSPP notification to SBIOS is required */ + uint16_t force_pcie_gen; /* The forced PCI-E speed if not 0xffff */ + uint16_t acpi_pcie_gen; /* The PCI-E speed at ACPI time */ + uint32_t pcie_gen_cap; /* The PCI-E speed capabilities bitmap from CAIL */ + uint32_t pcie_lane_cap; /* The PCI-E lane capabilities bitmap from CAIL */ + uint32_t pcie_spc_cap; /* Symbol Per Clock Capabilities from registry */ + phw_tonga_leakage_voltage vddc_leakage; /* The Leakage VDDC supported (based on leakage ID).*/ + phw_tonga_leakage_voltage vddcgfx_leakage; /* The Leakage VDDC supported (based on leakage ID). */ + phw_tonga_leakage_voltage vddci_leakage; /* The Leakage VDDCI supported (based on leakage ID). */ + + uint32_t mvdd_control; + uint32_t vddc_mask_low; + uint32_t mvdd_mask_low; + uint16_t max_vddc_in_pp_table; /* the maximum VDDC value in the powerplay table*/ + uint16_t min_vddc_in_pp_table; + uint16_t max_vddci_in_pp_table; /* the maximum VDDCI value in the powerplay table */ + uint16_t min_vddci_in_pp_table; + uint32_t mclk_strobe_mode_threshold; + uint32_t mclk_stutter_mode_threshold; + uint32_t mclk_edc_enable_threshold; + uint32_t mclk_edc_wr_enable_threshold; + bool is_uvd_enabled; + bool is_xdma_enabled; + phw_tonga_vbios_boot_state vbios_boot_state; + + bool battery_state; + bool is_tlu_enabled; + bool pcie_performance_request; + + /* -------------- SMC SRAM Address of firmware header tables ----------------*/ + uint32_t sram_end; /* The first address after the SMC SRAM. */ + uint32_t dpm_table_start; /* The start of the dpm table in the SMC SRAM. */ + uint32_t soft_regs_start; /* The start of the soft registers in the SMC SRAM. */ + uint32_t mc_reg_table_start; /* The start of the mc register table in the SMC SRAM. */ + uint32_t fan_table_start; /* The start of the fan table in the SMC SRAM. */ + uint32_t arb_table_start; /* The start of the ARB setting table in the SMC SRAM. */ + SMU72_Discrete_DpmTable smc_state_table; /* The carbon copy of the SMC state table. */ + SMU72_Discrete_MCRegisters mc_reg_table; + SMU72_Discrete_Ulv ulv_setting; /* The carbon copy of ULV setting. */ + /* -------------- Stuff originally coming from Evergreen --------------------*/ + phw_tonga_mc_reg_table tonga_mc_reg_table; + uint32_t vdd_ci_control; + pp_atomctrl_voltage_table vddc_voltage_table; + pp_atomctrl_voltage_table vddci_voltage_table; + pp_atomctrl_voltage_table vddgfx_voltage_table; + pp_atomctrl_voltage_table mvdd_voltage_table; + + uint32_t mgcg_cgtt_local2; + uint32_t mgcg_cgtt_local3; + uint32_t gpio_debug; + uint32_t mc_micro_code_feature; + uint32_t highest_mclk; + uint16_t acpi_vdd_ci; + uint8_t mvdd_high_index; + uint8_t mvdd_low_index; + bool dll_defaule_on; + bool performance_request_registered; + + /* ----------------- Low Power Features ---------------------*/ + phw_tonga_bacos bacos; + phw_tonga_ulv_parm ulv; + /* ----------------- CAC Stuff ---------------------*/ + uint32_t cac_table_start; + bool cac_configuration_required; /* TRUE if PP_CACConfigurationRequired == 1 */ + bool driver_calculate_cac_leakage; /* TRUE if PP_DriverCalculateCACLeakage == 1 */ + bool cac_enabled; + /* ----------------- DPM2 Parameters ---------------------*/ + uint32_t power_containment_features; + bool enable_bapm_feature; + bool enable_tdc_limit_feature; + bool enable_pkg_pwr_tracking_feature; + bool disable_uvd_power_tune_feature; + phw_tonga_pt_defaults *power_tune_defaults; + SMU72_Discrete_PmFuses power_tune_table; + uint32_t ul_dte_tj_offset; /* Fudge factor in DPM table to correct HW DTE errors */ + uint32_t fast_watemark_threshold; /* use fast watermark if clock is equal or above this. In percentage of the target high sclk. */ + + /* ----------------- Phase Shedding ---------------------*/ + bool vddc_phase_shed_control; + /* --------------------- DI/DT --------------------------*/ + phw_tonga_display_timing display_timing; + /* --------- ReadRegistry data for memory and engine clock margins ---- */ + uint32_t engine_clock_data; + uint32_t memory_clock_data; + /* -------- Thermal Temperature Setting --------------*/ + phw_tonga_dpmlevel_enable_mask dpm_level_enable_mask; + uint32_t need_update_smu7_dpm_table; + uint32_t sclk_dpm_key_disabled; + uint32_t mclk_dpm_key_disabled; + uint32_t pcie_dpm_key_disabled; + uint32_t min_engine_clocks; /* used to store the previous dal min sclock */ + phw_tonga_pcie_perf_range pcie_gen_performance; + phw_tonga_pcie_perf_range pcie_lane_performance; + phw_tonga_pcie_perf_range pcie_gen_power_saving; + phw_tonga_pcie_perf_range pcie_lane_power_saving; + bool use_pcie_performance_levels; + bool use_pcie_power_saving_levels; + uint32_t activity_target[SMU72_MAX_LEVELS_GRAPHICS]; /* percentage value from 0-100, default 50 */ + uint32_t mclk_activity_target; + uint32_t low_sclk_interrupt_threshold; + uint32_t last_mclk_dpm_enable_mask; + bool uvd_enabled; + uint32_t pcc_monitor_enabled; + + /* --------- Power Gating States ------------*/ + bool uvd_power_gated; /* 1: gated, 0:not gated */ + bool vce_power_gated; /* 1: gated, 0:not gated */ + bool samu_power_gated; /* 1: gated, 0:not gated */ + bool acp_power_gated; /* 1: gated, 0:not gated */ + bool pg_acp_init; + +}; + +typedef struct tonga_hwmgr tonga_hwmgr; + +#define TONGA_DPM2_NEAR_TDP_DEC 10 +#define TONGA_DPM2_ABOVE_SAFE_INC 5 +#define TONGA_DPM2_BELOW_SAFE_INC 20 + +#define TONGA_DPM2_LTA_WINDOW_SIZE 7 /* Log2 of the LTA window size (l2numWin_TDP). Eg. If LTA windows size is 128, then this value should be Log2(128) = 7. */ + +#define TONGA_DPM2_LTS_TRUNCATE 0 + +#define TONGA_DPM2_TDP_SAFE_LIMIT_PERCENT 80 /* Maximum 100 */ + +#define TONGA_DPM2_MAXPS_PERCENT_H 90 /* Maximum 0xFF */ +#define TONGA_DPM2_MAXPS_PERCENT_M 90 /* Maximum 0xFF */ + +#define TONGA_DPM2_PWREFFICIENCYRATIO_MARGIN 50 + +#define TONGA_DPM2_SQ_RAMP_MAX_POWER 0x3FFF +#define TONGA_DPM2_SQ_RAMP_MIN_POWER 0x12 +#define TONGA_DPM2_SQ_RAMP_MAX_POWER_DELTA 0x15 +#define TONGA_DPM2_SQ_RAMP_SHORT_TERM_INTERVAL_SIZE 0x1E +#define TONGA_DPM2_SQ_RAMP_LONG_TERM_INTERVAL_RATIO 0xF + +#define TONGA_VOLTAGE_CONTROL_NONE 0x0 +#define TONGA_VOLTAGE_CONTROL_BY_GPIO 0x1 +#define TONGA_VOLTAGE_CONTROL_BY_SVID2 0x2 +#define TONGA_VOLTAGE_CONTROL_MERGED 0x3 + +#define TONGA_Q88_FORMAT_CONVERSION_UNIT 256 /*To convert to Q8.8 format for firmware */ + +#define TONGA_UNUSED_GPIO_PIN 0x7F + +#define PP_HOST_TO_SMC_UL(X) cpu_to_be32(X) +#define PP_SMC_TO_HOST_UL(X) be32_to_cpu(X) + +#define PP_HOST_TO_SMC_US(X) cpu_to_be16(X) +#define PP_SMC_TO_HOST_US(X) be16_to_cpu(X) + +#define CONVERT_FROM_HOST_TO_SMC_UL(X) ((X) = PP_HOST_TO_SMC_UL(X)) +#define CONVERT_FROM_SMC_TO_HOST_UL(X) ((X) = PP_SMC_TO_HOST_UL(X)) + +#define CONVERT_FROM_HOST_TO_SMC_US(X) ((X) = PP_HOST_TO_SMC_US(X)) + +int tonga_hwmgr_init(struct pp_hwmgr *hwmgr); +int tonga_update_vce_dpm(struct pp_hwmgr *hwmgr, const void *input); +int tonga_update_uvd_dpm(struct pp_hwmgr *hwmgr, bool bgate); +int tonga_enable_disable_uvd_dpm(struct pp_hwmgr *hwmgr, bool enable); +int tonga_enable_disable_vce_dpm(struct pp_hwmgr *hwmgr, bool enable); +uint32_t tonga_get_xclk(struct pp_hwmgr *hwmgr); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h new file mode 100644 index 000000000000..8e6670b3cb67 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_powertune.h @@ -0,0 +1,66 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef TONGA_POWERTUNE_H +#define TONGA_POWERTUNE_H + +enum _phw_tonga_ptc_config_reg_type { + TONGA_CONFIGREG_MMR = 0, + TONGA_CONFIGREG_SMC_IND, + TONGA_CONFIGREG_DIDT_IND, + TONGA_CONFIGREG_CACHE, + + TONGA_CONFIGREG_MAX +}; +typedef enum _phw_tonga_ptc_config_reg_type phw_tonga_ptc_config_reg_type; + +/* PowerContainment Features */ +#define POWERCONTAINMENT_FEATURE_BAPM 0x00000001 +#define POWERCONTAINMENT_FEATURE_TDCLimit 0x00000002 +#define POWERCONTAINMENT_FEATURE_PkgPwrLimit 0x00000004 + +struct _phw_tonga_pt_config_reg { + uint32_t Offset; + uint32_t Mask; + uint32_t Shift; + uint32_t Value; + phw_tonga_ptc_config_reg_type Type; +}; +typedef struct _phw_tonga_pt_config_reg phw_tonga_pt_config_reg; + +struct _phw_tonga_pt_defaults { + uint8_t svi_load_line_en; + uint8_t svi_load_line_vddC; + uint8_t tdc_vddc_throttle_release_limit_perc; + uint8_t tdc_mawt; + uint8_t tdc_waterfall_ctl; + uint8_t dte_ambient_temp_base; + uint32_t display_cac; + uint32_t bamp_temp_gradient; + uint16_t bapmti_r[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; + uint16_t bapmti_rc[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; +}; +typedef struct _phw_tonga_pt_defaults phw_tonga_pt_defaults; + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h new file mode 100644 index 000000000000..9a4456e6521b --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_pptable.h @@ -0,0 +1,406 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef TONGA_PPTABLE_H +#define TONGA_PPTABLE_H + +/** \file + * This is a PowerPlay table header file + */ +#pragma pack(push, 1) + +#include "hwmgr.h" + +#define ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK 0x0f +#define ATOM_TONGA_PP_FANPARAMETERS_NOFAN 0x80 /* No fan is connected to this controller. */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_NONE 0 +#define ATOM_TONGA_PP_THERMALCONTROLLER_LM96163 17 +#define ATOM_TONGA_PP_THERMALCONTROLLER_TONGA 21 +#define ATOM_TONGA_PP_THERMALCONTROLLER_FIJI 22 + +/* + * Thermal controller 'combo type' to use an external controller for Fan control and an internal controller for thermal. + * We probably should reserve the bit 0x80 for this use. + * To keep the number of these types low we should also use the same code for all ASICs (i.e. do not distinguish RV6xx and RV7xx Internal here). + * The driver can pick the correct internal controller based on the ASIC. + */ + +#define ATOM_TONGA_PP_THERMALCONTROLLER_ADT7473_WITH_INTERNAL 0x89 /* ADT7473 Fan Control + Internal Thermal Controller */ +#define ATOM_TONGA_PP_THERMALCONTROLLER_EMC2103_WITH_INTERNAL 0x8D /* EMC2103 Fan Control + Internal Thermal Controller */ + +/*/* ATOM_TONGA_POWERPLAYTABLE::ulPlatformCaps */ +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL 0x1 /* This cap indicates whether vddgfx will be a separated power rail. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY 0x2 /* This cap indicates whether this is a mobile part and CCC need to show Powerplay page. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE 0x4 /* This cap indicates whether power source notificaiton is done by SBIOS directly. */ +#define ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND 0x8 /* Enable the option to overwrite voltage island feature to be disabled, regardless of VddGfx power rail support. */ +#define ____RETIRE16____ 0x10 +#define ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC 0x20 /* This cap indicates whether power source notificaiton is done by GPIO directly. */ +#define ____RETIRE64____ 0x40 +#define ____RETIRE128____ 0x80 +#define ____RETIRE256____ 0x100 +#define ____RETIRE512____ 0x200 +#define ____RETIRE1024____ 0x400 +#define ____RETIRE2048____ 0x800 +#define ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL 0x1000 /* This cap indicates dynamic MVDD is required. Uncheck to disable it. */ +#define ____RETIRE2000____ 0x2000 +#define ____RETIRE4000____ 0x4000 +#define ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL 0x8000 /* This cap indicates dynamic VDDCI is required. Uncheck to disable it. */ +#define ____RETIRE10000____ 0x10000 +#define ATOM_TONGA_PP_PLATFORM_CAP_BACO 0x20000 /* Enable to indicate the driver supports BACO state. */ + +#define ATOM_TONGA_PP_PLATFORM_CAP_OUTPUT_THERMAL2GPIO17 0x100000 /* Enable to indicate the driver supports thermal2GPIO17. */ +#define ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL 0x1000000 /* Enable to indicate if thermal and PCC are sharing the same GPIO */ +#define ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE 0x2000000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification */ +#define ATOM_PPLIB_CLASSIFICATION_UI_MASK 0x0007 +#define ATOM_PPLIB_CLASSIFICATION_UI_SHIFT 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_NONE 0 +#define ATOM_PPLIB_CLASSIFICATION_UI_BATTERY 1 +#define ATOM_PPLIB_CLASSIFICATION_UI_BALANCED 3 +#define ATOM_PPLIB_CLASSIFICATION_UI_PERFORMANCE 5 +/* 2, 4, 6, 7 are reserved */ + +#define ATOM_PPLIB_CLASSIFICATION_BOOT 0x0008 +#define ATOM_PPLIB_CLASSIFICATION_THERMAL 0x0010 +#define ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE 0x0020 +#define ATOM_PPLIB_CLASSIFICATION_REST 0x0040 +#define ATOM_PPLIB_CLASSIFICATION_FORCED 0x0080 +#define ATOM_PPLIB_CLASSIFICATION_ACPI 0x1000 + +/* ATOM_PPLIB_NONCLOCK_INFO::usClassification2 */ +#define ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2 0x0001 + +#define ATOM_Tonga_DISALLOW_ON_DC 0x00004000 +#define ATOM_Tonga_ENABLE_VARIBRIGHT 0x00008000 + +#define ATOM_Tonga_TABLE_REVISION_TONGA 7 + +typedef struct _ATOM_Tonga_POWERPLAYTABLE { + ATOM_COMMON_TABLE_HEADER sHeader; + + UCHAR ucTableRevision; + USHORT usTableSize; /*the size of header structure */ + + ULONG ulGoldenPPID; + ULONG ulGoldenRevision; + USHORT usFormatID; + + USHORT usVoltageTime; /*in microseconds */ + ULONG ulPlatformCaps; /*See ATOM_Tonga_CAPS_* */ + + ULONG ulMaxODEngineClock; /*For Overdrive. */ + ULONG ulMaxODMemoryClock; /*For Overdrive. */ + + USHORT usPowerControlLimit; + USHORT usUlvVoltageOffset; /*in mv units */ + + USHORT usStateArrayOffset; /*points to ATOM_Tonga_State_Array */ + USHORT usFanTableOffset; /*points to ATOM_Tonga_Fan_Table */ + USHORT usThermalControllerOffset; /*points to ATOM_Tonga_Thermal_Controller */ + USHORT usReserv; /*CustomThermalPolicy removed for Tonga. Keep this filed as reserved. */ + + USHORT usMclkDependencyTableOffset; /*points to ATOM_Tonga_MCLK_Dependency_Table */ + USHORT usSclkDependencyTableOffset; /*points to ATOM_Tonga_SCLK_Dependency_Table */ + USHORT usVddcLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + USHORT usVddgfxLookupTableOffset; /*points to ATOM_Tonga_Voltage_Lookup_Table */ + + USHORT usMMDependencyTableOffset; /*points to ATOM_Tonga_MM_Dependency_Table */ + + USHORT usVCEStateTableOffset; /*points to ATOM_Tonga_VCE_State_Table; */ + + USHORT usPPMTableOffset; /*points to ATOM_Tonga_PPM_Table */ + USHORT usPowerTuneTableOffset; /*points to ATOM_PowerTune_Table */ + + USHORT usHardLimitTableOffset; /*points to ATOM_Tonga_Hard_Limit_Table */ + + USHORT usPCIETableOffset; /*points to ATOM_Tonga_PCIE_Table */ + + USHORT usGPIOTableOffset; /*points to ATOM_Tonga_GPIO_Table */ + + USHORT usReserved[6]; /*TODO: modify reserved size to fit structure aligning */ +} ATOM_Tonga_POWERPLAYTABLE; + +typedef struct _ATOM_Tonga_State { + UCHAR ucEngineClockIndexHigh; + UCHAR ucEngineClockIndexLow; + + UCHAR ucMemoryClockIndexHigh; + UCHAR ucMemoryClockIndexLow; + + UCHAR ucPCIEGenLow; + UCHAR ucPCIEGenHigh; + + UCHAR ucPCIELaneLow; + UCHAR ucPCIELaneHigh; + + USHORT usClassification; + ULONG ulCapsAndSettings; + USHORT usClassification2; + UCHAR ucUnused[4]; +} ATOM_Tonga_State; + +typedef struct _ATOM_Tonga_State_Array { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_State states[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_State_Array; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Record { + UCHAR ucVddcInd; /* Vddc voltage */ + USHORT usVddci; + USHORT usVddgfxOffset; /* Offset relative to Vddc voltage */ + USHORT usMvdd; + ULONG ulMclk; + USHORT usReserved; +} ATOM_Tonga_MCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_MCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Record { + UCHAR ucVddInd; /* Base voltage */ + USHORT usVddcOffset; /* Offset relative to base voltage */ + ULONG ulSclk; + USHORT usEdcCurrent; + UCHAR ucReliabilityTemperature; + UCHAR ucCKSVOffsetandDisable; /* Bits 0~6: Voltage offset for CKS, Bit 7: Disable/enable for the SCLK level. */ +} ATOM_Tonga_SCLK_Dependency_Record; + +typedef struct _ATOM_Tonga_SCLK_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_SCLK_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_SCLK_Dependency_Table; + +typedef struct _ATOM_Tonga_PCIE_Record { + UCHAR ucPCIEGenSpeed; + UCHAR usPCIELaneWidth; + UCHAR ucReserved[2]; +} ATOM_Tonga_PCIE_Record; + +typedef struct _ATOM_Tonga_PCIE_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_PCIE_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_PCIE_Table; + +typedef struct _ATOM_Tonga_MM_Dependency_Record { + UCHAR ucVddcInd; /* VDDC voltage */ + USHORT usVddgfxOffset; /* Offset relative to VDDC voltage */ + ULONG ulDClk; /* UVD D-clock */ + ULONG ulVClk; /* UVD V-clock */ + ULONG ulEClk; /* VCE clock */ + ULONG ulAClk; /* ACP clock */ + ULONG ulSAMUClk; /* SAMU clock */ +} ATOM_Tonga_MM_Dependency_Record; + +typedef struct _ATOM_Tonga_MM_Dependency_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_MM_Dependency_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_MM_Dependency_Table; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Record { + USHORT usVdd; /* Base voltage */ + USHORT usCACLow; + USHORT usCACMid; + USHORT usCACHigh; +} ATOM_Tonga_Voltage_Lookup_Record; + +typedef struct _ATOM_Tonga_Voltage_Lookup_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; /* Number of entries. */ + ATOM_Tonga_Voltage_Lookup_Record entries[1]; /* Dynamically allocate entries. */ +} ATOM_Tonga_Voltage_Lookup_Table; + +typedef struct _ATOM_Tonga_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usReserved; +} ATOM_Tonga_Fan_Table; + +typedef struct _ATOM_Fiji_Fan_Table { + UCHAR ucRevId; /* Change this if the table format changes or version changes so that the other fields are not the same. */ + UCHAR ucTHyst; /* Temperature hysteresis. Integer. */ + USHORT usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + USHORT usTMed; /* The middle temperature where we change slopes. */ + USHORT usTHigh; /* The high point above TMed for adjusting the second slope. */ + USHORT usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + USHORT usPWMMed; /* The PWM value (in percent) at TMed. */ + USHORT usPWMHigh; /* The PWM value at THigh. */ + USHORT usTMax; /* The max temperature */ + UCHAR ucFanControlMode; /* Legacy or Fuzzy Fan mode */ + USHORT usFanPWMMax; /* Maximum allowed fan power in percent */ + USHORT usFanOutputSensitivity; /* Sensitivity of fan reaction to temepature changes */ + USHORT usFanRPMMax; /* The default value in RPM */ + ULONG ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + UCHAR ucTargetTemperature; /* Advanced fan controller target temperature. */ + UCHAR ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + USHORT usFanGainEdge; + USHORT usFanGainHotspot; + USHORT usFanGainLiquid; + USHORT usFanGainVrVddc; + USHORT usFanGainVrMvdd; + USHORT usFanGainPlx; + USHORT usFanGainHbm; + USHORT usReserved; +} ATOM_Fiji_Fan_Table; + +typedef struct _ATOM_Tonga_Thermal_Controller { + UCHAR ucRevId; + UCHAR ucType; /* one of ATOM_TONGA_PP_THERMALCONTROLLER_* */ + UCHAR ucI2cLine; /* as interpreted by DAL I2C */ + UCHAR ucI2cAddress; + UCHAR ucFanParameters; /* Fan Control Parameters. */ + UCHAR ucFanMinRPM; /* Fan Minimum RPM (hundreds) -- for display purposes only. */ + UCHAR ucFanMaxRPM; /* Fan Maximum RPM (hundreds) -- for display purposes only. */ + UCHAR ucReserved; + UCHAR ucFlags; /* to be defined */ +} ATOM_Tonga_Thermal_Controller; + +typedef struct _ATOM_Tonga_VCE_State_Record { + UCHAR ucVCEClockIndex; /*index into usVCEDependencyTableOffset of 'ATOM_Tonga_MM_Dependency_Table' type */ + UCHAR ucFlag; /* 2 bits indicates memory p-states */ + UCHAR ucSCLKIndex; /*index into ATOM_Tonga_SCLK_Dependency_Table */ + UCHAR ucMCLKIndex; /*index into ATOM_Tonga_MCLK_Dependency_Table */ +} ATOM_Tonga_VCE_State_Record; + +typedef struct _ATOM_Tonga_VCE_State_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_VCE_State_Record entries[1]; +} ATOM_Tonga_VCE_State_Table; + +typedef struct _ATOM_Tonga_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usReserve[2]; +} ATOM_Tonga_PowerTune_Table; + +typedef struct _ATOM_Fiji_PowerTune_Table { + UCHAR ucRevId; + USHORT usTDP; + USHORT usConfigurableTDP; + USHORT usTDC; + USHORT usBatteryPowerLimit; + USHORT usSmallPowerLimit; + USHORT usLowCACLeakage; + USHORT usHighCACLeakage; + USHORT usMaximumPowerDeliveryLimit; + USHORT usTjMax; /* For Fiji, this is also usTemperatureLimitEdge; */ + USHORT usPowerTuneDataSetID; + USHORT usEDCLimit; + USHORT usSoftwareShutdownTemp; + USHORT usClockStretchAmount; + USHORT usTemperatureLimitHotspot; /*The following are added for Fiji */ + USHORT usTemperatureLimitLiquid1; + USHORT usTemperatureLimitLiquid2; + USHORT usTemperatureLimitVrVddc; + USHORT usTemperatureLimitVrMvdd; + USHORT usTemperatureLimitPlx; + UCHAR ucLiquid1_I2C_address; /*Liquid */ + UCHAR ucLiquid2_I2C_address; + UCHAR ucLiquid_I2C_Line; + UCHAR ucVr_I2C_address; /*VR */ + UCHAR ucVr_I2C_Line; + UCHAR ucPlx_I2C_address; /*PLX */ + UCHAR ucPlx_I2C_Line; + USHORT usReserved; +} ATOM_Fiji_PowerTune_Table; + +#define ATOM_PPM_A_A 1 +#define ATOM_PPM_A_I 2 +typedef struct _ATOM_Tonga_PPM_Table { + UCHAR ucRevId; + UCHAR ucPpmDesign; /*A+I or A+A */ + USHORT usCpuCoreNumber; + ULONG ulPlatformTDP; + ULONG ulSmallACPlatformTDP; + ULONG ulPlatformTDC; + ULONG ulSmallACPlatformTDC; + ULONG ulApuTDP; + ULONG ulDGpuTDP; + ULONG ulDGpuUlvPower; + ULONG ulTjmax; +} ATOM_Tonga_PPM_Table; + +typedef struct _ATOM_Tonga_Hard_Limit_Record { + ULONG ulSCLKLimit; + ULONG ulMCLKLimit; + USHORT usVddcLimit; + USHORT usVddciLimit; + USHORT usVddgfxLimit; +} ATOM_Tonga_Hard_Limit_Record; + +typedef struct _ATOM_Tonga_Hard_Limit_Table { + UCHAR ucRevId; + UCHAR ucNumEntries; + ATOM_Tonga_Hard_Limit_Record entries[1]; +} ATOM_Tonga_Hard_Limit_Table; + +typedef struct _ATOM_Tonga_GPIO_Table { + UCHAR ucRevId; + UCHAR ucVRHotTriggeredSclkDpmIndex; /* If VRHot signal is triggered SCLK will be limited to this DPM level */ + UCHAR ucReserve[5]; +} ATOM_Tonga_GPIO_Table; + +typedef struct _PPTable_Generic_SubTable_Header { + UCHAR ucRevId; +} PPTable_Generic_SubTable_Header; + + +#pragma pack(pop) + + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c new file mode 100644 index 000000000000..ae216fe8547d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.c @@ -0,0 +1,1142 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/module.h> +#include <linux/slab.h> +#include <linux/fb.h> + +#include "tonga_processpptables.h" +#include "ppatomctrl.h" +#include "atombios.h" +#include "pp_debug.h" +#include "hwmgr.h" +#include "cgs_common.h" +#include "tonga_pptable.h" + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param setIt A flag indication if the capability should be set (TRUE) or reset (FALSE). + * @param cap Which capability to set/reset. + */ +static void set_hw_cap(struct pp_hwmgr *hwmgr, bool setIt, enum phm_platform_caps cap) +{ + if (setIt) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, cap); + else + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, cap); +} + + +/** + * Private Function used during initialization. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_caps the bit array (from BIOS) of capability bits. + * @exception the current implementation always returns 1. + */ +static int set_platform_caps(struct pp_hwmgr *hwmgr, uint32_t powerplay_caps) +{ + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE16____), + "ATOM_PP_PLATFORM_CAP_ASPM_L1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE64____), + "ATOM_PP_PLATFORM_CAP_GEMINIPRIMARY is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE512____), + "ATOM_PP_PLATFORM_CAP_SIDEPORTCONTROL is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE1024____), + "ATOM_PP_PLATFORM_CAP_TURNOFFPLL_ASPML1 is not supported!", continue); + PP_ASSERT_WITH_CODE((~powerplay_caps & ____RETIRE2048____), + "ATOM_PP_PLATFORM_CAP_HTLINKCONTROL is not supported!", continue); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_POWERPLAY), + PHM_PlatformCaps_PowerPlaySupport + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_SBIOSPOWERSOURCE), + PHM_PlatformCaps_BiosPowerSourceControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_HARDWAREDC), + PHM_PlatformCaps_AutomaticDCTransition + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_MVDD_CONTROL), + PHM_PlatformCaps_EnableMVDDControl + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDCI_CONTROL), + PHM_PlatformCaps_ControlVDDCI + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_VDDGFX_CONTROL), + PHM_PlatformCaps_ControlVDDGFX + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_BACO), + PHM_PlatformCaps_BACO + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_CAP_DISABLE_VOLTAGE_ISLAND), + PHM_PlatformCaps_DisableVoltageIsland + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PP_PLATFORM_COMBINE_PCC_WITH_THERMAL_SIGNAL), + PHM_PlatformCaps_CombinePCCWithThermalSignal + ); + + set_hw_cap( + hwmgr, + 0 != (powerplay_caps & ATOM_TONGA_PLATFORM_LOAD_POST_PRODUCTION_FIRMWARE), + PHM_PlatformCaps_LoadPostProductionFirmware + ); + + return 0; +} + +/** + * Private Function to get the PowerPlay Table Address. + */ +const void *get_powerplay_table(struct pp_hwmgr *hwmgr) +{ + int index = GetIndexIntoMasterTable(DATA, PowerPlayInfo); + + u16 size; + u8 frev, crev; + void *table_address; + + table_address = (ATOM_Tonga_POWERPLAYTABLE *) + cgs_atom_get_data_table(hwmgr->device, index, &size, &frev, &crev); + + hwmgr->soft_pp_table = table_address; /*Cache the result in RAM.*/ + + return table_address; +} + +static int get_vddc_lookup_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_voltage_lookup_table **lookup_table, + const ATOM_Tonga_Voltage_Lookup_Table *vddc_lookup_pp_tables, + uint32_t max_levels + ) +{ + uint32_t table_size, i; + phm_ppt_v1_voltage_lookup_table *table; + + PP_ASSERT_WITH_CODE((0 != vddc_lookup_pp_tables->ucNumEntries), + "Invalid CAC Leakage PowerPlay Table!", return 1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_voltage_lookup_record) * max_levels; + + table = (phm_ppt_v1_voltage_lookup_table *) + kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -1; + + memset(table, 0x00, table_size); + + table->count = vddc_lookup_pp_tables->ucNumEntries; + + for (i = 0; i < vddc_lookup_pp_tables->ucNumEntries; i++) { + table->entries[i].us_calculated = 0; + table->entries[i].us_vdd = + vddc_lookup_pp_tables->entries[i].usVdd; + table->entries[i].us_cac_low = + vddc_lookup_pp_tables->entries[i].usCACLow; + table->entries[i].us_cac_mid = + vddc_lookup_pp_tables->entries[i].usCACMid; + table->entries[i].us_cac_high = + vddc_lookup_pp_tables->entries[i].usCACHigh; + } + + *lookup_table = table; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize Platform Power Management Parameter table + * @param hwmgr Pointer to the hardware manager. + * @param atom_ppm_table Pointer to PPM table in VBIOS + */ +static int get_platform_power_management_table( + struct pp_hwmgr *hwmgr, + ATOM_Tonga_PPM_Table *atom_ppm_table) +{ + struct phm_ppm_table *ptr = kzalloc(sizeof(ATOM_Tonga_PPM_Table), GFP_KERNEL); + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (NULL == ptr) + return -1; + + ptr->ppm_design + = atom_ppm_table->ucPpmDesign; + ptr->cpu_core_number + = atom_ppm_table->usCpuCoreNumber; + ptr->platform_tdp + = atom_ppm_table->ulPlatformTDP; + ptr->small_ac_platform_tdp + = atom_ppm_table->ulSmallACPlatformTDP; + ptr->platform_tdc + = atom_ppm_table->ulPlatformTDC; + ptr->small_ac_platform_tdc + = atom_ppm_table->ulSmallACPlatformTDC; + ptr->apu_tdp + = atom_ppm_table->ulApuTDP; + ptr->dgpu_tdp + = atom_ppm_table->ulDGpuTDP; + ptr->dgpu_ulv_power + = atom_ppm_table->ulDGpuUlvPower; + ptr->tj_max + = atom_ppm_table->ulTjmax; + + pp_table_information->ppm_parameter_table = ptr; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize TDP limits for DPM2 + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_dpm_2_parameters( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = (struct phm_ppt_v1_information *)(hwmgr->pptable); + ATOM_Tonga_PPM_Table *atom_ppm_table; + uint32_t disable_ppm = 0; + uint32_t disable_power_control = 0; + + pp_table_information->us_ulv_voltage_offset = + le16_to_cpu(powerplay_table->usUlvVoltageOffset); + + pp_table_information->ppm_parameter_table = NULL; + pp_table_information->vddc_lookup_table = NULL; + pp_table_information->vddgfx_lookup_table = NULL; + /* TDP limits */ + hwmgr->platform_descriptor.TDPODLimit = + le16_to_cpu(powerplay_table->usPowerControlLimit); + hwmgr->platform_descriptor.TDPAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustment = 0; + hwmgr->platform_descriptor.VidAdjustmentPolarity = 0; + hwmgr->platform_descriptor.VidMinLimit = 0; + hwmgr->platform_descriptor.VidMaxLimit = 1500000; + hwmgr->platform_descriptor.VidStep = 6250; + + disable_power_control = 0; + if (0 == disable_power_control) { + /* enable TDP overdrive (PowerControl) feature as well if supported */ + if (hwmgr->platform_descriptor.TDPODLimit != 0) + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_PowerControl); + } + + if (0 != powerplay_table->usVddcLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddcCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddcLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddc_lookup_table, pVddcCACTable, 16); + } + + if (0 != powerplay_table->usVddgfxLookupTableOffset) { + const ATOM_Tonga_Voltage_Lookup_Table *pVddgfxCACTable = + (ATOM_Tonga_Voltage_Lookup_Table *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usVddgfxLookupTableOffset)); + + result = get_vddc_lookup_table(hwmgr, + &pp_table_information->vddgfx_lookup_table, pVddgfxCACTable, 16); + } + + disable_ppm = 0; + if (0 == disable_ppm) { + atom_ppm_table = (ATOM_Tonga_PPM_Table *) + (((unsigned long)powerplay_table) + le16_to_cpu(powerplay_table->usPPMTableOffset)); + + if (0 != powerplay_table->usPPMTableOffset) { + if (1 == get_platform_power_management_table(hwmgr, atom_ppm_table)) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_EnablePlatformPowerManagement); + } + } + } + + return result; +} + +static int get_valid_clk( + struct pp_hwmgr *hwmgr, + struct phm_clock_array **clk_table, + const phm_ppt_v1_clock_voltage_dependency_table * clk_volt_pp_table + ) +{ + uint32_t table_size, i; + struct phm_clock_array *table; + + PP_ASSERT_WITH_CODE((0 != clk_volt_pp_table->count), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(uint32_t) * clk_volt_pp_table->count; + + table = (struct phm_clock_array *)kzalloc(table_size, GFP_KERNEL); + + if (NULL == table) + return -1; + + memset(table, 0x00, table_size); + + table->count = (uint32_t)clk_volt_pp_table->count; + + for (i = 0; i < table->count; i++) + table->values[i] = (uint32_t)clk_volt_pp_table->entries[i].clk; + + *clk_table = table; + + return 0; +} + +static int get_hard_limits( + struct pp_hwmgr *hwmgr, + struct phm_clock_and_voltage_limits *limits, + const ATOM_Tonga_Hard_Limit_Table * limitable + ) +{ + PP_ASSERT_WITH_CODE((0 != limitable->ucNumEntries), "Invalid PowerPlay Table!", return -1); + + /* currently we always take entries[0] parameters */ + limits->sclk = (uint32_t)limitable->entries[0].ulSCLKLimit; + limits->mclk = (uint32_t)limitable->entries[0].ulMCLKLimit; + limits->vddc = (uint16_t)limitable->entries[0].usVddcLimit; + limits->vddci = (uint16_t)limitable->entries[0].usVddciLimit; + limits->vddgfx = (uint16_t)limitable->entries[0].usVddgfxLimit; + + return 0; +} + +static int get_mclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_mclk_dep_table, + const ATOM_Tonga_MCLK_Dependency_Table * mclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *mclk_table; + + PP_ASSERT_WITH_CODE((0 != mclk_dep_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * mclk_dep_table->ucNumEntries; + + mclk_table = (phm_ppt_v1_clock_voltage_dependency_table *) + kzalloc(table_size, GFP_KERNEL); + + if (NULL == mclk_table) + return -1; + + memset(mclk_table, 0x00, table_size); + + mclk_table->count = (uint32_t)mclk_dep_table->ucNumEntries; + + for (i = 0; i < mclk_dep_table->ucNumEntries; i++) { + mclk_table->entries[i].vddInd = + mclk_dep_table->entries[i].ucVddcInd; + mclk_table->entries[i].vdd_offset = + mclk_dep_table->entries[i].usVddgfxOffset; + mclk_table->entries[i].vddci = + mclk_dep_table->entries[i].usVddci; + mclk_table->entries[i].mvdd = + mclk_dep_table->entries[i].usMvdd; + mclk_table->entries[i].clk = + mclk_dep_table->entries[i].ulMclk; + } + + *pp_tonga_mclk_dep_table = mclk_table; + + return 0; +} + +static int get_sclk_voltage_dependency_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_clock_voltage_dependency_table **pp_tonga_sclk_dep_table, + const ATOM_Tonga_SCLK_Dependency_Table * sclk_dep_table + ) +{ + uint32_t table_size, i; + phm_ppt_v1_clock_voltage_dependency_table *sclk_table; + + PP_ASSERT_WITH_CODE((0 != sclk_dep_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + sizeof(phm_ppt_v1_clock_voltage_dependency_record) + * sclk_dep_table->ucNumEntries; + + sclk_table = (phm_ppt_v1_clock_voltage_dependency_table *) + kzalloc(table_size, GFP_KERNEL); + + if (NULL == sclk_table) + return -1; + + memset(sclk_table, 0x00, table_size); + + sclk_table->count = (uint32_t)sclk_dep_table->ucNumEntries; + + for (i = 0; i < sclk_dep_table->ucNumEntries; i++) { + sclk_table->entries[i].vddInd = + sclk_dep_table->entries[i].ucVddInd; + sclk_table->entries[i].vdd_offset = + sclk_dep_table->entries[i].usVddcOffset; + sclk_table->entries[i].clk = + sclk_dep_table->entries[i].ulSclk; + sclk_table->entries[i].cks_enable = + (((sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x80) >> 7) == 0) ? 1 : 0; + sclk_table->entries[i].cks_voffset = + (sclk_dep_table->entries[i].ucCKSVOffsetandDisable & 0x7F); + } + + *pp_tonga_sclk_dep_table = sclk_table; + + return 0; +} + +static int get_pcie_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_pcie_table **pp_tonga_pcie_table, + const ATOM_Tonga_PCIE_Table * atom_pcie_table + ) +{ + uint32_t table_size, i, pcie_count; + phm_ppt_v1_pcie_table *pcie_table; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + PP_ASSERT_WITH_CODE((0 != atom_pcie_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_pcie_record) * atom_pcie_table->ucNumEntries; + + pcie_table = (phm_ppt_v1_pcie_table *)kzalloc(table_size, GFP_KERNEL); + + if (NULL == pcie_table) + return -1; + + memset(pcie_table, 0x00, table_size); + + /* + * Make sure the number of pcie entries are less than or equal to sclk dpm levels. + * Since first PCIE entry is for ULV, #pcie has to be <= SclkLevel + 1. + */ + pcie_count = (pp_table_information->vdd_dep_on_sclk->count) + 1; + if ((uint32_t)atom_pcie_table->ucNumEntries <= pcie_count) + pcie_count = (uint32_t)atom_pcie_table->ucNumEntries; + else + printk(KERN_ERR "[ powerplay ] Number of Pcie Entries exceed the number of SCLK Dpm Levels! \ + Disregarding the excess entries... \n"); + + pcie_table->count = pcie_count; + + for (i = 0; i < pcie_count; i++) { + pcie_table->entries[i].gen_speed = + atom_pcie_table->entries[i].ucPCIEGenSpeed; + pcie_table->entries[i].lane_width = + atom_pcie_table->entries[i].usPCIELaneWidth; + } + + *pp_tonga_pcie_table = pcie_table; + + return 0; +} + +static int get_cac_tdp_table( + struct pp_hwmgr *hwmgr, + struct phm_cac_tdp_table **cac_tdp_table, + const PPTable_Generic_SubTable_Header * table + ) +{ + uint32_t table_size; + struct phm_cac_tdp_table *tdp_table; + + table_size = sizeof(uint32_t) + sizeof(struct phm_cac_tdp_table); + tdp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == tdp_table) + return -1; + + memset(tdp_table, 0x00, table_size); + + hwmgr->dyn_state.cac_dtp_table = kzalloc(table_size, GFP_KERNEL); + + if (NULL == hwmgr->dyn_state.cac_dtp_table) + return -1; + + memset(hwmgr->dyn_state.cac_dtp_table, 0x00, table_size); + + if (table->ucRevId < 3) { + const ATOM_Tonga_PowerTune_Table *tonga_table = + (ATOM_Tonga_PowerTune_Table *)table; + tdp_table->usTDP = tonga_table->usTDP; + tdp_table->usConfigurableTDP = + tonga_table->usConfigurableTDP; + tdp_table->usTDC = tonga_table->usTDC; + tdp_table->usBatteryPowerLimit = + tonga_table->usBatteryPowerLimit; + tdp_table->usSmallPowerLimit = + tonga_table->usSmallPowerLimit; + tdp_table->usLowCACLeakage = + tonga_table->usLowCACLeakage; + tdp_table->usHighCACLeakage = + tonga_table->usHighCACLeakage; + tdp_table->usMaximumPowerDeliveryLimit = + tonga_table->usMaximumPowerDeliveryLimit; + tdp_table->usDefaultTargetOperatingTemp = + tonga_table->usTjMax; + tdp_table->usTargetOperatingTemp = + tonga_table->usTjMax; /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + tonga_table->usPowerTuneDataSetID; + tdp_table->usSoftwareShutdownTemp = + tonga_table->usSoftwareShutdownTemp; + tdp_table->usClockStretchAmount = + tonga_table->usClockStretchAmount; + } else { /* Fiji and newer */ + const ATOM_Fiji_PowerTune_Table *fijitable = + (ATOM_Fiji_PowerTune_Table *)table; + tdp_table->usTDP = fijitable->usTDP; + tdp_table->usConfigurableTDP = fijitable->usConfigurableTDP; + tdp_table->usTDC = fijitable->usTDC; + tdp_table->usBatteryPowerLimit = fijitable->usBatteryPowerLimit; + tdp_table->usSmallPowerLimit = fijitable->usSmallPowerLimit; + tdp_table->usLowCACLeakage = fijitable->usLowCACLeakage; + tdp_table->usHighCACLeakage = fijitable->usHighCACLeakage; + tdp_table->usMaximumPowerDeliveryLimit = + fijitable->usMaximumPowerDeliveryLimit; + tdp_table->usDefaultTargetOperatingTemp = + fijitable->usTjMax; + tdp_table->usTargetOperatingTemp = + fijitable->usTjMax; /*Set the initial temp to the same as default */ + tdp_table->usPowerTuneDataSetID = + fijitable->usPowerTuneDataSetID; + tdp_table->usSoftwareShutdownTemp = + fijitable->usSoftwareShutdownTemp; + tdp_table->usClockStretchAmount = + fijitable->usClockStretchAmount; + tdp_table->usTemperatureLimitHotspot = + fijitable->usTemperatureLimitHotspot; + tdp_table->usTemperatureLimitLiquid1 = + fijitable->usTemperatureLimitLiquid1; + tdp_table->usTemperatureLimitLiquid2 = + fijitable->usTemperatureLimitLiquid2; + tdp_table->usTemperatureLimitVrVddc = + fijitable->usTemperatureLimitVrVddc; + tdp_table->usTemperatureLimitVrMvdd = + fijitable->usTemperatureLimitVrMvdd; + tdp_table->usTemperatureLimitPlx = + fijitable->usTemperatureLimitPlx; + tdp_table->ucLiquid1_I2C_address = + fijitable->ucLiquid1_I2C_address; + tdp_table->ucLiquid2_I2C_address = + fijitable->ucLiquid2_I2C_address; + tdp_table->ucLiquid_I2C_Line = + fijitable->ucLiquid_I2C_Line; + tdp_table->ucVr_I2C_address = fijitable->ucVr_I2C_address; + tdp_table->ucVr_I2C_Line = fijitable->ucVr_I2C_Line; + tdp_table->ucPlx_I2C_address = fijitable->ucPlx_I2C_address; + tdp_table->ucPlx_I2C_Line = fijitable->ucPlx_I2C_Line; + } + + *cac_tdp_table = tdp_table; + + return 0; +} + +static int get_mm_clock_voltage_table( + struct pp_hwmgr *hwmgr, + phm_ppt_v1_mm_clock_voltage_dependency_table **tonga_mm_table, + const ATOM_Tonga_MM_Dependency_Table * mm_dependency_table + ) +{ + uint32_t table_size, i; + const ATOM_Tonga_MM_Dependency_Record *mm_dependency_record; + phm_ppt_v1_mm_clock_voltage_dependency_table *mm_table; + + PP_ASSERT_WITH_CODE((0 != mm_dependency_table->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + table_size = sizeof(uint32_t) + + sizeof(phm_ppt_v1_mm_clock_voltage_dependency_record) + * mm_dependency_table->ucNumEntries; + mm_table = (phm_ppt_v1_mm_clock_voltage_dependency_table *) + kzalloc(table_size, GFP_KERNEL); + + if (NULL == mm_table) + return -1; + + memset(mm_table, 0x00, table_size); + + mm_table->count = mm_dependency_table->ucNumEntries; + + for (i = 0; i < mm_dependency_table->ucNumEntries; i++) { + mm_dependency_record = &mm_dependency_table->entries[i]; + mm_table->entries[i].vddcInd = mm_dependency_record->ucVddcInd; + mm_table->entries[i].vddgfx_offset = mm_dependency_record->usVddgfxOffset; + mm_table->entries[i].aclk = mm_dependency_record->ulAClk; + mm_table->entries[i].samclock = mm_dependency_record->ulSAMUClk; + mm_table->entries[i].eclk = mm_dependency_record->ulEClk; + mm_table->entries[i].vclk = mm_dependency_record->ulVClk; + mm_table->entries[i].dclk = mm_dependency_record->ulDClk; + } + + *tonga_mm_table = mm_table; + + return 0; +} + +/** + * Private Function used during initialization. + * Initialize clock voltage dependency + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + */ +static int init_clock_voltage_dependency( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + const ATOM_Tonga_MM_Dependency_Table *mm_dependency_table = + (const ATOM_Tonga_MM_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMMDependencyTableOffset)); + const PPTable_Generic_SubTable_Header *pPowerTuneTable = + (const PPTable_Generic_SubTable_Header *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPowerTuneTableOffset)); + const ATOM_Tonga_MCLK_Dependency_Table *mclk_dep_table = + (const ATOM_Tonga_MCLK_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usMclkDependencyTableOffset)); + const ATOM_Tonga_SCLK_Dependency_Table *sclk_dep_table = + (const ATOM_Tonga_SCLK_Dependency_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usSclkDependencyTableOffset)); + const ATOM_Tonga_Hard_Limit_Table *pHardLimits = + (const ATOM_Tonga_Hard_Limit_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usHardLimitTableOffset)); + const ATOM_Tonga_PCIE_Table *pcie_table = + (const ATOM_Tonga_PCIE_Table *)(((unsigned long) powerplay_table) + + le16_to_cpu(powerplay_table->usPCIETableOffset)); + + pp_table_information->vdd_dep_on_sclk = NULL; + pp_table_information->vdd_dep_on_mclk = NULL; + pp_table_information->mm_dep_table = NULL; + pp_table_information->pcie_table = NULL; + + if (powerplay_table->usMMDependencyTableOffset != 0) + result = get_mm_clock_voltage_table(hwmgr, + &pp_table_information->mm_dep_table, mm_dependency_table); + + if (result == 0 && powerplay_table->usPowerTuneTableOffset != 0) + result = get_cac_tdp_table(hwmgr, + &pp_table_information->cac_dtp_table, pPowerTuneTable); + + if (result == 0 && powerplay_table->usSclkDependencyTableOffset != 0) + result = get_sclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_sclk, sclk_dep_table); + + if (result == 0 && powerplay_table->usMclkDependencyTableOffset != 0) + result = get_mclk_voltage_dependency_table(hwmgr, + &pp_table_information->vdd_dep_on_mclk, mclk_dep_table); + + if (result == 0 && powerplay_table->usPCIETableOffset != 0) + result = get_pcie_table(hwmgr, + &pp_table_information->pcie_table, pcie_table); + + if (result == 0 && powerplay_table->usHardLimitTableOffset != 0) + result = get_hard_limits(hwmgr, + &pp_table_information->max_clock_voltage_on_dc, pHardLimits); + + hwmgr->dyn_state.max_clock_voltage_on_dc.sclk = + pp_table_information->max_clock_voltage_on_dc.sclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.mclk = + pp_table_information->max_clock_voltage_on_dc.mclk; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddc = + pp_table_information->max_clock_voltage_on_dc.vddc; + hwmgr->dyn_state.max_clock_voltage_on_dc.vddci = + pp_table_information->max_clock_voltage_on_dc.vddci; + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_mclk) + && (0 != pp_table_information->vdd_dep_on_mclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_mclk_values, + pp_table_information->vdd_dep_on_mclk); + + if (result == 0 && (NULL != pp_table_information->vdd_dep_on_sclk) + && (0 != pp_table_information->vdd_dep_on_sclk->count)) + result = get_valid_clk(hwmgr, &pp_table_information->valid_sclk_values, + pp_table_information->vdd_dep_on_sclk); + + return result; +} + +/** Retrieves the (signed) Overdrive limits from VBIOS. + * The max engine clock, memory clock and max temperature come from the firmware info table. + * + * The information is placed into the platform descriptor. + * + * @param hwmgr source of the VBIOS table and owner of the platform descriptor to be updated. + * @param powerplay_table the address of the PowerPlay table. + * + * @return 1 as long as the firmware info table was present and of a supported version. + */ +static int init_over_drive_limits( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table) +{ + hwmgr->platform_descriptor.overdriveLimit.engineClock = + le16_to_cpu(powerplay_table->ulMaxODEngineClock); + hwmgr->platform_descriptor.overdriveLimit.memoryClock = + le16_to_cpu(powerplay_table->ulMaxODMemoryClock); + + hwmgr->platform_descriptor.minOverdriveVDDC = 0; + hwmgr->platform_descriptor.maxOverdriveVDDC = 0; + hwmgr->platform_descriptor.overdriveVDDCStep = 0; + + if (hwmgr->platform_descriptor.overdriveLimit.engineClock > 0 \ + && hwmgr->platform_descriptor.overdriveLimit.memoryClock > 0) { + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_ACOverdriveSupport); + } + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception This implementation always returns 1. + */ +static int init_thermal_controller( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const PPTable_Generic_SubTable_Header *fan_table; + ATOM_Tonga_Thermal_Controller *thermal_controller; + + thermal_controller = (ATOM_Tonga_Thermal_Controller *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usThermalControllerOffset)); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usThermalControllerOffset), + "Thermal controller table not set!", return -1); + + hwmgr->thermal_controller.ucType = thermal_controller->ucType; + hwmgr->thermal_controller.ucI2cLine = thermal_controller->ucI2cLine; + hwmgr->thermal_controller.ucI2cAddress = thermal_controller->ucI2cAddress; + + hwmgr->thermal_controller.fanInfo.bNoFan = + (0 != (thermal_controller->ucFanParameters & ATOM_TONGA_PP_FANPARAMETERS_NOFAN)); + + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution = + thermal_controller->ucFanParameters & + ATOM_TONGA_PP_FANPARAMETERS_TACHOMETER_PULSES_PER_REVOLUTION_MASK; + + hwmgr->thermal_controller.fanInfo.ulMinRPM + = thermal_controller->ucFanMinRPM * 100UL; + hwmgr->thermal_controller.fanInfo.ulMaxRPM + = thermal_controller->ucFanMaxRPM * 100UL; + + set_hw_cap( + hwmgr, + ATOM_TONGA_PP_THERMALCONTROLLER_NONE != hwmgr->thermal_controller.ucType, + PHM_PlatformCaps_ThermalController + ); + + if (0 == powerplay_table->usFanTableOffset) + return 0; + + fan_table = (const PPTable_Generic_SubTable_Header *) + (((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usFanTableOffset)); + + PP_ASSERT_WITH_CODE((0 != powerplay_table->usFanTableOffset), + "Fan table not set!", return -1); + PP_ASSERT_WITH_CODE((0 < fan_table->ucRevId), + "Unsupported fan table format!", return -1); + + hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay + = 100000; + phm_cap_set(hwmgr->platform_descriptor.platformCaps, + PHM_PlatformCaps_MicrocodeFanControl); + + if (fan_table->ucRevId < 8) { + const ATOM_Tonga_Fan_Table *tonga_fan_table = + (ATOM_Tonga_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = tonga_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = tonga_fan_table->usTMin; + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = tonga_fan_table->usTMed; + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = tonga_fan_table->usTHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = tonga_fan_table->usPWMMin; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = tonga_fan_table->usPWMMed; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = tonga_fan_table->usPWMHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = 10900; /* hard coded */ + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = tonga_fan_table->usTMax; + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = tonga_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = tonga_fan_table->usFanPWMMax; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = tonga_fan_table->usFanOutputSensitivity; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = tonga_fan_table->usFanRPMMax; + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (tonga_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = tonga_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = tonga_fan_table->ucMinimumPWMLimit; + } else { + const ATOM_Fiji_Fan_Table *fiji_fan_table = + (ATOM_Fiji_Fan_Table *)fan_table; + hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst + = fiji_fan_table->ucTHyst; + hwmgr->thermal_controller.advanceFanControlParameters.usTMin + = fiji_fan_table->usTMin; + hwmgr->thermal_controller.advanceFanControlParameters.usTMed + = fiji_fan_table->usTMed; + hwmgr->thermal_controller.advanceFanControlParameters.usTHigh + = fiji_fan_table->usTHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin + = fiji_fan_table->usPWMMin; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed + = fiji_fan_table->usPWMMed; + hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh + = fiji_fan_table->usPWMHigh; + hwmgr->thermal_controller.advanceFanControlParameters.usTMax + = fiji_fan_table->usTMax; + hwmgr->thermal_controller.advanceFanControlParameters.ucFanControlMode + = fiji_fan_table->ucFanControlMode; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanPWM + = fiji_fan_table->usFanPWMMax; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultFanOutputSensitivity + = 4836; + hwmgr->thermal_controller.advanceFanControlParameters.usFanOutputSensitivity + = fiji_fan_table->usFanOutputSensitivity; + hwmgr->thermal_controller.advanceFanControlParameters.usDefaultMaxFanRPM + = fiji_fan_table->usFanRPMMax; + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit + = (fiji_fan_table->ulMinFanSCLKAcousticLimit / 100); /* PPTable stores it in 10Khz unit for 2 decimal places. SMC wants MHz. */ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature + = fiji_fan_table->ucTargetTemperature; + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit + = fiji_fan_table->ucMinimumPWMLimit; + + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainEdge + = fiji_fan_table->usFanGainEdge; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHotspot + = fiji_fan_table->usFanGainHotspot; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainLiquid + = fiji_fan_table->usFanGainLiquid; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrVddc + = fiji_fan_table->usFanGainVrVddc; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainVrMvdd + = fiji_fan_table->usFanGainVrMvdd; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainPlx + = fiji_fan_table->usFanGainPlx; + hwmgr->thermal_controller.advanceFanControlParameters.usFanGainHbm + = fiji_fan_table->usFanGainHbm; + } + + return 0; +} + +/** + * Private Function used during initialization. + * Inspect the PowerPlay table for obvious signs of corruption. + * @param hwmgr Pointer to the hardware manager. + * @param powerplay_table Pointer to the PowerPlay Table. + * @exception 2 if the powerplay table is incorrect. + */ +static int check_powerplay_tables( + struct pp_hwmgr *hwmgr, + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table + ) +{ + const ATOM_Tonga_State_Array *state_arrays; + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)powerplay_table) + + le16_to_cpu(powerplay_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((ATOM_Tonga_TABLE_REVISION_TONGA <= + powerplay_table->sHeader.ucTableFormatRevision), + "Unsupported PPTable format!", return -1); + PP_ASSERT_WITH_CODE((0 != powerplay_table->usStateArrayOffset), + "State table is not set!", return -1); + PP_ASSERT_WITH_CODE((0 < powerplay_table->sHeader.usStructureSize), + "Invalid PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table!", return -1); + + return 0; +} + +int tonga_pp_tables_initialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + const ATOM_Tonga_POWERPLAYTABLE *powerplay_table; + + hwmgr->pptable = kzalloc(sizeof(struct phm_ppt_v1_information), GFP_KERNEL); + + PP_ASSERT_WITH_CODE((NULL != hwmgr->pptable), + "Failed to allocate hwmgr->pptable!", return -1); + + memset(hwmgr->pptable, 0x00, sizeof(struct phm_ppt_v1_information)); + + powerplay_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != powerplay_table), + "Missing PowerPlay Table!", return -1); + + result = check_powerplay_tables(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "check_powerplay_tables failed", return result); + + result = set_platform_caps(hwmgr, + le32_to_cpu(powerplay_table->ulPlatformCaps)); + + PP_ASSERT_WITH_CODE((result == 0), + "set_platform_caps failed", return result); + + result = init_thermal_controller(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_thermal_controller failed", return result); + + result = init_over_drive_limits(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_over_drive_limits failed", return result); + + result = init_clock_voltage_dependency(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_clock_voltage_dependency failed", return result); + + result = init_dpm_2_parameters(hwmgr, powerplay_table); + + PP_ASSERT_WITH_CODE((result == 0), + "init_dpm_2_parameters failed", return result); + + return result; +} + +int tonga_pp_tables_uninitialize(struct pp_hwmgr *hwmgr) +{ + int result = 0; + struct phm_ppt_v1_information *pp_table_information = + (struct phm_ppt_v1_information *)(hwmgr->pptable); + + if (NULL != hwmgr->soft_pp_table) { + kfree(hwmgr->soft_pp_table); + hwmgr->soft_pp_table = NULL; + } + + if (NULL != pp_table_information->vdd_dep_on_sclk) + pp_table_information->vdd_dep_on_sclk = NULL; + + if (NULL != pp_table_information->vdd_dep_on_mclk) + pp_table_information->vdd_dep_on_mclk = NULL; + + if (NULL != pp_table_information->valid_mclk_values) + pp_table_information->valid_mclk_values = NULL; + + if (NULL != pp_table_information->valid_sclk_values) + pp_table_information->valid_sclk_values = NULL; + + if (NULL != pp_table_information->vddc_lookup_table) + pp_table_information->vddc_lookup_table = NULL; + + if (NULL != pp_table_information->vddgfx_lookup_table) + pp_table_information->vddgfx_lookup_table = NULL; + + if (NULL != pp_table_information->mm_dep_table) + pp_table_information->mm_dep_table = NULL; + + if (NULL != pp_table_information->cac_dtp_table) + pp_table_information->cac_dtp_table = NULL; + + if (NULL != hwmgr->dyn_state.cac_dtp_table) + hwmgr->dyn_state.cac_dtp_table = NULL; + + if (NULL != pp_table_information->ppm_parameter_table) + pp_table_information->ppm_parameter_table = NULL; + + if (NULL != pp_table_information->pcie_table) + pp_table_information->pcie_table = NULL; + + if (NULL != hwmgr->pptable) { + kfree(hwmgr->pptable); + hwmgr->pptable = NULL; + } + + return result; +} + +const struct pp_table_func tonga_pptable_funcs = { + .pptable_init = tonga_pp_tables_initialize, + .pptable_fini = tonga_pp_tables_uninitialize, +}; + +int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr) +{ + const ATOM_Tonga_State_Array * state_arrays; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != pp_table), + "Missing PowerPlay Table!", return -1); + PP_ASSERT_WITH_CODE((pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA), + "Incorrect PowerPlay table revision!", return -1); + + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + return (uint32_t)(state_arrays->ucNumEntries); +} + +/** +* Private function to convert flags stored in the BIOS to software flags in PowerPlay. +*/ +static uint32_t make_classification_flags(struct pp_hwmgr *hwmgr, + uint16_t classification, uint16_t classification2) +{ + uint32_t result = 0; + + if (classification & ATOM_PPLIB_CLASSIFICATION_BOOT) + result |= PP_StateClassificationFlag_Boot; + + if (classification & ATOM_PPLIB_CLASSIFICATION_THERMAL) + result |= PP_StateClassificationFlag_Thermal; + + if (classification & ATOM_PPLIB_CLASSIFICATION_LIMITEDPOWERSOURCE) + result |= PP_StateClassificationFlag_LimitedPowerSource; + + if (classification & ATOM_PPLIB_CLASSIFICATION_REST) + result |= PP_StateClassificationFlag_Rest; + + if (classification & ATOM_PPLIB_CLASSIFICATION_FORCED) + result |= PP_StateClassificationFlag_Forced; + + if (classification & ATOM_PPLIB_CLASSIFICATION_ACPI) + result |= PP_StateClassificationFlag_ACPI; + + if (classification2 & ATOM_PPLIB_CLASSIFICATION2_LIMITEDPOWERSOURCE_2) + result |= PP_StateClassificationFlag_LimitedPowerSource_2; + + return result; +} + +/** +* Create a Power State out of an entry in the PowerPlay table. +* This function is called by the hardware back-end. +* @param hwmgr Pointer to the hardware manager. +* @param entry_index The index of the entry to be extracted from the table. +* @param power_state The address of the PowerState instance being created. +* @return -1 if the entry cannot be retrieved. +*/ +int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, + uint32_t entry_index, struct pp_power_state *power_state, + int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)) +{ + int result = 0; + const ATOM_Tonga_State_Array * state_arrays; + const ATOM_Tonga_State *state_entry; + const ATOM_Tonga_POWERPLAYTABLE *pp_table = get_powerplay_table(hwmgr); + + PP_ASSERT_WITH_CODE((NULL != pp_table), "Missing PowerPlay Table!", return -1;); + power_state->classification.bios_index = entry_index; + + if (pp_table->sHeader.ucTableFormatRevision >= + ATOM_Tonga_TABLE_REVISION_TONGA) { + state_arrays = (ATOM_Tonga_State_Array *)(((unsigned long)pp_table) + + le16_to_cpu(pp_table->usStateArrayOffset)); + + PP_ASSERT_WITH_CODE((0 < pp_table->usStateArrayOffset), + "Invalid PowerPlay Table State Array Offset.", return -1); + PP_ASSERT_WITH_CODE((0 < state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array.", return -1); + PP_ASSERT_WITH_CODE((entry_index <= state_arrays->ucNumEntries), + "Invalid PowerPlay Table State Array Entry.", return -1); + + state_entry = &(state_arrays->states[entry_index]); + + result = call_back_func(hwmgr, (void *)state_entry, power_state, + (void *)pp_table, + make_classification_flags(hwmgr, + le16_to_cpu(state_entry->usClassification), + le16_to_cpu(state_entry->usClassification2))); + } + + if (!result && (power_state->classification.flags & + PP_StateClassificationFlag_Boot)) + result = hwmgr->hwmgr_func->patch_boot_state(hwmgr, &(power_state->hardware)); + + return result; +} diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h new file mode 100644 index 000000000000..d24b8887f466 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_processpptables.h @@ -0,0 +1,35 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef TONGA_PROCESSPPTABLES_H +#define TONGA_PROCESSPPTABLES_H + +#include "hwmgr.h" + +extern const struct pp_table_func tonga_pptable_funcs; +extern int tonga_get_number_of_powerplay_table_entries(struct pp_hwmgr *hwmgr); +extern int tonga_get_powerplay_table_entry(struct pp_hwmgr *hwmgr, uint32_t entry_index, + struct pp_power_state *power_state, int (*call_back_func)(struct pp_hwmgr *, void *, + struct pp_power_state *, void *, uint32_t)); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c new file mode 100644 index 000000000000..2e159b003e71 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.c @@ -0,0 +1,590 @@ +/* + * Copyright 2015 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. + * + */ + +#include "tonga_thermal.h" +#include "tonga_hwmgr.h" +#include "tonga_smumgr.h" +#include "tonga_ppsmc.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" + +/** +* Get Fan Speed Control Parameters. +* @param hwmgr the address of the powerplay hardware manager. +* @param pSpeed is the address of the structure where the result is to be placed. +* @exception Always succeeds except if we cannot zero out the output structure. +*/ +int tonga_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info) +{ + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + fan_speed_info->supports_percent_read = true; + fan_speed_info->supports_percent_write = true; + fan_speed_info->min_percent = 0; + fan_speed_info->max_percent = 100; + + if (0 != hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) { + fan_speed_info->supports_rpm_read = true; + fan_speed_info->supports_rpm_write = true; + fan_speed_info->min_rpm = hwmgr->thermal_controller.fanInfo.ulMinRPM; + fan_speed_info->max_rpm = hwmgr->thermal_controller.fanInfo.ulMaxRPM; + } else { + fan_speed_info->min_rpm = 0; + fan_speed_info->max_rpm = 0; + } + + return 0; +} + +/** +* Get Fan Speed in percent. +* @param hwmgr the address of the powerplay hardware manager. +* @param pSpeed is the address of the structure where the result is to be placed. +* @exception Fails is the 100% setting appears to be 0. +*/ +int tonga_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + duty = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_STATUS, FDO_PWM_DUTY); + + if (0 == duty100) + return -EINVAL; + + + tmp64 = (uint64_t)duty * 100; + do_div(tmp64, duty100); + *speed = (uint32_t)tmp64; + + if (*speed > 100) + *speed = 100; + + return 0; +} + +/** +* Get Fan Speed in RPM. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the address of the structure where the result is to be placed. +* @exception Returns not supported if no fan is found or if pulses per revolution are not set +*/ +int tonga_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed) +{ + return 0; +} + +/** +* Set Fan Speed Control to static mode, so that the user can decide what speed to use. +* @param hwmgr the address of the powerplay hardware manager. +* mode the fan control mode, 0 default, 1 by percent, 5, by RPM +* @exception Should always succeed. +*/ +int tonga_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode) +{ + + if (hwmgr->fan_ctrl_is_in_default_mode) { + hwmgr->fan_ctrl_default_mode = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE); + hwmgr->tmin = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN); + hwmgr->fan_ctrl_is_in_default_mode = false; + } + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, 0); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, mode); + + return 0; +} + +/** +* Reset Fan Speed Control to default mode. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Should always succeed. +*/ +int tonga_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->fan_ctrl_is_in_default_mode) { + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, FDO_PWM_MODE, hwmgr->fan_ctrl_default_mode); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TMIN, hwmgr->tmin); + hwmgr->fan_ctrl_is_in_default_mode = true; + } + + return 0; +} + +int tonga_fan_ctrl_start_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + int result; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_ODFuzzyFanControlSupport)) { + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_FUZZY); + result = (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl) == 0) ? 0 : -EINVAL; +/* + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_FanSpeedInTableIsRPM)) + hwmgr->set_max_fan_rpm_output(hwmgr, hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanRPM); + else + hwmgr->set_max_fan_pwm_output(hwmgr, hwmgr->thermal_controller.advanceFanControlParameters.usMaxFanPWM); +*/ + } else { + cgs_write_register(hwmgr->device, mmSMC_MSG_ARG_0, FAN_CONTROL_TABLE); + result = (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StartFanControl) == 0) ? 0 : -EINVAL; + } +/* TO DO FOR SOME DEVICE ID 0X692b, send this msg return invalid command. + if (result == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature != 0) + result = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanTemperatureTarget, \ + hwmgr->thermal_controller.advanceFanControlParameters.ucTargetTemperature) ? 0 : -EINVAL); +*/ + return result; +} + + +int tonga_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr) +{ + return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_StopFanControl) == 0) ? 0 : -EINVAL; +} + +/** +* Set Fan Speed in percent. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (0% - 100%) to be set. +* @exception Fails is the 100% setting appears to be 0. +*/ +int tonga_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + uint32_t duty100; + uint32_t duty; + uint64_t tmp64; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return -EINVAL; + + if (speed > 100) + speed = 100; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + tonga_fan_ctrl_stop_smc_fan_control(hwmgr); + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) + return -EINVAL; + + tmp64 = (uint64_t)speed * 100; + do_div(tmp64, duty100); + duty = (uint32_t)tmp64; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL0, FDO_STATIC_DUTY, duty); + + return tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); +} + +/** +* Reset Fan Speed to default. +* @param hwmgr the address of the powerplay hardware manager. +* @exception Always succeeds. +*/ +int tonga_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr) +{ + int result; + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + return 0; + + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) { + result = tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + if (0 == result) + result = tonga_fan_ctrl_start_smc_fan_control(hwmgr); + } else + result = tonga_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set Fan Speed in RPM. +* @param hwmgr the address of the powerplay hardware manager. +* @param speed is the percentage value (min - max) to be set. +* @exception Fails is the speed not lie between min and max. +*/ +int tonga_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed) +{ + return 0; +} + +/** +* Reads the remote temperature from the SIslands thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +int tonga_thermal_get_temperature(struct pp_hwmgr *hwmgr) +{ + int temp; + + temp = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_STATUS, CTF_TEMP); + +/* Bit 9 means the reading is lower than the lowest usable value. */ + if (0 != (0x200 & temp)) + temp = TONGA_THERMAL_MAXIMUM_TEMP_READING; + else + temp = (temp & 0x1ff); + + temp = temp * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + return temp; +} + +/** +* Set the requested temperature range for high and low alert signals +* +* @param hwmgr The address of the hardware manager. +* @param range Temperature range to be programmed for high and low alert signals +* @exception PP_Result_BadInput if the input data is not valid. +*/ +static int tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, uint32_t low_temp, uint32_t high_temp) +{ + uint32_t low = TONGA_THERMAL_MINIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + uint32_t high = TONGA_THERMAL_MAXIMUM_ALERT_TEMP * PP_TEMPERATURE_UNITS_PER_CENTIGRADES; + + if (low < low_temp) + low = low_temp; + if (high > high_temp) + high = high_temp; + + if (low > high) + return -EINVAL; + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTH, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, DIG_THERM_INTL, (low / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_CTRL, DIG_THERM_DPM, (high / PP_TEMPERATURE_UNITS_PER_CENTIGRADES)); + + return 0; +} + +/** +* Programs thermal controller one-time setting registers +* +* @param hwmgr The address of the hardware manager. +*/ +static int tonga_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + if (0 != hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution) + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, + CG_TACH_CTRL, EDGE_PER_REV, + hwmgr->thermal_controller.fanInfo.ucTachometerPulsesPerRevolution - 1); + + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL2, TACH_PWM_RESP_RATE, 0x28); + + return 0; +} + +/** +* Enable thermal alerts on the RV770 thermal controller. +* +* @param hwmgr The address of the hardware manager. +*/ +static int tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK); + alert &= ~(TONGA_THERMAL_HIGH_ALERT_MASK | TONGA_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to enable internal thermal interrupts */ + return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Enable) == 0) ? 0 : -1; +} + +/** +* Disable thermal alerts on the RV770 thermal controller. +* @param hwmgr The address of the hardware manager. +*/ +static int tonga_thermal_disable_alert(struct pp_hwmgr *hwmgr) +{ + uint32_t alert; + + alert = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK); + alert |= (TONGA_THERMAL_HIGH_ALERT_MASK | TONGA_THERMAL_LOW_ALERT_MASK); + PHM_WRITE_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_THERMAL_INT, THERM_INT_MASK, alert); + + /* send message to SMU to disable internal thermal interrupts */ + return (smum_send_msg_to_smc(hwmgr->smumgr, PPSMC_MSG_Thermal_Cntl_Disable) == 0) ? 0 : -1; +} + +/** +* Uninitialize the thermal controller. +* Currently just disables alerts. +* @param hwmgr The address of the hardware manager. +*/ +int tonga_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr) +{ + int result = tonga_thermal_disable_alert(hwmgr); + + if (hwmgr->thermal_controller.fanInfo.bNoFan) + tonga_fan_ctrl_set_default_mode(hwmgr); + + return result; +} + +/** +* Set up the fan table to control the fan using the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_tonga_thermal_setup_fan_table(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ + struct tonga_hwmgr *data = (struct tonga_hwmgr *)(hwmgr->backend); + SMU72_Discrete_FanTable fan_table = { FDO_MODE_HARDWARE }; + uint32_t duty100; + uint32_t t_diff1, t_diff2, pwm_diff1, pwm_diff2; + uint16_t fdo_min, slope1, slope2; + uint32_t reference_clock; + int res; + uint64_t tmp64; + + if (!phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) + return 0; + + if (0 == data->fan_table_start) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + duty100 = PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_FDO_CTRL1, FMAX_DUTY100); + + if (0 == duty100) { + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); + return 0; + } + + tmp64 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin * duty100; + do_div(tmp64, 10000); + fdo_min = (uint16_t)tmp64; + + t_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usTMed - hwmgr->thermal_controller.advanceFanControlParameters.usTMin; + t_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usTHigh - hwmgr->thermal_controller.advanceFanControlParameters.usTMed; + + pwm_diff1 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMin; + pwm_diff2 = hwmgr->thermal_controller.advanceFanControlParameters.usPWMHigh - hwmgr->thermal_controller.advanceFanControlParameters.usPWMMed; + + slope1 = (uint16_t)((50 + ((16 * duty100 * pwm_diff1) / t_diff1)) / 100); + slope2 = (uint16_t)((50 + ((16 * duty100 * pwm_diff2) / t_diff2)) / 100); + + fan_table.TempMin = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMin) / 100); + fan_table.TempMed = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMed) / 100); + fan_table.TempMax = cpu_to_be16((50 + hwmgr->thermal_controller.advanceFanControlParameters.usTMax) / 100); + + fan_table.Slope1 = cpu_to_be16(slope1); + fan_table.Slope2 = cpu_to_be16(slope2); + + fan_table.FdoMin = cpu_to_be16(fdo_min); + + fan_table.HystDown = cpu_to_be16(hwmgr->thermal_controller.advanceFanControlParameters.ucTHyst); + + fan_table.HystUp = cpu_to_be16(1); + + fan_table.HystSlope = cpu_to_be16(1); + + fan_table.TempRespLim = cpu_to_be16(5); + + reference_clock = tonga_get_xclk(hwmgr); + + fan_table.RefreshPeriod = cpu_to_be32((hwmgr->thermal_controller.advanceFanControlParameters.ulCycleDelay * reference_clock) / 1600); + + fan_table.FdoMax = cpu_to_be16((uint16_t)duty100); + + fan_table.TempSrc = (uint8_t)PHM_READ_VFPF_INDIRECT_FIELD(hwmgr->device, CGS_IND_REG__SMC, CG_MULT_THERMAL_CTRL, TEMP_SEL); + + fan_table.FanControl_GL_Flag = 1; + + res = tonga_copy_bytes_to_smc(hwmgr->smumgr, data->fan_table_start, (uint8_t *)&fan_table, (uint32_t)sizeof(fan_table), data->sram_end); +/* TO DO FOR SOME DEVICE ID 0X692b, send this msg return invalid command. + if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit != 0) + res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanMinPwm, \ + hwmgr->thermal_controller.advanceFanControlParameters.ucMinimumPWMLimit) ? 0 : -1); + + if (res == 0 && hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit != 0) + res = (0 == smum_send_msg_to_smc_with_parameter(hwmgr->smumgr, PPSMC_MSG_SetFanSclkTarget, \ + hwmgr->thermal_controller.advanceFanControlParameters.ulMinFanSCLKAcousticLimit) ? 0 : -1); + + if (0 != res) + phm_cap_unset(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl); +*/ + return 0; +} + +/** +* Start the fan control on the SMC. +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_tonga_thermal_start_smc_fan_control(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ +/* If the fantable setup has failed we could have disabled PHM_PlatformCaps_MicrocodeFanControl even after this function was included in the table. + * Make sure that we still think controlling the fan is OK. +*/ + if (phm_cap_enabled(hwmgr->platform_descriptor.platformCaps, PHM_PlatformCaps_MicrocodeFanControl)) { + tonga_fan_ctrl_start_smc_fan_control(hwmgr); + tonga_fan_ctrl_set_static_mode(hwmgr, FDO_PWM_MODE_STATIC); + } + + return 0; +} + +/** +* Set temperature range for high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from set temperature range routine +*/ +int tf_tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ + struct PP_TemperatureRange *range = (struct PP_TemperatureRange *)input; + + if (range == NULL) + return -EINVAL; + + return tonga_thermal_set_temperature_range(hwmgr, range->min, range->max); +} + +/** +* Programs one-time setting registers +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from initialize thermal controller routine +*/ +int tf_tonga_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ + return tonga_thermal_initialize(hwmgr); +} + +/** +* Enable high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from enable alert routine +*/ +int tf_tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ + return tonga_thermal_enable_alert(hwmgr); +} + +/** +* Disable high and low alerts +* @param hwmgr the address of the powerplay hardware manager. +* @param pInput the pointer to input data +* @param pOutput the pointer to output data +* @param pStorage the pointer to temporary storage +* @param Result the last failure code +* @return result from disable alert routine +*/ +static int tf_tonga_thermal_disable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result) +{ + return tonga_thermal_disable_alert(hwmgr); +} + +static struct phm_master_table_item tonga_thermal_start_thermal_controller_master_list[] = { + { NULL, tf_tonga_thermal_initialize }, + { NULL, tf_tonga_thermal_set_temperature_range }, + { NULL, tf_tonga_thermal_enable_alert }, +/* We should restrict performance levels to low before we halt the SMC. + * On the other hand we are still in boot state when we do this so it would be pointless. + * If this assumption changes we have to revisit this table. + */ + { NULL, tf_tonga_thermal_setup_fan_table}, + { NULL, tf_tonga_thermal_start_smc_fan_control}, + { NULL, NULL } +}; + +static struct phm_master_table_header tonga_thermal_start_thermal_controller_master = { + 0, + PHM_MasterTableFlag_None, + tonga_thermal_start_thermal_controller_master_list +}; + +static struct phm_master_table_item tonga_thermal_set_temperature_range_master_list[] = { + { NULL, tf_tonga_thermal_disable_alert}, + { NULL, tf_tonga_thermal_set_temperature_range}, + { NULL, tf_tonga_thermal_enable_alert}, + { NULL, NULL } +}; + +struct phm_master_table_header tonga_thermal_set_temperature_range_master = { + 0, + PHM_MasterTableFlag_None, + tonga_thermal_set_temperature_range_master_list +}; + +int tonga_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr) +{ + if (!hwmgr->thermal_controller.fanInfo.bNoFan) + tonga_fan_ctrl_set_default_mode(hwmgr); + return 0; +} + +/** +* Initializes the thermal controller related functions in the Hardware Manager structure. +* @param hwmgr The address of the hardware manager. +* @exception Any error code from the low-level communication. +*/ +int pp_tonga_thermal_initialize(struct pp_hwmgr *hwmgr) +{ + int result; + + result = phm_construct_table(hwmgr, &tonga_thermal_set_temperature_range_master, &(hwmgr->set_temperature_range)); + + if (0 == result) { + result = phm_construct_table(hwmgr, + &tonga_thermal_start_thermal_controller_master, + &(hwmgr->start_thermal_controller)); + if (0 != result) + phm_destroy_table(hwmgr, &(hwmgr->set_temperature_range)); + } + + if (0 == result) + hwmgr->fan_ctrl_is_in_default_mode = true; + return result; +} + diff --git a/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h new file mode 100644 index 000000000000..aa335f267e25 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/hwmgr/tonga_thermal.h @@ -0,0 +1,61 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef TONGA_THERMAL_H +#define TONGA_THERMAL_H + +#include "hwmgr.h" + +#define TONGA_THERMAL_HIGH_ALERT_MASK 0x1 +#define TONGA_THERMAL_LOW_ALERT_MASK 0x2 + +#define TONGA_THERMAL_MINIMUM_TEMP_READING -256 +#define TONGA_THERMAL_MAXIMUM_TEMP_READING 255 + +#define TONGA_THERMAL_MINIMUM_ALERT_TEMP 0 +#define TONGA_THERMAL_MAXIMUM_ALERT_TEMP 255 + +#define FDO_PWM_MODE_STATIC 1 +#define FDO_PWM_MODE_STATIC_RPM 5 + + +extern int tf_tonga_thermal_initialize(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); +extern int tf_tonga_thermal_set_temperature_range(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); +extern int tf_tonga_thermal_enable_alert(struct pp_hwmgr *hwmgr, void *input, void *output, void *storage, int result); + +extern int tonga_thermal_get_temperature(struct pp_hwmgr *hwmgr); +extern int tonga_thermal_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern int tonga_fan_ctrl_get_fan_speed_info(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); +extern int tonga_fan_ctrl_get_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int tonga_fan_ctrl_set_default_mode(struct pp_hwmgr *hwmgr); +extern int tonga_fan_ctrl_set_static_mode(struct pp_hwmgr *hwmgr, uint32_t mode); +extern int tonga_fan_ctrl_set_fan_speed_percent(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int tonga_fan_ctrl_reset_fan_speed_to_default(struct pp_hwmgr *hwmgr); +extern int pp_tonga_thermal_initialize(struct pp_hwmgr *hwmgr); +extern int tonga_thermal_ctrl_uninitialize_thermal_controller(struct pp_hwmgr *hwmgr); +extern int tonga_fan_ctrl_set_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t speed); +extern int tonga_fan_ctrl_get_fan_speed_rpm(struct pp_hwmgr *hwmgr, uint32_t *speed); +extern int tonga_fan_ctrl_stop_smc_fan_control(struct pp_hwmgr *hwmgr); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h new file mode 100644 index 000000000000..e61a3e67852e --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/amd_powerplay.h @@ -0,0 +1,299 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _AMD_POWERPLAY_H_ +#define _AMD_POWERPLAY_H_ + +#include <linux/seq_file.h> +#include <linux/types.h> +#include <linux/errno.h> +#include "amd_shared.h" +#include "cgs_common.h" + +enum amd_pp_event { + AMD_PP_EVENT_INITIALIZE = 0, + AMD_PP_EVENT_UNINITIALIZE, + AMD_PP_EVENT_POWER_SOURCE_CHANGE, + AMD_PP_EVENT_SUSPEND, + AMD_PP_EVENT_RESUME, + AMD_PP_EVENT_ENTER_REST_STATE, + AMD_PP_EVENT_EXIT_REST_STATE, + AMD_PP_EVENT_DISPLAY_CONFIG_CHANGE, + AMD_PP_EVENT_THERMAL_NOTIFICATION, + AMD_PP_EVENT_VBIOS_NOTIFICATION, + AMD_PP_EVENT_ENTER_THERMAL_STATE, + AMD_PP_EVENT_EXIT_THERMAL_STATE, + AMD_PP_EVENT_ENTER_FORCED_STATE, + AMD_PP_EVENT_EXIT_FORCED_STATE, + AMD_PP_EVENT_ENTER_EXCLUSIVE_MODE, + AMD_PP_EVENT_EXIT_EXCLUSIVE_MODE, + AMD_PP_EVENT_ENTER_SCREEN_SAVER, + AMD_PP_EVENT_EXIT_SCREEN_SAVER, + AMD_PP_EVENT_VPU_RECOVERY_BEGIN, + AMD_PP_EVENT_VPU_RECOVERY_END, + AMD_PP_EVENT_ENABLE_POWER_PLAY, + AMD_PP_EVENT_DISABLE_POWER_PLAY, + AMD_PP_EVENT_CHANGE_POWER_SOURCE_UI_LABEL, + AMD_PP_EVENT_ENABLE_USER2D_PERFORMANCE, + AMD_PP_EVENT_DISABLE_USER2D_PERFORMANCE, + AMD_PP_EVENT_ENABLE_USER3D_PERFORMANCE, + AMD_PP_EVENT_DISABLE_USER3D_PERFORMANCE, + AMD_PP_EVENT_ENABLE_OVER_DRIVE_TEST, + AMD_PP_EVENT_DISABLE_OVER_DRIVE_TEST, + AMD_PP_EVENT_ENABLE_REDUCED_REFRESH_RATE, + AMD_PP_EVENT_DISABLE_REDUCED_REFRESH_RATE, + AMD_PP_EVENT_ENABLE_GFX_CLOCK_GATING, + AMD_PP_EVENT_DISABLE_GFX_CLOCK_GATING, + AMD_PP_EVENT_ENABLE_CGPG, + AMD_PP_EVENT_DISABLE_CGPG, + AMD_PP_EVENT_ENTER_TEXT_MODE, + AMD_PP_EVENT_EXIT_TEXT_MODE, + AMD_PP_EVENT_VIDEO_START, + AMD_PP_EVENT_VIDEO_STOP, + AMD_PP_EVENT_ENABLE_USER_STATE, + AMD_PP_EVENT_DISABLE_USER_STATE, + AMD_PP_EVENT_READJUST_POWER_STATE, + AMD_PP_EVENT_START_INACTIVITY, + AMD_PP_EVENT_STOP_INACTIVITY, + AMD_PP_EVENT_LINKED_ADAPTERS_READY, + AMD_PP_EVENT_ADAPTER_SAFE_TO_DISABLE, + AMD_PP_EVENT_COMPLETE_INIT, + AMD_PP_EVENT_CRITICAL_THERMAL_FAULT, + AMD_PP_EVENT_BACKLIGHT_CHANGED, + AMD_PP_EVENT_ENABLE_VARI_BRIGHT, + AMD_PP_EVENT_DISABLE_VARI_BRIGHT, + AMD_PP_EVENT_ENABLE_VARI_BRIGHT_ON_POWER_XPRESS, + AMD_PP_EVENT_DISABLE_VARI_BRIGHT_ON_POWER_XPRESS, + AMD_PP_EVENT_SET_VARI_BRIGHT_LEVEL, + AMD_PP_EVENT_VARI_BRIGHT_MONITOR_MEASUREMENT, + AMD_PP_EVENT_SCREEN_ON, + AMD_PP_EVENT_SCREEN_OFF, + AMD_PP_EVENT_PRE_DISPLAY_CONFIG_CHANGE, + AMD_PP_EVENT_ENTER_ULP_STATE, + AMD_PP_EVENT_EXIT_ULP_STATE, + AMD_PP_EVENT_REGISTER_IP_STATE, + AMD_PP_EVENT_UNREGISTER_IP_STATE, + AMD_PP_EVENT_ENTER_MGPU_MODE, + AMD_PP_EVENT_EXIT_MGPU_MODE, + AMD_PP_EVENT_ENTER_MULTI_GPU_MODE, + AMD_PP_EVENT_PRE_SUSPEND, + AMD_PP_EVENT_PRE_RESUME, + AMD_PP_EVENT_ENTER_BACOS, + AMD_PP_EVENT_EXIT_BACOS, + AMD_PP_EVENT_RESUME_BACO, + AMD_PP_EVENT_RESET_BACO, + AMD_PP_EVENT_PRE_DISPLAY_PHY_ACCESS, + AMD_PP_EVENT_POST_DISPLAY_PHY_CCESS, + AMD_PP_EVENT_START_COMPUTE_APPLICATION, + AMD_PP_EVENT_STOP_COMPUTE_APPLICATION, + AMD_PP_EVENT_REDUCE_POWER_LIMIT, + AMD_PP_EVENT_ENTER_FRAME_LOCK, + AMD_PP_EVENT_EXIT_FRAME_LOOCK, + AMD_PP_EVENT_LONG_IDLE_REQUEST_BACO, + AMD_PP_EVENT_LONG_IDLE_ENTER_BACO, + AMD_PP_EVENT_LONG_IDLE_EXIT_BACO, + AMD_PP_EVENT_HIBERNATE, + AMD_PP_EVENT_CONNECTED_STANDBY, + AMD_PP_EVENT_ENTER_SELF_REFRESH, + AMD_PP_EVENT_EXIT_SELF_REFRESH, + AMD_PP_EVENT_START_AVFS_BTC, + AMD_PP_EVENT_MAX +}; + +enum amd_dpm_forced_level { + AMD_DPM_FORCED_LEVEL_AUTO = 0, + AMD_DPM_FORCED_LEVEL_LOW = 1, + AMD_DPM_FORCED_LEVEL_HIGH = 2, +}; + +struct amd_pp_init { + struct cgs_device *device; + uint32_t chip_family; + uint32_t chip_id; + uint32_t rev_id; +}; +enum amd_pp_display_config_type{ + AMD_PP_DisplayConfigType_None = 0, + AMD_PP_DisplayConfigType_DP54 , + AMD_PP_DisplayConfigType_DP432 , + AMD_PP_DisplayConfigType_DP324 , + AMD_PP_DisplayConfigType_DP27, + AMD_PP_DisplayConfigType_DP243, + AMD_PP_DisplayConfigType_DP216, + AMD_PP_DisplayConfigType_DP162, + AMD_PP_DisplayConfigType_HDMI6G , + AMD_PP_DisplayConfigType_HDMI297 , + AMD_PP_DisplayConfigType_HDMI162, + AMD_PP_DisplayConfigType_LVDS, + AMD_PP_DisplayConfigType_DVI, + AMD_PP_DisplayConfigType_WIRELESS, + AMD_PP_DisplayConfigType_VGA +}; + +struct single_display_configuration +{ + uint32_t controller_index; + uint32_t controller_id; + uint32_t signal_type; + uint32_t display_state; + /* phy id for the primary internal transmitter */ + uint8_t primary_transmitter_phyi_d; + /* bitmap with the active lanes */ + uint8_t primary_transmitter_active_lanemap; + /* phy id for the secondary internal transmitter (for dual-link dvi) */ + uint8_t secondary_transmitter_phy_id; + /* bitmap with the active lanes */ + uint8_t secondary_transmitter_active_lanemap; + /* misc phy settings for SMU. */ + uint32_t config_flags; + uint32_t display_type; + uint32_t view_resolution_cx; + uint32_t view_resolution_cy; + enum amd_pp_display_config_type displayconfigtype; + uint32_t vertical_refresh; /* for active display */ +}; + +#define MAX_NUM_DISPLAY 32 + +struct amd_pp_display_configuration { + bool nb_pstate_switch_disable;/* controls NB PState switch */ + bool cpu_cc6_disable; /* controls CPU CState switch ( on or off) */ + bool cpu_pstate_disable; + uint32_t cpu_pstate_separation_time; + + uint32_t num_display; /* total number of display*/ + uint32_t num_path_including_non_display; + uint32_t crossfire_display_index; + uint32_t min_mem_set_clock; + uint32_t min_core_set_clock; + /* unit 10KHz x bit*/ + uint32_t min_bus_bandwidth; + /* minimum required stutter sclk, in 10khz uint32_t ulMinCoreSetClk;*/ + uint32_t min_core_set_clock_in_sr; + + struct single_display_configuration displays[MAX_NUM_DISPLAY]; + + uint32_t vrefresh; /* for active display*/ + + uint32_t min_vblank_time; /* for active display*/ + bool multi_monitor_in_sync; + /* Controller Index of primary display - used in MCLK SMC switching hang + * SW Workaround*/ + uint32_t crtc_index; + /* htotal*1000/pixelclk - used in MCLK SMC switching hang SW Workaround*/ + uint32_t line_time_in_us; + bool invalid_vblank_time; + + uint32_t display_clk; + /* + * for given display configuration if multimonitormnsync == false then + * Memory clock DPMS with this latency or below is allowed, DPMS with + * higher latency not allowed. + */ + uint32_t dce_tolerable_mclk_in_active_latency; +}; + +struct amd_pp_dal_clock_info { + uint32_t engine_max_clock; + uint32_t memory_max_clock; + uint32_t level; +}; + +enum { + PP_GROUP_UNKNOWN = 0, + PP_GROUP_GFX = 1, + PP_GROUP_SYS, + PP_GROUP_MAX +}; + +#define PP_GROUP_MASK 0xF0000000 +#define PP_GROUP_SHIFT 28 + +#define PP_BLOCK_MASK 0x0FFFFF00 +#define PP_BLOCK_SHIFT 8 + +#define PP_BLOCK_GFX_CG 0x01 +#define PP_BLOCK_GFX_MG 0x02 +#define PP_BLOCK_SYS_BIF 0x01 +#define PP_BLOCK_SYS_MC 0x02 +#define PP_BLOCK_SYS_ROM 0x04 +#define PP_BLOCK_SYS_DRM 0x08 +#define PP_BLOCK_SYS_HDP 0x10 +#define PP_BLOCK_SYS_SDMA 0x20 + +#define PP_STATE_MASK 0x0000000F +#define PP_STATE_SHIFT 0 +#define PP_STATE_SUPPORT_MASK 0x000000F0 +#define PP_STATE_SUPPORT_SHIFT 0 + +#define PP_STATE_CG 0x01 +#define PP_STATE_LS 0x02 +#define PP_STATE_DS 0x04 +#define PP_STATE_SD 0x08 +#define PP_STATE_SUPPORT_CG 0x10 +#define PP_STATE_SUPPORT_LS 0x20 +#define PP_STATE_SUPPORT_DS 0x40 +#define PP_STATE_SUPPORT_SD 0x80 + +#define PP_CG_MSG_ID(group, block, support, state) (group << PP_GROUP_SHIFT |\ + block << PP_BLOCK_SHIFT |\ + support << PP_STATE_SUPPORT_SHIFT |\ + state << PP_STATE_SHIFT) + +struct amd_powerplay_funcs { + int (*get_temperature)(void *handle); + int (*load_firmware)(void *handle); + int (*wait_for_fw_loading_complete)(void *handle); + int (*force_performance_level)(void *handle, enum amd_dpm_forced_level level); + enum amd_dpm_forced_level (*get_performance_level)(void *handle); + enum amd_pm_state_type (*get_current_power_state)(void *handle); + int (*get_sclk)(void *handle, bool low); + int (*get_mclk)(void *handle, bool low); + int (*powergate_vce)(void *handle, bool gate); + int (*powergate_uvd)(void *handle, bool gate); + int (*dispatch_tasks)(void *handle, enum amd_pp_event event_id, + void *input, void *output); + void (*print_current_performance_level)(void *handle, + struct seq_file *m); + int (*set_fan_control_mode)(void *handle, uint32_t mode); + int (*get_fan_control_mode)(void *handle); + int (*set_fan_speed_percent)(void *handle, uint32_t percent); + int (*get_fan_speed_percent)(void *handle, uint32_t *speed); +}; + +struct amd_powerplay { + void *pp_handle; + const struct amd_ip_funcs *ip_funcs; + const struct amd_powerplay_funcs *pp_funcs; +}; + +int amd_powerplay_init(struct amd_pp_init *pp_init, + struct amd_powerplay *amd_pp); +int amd_powerplay_fini(void *handle); + +int amd_powerplay_display_configuration_change(void *handle, const void *input); + +int amd_powerplay_get_display_power_level(void *handle, + struct amd_pp_dal_clock_info *output); + + +#endif /* _AMD_POWERPLAY_H_ */ diff --git a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h index 273616ab43db..9b698780aed8 100644 --- a/drivers/gpu/drm/amd/amdgpu/cz_ppsmc.h +++ b/drivers/gpu/drm/amd/powerplay/inc/cz_ppsmc.h @@ -164,6 +164,7 @@ enum DPM_ARRAY { #define PPSMC_MSG_SetLoggerAddressHigh ((uint16_t) 0x26C) #define PPSMC_MSG_SetLoggerAddressLow ((uint16_t) 0x26D) #define PPSMC_MSG_SetWatermarkFrequency ((uint16_t) 0x26E) +#define PPSMC_MSG_SetDisplaySizePowerParams ((uint16_t) 0x26F) /* REMOVE LATER*/ #define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h b/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h new file mode 100644 index 000000000000..b9d84de8a44d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/eventmanager.h @@ -0,0 +1,109 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _EVENT_MANAGER_H_ +#define _EVENT_MANAGER_H_ + +#include "power_state.h" +#include "pp_power_source.h" +#include "hardwaremanager.h" +#include "pp_asicblocks.h" + +struct pp_eventmgr; +enum amd_pp_event; + +enum PEM_EventDataValid { + PEM_EventDataValid_RequestedStateID = 0, + PEM_EventDataValid_RequestedUILabel, + PEM_EventDataValid_NewPowerState, + PEM_EventDataValid_RequestedPowerSource, + PEM_EventDataValid_RequestedClocks, + PEM_EventDataValid_CurrentTemperature, + PEM_EventDataValid_AsicBlocks, + PEM_EventDataValid_ODParameters, + PEM_EventDataValid_PXAdapterPrefs, + PEM_EventDataValid_PXUserPrefs, + PEM_EventDataValid_PXSwitchReason, + PEM_EventDataValid_PXSwitchPhase, + PEM_EventDataValid_HdVideo, + PEM_EventDataValid_BacklightLevel, + PEM_EventDatavalid_VariBrightParams, + PEM_EventDataValid_VariBrightLevel, + PEM_EventDataValid_VariBrightImmediateChange, + PEM_EventDataValid_PercentWhite, + PEM_EventDataValid_SdVideo, + PEM_EventDataValid_HTLinkChangeReason, + PEM_EventDataValid_HWBlocks, + PEM_EventDataValid_RequestedThermalState, + PEM_EventDataValid_MvcVideo, + PEM_EventDataValid_Max +}; + +typedef enum PEM_EventDataValid PEM_EventDataValid; + +/* Number of bits in ULONG variable */ +#define PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD (sizeof(unsigned long)*8) + +/* Number of ULONG entries used by event data valid bits */ +#define PEM_MAX_NUM_EVENTDATAVALID_ULONG_ENTRIES \ + ((PEM_EventDataValid_Max + PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD - 1) / \ + PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD) + +static inline void pem_set_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field) +{ + fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] |= + (1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); +} + +static inline void pem_unset_event_data_valid(unsigned long *fields, PEM_EventDataValid valid_field) +{ + fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] &= + ~(1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); +} + +static inline unsigned long pem_is_event_data_valid(const unsigned long *fields, PEM_EventDataValid valid_field) +{ + return fields[valid_field / PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD] & + (1UL << (valid_field % PEM_MAX_NUM_EVENTDATAVALID_BITS_PER_FIELD)); +} + +struct pem_event_data { + unsigned long valid_fields[100]; + unsigned long requested_state_id; + enum PP_StateUILabel requested_ui_label; + struct pp_power_state *pnew_power_state; + enum pp_power_source requested_power_source; + struct PP_Clocks requested_clocks; + bool skip_state_adjust_rules; + struct phm_asic_blocks asic_blocks; + /* to doPP_ThermalState requestedThermalState; + enum ThermalStateRequestSrc requestThermalStateSrc; + PP_Temperature currentTemperature;*/ + +}; + +int pem_handle_event(struct pp_eventmgr *eventmgr, enum amd_pp_event event, + struct pem_event_data *event_data); + +bool pem_is_hw_access_blocked(struct pp_eventmgr *eventmgr); + +#endif /* _EVENT_MANAGER_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h b/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h new file mode 100644 index 000000000000..10437dcfd365 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/eventmgr.h @@ -0,0 +1,125 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _EVENTMGR_H_ +#define _EVENTMGR_H_ + +#include <linux/mutex.h> +#include "pp_instance.h" +#include "hardwaremanager.h" +#include "eventmanager.h" +#include "pp_feature.h" +#include "pp_power_source.h" +#include "power_state.h" + +typedef int (*pem_event_action)(struct pp_eventmgr *eventmgr, + struct pem_event_data *event_data); + +struct action_chain { + const char *description; /* action chain description for debugging purpose */ + const pem_event_action **action_chain; /* pointer to chain of event actions */ +}; + +struct pem_power_source_ui_state_info { + enum PP_StateUILabel current_ui_label; + enum PP_StateUILabel default_ui_lable; + unsigned long configurable_ui_mapping; +}; + +struct pp_clock_range { + uint32_t min_sclk_khz; + uint32_t max_sclk_khz; + + uint32_t min_mclk_khz; + uint32_t max_mclk_khz; + + uint32_t min_vclk_khz; + uint32_t max_vclk_khz; + + uint32_t min_dclk_khz; + uint32_t max_dclk_khz; + + uint32_t min_aclk_khz; + uint32_t max_aclk_khz; + + uint32_t min_eclk_khz; + uint32_t max_eclk_khz; +}; + +enum pp_state { + UNINITIALIZED, + INACTIVE, + ACTIVE +}; + +enum pp_ring_index { + PP_RING_TYPE_GFX_INDEX = 0, + PP_RING_TYPE_DMA_INDEX, + PP_RING_TYPE_DMA1_INDEX, + PP_RING_TYPE_UVD_INDEX, + PP_RING_TYPE_VCE0_INDEX, + PP_RING_TYPE_VCE1_INDEX, + PP_RING_TYPE_CP1_INDEX, + PP_RING_TYPE_CP2_INDEX, + PP_NUM_RINGS, +}; + +struct pp_request { + uint32_t flags; + uint32_t sclk; + uint32_t sclk_throttle; + uint32_t mclk; + uint32_t vclk; + uint32_t dclk; + uint32_t eclk; + uint32_t aclk; + uint32_t iclk; + uint32_t vp8clk; + uint32_t rsv[32]; +}; + +struct pp_eventmgr { + struct pp_hwmgr *hwmgr; + struct pp_smumgr *smumgr; + + struct pp_feature_info features[PP_Feature_Max]; + const struct action_chain *event_chain[AMD_PP_EVENT_MAX]; + struct phm_platform_descriptor *platform_descriptor; + struct pp_clock_range clock_range; + enum pp_power_source current_power_source; + struct pem_power_source_ui_state_info ui_state_info[PP_PowerSource_Max]; + enum pp_state states[PP_NUM_RINGS]; + struct pp_request hi_req; + struct list_head context_list; + struct mutex lock; + bool block_adjust_power_state; + bool enable_cg; + bool enable_gfx_cgpg; + int (*pp_eventmgr_init)(struct pp_eventmgr *eventmgr); + void (*pp_eventmgr_fini)(struct pp_eventmgr *eventmgr); +}; + +int eventmgr_init(struct pp_instance *handle); +int eventmgr_fini(struct pp_eventmgr *eventmgr); + +#endif /* _EVENTMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h new file mode 100644 index 000000000000..7ae494569a60 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/fiji_ppsmc.h @@ -0,0 +1,412 @@ +/* + * Copyright 2015 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. + * + */ + + +#ifndef _FIJI_PP_SMC_H_ +#define _FIJI_PP_SMC_H_ + +#pragma pack(push, 1) + +#define PPSMC_SWSTATE_FLAG_DC 0x01 +#define PPSMC_SWSTATE_FLAG_UVD 0x02 +#define PPSMC_SWSTATE_FLAG_VCE 0x04 + +#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 +#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 +#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff + +#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 +#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 +#define PPSMC_SYSTEMFLAG_GDDR5 0x04 + +#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 + +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 +#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 + +/* Defines for DPM 2.0 */ +#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 +#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 +#define PPSMC_DPM2FLAGS_OCP 0x04 + +/* Defines for display watermark level */ +#define PPSMC_DISPLAY_WATERMARK_LOW 0 +#define PPSMC_DISPLAY_WATERMARK_HIGH 1 + +/* In the HW performance level's state flags: */ +#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 +#define PPSMC_STATEFLAG_POWERBOOST 0x02 +#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 +#define PPSMC_STATEFLAG_POWERSHIFT 0x08 +#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 +#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 +#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 + +/* Fan control algorithm: */ +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +/* Gemini Modes*/ +#define PPSMC_GeminiModeNone 0 /*Single GPU board*/ +#define PPSMC_GeminiModeMaster 1 /*Master GPU on a Gemini board*/ +#define PPSMC_GeminiModeSlave 2 /*Slave GPU on a Gemini board*/ + + +/* Return codes for driver to SMC communication. */ +#define PPSMC_Result_OK ((uint16_t)0x01) +#define PPSMC_Result_NoMore ((uint16_t)0x02) + +#define PPSMC_Result_NotNow ((uint16_t)0x03) + +#define PPSMC_Result_Failed ((uint16_t)0xFF) +#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) + +#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) + + +#define PPSMC_MSG_Halt ((uint16_t)0x10) +#define PPSMC_MSG_Resume ((uint16_t)0x11) +#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) +#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) +#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) +#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) +#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) +#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) +#define PPSMC_MSG_LevelUp ((uint16_t)0x18) +#define PPSMC_MSG_LevelDown ((uint16_t)0x19) +#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) +#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) + +#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) +#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) +#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) +#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) +#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) + +#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) +#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) +#define PPSMC_MSG_EnableCac ((uint16_t)0x53) +#define PPSMC_MSG_DisableCac ((uint16_t)0x54) +#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) +#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) +#define PPSMC_CACHistoryStart ((uint16_t)0x57) +#define PPSMC_CACHistoryStop ((uint16_t)0x58) +#define PPSMC_TDPClampingActive ((uint16_t)0x59) +#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) +#define PPSMC_StartFanControl ((uint16_t)0x5B) +#define PPSMC_StopFanControl ((uint16_t)0x5C) +#define PPSMC_NoDisplay ((uint16_t)0x5D) +#define PPSMC_HasDisplay ((uint16_t)0x5E) +#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) +#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) +#define PPSMC_MSG_EnableULV ((uint16_t)0x62) +#define PPSMC_MSG_DisableULV ((uint16_t)0x63) +#define PPSMC_MSG_EnterULV ((uint16_t)0x64) +#define PPSMC_MSG_ExitULV ((uint16_t)0x65) +#define PPSMC_PowerShiftActive ((uint16_t)0x6A) +#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) +#define PPSMC_OCPActive ((uint16_t)0x6C) +#define PPSMC_OCPInactive ((uint16_t)0x6D) +#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) +#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) +#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) +#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) +#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) +#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) +#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) +#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) +#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) +#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) +#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) +#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) +#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) +#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) +#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) +#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) + +#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) +#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) +#define PPSMC_FlushDataCache ((uint16_t)0x80) +#define PPSMC_FlushInstrCache ((uint16_t)0x81) + +#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) +#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) + +#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) + +#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) +#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) +#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) +#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) + +#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) + +#define PPSMC_MSG_BREAK ((uint16_t)0xF8) + +/* Trinity Specific Messages*/ +#define PPSMC_MSG_Test ((uint16_t) 0x100) +#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) +#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) +#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) +#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) +#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) +#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) +#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) +#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) +#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) +#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) +#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) +#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) +#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) +#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) +#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) +#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) +#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) +#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) +#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) +#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) +#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) +#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) +#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) +#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) +#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) +#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) +#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) +#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) +#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_VddNB_Request ((uint16_t) 0x125) +#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint32_t) 0x126) +#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint32_t) 0x127) +#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) + +#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) +#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) +#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) +#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) +#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) +#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) +#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) +#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) +#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) +#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) +#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) +#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) +#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) +#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) +#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) +#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) +#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) +#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) +#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) +#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) +#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) +#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) +#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) +#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) +#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) +#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) +#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) + +#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) +#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) + +#define PPSMC_MSG_DPM_Enable ((uint16_t) 0x14e) +#define PPSMC_MSG_DPM_Disable ((uint16_t) 0x14f) +#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t) 0x150) +#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t) 0x151) +#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t) 0x152) +#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t) 0x153) +#define PPSMC_MSG_UVDDPM_Enable ((uint16_t) 0x154) +#define PPSMC_MSG_UVDDPM_Disable ((uint16_t) 0x155) +#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t) 0x156) +#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t) 0x157) +#define PPSMC_MSG_ACPDPM_Enable ((uint16_t) 0x158) +#define PPSMC_MSG_ACPDPM_Disable ((uint16_t) 0x159) +#define PPSMC_MSG_VCEDPM_Enable ((uint16_t) 0x15a) +#define PPSMC_MSG_VCEDPM_Disable ((uint16_t) 0x15b) +#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t) 0x15c) +#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) +#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) +#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) +#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) +#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) +#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) +#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) +#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) +#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) +#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) +#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) +#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) +#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) +#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) +#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t) 0x16c) +#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t) 0x16d) +#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t) 0x16e) +#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t) 0x16f) +#define PPSMC_MSG_PmStatusLogStart ((uint16_t) 0x170) +#define PPSMC_MSG_PmStatusLogSample ((uint16_t) 0x171) +#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) +#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) +#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) +#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) +#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) +#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) +#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) +#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) +#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) +#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) +#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) +#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) +#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) +#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) +#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) +#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) +#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) +#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) +#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) +#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) +#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) +#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) +#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) +#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) +#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) +#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) +#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) +#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) +#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) +#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) +#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) +#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) +#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) +#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) +#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) +#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) +#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) +#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) +#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) +#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) +#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) + +#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) +#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) +#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) +#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) +#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) +#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) +#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) +#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) +#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) + +#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) +#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) +#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) +#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) +#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) +#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) +#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) + +#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) +#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) +#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) +#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) +#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) +#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) +#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) +#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) +#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) +#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) +#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) +#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) +#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) +#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) +#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) +#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) +#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) +#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) +#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) +#define PPSMC_MSG_EnableAvfs ((uint16_t) 0x26A) +#define PPSMC_MSG_DisableAvfs ((uint16_t) 0x26B) +#define PPSMC_MSG_PerformBtc ((uint16_t) 0x26C) +#define PPSMC_MSG_GetHbmCode ((uint16_t) 0x26D) +#define PPSMC_MSG_GetVrVddcTemperature ((uint16_t) 0x26E) +#define PPSMC_MSG_GetVrMvddTemperature ((uint16_t) 0x26F) +#define PPSMC_MSG_GetLiquidTemperature ((uint16_t) 0x270) +#define PPSMC_MSG_GetPlxTemperature ((uint16_t) 0x271) +#define PPSMC_MSG_RequestI2CControl ((uint16_t) 0x272) +#define PPSMC_MSG_ReleaseI2CControl ((uint16_t) 0x273) +#define PPSMC_MSG_LedConfig ((uint16_t) 0x274) +#define PPSMC_MSG_SetHbmFanCode ((uint16_t) 0x275) +#define PPSMC_MSG_SetHbmThrottleCode ((uint16_t) 0x276) + +#define PPSMC_MSG_GetEnabledPsm ((uint16_t) 0x400) +#define PPSMC_MSG_AgmStartPsm ((uint16_t) 0x401) +#define PPSMC_MSG_AgmReadPsm ((uint16_t) 0x402) +#define PPSMC_MSG_AgmResetPsm ((uint16_t) 0x403) +#define PPSMC_MSG_ReadVftCell ((uint16_t) 0x404) + +/* AVFS Only - Remove Later */ +#define PPSMC_MSG_VftTableIsValid ((uint16_t) 0x666) + +/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ +#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 +#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 +#define PPSMC_EVENT_STATUS_DC 0x00000004 + +typedef uint16_t PPSMC_Msg; + +#pragma pack(pop) + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h b/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h new file mode 100644 index 000000000000..0262ad35502a --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/fiji_pwrvirus.h @@ -0,0 +1,10299 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _FIJI_PWRVIRUS_H_ +#define _FIJI_PWRVIRUS_H_ + +#define mmCP_HYP_MEC1_UCODE_ADDR 0xf81a +#define mmCP_HYP_MEC1_UCODE_DATA 0xf81b +#define mmCP_HYP_MEC2_UCODE_ADDR 0xf81c +#define mmCP_HYP_MEC2_UCODE_DATA 0xf81d + +enum PWR_Command +{ + PwrCmdNull = 0, + PwrCmdWrite, + PwrCmdEnd, + PwrCmdMax +}; +typedef enum PWR_Command PWR_Command; + +struct PWR_Command_Table +{ + PWR_Command command; + ULONG data; + ULONG reg; +}; +typedef struct PWR_Command_Table PWR_Command_Table; + +#define PWR_VIRUS_TABLE_SIZE 10243 +static PWR_Command_Table PwrVirusTable[PWR_VIRUS_TABLE_SIZE] = +{ + { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX }, + { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, + { PwrCmdWrite, 0x100100b6, mmPCIE_INDEX }, + { PwrCmdWrite, 0x0300078c, mmPCIE_DATA }, + { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL }, + { PwrCmdWrite, 0x00000001, mmBIF_CLK_CTRL }, + { PwrCmdWrite, 0x00000000, mmBIF_CLK_CTRL }, + { PwrCmdWrite, 0x00000003, mmBIF_FB_EN }, + { PwrCmdWrite, 0x00000000, mmBIF_FB_EN }, + { PwrCmdWrite, 0x00000001, mmBIF_DOORBELL_APER_EN }, + { PwrCmdWrite, 0x00000000, mmBIF_DOORBELL_APER_EN }, + { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, + { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, + { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, + { PwrCmdWrite, 0x22000000, mmPCIE_DATA }, + { PwrCmdWrite, 0x014000c0, mmPCIE_INDEX }, + { PwrCmdWrite, 0x00000000, mmPCIE_DATA }, + /* + { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x00000000, mmMC_CITF_CNTL }, + { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET },*/ + { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_LO }, + { PwrCmdWrite, 0x00000000, mmRLC_CSIB_ADDR_HI }, + { PwrCmdWrite, 0x00000000, mmRLC_CSIB_LENGTH }, + /* + { PwrCmdWrite, 0x00000000, mmMC_VM_MX_L1_TLB_CNTL }, + { PwrCmdWrite, 0x00000001, mmMC_VM_SYSTEM_APERTURE_LOW_ADDR }, + { PwrCmdWrite, 0x00000000, mmMC_VM_SYSTEM_APERTURE_HIGH_ADDR }, + { PwrCmdWrite, 0x00000000, mmMC_VM_FB_LOCATION }, + { PwrCmdWrite, 0x009f0090, mmMC_VM_FB_LOCATION },*/ + { PwrCmdWrite, 0x00000000, mmVM_CONTEXT0_CNTL }, + { PwrCmdWrite, 0x00000000, mmVM_CONTEXT1_CNTL }, + /* + { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_BASE }, + { PwrCmdWrite, 0x00000002, mmMC_VM_AGP_BOT }, + { PwrCmdWrite, 0x00000000, mmMC_VM_AGP_TOP },*/ + { PwrCmdWrite, 0x04000000, mmATC_VM_APERTURE0_LOW_ADDR }, + { PwrCmdWrite, 0x0400ff20, mmATC_VM_APERTURE0_HIGH_ADDR }, + { PwrCmdWrite, 0x00000002, mmATC_VM_APERTURE0_CNTL }, + { PwrCmdWrite, 0x0000ffff, mmATC_VM_APERTURE0_CNTL2 }, + { PwrCmdWrite, 0x00000001, mmATC_VM_APERTURE1_LOW_ADDR }, + { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_HIGH_ADDR }, + { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL }, + { PwrCmdWrite, 0x00000000, mmATC_VM_APERTURE1_CNTL2 }, + //{ PwrCmdWrite, 0x00000000, mmMC_ARB_RAMCFG }, + { PwrCmdWrite, 0x12011003, mmGB_ADDR_CONFIG }, + { PwrCmdWrite, 0x00800010, mmGB_TILE_MODE0 }, + { PwrCmdWrite, 0x00800810, mmGB_TILE_MODE1 }, + { PwrCmdWrite, 0x00801010, mmGB_TILE_MODE2 }, + { PwrCmdWrite, 0x00801810, mmGB_TILE_MODE3 }, + { PwrCmdWrite, 0x00802810, mmGB_TILE_MODE4 }, + { PwrCmdWrite, 0x00802808, mmGB_TILE_MODE5 }, + { PwrCmdWrite, 0x00802814, mmGB_TILE_MODE6 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE7 }, + { PwrCmdWrite, 0x00000004, mmGB_TILE_MODE8 }, + { PwrCmdWrite, 0x02000008, mmGB_TILE_MODE9 }, + { PwrCmdWrite, 0x02000010, mmGB_TILE_MODE10 }, + { PwrCmdWrite, 0x06000014, mmGB_TILE_MODE11 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE12 }, + { PwrCmdWrite, 0x02400008, mmGB_TILE_MODE13 }, + { PwrCmdWrite, 0x02400010, mmGB_TILE_MODE14 }, + { PwrCmdWrite, 0x02400030, mmGB_TILE_MODE15 }, + { PwrCmdWrite, 0x06400014, mmGB_TILE_MODE16 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE17 }, + { PwrCmdWrite, 0x0040000c, mmGB_TILE_MODE18 }, + { PwrCmdWrite, 0x0100000c, mmGB_TILE_MODE19 }, + { PwrCmdWrite, 0x0100001c, mmGB_TILE_MODE20 }, + { PwrCmdWrite, 0x01000034, mmGB_TILE_MODE21 }, + { PwrCmdWrite, 0x01000024, mmGB_TILE_MODE22 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE23 }, + { PwrCmdWrite, 0x0040001c, mmGB_TILE_MODE24 }, + { PwrCmdWrite, 0x01000020, mmGB_TILE_MODE25 }, + { PwrCmdWrite, 0x01000038, mmGB_TILE_MODE26 }, + { PwrCmdWrite, 0x02c00008, mmGB_TILE_MODE27 }, + { PwrCmdWrite, 0x02c00010, mmGB_TILE_MODE28 }, + { PwrCmdWrite, 0x06c00014, mmGB_TILE_MODE29 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE30 }, + { PwrCmdWrite, 0x00000000, mmGB_TILE_MODE31 }, + { PwrCmdWrite, 0x000000a8, mmGB_MACROTILE_MODE0 }, + { PwrCmdWrite, 0x000000a4, mmGB_MACROTILE_MODE1 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE2 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE3 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE4 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE5 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE6 }, + { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE7 }, + { PwrCmdWrite, 0x000000ee, mmGB_MACROTILE_MODE8 }, + { PwrCmdWrite, 0x000000ea, mmGB_MACROTILE_MODE9 }, + { PwrCmdWrite, 0x000000e9, mmGB_MACROTILE_MODE10 }, + { PwrCmdWrite, 0x000000e5, mmGB_MACROTILE_MODE11 }, + { PwrCmdWrite, 0x000000e4, mmGB_MACROTILE_MODE12 }, + { PwrCmdWrite, 0x000000e0, mmGB_MACROTILE_MODE13 }, + { PwrCmdWrite, 0x00000090, mmGB_MACROTILE_MODE14 }, + { PwrCmdWrite, 0x00000000, mmGB_MACROTILE_MODE15 }, + { PwrCmdWrite, 0x00900000, mmHDP_NONSURFACE_BASE }, + { PwrCmdWrite, 0x00008000, mmHDP_NONSURFACE_INFO }, + { PwrCmdWrite, 0x3fffffff, mmHDP_NONSURFACE_SIZE }, + { PwrCmdWrite, 0x00000003, mmBIF_FB_EN }, + //{ PwrCmdWrite, 0x00000000, mmMC_VM_FB_OFFSET }, + { PwrCmdWrite, 0x00000000, mmSRBM_CNTL }, + { PwrCmdWrite, 0x00020000, mmSRBM_CNTL }, + { PwrCmdWrite, 0x80000000, mmATC_VMID0_PASID_MAPPING }, + { PwrCmdWrite, 0x00000000, mmATC_VMID_PASID_MAPPING_UPDATE_STATUS }, + { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, + { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, + { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, + { PwrCmdWrite, 0xe0000000, mmGRBM_GFX_INDEX }, + { PwrCmdWrite, 0x00000000, mmCGTS_TCC_DISABLE }, + { PwrCmdWrite, 0x00000000, mmTCP_ADDR_CONFIG }, + { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG }, + { PwrCmdWrite, 0x76543210, mmTCP_CHAN_STEER_LO }, + { PwrCmdWrite, 0xfedcba98, mmTCP_CHAN_STEER_HI }, + { PwrCmdWrite, 0x00000000, mmDB_DEBUG2 }, + { PwrCmdWrite, 0x00000000, mmDB_DEBUG }, + { PwrCmdWrite, 0x00002b16, mmCP_QUEUE_THRESHOLDS }, + { PwrCmdWrite, 0x00006030, mmCP_MEQ_THRESHOLDS }, + { PwrCmdWrite, 0x01000104, mmSPI_CONFIG_CNTL_1 }, + { PwrCmdWrite, 0x98184020, mmPA_SC_FIFO_SIZE }, + { PwrCmdWrite, 0x00000001, mmVGT_NUM_INSTANCES }, + { PwrCmdWrite, 0x00000000, mmCP_PERFMON_CNTL }, + { PwrCmdWrite, 0x01180000, mmSQ_CONFIG }, + { PwrCmdWrite, 0x00000000, mmVGT_CACHE_INVALIDATION }, + { PwrCmdWrite, 0x00000000, mmSQ_THREAD_TRACE_BASE }, + { PwrCmdWrite, 0x0000df80, mmSQ_THREAD_TRACE_MASK }, + { PwrCmdWrite, 0x02249249, mmSQ_THREAD_TRACE_MODE }, + { PwrCmdWrite, 0x00000000, mmPA_SC_LINE_STIPPLE_STATE }, + { PwrCmdWrite, 0x00000000, mmCB_PERFCOUNTER0_SELECT1 }, + { PwrCmdWrite, 0x06000100, mmCGTT_VGT_CLK_CTRL }, + { PwrCmdWrite, 0x00000007, mmPA_CL_ENHANCE }, + { PwrCmdWrite, 0x00000001, mmPA_SC_ENHANCE }, + { PwrCmdWrite, 0x00ffffff, mmPA_SC_FORCE_EOV_MAX_CNTS }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000010, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000020, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000030, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000040, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000050, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000060, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000070, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000080, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000090, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000a0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000b0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000c0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000d0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000e0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x000000f0, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmRLC_PG_CNTL }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS2 }, + { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL }, + { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x0000000e, mmSH_MEM_APE1_BASE }, + { PwrCmdWrite, 0x0000020d, mmSH_MEM_APE1_LIMIT }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000320, mmSH_MEM_CONFIG }, + { PwrCmdWrite, 0x00000000, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_RB_VMID }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, + { PwrCmdWrite, 0x00000000, mmRLC_CNTL }, + { PwrCmdWrite, 0x00000000, mmRLC_SRM_CNTL }, + { PwrCmdWrite, 0x00000002, mmRLC_SRM_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_ME_CNTL }, + { PwrCmdWrite, 0x15000000, mmCP_ME_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, + { PwrCmdWrite, 0x50000000, mmCP_MEC_CNTL }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x0840800a, mmCP_RB0_CNTL }, + { PwrCmdWrite, 0xf30fff0f, mmTCC_CTRL }, + { PwrCmdWrite, 0x00000002, mmTCC_EXE_DISABLE }, + { PwrCmdWrite, 0x000000ff, mmTCP_ADDR_CONFIG }, + { PwrCmdWrite, 0x540ff000, mmCP_CPC_IC_BASE_LO }, + { PwrCmdWrite, 0x000000b4, mmCP_CPC_IC_BASE_HI }, + { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC1_UCODE_ADDR }, + { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC1_UCODE_DATA }, + { PwrCmdWrite, 0x00010000, mmCP_HYP_MEC2_UCODE_ADDR }, + { PwrCmdWrite, 0x00041b75, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000710e8, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000910dd, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000a1081, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000b016f, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000c0e3c, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000d10ec, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000e0188, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00101b5d, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00150a6c, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00170c5e, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x001d0c8c, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x001e0cfe, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00221408, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00370d7b, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00390dcb, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x003c142f, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x003f0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00400e63, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00500f62, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00460fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00490fa7, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x005811d4, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00680ad6, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00760b00, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00780b0c, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00790af7, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x007d1aba, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x007e1abe, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00591260, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x005a12fb, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00861ac7, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x008c1b01, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x008d1b34, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a014b9, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a1152e, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a216fb, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a41890, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a31906, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00a50b14, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00621387, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x005c0b27, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x00160a75, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x000f016a, mmCP_HYP_MEC2_UCODE_DATA }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x540fe800, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e020201, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e040204, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e060205, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a080500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a0a0303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54106f00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000400b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00004000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00804fac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x540fef00, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0xc0031502, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00001e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x540ff000, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000145, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080061, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24ccffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3cd08000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1cd0ffcf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d018001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x050c0019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x84c00000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000067, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000006a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000006d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000008f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000099, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800000a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800000af, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x388c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08880002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98800003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000002d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d808001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc0700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0d000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000005d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14d00011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c01b10, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00e0080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00e0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x280c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x280c0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x280c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00052, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28180039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28080001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca88004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc00006f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28180080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d10c017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000013b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd4c0380, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdcc0388, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55dc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdcc038c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce0c0390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce0c0394, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce4c0398, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce4c039c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce8c03a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56a80020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce8c03a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcecc03a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcecc03ac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf0c03b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf0c03b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4c03b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57740020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4c03bc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8c03c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57b80020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8c03c4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfcc03c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57fc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfcc03cc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05dc002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc12009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d200a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc012009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25e01c00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25e40300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25e800c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25ec003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e25c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31100006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4df0388, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d7038c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d5dc01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4e30390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d70394, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d62001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4e70398, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d7039c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d66401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4eb03a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d6a801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ef03a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703ac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d6ec01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4f303b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d73001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4f703b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703bc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d77401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4fb03c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703c4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d7b801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ff03c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d703cc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d7fc01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4d70380, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0e0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0085, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc006a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc01e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3cd00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1c88001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc080000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400051, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04180018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aac0027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04080002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000367, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9880fff3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04080010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08880001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80c0309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80c0319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9880fffc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00e0100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d4001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x155c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e80180, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900091a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05280196, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d4fe04, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800001b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000032b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000350, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000352, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000035f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000701, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000047c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000019f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d98001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0044, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9400036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40005b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40005d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840006d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11540015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1998003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af0007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15dc000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d65400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a38003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd5c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7df1c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800045, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411326a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc415326b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293279, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000056, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00059, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c8000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40005a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29988000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000073, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25140fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153279, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd00005f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26f00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15100010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af07fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04343000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf413267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd1c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0160, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc810001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b4c0057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f4f400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55180020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af4007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33740003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26d80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ae8003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413348, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253348, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x958000d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000315, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04303000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26680001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1714000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25540800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x459801b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d77400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x199c01e2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e5c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000282, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc80c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1334e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01334f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd413350, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813351, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd881334d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153274, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cdcc011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05900008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd00006a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0006b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d594002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54d00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc12e23, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd012e24, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc12e25, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15540002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b340057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b280213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980198, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20cc003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01e0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2d540002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x078c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001239, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04f80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd5c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840007c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400069, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c018a6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4412e22, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800007c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c018a2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd4c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680fffc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800002e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000069, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9540188f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc013cfff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x38d00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdcc30000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c01882, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000304, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x49980198, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e40020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x459801a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000329, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16ec001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1998003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce00000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a18003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24dc00ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31e00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95801827, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14dc0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800006d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a0000ad, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04080000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af4003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740004d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca88005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24880001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f4b4009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313274, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d33400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1eecffdd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800003c3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aa80030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a8004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3272, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19e80042, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e8e800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de9c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3271, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50cc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ce8c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd30011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11e80007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd300001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240059, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1660001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e320009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0328000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e72400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0430000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02ac000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d310002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa87600, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280222, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4280058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x22ec003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8380018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57b00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04343108, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2374007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32a80003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800003e7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980104, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x49980104, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800003f2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813279, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf41326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x254c0700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a641fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0726, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a640200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1237b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8813260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4280034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c01755, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde830000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0174c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bb80040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100044, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19180024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x551c003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000043d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c8000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840006c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28200000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000043f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x282000f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x195c00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5e124dc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e624001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2555fff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980158, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x49980158, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980170, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16200010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x195400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1154000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e80488, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18f807f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e40077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ec0199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000048e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000494, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004de, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000685, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000686, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800006ac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ccc001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1264000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d79400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e7a400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52a8001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aec0028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004cc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419324e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26e8003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d324d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d290004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f8f4001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f52800f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50e00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004d1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0dc002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f534002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x6665fc00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004d7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aec003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3257, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12f4000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d75401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1c011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a644000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202c003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e804e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004e7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800004f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000505, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640fff4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26edf000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05a80507, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000050c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000528, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000057d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800005c2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800005f3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1be00fe4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000066, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400068, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c004d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00063b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000624, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bd400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ed6c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113271, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193272, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d51401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113274, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253276, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400061, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2730000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7db1800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00062, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000063, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400065, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b700057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b680213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46ec0188, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17e00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26e01000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c131fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x192007ec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x69dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de20014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x561c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013344, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13345, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800068, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2010007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd00001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2010003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x191807e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9540000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2511fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013344, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013345, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180050, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0052, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280042, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813273, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13275, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000068, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400067, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07d40000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00124f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x057c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46ec0190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2154003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bd800e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420004d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f598004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1be800e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801327a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800005f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000075, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424004c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a4004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x277401ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf41325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xda000068, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113277, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9540002d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425334d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419334e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d334f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213350, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253351, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b680057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b700213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b740199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46ec01b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1334a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1be000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0360001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc63124dc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80fff9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02ee000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fc14001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000697, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25100007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31100005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900008e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202c007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a9feff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d30b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce813265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00ac006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00e0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28880700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0006de, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14cc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30d4000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41530b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19980028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800006c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8380023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fa38011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd3800025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202400d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x194c00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c004c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27301fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce00005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cf0c00d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000712, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x194c1c03, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc0003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c002d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e80714, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000071c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000720, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000747, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000071d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800007c4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000732, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000745, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000744, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a64008c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b301fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000075e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0fff1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000723, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41f02f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000743, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0ffde, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000072e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0007e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84131db, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b301ff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8413260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc8000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x195800e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd80005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418004c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dd7fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1a001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46200200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04283247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af80057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af40213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6f400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc6990000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x329c325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x329c3269, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x329c3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01defff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d8009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000078a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fff2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03e7ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3f0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03e4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d30b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bf0003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000b80, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x203c003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf0130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46200008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2000025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31dc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ec0057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e40213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc0199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cecc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ce4c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000448, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31980002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19580066, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15600008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0120001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11980003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da18001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d24db, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580137b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00ee000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113269, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19080070, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x190c00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2518000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05a80809, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000080e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000080f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000898, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000946, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800009e1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04a80811, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000815, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000834, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3045, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c091, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000241, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02f0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4252087, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5668001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000084a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31300021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84002f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293059, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56a8001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00021d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001a41, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43b02f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec80278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56f00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8813247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000085e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x950001fa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02e0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aec0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a40006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de6000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10e40008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e2e000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d10ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2110003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d10ff9e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0245301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801325f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0121fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29108eff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0127ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0131fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e524009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013279, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0100010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd2400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0180003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd1c002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000866, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04a8089a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000089e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800008fa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000945, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31300022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x964012a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02620c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0260400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800008d2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000903, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31240022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ec30011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32f80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x67180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bfc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd981325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000915, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c1325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0fff6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f818001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001606, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d838001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16240014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a2801f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00075e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1330000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13f40014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33e80010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680ffec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04a80948, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000094c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000099b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800009e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x459801e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2738000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc79d3300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc7a13301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8393300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0260001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce793301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x964011fe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c028009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x242c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0260010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0260800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6e400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae8001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2f0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000978, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdf93300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce393301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dda801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e838011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001802, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x469c0390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4280011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0014df, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31280014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce8802ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800062, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31280034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04a809e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800009ec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a45, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a59, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d91801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e72401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b342010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x172c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b30c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef7400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x66740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04383000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b38007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x4598001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740002f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4002eb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4002ec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4002ed, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4002ee, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd84802e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001715, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04382000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffbc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04341001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431ecaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a55, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x233c0032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf0130b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49302ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5198001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193269, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2598000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80002f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53b8001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7db9801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000a5e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c01106, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c010fd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ce4c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc80c0072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x58e801fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc01e2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e4002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e5c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e540002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9540000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x44cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55900020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x44cc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd812e01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd012e02, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd412e03, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2264003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1e64001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14d00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ab1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a0010ac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd880003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d403f7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41b0367, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d85800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d001fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05280adc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000af1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000adf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ae7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd8d2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d803f7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc010ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0cc009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11940014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29544001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29544003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000af4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd44d2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd44dc000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000ace, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd8d2c00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000b0a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd44d2c00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28148004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4593240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0105e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef3400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14e80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a8000af, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c01043, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a01fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3620005c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2464003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc6290ce7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16ac001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ac003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ee6c00d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00fff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000367, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640102e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x199c0037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a00035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0005d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16f8001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9780000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc035f0ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e764009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19b401f8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13740008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x199c0034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ae4003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000b7c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a4003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc01e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13fc0018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dbd800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d98ff15, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x592c00fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd80000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12e00016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x592c007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12e00015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1264001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1620000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12e4001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5924007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a4003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013257, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd413258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00fdb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9780f5ca, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001b6d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07740003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x269c003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e4004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f67000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f674002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab8c006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000bec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000b47, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a8004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc415325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18580037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x262001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d54001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd280200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd680208, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcda80210, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc6930200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc6970208, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc69b0210, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd900003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd940003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9400040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14fc0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24f800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd88130b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d83c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4093249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1888003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000671, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419324c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1598001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14d80011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24e000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x321c0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580ffee, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c30, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9480000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800f29, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800f23, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800f1a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9600f502, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0f500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000f05, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1f30001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16e4001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640f4f4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33740002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40f4f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aec003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12ec001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1374000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02e4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1774000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00ac005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00e0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc8000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28884900, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ff3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400ee1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c40a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c40c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c40d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d0007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15580010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x255400ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c411, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c40f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c40e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c410, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e80033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ec0034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c414, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c415, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c413, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc0032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c030011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c038011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431c417, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435c416, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c419, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc418, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf413261, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013262, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13263, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813264, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc0030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d77000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51b80020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f97801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000cd6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ca7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc0031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435c40b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4280032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000cf4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc032800b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d42011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800e6c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x596001fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ce0c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x505c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e800c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x122c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000d1f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8240010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x566c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce413261, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec13262, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f8cc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000d57, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0328009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04143000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e51001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d2d0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19640057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19580213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19600199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da6400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04142000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd413267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4153267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d80034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05280d83, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000d8a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000db1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000d95, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000dbc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e010001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d75400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580f3d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x526c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e2ec01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5ae0073a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580f3c6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc3a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980fff5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01c405, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd441c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580f3b1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11540010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4610000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580f3a5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00da7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5aac007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12d80017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56a00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e82400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e58c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19d4003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20880188, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20240090, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd901a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841325f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ac0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ac0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b301ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2330003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0001a2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1910003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2220003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e2a000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00038, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d40030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18fc0034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24e8000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80e71, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000edd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e91, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ea1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000eaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e7c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e7f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e87, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000e8f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9e001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213262, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253261, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a200008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213264, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253263, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc820001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e82005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da1801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1800072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8180072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x59a001fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea2800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce80001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd180001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421c401, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425c401, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ee6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ede, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db09001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db09011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ebc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5a10000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5a50000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05280eea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f11, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f2e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000efe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f1f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0f26f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e80058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7daec01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5af8073a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eba800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0f25c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15980002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c405, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56240020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0f24e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c409, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40f247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce190000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0f240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439c040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2580, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac260c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0828, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2440, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac2390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac0093, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac31dc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31ac31e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ef2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac7c06, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db07c00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acc337, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0c330, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acc335, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0c336, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39acec70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db0ec6f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac9002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db09002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39ac9012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3db09012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ef1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b740008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c034001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c038001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f88, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e52401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1334000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24e02000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f63400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32240003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000f9d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51e40020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5a401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8280072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ac0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26f0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1af000fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13380016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e00039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e0007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1220001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e00074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fa3800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1c084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d001e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31140005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31140006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05280fb7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28140002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fc2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fbe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fd1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ff2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e80039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52a8003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d69401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140004b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d958004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d150005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x159c0011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31a00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31a40001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e25800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0fff5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fff4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000fef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d100010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01326f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc011000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33b40003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0340008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000ffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c908009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x282c2002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x208801a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000102f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1cccfe08, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00b33, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da2400f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da28002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1ac002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d2ac002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3ef40010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40f11d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde410000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdcc10000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd010000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd410000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdd810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xddc10000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde010000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c024001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100086, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5510003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001075, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15800f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15c002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d520002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cde0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e20001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001071, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c00036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00b01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc200000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc1c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc180000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc0c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc240000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc40003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4080029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a400e5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12500009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x248c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x200c006d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x200c0228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410002b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18881fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d4072c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc00d1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd4c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3094000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x38d80000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x311c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30940007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1620001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010c4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x259c007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a00030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x199c0fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010cb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000aac, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07a810d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000104c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x200c007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28240007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xde430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d3249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x192400fd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06681110, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19180070, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19100078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18f40058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001117, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001118, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000112d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001130, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001133, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24ec0f00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32ec0600, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000117b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc81c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55e00020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001122, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02a0200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e8e8009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x22a8003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x22a80074, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2774001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13740014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eb6800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25ecffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55700020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15f40010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13740002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x275c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15dc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39e00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc1c01e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e40008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e62000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001165, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc2001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1a0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e0d000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95000007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e02401e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06640008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05d80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc2401e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da58001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05e00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da2000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9600ffe6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00116b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce00001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81c078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x22640435, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0528117e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x312c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001185, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001182, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a0400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d81c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19a000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de2c00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc420007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011a3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d654001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c020001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011b6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253279, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc415326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2730003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3b380006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3f38000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0430000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb10004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e57000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e578002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d67c002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0be40001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d3a4002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x202c002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26200010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e640010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce81325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434002e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07a811cf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00feb8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x954009a7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000bfc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1c07c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c07d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c08c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c07e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18f0012f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18f40612, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc00c1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cf7400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x39600004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0140004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18fc003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9740001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011ee, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a6c003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800011e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ac007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab00030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aac0fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001205, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11600001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a2800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a0800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03ae000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a4000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81c07c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17fc001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30d00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000052, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640090f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19180038, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d324e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431324d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab0c006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000127f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d3258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313257, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab0c012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f67800f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53740002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ab42010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a8000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b740000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f6b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf40001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1514001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0012e1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x964008d7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9800036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300677, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012aa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b34060b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f37000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec00ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a8002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef6c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7edec00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4140032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1858003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0cc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0006c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d407f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2598003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d190004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d5d4001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d52000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d514002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d958001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd5c002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc1325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1ccc001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14f00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd980003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9800040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd9c00040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800010de, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800051, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc80003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24b00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18a800e5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1d980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7da9800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b74003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b304000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431326c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50700020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04e81324, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18ac0024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50600020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d71401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x596401fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b74008d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e76400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a640000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000132c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000133b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001344, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42530b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a68003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2024003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11980014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d19000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd0130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce4130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce40001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc428000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8240011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de6800f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffe0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00104f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28182002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340035, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140023, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d614011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4100026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05980008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1a0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb0800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3e280008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cb4800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20240030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ca48001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b4c00f8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28340000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x507c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30e40004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d7d401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x557c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28342002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c018001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf81a2a4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c007eb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d0d001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8100072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x591c01fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45140210, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x595801fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11980009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1624001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400069, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a307fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x23304076, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc00e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0015, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x4514020c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a2001e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a204001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a64003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1264001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15dc000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dcdc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5dc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340022, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4412e01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0434001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf430000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4412e40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c030, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41c031, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x248dfffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc12e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc812e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45140248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013257, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0434000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdb000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd140001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9980ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8200011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013259, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0337fff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f220009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d01c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f01c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c01c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c000d61, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50500020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd0c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd0c00072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8240072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd240001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19682011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5a6c01fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eeac00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4180011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfa0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4380007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d40038, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400029, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9540073d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18c80066, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30880001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x4220000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24e80007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24ec0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5310000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001465, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1000072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc82c0072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2c0001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18f02011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5aec01fc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12ec0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aec0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a8146a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1f0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001478, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f1b400e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000147a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f334002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000147b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e024001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000144a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fbfc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x251001ef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94800007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00187c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42c0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd910000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40d325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800012c2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13f4000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bf0060b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800014a9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d325a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0677, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb81ff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0328007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb7800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13fc0017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ffbc00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03a0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45dc0390, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04183000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c424001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c428001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c430001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c434001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04182000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd813267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a0800fd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x109c000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce080228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9880000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0ec75, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce480250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce880258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52a80020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x66580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc80260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec80288, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf080290, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec80298, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf0802a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4802a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27580001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc802b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80802b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x178c000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b8003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cf8c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8802c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc802c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8802d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf8802d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25b8ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd2800c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5230309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e3a400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001539, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd880353, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b0353, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd14005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000154f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd080238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd08034b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d200008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd900309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2198003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd910ce7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4190ce6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d918005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d918004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd810ce6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdd1054f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000156e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x090c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdcd050e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x040c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x110c0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc4001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41230a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41230b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41230c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc41230d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc480329, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc48032a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc4802e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d8003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09940001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x44100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x69100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000157f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970290, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b0288, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b02a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49f0298, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x041c0040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dcdc002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d924019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d26400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001579, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d010021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d914019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd480298, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd8802a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10d40010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12180016, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc51f0309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d95800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d62000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdd00309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce113320, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f02e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b02b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18dc01e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9400e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c0001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015aa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a302b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12240004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e5e400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ab02a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04100000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce4c0319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d9d8002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea14005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015bc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04240001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e624004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d25000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2620000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fff4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd0d3330, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce0802b8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd8802b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ab02e0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aa807f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f02d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49702d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b02c8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49f02c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96800028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d4e000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9600000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d964002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cde4002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de94001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd64002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d694001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00163f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800015cd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930238, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d698002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd4802d8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x129c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc50f0319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11a0000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1e000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1198000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd953300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e0e000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a8000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce953301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce100319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b70280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73800a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x536c0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9780eb68, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001609, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30b40000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b400011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b70258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53780020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb3801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7faf8019, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x67b40001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x57b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bb0260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fab8001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf880260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x66f40001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4353247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7f4009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fff7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x269c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a00018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a00060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x269c0018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a40060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11dc0006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29dc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de5c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b70228, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc80230, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f514005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2510000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001644, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd080240, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f130005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001688, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00120d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001219, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001232, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340801, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f130004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01051e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42d051f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ed2c005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96c0fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01051f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000055, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5170309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x195c07f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x196007f6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04340001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x6b740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001665, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a702a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ab0298, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f634014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e76401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8113320, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce480298, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce8802a0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc5170319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b702b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x255c000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f5f4001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8113330, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf4802b0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11340001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x195c07e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x196007ee, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8353300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1e4001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8353301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce4802d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8100309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8100319, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc48f0250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd4c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x64d80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580005c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd2000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc435324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7df5c00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800016f1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a7003e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a700064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800016df, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800016f2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd80802e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18fc0064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00042, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51980020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dd9801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x45980400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b380057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b340213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f7b400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f73400a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bf0258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a70250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53fc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e7e401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x667c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0aec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eebc00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x43300007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7db30011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd3000025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc03ec005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfca200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x192807fa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x203c003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0017f5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18fc01e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00185b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40ffd5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0ea24, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14d4001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d52400e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49f0258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a30250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51dc0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400017, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d534002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dae4005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000174f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b740001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00178a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40fff3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001608, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ab0268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7daa4005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32a0001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001765, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d1d0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2110007d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8013256, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c0017f2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd013254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4113248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b3034b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f13000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001855, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32a4001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8413247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd080260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce880268, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ffc0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ec28001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32e0001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253255, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431324f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e72400c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9680fff7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aa4003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aa400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32680003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a800046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4293260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1aa400e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800017e2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc027ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2e6400ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a4009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4240009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19e403e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26680003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12a80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19e400e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea68001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19e40064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x32640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06640003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a640003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800017d0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16a40005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce412082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea64002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4292083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ea68005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a80ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc429325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26a400ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40ffca, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2024007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800017e3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4a70280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4ab0278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52640020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7eae8014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e6a401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56680020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce480278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce880280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x042c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec80270, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800017fe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43b02eb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42302ec, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fa3801a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x47b8020c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x15e00008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1220000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2a206032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x513c001e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e3e001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4bf02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000180f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b3c0077, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1330000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd200000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4200007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd3800002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc30001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc1e0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04380032, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf80000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001427, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc413248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3269, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33fc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bfc0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd441326a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x173c0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300303, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3f0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ff3c004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001842, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdfc30000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4413249, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c43c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x23fc003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1326d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdf830000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd441326e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1fb8ffc6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xddc30000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf813265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001852, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c00142b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49f02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c00018, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c420001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c3000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c0012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001878, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41f02ed, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42302ee, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc13252, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013253, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e2a0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28340001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x313c0bcc, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x393c051f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d3c050e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x393c0560, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d3c054f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x393c1538, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d3c1537, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b740800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e8007c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c42c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a8189a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800018c5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800018f2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c414001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0007e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x50580020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d59401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc8140072, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09240002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c418001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4340004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc42130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a24002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2020002c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc418000d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1198001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14cc0004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7cd8c00a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc130b7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce0130b5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd1400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x5978073a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bb80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf800024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd800026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9600e8a8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9640e8a5, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800018a9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dad800c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0ffd2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fff9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x442c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940fff1, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x66d80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x56ec0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26240007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940fff7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc023007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19e4003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7de1c009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dee000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96000007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c13260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd901325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc421325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x261c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940fff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000189e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28cc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43d3265, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bc800ea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18e00064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06281911, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14f4001d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24cc0003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x86800000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001915, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x800019af, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001a2b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8000016a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc48032b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc480333, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc48033b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc480343, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98800011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b3c0057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e3e000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04180000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f438001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00068, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213254, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a1c003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00065, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc01f007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1e0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97800062, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0bb80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x43bc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fcbc001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc7df032b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1fc00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0101, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c0102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001994, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001982, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffcb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001995, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc1325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98800009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x41bc0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x53fc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e7fc011, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd3c00025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0012, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9bc0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x653c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dbd8001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ff8f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2bfc0008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x043c2000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcfc13267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c410001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc55b0309, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x3d5c0010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2598ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x05540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d91800c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580fff8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09780001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9580005d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400058, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dc24001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41d3248, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25dc000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7df9c00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95c00053, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e41c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a70003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a7000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33240003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a400046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1a7000e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001a21, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f270009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x266400ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27240003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12640004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e724001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06640002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001a0f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x16700005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e730002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4252083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e724005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x26640001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a40ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x267000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001a22, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ff9f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001a31, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8080280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213246, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4253245, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52200020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e26401a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x46640400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04203000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4213267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b180057, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b200213, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1b300199, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e1a000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e32000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce000024, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4970258, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4930250, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x51540020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4af0280, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4b30278, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x52ec0020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140020, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04280000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x65180001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800060, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x8c001628, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4193247, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x25980001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200101, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x30f00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95800056, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb0003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b800046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4393260, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bb000e4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001aa2, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc033ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2f3000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f3b0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf01325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b800ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4300009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9700fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f003e6, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27380003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13b80004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f000e8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07b80002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x19f00064, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33300002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0b300003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001a90, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x17b00005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf012082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01203f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x13300005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb30002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4392083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7fb38005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b80ffdf, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c00034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc00013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc431325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27300010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc439325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27b000ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b00ffca, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2030007b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf00325b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001aa3, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce01325d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04300001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7f2b0014, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ef2c01a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd2400025, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x4664001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000026, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400027, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x06a80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55100001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ff9c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc49b02e9, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99800008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc430000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2b300008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf000013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04302000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcf013267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc4313267, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x244c00ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc4c0200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc44f0200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc410000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d158010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x059cc000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccdd0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0037, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000049, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c003a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500e69a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d0003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d40021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd840004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c003c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x14cc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c00028, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000033, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc438000b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0009, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x27fc0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43dc07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1bfc0078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7ffbc00c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x97c0fffd, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x99000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0120840, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x282c0040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001ae8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0121841, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x282c001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c07c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c08c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c079, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c07e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcec0001b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a200001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9a00ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x166c001f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04200004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9ac0fffb, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc434000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9b40ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc425c07f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8000034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940e66b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800004a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0036, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9900fffe, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18cc0021, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc00047, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc000046, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0039, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c003d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c40c001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24d003ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d47fea, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x18d87ff4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd00004c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd40004e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd80004d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c405, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc02a0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2aa80001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c406, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc414000e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x29540008, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x295c0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8c1325e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcdc0001a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11980002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x4110000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0160800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7d15000a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0164010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c080, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c081, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c082, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc01c083, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c084, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x98c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400048, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c003b, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x94c0ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000c16, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c40a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd901c40d, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c410, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c40e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd801c40f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc40c0040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x09540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9940ffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04140096, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8400013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1c400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc411c401, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9500fffa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424003e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04d00001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x11100002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd01c40c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0180034, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd81c411, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd841c414, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0a540001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcd41c412, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x2468000f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc419c416, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x41980003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc41c003f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7dda0001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x12200002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x10cc0002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xccc1c40c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd901c411, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce41c412, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd8800013, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xce292e40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e01, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e02, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e03, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc412e00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000aa7, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc43c0007, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc120000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x31144000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x95400005, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xdc030000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd800002a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xcc3c000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b70, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x33f80003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd4400078, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x9780e601, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x188cfff0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x04e40002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001190, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400006, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x90000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc424005e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x96400003, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7c408001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x88000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80001b74, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000168, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110501, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120206, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130703, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92100400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92110105, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92120602, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x92130307, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x54106500, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0x7e000200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e020204, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc00a0505, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbf8c007f, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb8900904, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb8911a04, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb8920304, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb8930b44, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x921c0d0c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x921c1c13, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x921d0c12, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x811c1d1c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x811c111c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x921cff1c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000400, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x921dff10, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000100, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x81181d1c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e040218, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0701000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050102, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xe0501000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80050302, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x54106900, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0x7e080200, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x7e100204, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbefc00ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00010000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x24200087, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x262200ff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000001f0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x20222282, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x28182111, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000040c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd81a0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000080c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xd86c0000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x1100000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xbf810000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x80000004, mmCP_DFY_CNTL }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_ADDR_HI }, + { PwrCmdWrite, 0x54116f00, mmCP_DFY_ADDR_LO }, + { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4540fe8, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000041, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000000c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54116f00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb454105e, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000c0, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54117300, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4541065, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000500, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000001c, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54117700, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xc0310800, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000040, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4541069, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000444, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x0000008a, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x07808000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xffffffff, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000002, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xaaaaaaaa, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x55555555, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee40, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000010, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000001, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000004, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x54117b00, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00005301, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0xb4540fef, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x540fee20, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x000000b4, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x08000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_DFY_DATA_0 }, + { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_MEC_CNTL }, + { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x54116f00, mmCP_MQD_BASE_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, + { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x54117300, mmCP_MQD_BASE_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, + { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x54117700, mmCP_MQD_BASE_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, + { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x54117b00, mmCP_MQD_BASE_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_MQD_BASE_ADDR_HI }, + { PwrCmdWrite, 0xb4540fef, mmCP_HQD_PQ_BASE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_BASE_HI }, + { PwrCmdWrite, 0x540fee20, mmCP_HQD_PQ_WPTR_POLL_ADDR }, + { PwrCmdWrite, 0x000000b4, mmCP_HQD_PQ_WPTR_POLL_ADDR_HI }, + { PwrCmdWrite, 0x00005301, mmCP_HQD_PERSISTENT_STATE }, + { PwrCmdWrite, 0x00010000, mmCP_HQD_VMID }, + { PwrCmdWrite, 0xc8318509, mmCP_HQD_PQ_CONTROL }, + { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000104, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000204, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000304, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000404, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000504, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000604, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000704, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000005, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000105, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000205, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000305, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000405, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000505, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000605, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000705, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000006, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000106, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000206, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000306, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000406, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000506, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000606, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000706, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000007, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000107, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000207, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000307, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000407, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000507, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000607, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000707, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000008, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000108, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000208, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000308, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000408, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000508, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000608, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000708, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000009, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000109, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000209, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000309, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000409, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000509, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000609, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000709, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_RPTR }, + { PwrCmdWrite, 0x00000000, mmCP_HQD_PQ_WPTR }, + { PwrCmdWrite, 0x00000001, mmCP_HQD_ACTIVE }, + { PwrCmdWrite, 0x00000004, mmSRBM_GFX_CNTL }, + { PwrCmdWrite, 0x01010101, mmCP_PQ_WPTR_POLL_CNTL1 }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdWrite, 0x00000000, mmGRBM_STATUS }, + { PwrCmdEnd, 0x00000000, 0x00000000 }, +}; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h new file mode 100644 index 000000000000..a503306c3d0e --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/hardwaremanager.h @@ -0,0 +1,383 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _HARDWARE_MANAGER_H_ +#define _HARDWARE_MANAGER_H_ + + + +struct pp_hwmgr; +struct pp_hw_power_state; +struct pp_power_state; +enum amd_dpm_forced_level; +struct PP_TemperatureRange; + +struct phm_fan_speed_info { + uint32_t min_percent; + uint32_t max_percent; + uint32_t min_rpm; + uint32_t max_rpm; + bool supports_percent_read; + bool supports_percent_write; + bool supports_rpm_read; + bool supports_rpm_write; +}; + +/* Automatic Power State Throttling */ +enum PHM_AutoThrottleSource +{ + PHM_AutoThrottleSource_Thermal, + PHM_AutoThrottleSource_External +}; + +typedef enum PHM_AutoThrottleSource PHM_AutoThrottleSource; + +enum phm_platform_caps { + PHM_PlatformCaps_AtomBiosPpV1 = 0, + PHM_PlatformCaps_PowerPlaySupport, + PHM_PlatformCaps_ACOverdriveSupport, + PHM_PlatformCaps_BacklightSupport, + PHM_PlatformCaps_ThermalController, + PHM_PlatformCaps_BiosPowerSourceControl, + PHM_PlatformCaps_DisableVoltageTransition, + PHM_PlatformCaps_DisableEngineTransition, + PHM_PlatformCaps_DisableMemoryTransition, + PHM_PlatformCaps_DynamicPowerManagement, + PHM_PlatformCaps_EnableASPML0s, + PHM_PlatformCaps_EnableASPML1, + PHM_PlatformCaps_OD5inACSupport, + PHM_PlatformCaps_OD5inDCSupport, + PHM_PlatformCaps_SoftStateOD5, + PHM_PlatformCaps_NoOD5Support, + PHM_PlatformCaps_ContinuousHardwarePerformanceRange, + PHM_PlatformCaps_ActivityReporting, + PHM_PlatformCaps_EnableBackbias, + PHM_PlatformCaps_OverdriveDisabledByPowerBudget, + PHM_PlatformCaps_ShowPowerBudgetWarning, + PHM_PlatformCaps_PowerBudgetWaiverAvailable, + PHM_PlatformCaps_GFXClockGatingSupport, + PHM_PlatformCaps_MMClockGatingSupport, + PHM_PlatformCaps_AutomaticDCTransition, + PHM_PlatformCaps_GeminiPrimary, + PHM_PlatformCaps_MemorySpreadSpectrumSupport, + PHM_PlatformCaps_EngineSpreadSpectrumSupport, + PHM_PlatformCaps_StepVddc, + PHM_PlatformCaps_DynamicPCIEGen2Support, + PHM_PlatformCaps_SMC, + PHM_PlatformCaps_FaultyInternalThermalReading, /* Internal thermal controller reports faulty temperature value when DAC2 is active */ + PHM_PlatformCaps_EnableVoltageControl, /* indicates voltage can be controlled */ + PHM_PlatformCaps_EnableSideportControl, /* indicates Sideport can be controlled */ + PHM_PlatformCaps_VideoPlaybackEEUNotification, /* indicates EEU notification of video start/stop is required */ + PHM_PlatformCaps_TurnOffPll_ASPML1, /* PCIE Turn Off PLL in ASPM L1 */ + PHM_PlatformCaps_EnableHTLinkControl, /* indicates HT Link can be controlled by ACPI or CLMC overrided/automated mode. */ + PHM_PlatformCaps_PerformanceStateOnly, /* indicates only performance power state to be used on current system. */ + PHM_PlatformCaps_ExclusiveModeAlwaysHigh, /* In Exclusive (3D) mode always stay in High state. */ + PHM_PlatformCaps_DisableMGClockGating, /* to disable Medium Grain Clock Gating or not */ + PHM_PlatformCaps_DisableMGCGTSSM, /* TO disable Medium Grain Clock Gating Shader Complex control */ + PHM_PlatformCaps_UVDAlwaysHigh, /* In UVD mode always stay in High state */ + PHM_PlatformCaps_DisablePowerGating, /* to disable power gating */ + PHM_PlatformCaps_CustomThermalPolicy, /* indicates only performance power state to be used on current system. */ + PHM_PlatformCaps_StayInBootState, /* Stay in Boot State, do not do clock/voltage or PCIe Lane and Gen switching (RV7xx and up). */ + PHM_PlatformCaps_SMCAllowSeparateSWThermalState, /* SMC use separate SW thermal state, instead of the default SMC thermal policy. */ + PHM_PlatformCaps_MultiUVDStateSupport, /* Powerplay state table supports multi UVD states. */ + PHM_PlatformCaps_EnableSCLKDeepSleepForUVD, /* With HW ECOs, we don't need to disable SCLK Deep Sleep for UVD state. */ + PHM_PlatformCaps_EnableMCUHTLinkControl, /* Enable HT link control by MCU */ + PHM_PlatformCaps_ABM, /* ABM support.*/ + PHM_PlatformCaps_KongThermalPolicy, /* A thermal policy specific for Kong */ + PHM_PlatformCaps_SwitchVDDNB, /* if the users want to switch VDDNB */ + PHM_PlatformCaps_ULPS, /* support ULPS mode either through ACPI state or ULPS state */ + PHM_PlatformCaps_NativeULPS, /* hardware capable of ULPS state (other than through the ACPI state) */ + PHM_PlatformCaps_EnableMVDDControl, /* indicates that memory voltage can be controlled */ + PHM_PlatformCaps_ControlVDDCI, /* Control VDDCI separately from VDDC. */ + PHM_PlatformCaps_DisableDCODT, /* indicates if DC ODT apply or not */ + PHM_PlatformCaps_DynamicACTiming, /* if the SMC dynamically re-programs MC SEQ register values */ + PHM_PlatformCaps_EnableThermalIntByGPIO, /* enable throttle control through GPIO */ + PHM_PlatformCaps_BootStateOnAlert, /* Go to boot state on alerts, e.g. on an AC->DC transition. */ + PHM_PlatformCaps_DontWaitForVBlankOnAlert, /* Do NOT wait for VBLANK during an alert (e.g. AC->DC transition). */ + PHM_PlatformCaps_Force3DClockSupport, /* indicates if the platform supports force 3D clock. */ + PHM_PlatformCaps_MicrocodeFanControl, /* Fan is controlled by the SMC microcode. */ + PHM_PlatformCaps_AdjustUVDPriorityForSP, + PHM_PlatformCaps_DisableLightSleep, /* Light sleep for evergreen family. */ + PHM_PlatformCaps_DisableMCLS, /* MC Light sleep */ + PHM_PlatformCaps_RegulatorHot, /* Enable throttling on 'regulator hot' events. */ + PHM_PlatformCaps_BACO, /* Support Bus Alive Chip Off mode */ + PHM_PlatformCaps_DisableDPM, /* Disable DPM, supported from Llano */ + PHM_PlatformCaps_DynamicM3Arbiter, /* support dynamically change m3 arbitor parameters */ + PHM_PlatformCaps_SclkDeepSleep, /* support sclk deep sleep */ + PHM_PlatformCaps_DynamicPatchPowerState, /* this ASIC supports to patch power state dynamically */ + PHM_PlatformCaps_ThermalAutoThrottling, /* enabling auto thermal throttling, */ + PHM_PlatformCaps_SumoThermalPolicy, /* A thermal policy specific for Sumo */ + PHM_PlatformCaps_PCIEPerformanceRequest, /* support to change RC voltage */ + PHM_PlatformCaps_BLControlledByGPU, /* support varibright */ + PHM_PlatformCaps_PowerContainment, /* support DPM2 power containment (AKA TDP clamping) */ + PHM_PlatformCaps_SQRamping, /* support DPM2 SQ power throttle */ + PHM_PlatformCaps_CAC, /* support Capacitance * Activity power estimation */ + PHM_PlatformCaps_NIChipsets, /* Northern Island and beyond chipsets */ + PHM_PlatformCaps_TrinityChipsets, /* Trinity chipset */ + PHM_PlatformCaps_EvergreenChipsets, /* Evergreen family chipset */ + PHM_PlatformCaps_PowerControl, /* Cayman and beyond chipsets */ + PHM_PlatformCaps_DisableLSClockGating, /* to disable Light Sleep control for HDP memories */ + PHM_PlatformCaps_BoostState, /* this ASIC supports boost state */ + PHM_PlatformCaps_UserMaxClockForMultiDisplays, /* indicates if max memory clock is used for all status when multiple displays are connected */ + PHM_PlatformCaps_RegWriteDelay, /* indicates if back to back reg write delay is required */ + PHM_PlatformCaps_NonABMSupportInPPLib, /* ABM is not supported in PPLIB, (moved from PPLIB to DAL) */ + PHM_PlatformCaps_GFXDynamicMGPowerGating, /* Enable Dynamic MG PowerGating on Trinity */ + PHM_PlatformCaps_DisableSMUUVDHandshake, /* Disable SMU UVD Handshake */ + PHM_PlatformCaps_DTE, /* Support Digital Temperature Estimation */ + PHM_PlatformCaps_W5100Specifc_SmuSkipMsgDTE, /* This is for the feature requested by David B., and Tonny W.*/ + PHM_PlatformCaps_UVDPowerGating, /* enable UVD power gating, supported from Llano */ + PHM_PlatformCaps_UVDDynamicPowerGating, /* enable UVD Dynamic power gating, supported from UVD5 */ + PHM_PlatformCaps_VCEPowerGating, /* Enable VCE power gating, supported for TN and later ASICs */ + PHM_PlatformCaps_SamuPowerGating, /* Enable SAMU power gating, supported for KV and later ASICs */ + PHM_PlatformCaps_UVDDPM, /* UVD clock DPM */ + PHM_PlatformCaps_VCEDPM, /* VCE clock DPM */ + PHM_PlatformCaps_SamuDPM, /* SAMU clock DPM */ + PHM_PlatformCaps_AcpDPM, /* ACP clock DPM */ + PHM_PlatformCaps_SclkDeepSleepAboveLow, /* Enable SCLK Deep Sleep on all DPM states */ + PHM_PlatformCaps_DynamicUVDState, /* Dynamic UVD State */ + PHM_PlatformCaps_WantSAMClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ + PHM_PlatformCaps_WantUVDClkWithDummyBackEnd, /* Set UVD Clk With Dummy Back End */ + PHM_PlatformCaps_WantVCEClkWithDummyBackEnd, /* Set VCE Clk With Dummy Back End */ + PHM_PlatformCaps_WantACPClkWithDummyBackEnd, /* Set SAM Clk With Dummy Back End */ + PHM_PlatformCaps_OD6inACSupport, /* indicates that the ASIC/back end supports OD6 */ + PHM_PlatformCaps_OD6inDCSupport, /* indicates that the ASIC/back end supports OD6 in DC */ + PHM_PlatformCaps_EnablePlatformPowerManagement, /* indicates that Platform Power Management feature is supported */ + PHM_PlatformCaps_SurpriseRemoval, /* indicates that surprise removal feature is requested */ + PHM_PlatformCaps_NewCACVoltage, /* indicates new CAC voltage table support */ + PHM_PlatformCaps_DBRamping, /* for dI/dT feature */ + PHM_PlatformCaps_TDRamping, /* for dI/dT feature */ + PHM_PlatformCaps_TCPRamping, /* for dI/dT feature */ + PHM_PlatformCaps_EnableSMU7ThermalManagement, /* SMC will manage thermal events */ + PHM_PlatformCaps_FPS, /* FPS support */ + PHM_PlatformCaps_ACP, /* ACP support */ + PHM_PlatformCaps_SclkThrottleLowNotification, /* SCLK Throttle Low Notification */ + PHM_PlatformCaps_XDMAEnabled, /* XDMA engine is enabled */ + PHM_PlatformCaps_UseDummyBackEnd, /* use dummy back end */ + PHM_PlatformCaps_EnableDFSBypass, /* Enable DFS bypass */ + PHM_PlatformCaps_VddNBDirectRequest, + PHM_PlatformCaps_PauseMMSessions, + PHM_PlatformCaps_UnTabledHardwareInterface, /* Tableless/direct call hardware interface for CI and newer ASICs */ + PHM_PlatformCaps_SMU7, /* indicates that vpuRecoveryBegin without SMU shutdown */ + PHM_PlatformCaps_RevertGPIO5Polarity, /* indicates revert GPIO5 plarity table support */ + PHM_PlatformCaps_Thermal2GPIO17, /* indicates thermal2GPIO17 table support */ + PHM_PlatformCaps_ThermalOutGPIO, /* indicates ThermalOutGPIO support, pin number is assigned by VBIOS */ + PHM_PlatformCaps_DisableMclkSwitchingForFrameLock, /* Disable memory clock switch during Framelock */ + PHM_PlatformCaps_VRHotGPIOConfigurable, /* indicates VR_HOT GPIO configurable */ + PHM_PlatformCaps_TempInversion, /* enable Temp Inversion feature */ + PHM_PlatformCaps_IOIC3, + PHM_PlatformCaps_ConnectedStandby, + PHM_PlatformCaps_EVV, + PHM_PlatformCaps_EnableLongIdleBACOSupport, + PHM_PlatformCaps_CombinePCCWithThermalSignal, + PHM_PlatformCaps_DisableUsingActualTemperatureForPowerCalc, + PHM_PlatformCaps_StablePState, + PHM_PlatformCaps_OD6PlusinACSupport, + PHM_PlatformCaps_OD6PlusinDCSupport, + PHM_PlatformCaps_ODThermalLimitUnlock, + PHM_PlatformCaps_ReducePowerLimit, + PHM_PlatformCaps_ODFuzzyFanControlSupport, + PHM_PlatformCaps_GeminiRegulatorFanControlSupport, + PHM_PlatformCaps_ControlVDDGFX, + PHM_PlatformCaps_BBBSupported, + PHM_PlatformCaps_DisableVoltageIsland, + PHM_PlatformCaps_FanSpeedInTableIsRPM, + PHM_PlatformCaps_GFXClockGatingManagedInCAIL, + PHM_PlatformCaps_IcelandULPSSWWorkAround, + PHM_PlatformCaps_FPSEnhancement, + PHM_PlatformCaps_LoadPostProductionFirmware, + PHM_PlatformCaps_VpuRecoveryInProgress, + PHM_PlatformCaps_Falcon_QuickTransition, + PHM_PlatformCaps_AVFS, + PHM_PlatformCaps_ClockStretcher, + PHM_PlatformCaps_TablelessHardwareInterface, + PHM_PlatformCaps_EnableDriverEVV, + PHM_PlatformCaps_Max +}; + +#define PHM_MAX_NUM_CAPS_BITS_PER_FIELD (sizeof(uint32_t)*8) + +/* Number of uint32_t entries used by CAPS table */ +#define PHM_MAX_NUM_CAPS_ULONG_ENTRIES \ + ((PHM_PlatformCaps_Max + ((PHM_MAX_NUM_CAPS_BITS_PER_FIELD) - 1)) / (PHM_MAX_NUM_CAPS_BITS_PER_FIELD)) + +struct pp_hw_descriptor { + uint32_t hw_caps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; +}; + +enum PHM_PerformanceLevelDesignation { + PHM_PerformanceLevelDesignation_Activity, + PHM_PerformanceLevelDesignation_PowerContainment +}; + +typedef enum PHM_PerformanceLevelDesignation PHM_PerformanceLevelDesignation; + +struct PHM_PerformanceLevel { + uint32_t coreClock; + uint32_t memory_clock; + uint32_t vddc; + uint32_t vddci; + uint32_t nonLocalMemoryFreq; + uint32_t nonLocalMemoryWidth; +}; + +typedef struct PHM_PerformanceLevel PHM_PerformanceLevel; + +/* Function for setting a platform cap */ +static inline void phm_cap_set(uint32_t *caps, + enum phm_platform_caps c) +{ + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] |= (1UL << + (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); +} + +static inline void phm_cap_unset(uint32_t *caps, + enum phm_platform_caps c) +{ + caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] &= ~(1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))); +} + +static inline bool phm_cap_enabled(const uint32_t *caps, enum phm_platform_caps c) +{ + return (0 != (caps[c / PHM_MAX_NUM_CAPS_BITS_PER_FIELD] & + (1UL << (c & (PHM_MAX_NUM_CAPS_BITS_PER_FIELD - 1))))); +} + +#define PP_PCIEGenInvalid 0xffff +enum PP_PCIEGen { + PP_PCIEGen1 = 0, /* PCIE 1.0 - Transfer rate of 2.5 GT/s */ + PP_PCIEGen2, /*PCIE 2.0 - Transfer rate of 5.0 GT/s */ + PP_PCIEGen3 /*PCIE 3.0 - Transfer rate of 8.0 GT/s */ +}; + +typedef enum PP_PCIEGen PP_PCIEGen; + +#define PP_Min_PCIEGen PP_PCIEGen1 +#define PP_Max_PCIEGen PP_PCIEGen3 +#define PP_Min_PCIELane 1 +#define PP_Max_PCIELane 32 + +enum phm_clock_Type { + PHM_DispClock = 1, + PHM_SClock, + PHM_MemClock +}; + +#define MAX_NUM_CLOCKS 16 + +struct PP_Clocks { + uint32_t engineClock; + uint32_t memoryClock; + uint32_t BusBandwidth; + uint32_t engineClockInSR; +}; + +struct phm_platform_descriptor { + uint32_t platformCaps[PHM_MAX_NUM_CAPS_ULONG_ENTRIES]; + uint32_t vbiosInterruptId; + struct PP_Clocks overdriveLimit; + struct PP_Clocks clockStep; + uint32_t hardwareActivityPerformanceLevels; + uint32_t minimumClocksReductionPercentage; + uint32_t minOverdriveVDDC; + uint32_t maxOverdriveVDDC; + uint32_t overdriveVDDCStep; + uint32_t hardwarePerformanceLevels; + uint16_t powerBudget; + uint32_t TDPLimit; + uint32_t nearTDPLimit; + uint32_t nearTDPLimitAdjusted; + uint32_t SQRampingThreshold; + uint32_t CACLeakage; + uint16_t TDPODLimit; + uint32_t TDPAdjustment; + bool TDPAdjustmentPolarity; + uint16_t LoadLineSlope; + uint32_t VidMinLimit; + uint32_t VidMaxLimit; + uint32_t VidStep; + uint32_t VidAdjustment; + bool VidAdjustmentPolarity; +}; + +struct phm_clocks { + uint32_t num_of_entries; + uint32_t clock[MAX_NUM_CLOCKS]; +}; + +enum PP_DAL_POWERLEVEL { + PP_DAL_POWERLEVEL_INVALID = 0, + PP_DAL_POWERLEVEL_ULTRALOW, + PP_DAL_POWERLEVEL_LOW, + PP_DAL_POWERLEVEL_NOMINAL, + PP_DAL_POWERLEVEL_PERFORMANCE, + + PP_DAL_POWERLEVEL_0 = PP_DAL_POWERLEVEL_ULTRALOW, + PP_DAL_POWERLEVEL_1 = PP_DAL_POWERLEVEL_LOW, + PP_DAL_POWERLEVEL_2 = PP_DAL_POWERLEVEL_NOMINAL, + PP_DAL_POWERLEVEL_3 = PP_DAL_POWERLEVEL_PERFORMANCE, + PP_DAL_POWERLEVEL_4 = PP_DAL_POWERLEVEL_3+1, + PP_DAL_POWERLEVEL_5 = PP_DAL_POWERLEVEL_4+1, + PP_DAL_POWERLEVEL_6 = PP_DAL_POWERLEVEL_5+1, + PP_DAL_POWERLEVEL_7 = PP_DAL_POWERLEVEL_6+1, +}; + + +extern int phm_enable_clock_power_gatings(struct pp_hwmgr *hwmgr); +extern int phm_powergate_uvd(struct pp_hwmgr *hwmgr, bool gate); +extern int phm_powergate_vce(struct pp_hwmgr *hwmgr, bool gate); +extern int phm_powerdown_uvd(struct pp_hwmgr *hwmgr); +extern int phm_setup_asic(struct pp_hwmgr *hwmgr); +extern int phm_enable_dynamic_state_management(struct pp_hwmgr *hwmgr); +extern void phm_init_dynamic_caps(struct pp_hwmgr *hwmgr); +extern bool phm_is_hw_access_blocked(struct pp_hwmgr *hwmgr); +extern int phm_block_hw_access(struct pp_hwmgr *hwmgr, bool block); +extern int phm_set_power_state(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pcurrent_state, + const struct pp_hw_power_state *pnew_power_state); + +extern int phm_apply_state_adjust_rules(struct pp_hwmgr *hwmgr, + struct pp_power_state *adjusted_ps, + const struct pp_power_state *current_ps); + +extern int phm_force_dpm_levels(struct pp_hwmgr *hwmgr, enum amd_dpm_forced_level level); +extern int phm_display_configuration_changed(struct pp_hwmgr *hwmgr); +extern int phm_notify_smc_display_config_after_ps_adjustment(struct pp_hwmgr *hwmgr); +extern int phm_register_thermal_interrupt(struct pp_hwmgr *hwmgr, const void *info); +extern int phm_start_thermal_controller(struct pp_hwmgr *hwmgr, struct PP_TemperatureRange *temperature_range); +extern int phm_stop_thermal_controller(struct pp_hwmgr *hwmgr); +extern bool phm_check_smc_update_required_for_display_configuration(struct pp_hwmgr *hwmgr); + +extern int phm_check_states_equal(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal); + +extern int phm_store_dal_configuration_data(struct pp_hwmgr *hwmgr, + const struct amd_pp_display_configuration *display_config); + +extern int phm_get_dal_power_level(struct pp_hwmgr *hwmgr, + struct amd_pp_dal_clock_info*info); + +extern int phm_set_cpu_power_state(struct pp_hwmgr *hwmgr); + +#endif /* _HARDWARE_MANAGER_H_ */ + diff --git a/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h new file mode 100644 index 000000000000..eb0f1b22d42d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/hwmgr.h @@ -0,0 +1,799 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _HWMGR_H_ +#define _HWMGR_H_ + +#include <linux/seq_file.h> +#include "amd_powerplay.h" +#include "pp_instance.h" +#include "hardwaremanager.h" +#include "pp_power_source.h" +#include "hwmgr_ppt.h" +#include "ppatomctrl.h" +#include "hwmgr_ppt.h" + +struct pp_instance; +struct pp_hwmgr; +struct pp_hw_power_state; +struct pp_power_state; +struct PP_VCEState; +struct phm_fan_speed_info; +struct pp_atomctrl_voltage_table; + + +enum DISPLAY_GAP { + DISPLAY_GAP_VBLANK_OR_WM = 0, /* Wait for vblank or MCHG watermark. */ + DISPLAY_GAP_VBLANK = 1, /* Wait for vblank. */ + DISPLAY_GAP_WATERMARK = 2, /* Wait for MCHG watermark. (Note that HW may deassert WM in VBI depending on DC_STUTTER_CNTL.) */ + DISPLAY_GAP_IGNORE = 3 /* Do not wait. */ +}; +typedef enum DISPLAY_GAP DISPLAY_GAP; + + +struct vi_dpm_level { + bool enabled; + uint32_t value; + uint32_t param1; +}; + +struct vi_dpm_table { + uint32_t count; + struct vi_dpm_level dpm_level[1]; +}; + +enum PP_Result { + PP_Result_TableImmediateExit = 0x13, +}; + +#define PCIE_PERF_REQ_REMOVE_REGISTRY 0 +#define PCIE_PERF_REQ_FORCE_LOWPOWER 1 +#define PCIE_PERF_REQ_GEN1 2 +#define PCIE_PERF_REQ_GEN2 3 +#define PCIE_PERF_REQ_GEN3 4 + +enum PHM_BackEnd_Magic { + PHM_Dummy_Magic = 0xAA5555AA, + PHM_RV770_Magic = 0xDCBAABCD, + PHM_Kong_Magic = 0x239478DF, + PHM_NIslands_Magic = 0x736C494E, + PHM_Sumo_Magic = 0x8339FA11, + PHM_SIslands_Magic = 0x369431AC, + PHM_Trinity_Magic = 0x96751873, + PHM_CIslands_Magic = 0x38AC78B0, + PHM_Kv_Magic = 0xDCBBABC0, + PHM_VIslands_Magic = 0x20130307, + PHM_Cz_Magic = 0x67DCBA25 +}; + + +#define PHM_PCIE_POWERGATING_TARGET_GFX 0 +#define PHM_PCIE_POWERGATING_TARGET_DDI 1 +#define PHM_PCIE_POWERGATING_TARGET_PLLCASCADE 2 +#define PHM_PCIE_POWERGATING_TARGET_PHY 3 + +typedef int (*phm_table_function)(struct pp_hwmgr *hwmgr, void *input, + void *output, void *storage, int result); + +typedef bool (*phm_check_function)(struct pp_hwmgr *hwmgr); + +struct phm_set_power_state_input { + const struct pp_hw_power_state *pcurrent_state; + const struct pp_hw_power_state *pnew_state; +}; + +struct phm_acp_arbiter { + uint32_t acpclk; +}; + +struct phm_uvd_arbiter { + uint32_t vclk; + uint32_t dclk; + uint32_t vclk_ceiling; + uint32_t dclk_ceiling; +}; + +struct phm_vce_arbiter { + uint32_t evclk; + uint32_t ecclk; +}; + +struct phm_gfx_arbiter { + uint32_t sclk; + uint32_t mclk; + uint32_t sclk_over_drive; + uint32_t mclk_over_drive; + uint32_t sclk_threshold; + uint32_t num_cus; +}; + +/* Entries in the master tables */ +struct phm_master_table_item { + phm_check_function isFunctionNeededInRuntimeTable; + phm_table_function tableFunction; +}; + +enum phm_master_table_flag { + PHM_MasterTableFlag_None = 0, + PHM_MasterTableFlag_ExitOnError = 1, +}; + +/* The header of the master tables */ +struct phm_master_table_header { + uint32_t storage_size; + uint32_t flags; + struct phm_master_table_item *master_list; +}; + +struct phm_runtime_table_header { + uint32_t storage_size; + bool exit_error; + phm_table_function *function_list; +}; + +struct phm_clock_array { + uint32_t count; + uint32_t values[1]; +}; + +struct phm_clock_voltage_dependency_record { + uint32_t clk; + uint32_t v; +}; + +struct phm_vceclock_voltage_dependency_record { + uint32_t ecclk; + uint32_t evclk; + uint32_t v; +}; + +struct phm_uvdclock_voltage_dependency_record { + uint32_t vclk; + uint32_t dclk; + uint32_t v; +}; + +struct phm_samuclock_voltage_dependency_record { + uint32_t samclk; + uint32_t v; +}; + +struct phm_acpclock_voltage_dependency_record { + uint32_t acpclk; + uint32_t v; +}; + +struct phm_clock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + struct phm_clock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_phase_shedding_limits_record { + uint32_t Voltage; + uint32_t Sclk; + uint32_t Mclk; +}; + + +extern int phm_dispatch_table(struct pp_hwmgr *hwmgr, + struct phm_runtime_table_header *rt_table, + void *input, void *output); + +extern int phm_construct_table(struct pp_hwmgr *hwmgr, + struct phm_master_table_header *master_table, + struct phm_runtime_table_header *rt_table); + +extern int phm_destroy_table(struct pp_hwmgr *hwmgr, + struct phm_runtime_table_header *rt_table); + + +struct phm_uvd_clock_voltage_dependency_record { + uint32_t vclk; + uint32_t dclk; + uint32_t v; +}; + +struct phm_uvd_clock_voltage_dependency_table { + uint8_t count; + struct phm_uvd_clock_voltage_dependency_record entries[1]; +}; + +struct phm_acp_clock_voltage_dependency_record { + uint32_t acpclk; + uint32_t v; +}; + +struct phm_acp_clock_voltage_dependency_table { + uint32_t count; + struct phm_acp_clock_voltage_dependency_record entries[1]; +}; + +struct phm_vce_clock_voltage_dependency_record { + uint32_t ecclk; + uint32_t evclk; + uint32_t v; +}; + +struct phm_phase_shedding_limits_table { + uint32_t count; + struct phm_phase_shedding_limits_record entries[1]; +}; + +struct phm_vceclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_vceclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_uvdclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_uvdclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_samuclock_voltage_dependency_table { + uint8_t count; /* Number of entries. */ + struct phm_samuclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_acpclock_voltage_dependency_table { + uint32_t count; /* Number of entries. */ + struct phm_acpclock_voltage_dependency_record entries[1]; /* Dynamically allocate count entries. */ +}; + +struct phm_vce_clock_voltage_dependency_table { + uint8_t count; + struct phm_vce_clock_voltage_dependency_record entries[1]; +}; + +struct pp_hwmgr_func { + int (*backend_init)(struct pp_hwmgr *hw_mgr); + int (*backend_fini)(struct pp_hwmgr *hw_mgr); + int (*asic_setup)(struct pp_hwmgr *hw_mgr); + int (*get_power_state_size)(struct pp_hwmgr *hw_mgr); + + int (*apply_state_adjust_rules)(struct pp_hwmgr *hwmgr, + struct pp_power_state *prequest_ps, + const struct pp_power_state *pcurrent_ps); + + int (*force_dpm_level)(struct pp_hwmgr *hw_mgr, + enum amd_dpm_forced_level level); + + int (*dynamic_state_management_enable)( + struct pp_hwmgr *hw_mgr); + + int (*patch_boot_state)(struct pp_hwmgr *hwmgr, + struct pp_hw_power_state *hw_ps); + + int (*get_pp_table_entry)(struct pp_hwmgr *hwmgr, + unsigned long, struct pp_power_state *); + int (*get_num_of_pp_table_entries)(struct pp_hwmgr *hwmgr); + int (*powerdown_uvd)(struct pp_hwmgr *hwmgr); + int (*powergate_vce)(struct pp_hwmgr *hwmgr, bool bgate); + int (*powergate_uvd)(struct pp_hwmgr *hwmgr, bool bgate); + int (*get_mclk)(struct pp_hwmgr *hwmgr, bool low); + int (*get_sclk)(struct pp_hwmgr *hwmgr, bool low); + int (*power_state_set)(struct pp_hwmgr *hwmgr, + const void *state); + void (*print_current_perforce_level)(struct pp_hwmgr *hwmgr, + struct seq_file *m); + int (*enable_clock_power_gating)(struct pp_hwmgr *hwmgr); + int (*notify_smc_display_config_after_ps_adjustment)(struct pp_hwmgr *hwmgr); + int (*display_config_changed)(struct pp_hwmgr *hwmgr); + int (*disable_clock_power_gating)(struct pp_hwmgr *hwmgr); + int (*update_clock_gatings)(struct pp_hwmgr *hwmgr, + const uint32_t *msg_id); + int (*set_max_fan_rpm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); + int (*set_max_fan_pwm_output)(struct pp_hwmgr *hwmgr, uint16_t us_max_fan_pwm); + int (*get_temperature)(struct pp_hwmgr *hwmgr); + int (*stop_thermal_controller)(struct pp_hwmgr *hwmgr); + int (*get_fan_speed_info)(struct pp_hwmgr *hwmgr, struct phm_fan_speed_info *fan_speed_info); + int (*set_fan_control_mode)(struct pp_hwmgr *hwmgr, uint32_t mode); + int (*get_fan_control_mode)(struct pp_hwmgr *hwmgr); + int (*set_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t percent); + int (*get_fan_speed_percent)(struct pp_hwmgr *hwmgr, uint32_t *speed); + int (*set_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t percent); + int (*get_fan_speed_rpm)(struct pp_hwmgr *hwmgr, uint32_t *speed); + int (*reset_fan_speed_to_default)(struct pp_hwmgr *hwmgr); + int (*uninitialize_thermal_controller)(struct pp_hwmgr *hwmgr); + int (*register_internal_thermal_interrupt)(struct pp_hwmgr *hwmgr, + const void *thermal_interrupt_info); + bool (*check_smc_update_required_for_display_configuration)(struct pp_hwmgr *hwmgr); + int (*check_states_equal)(struct pp_hwmgr *hwmgr, + const struct pp_hw_power_state *pstate1, + const struct pp_hw_power_state *pstate2, + bool *equal); + int (*set_cpu_power_state)(struct pp_hwmgr *hwmgr); + int (*store_cc6_data)(struct pp_hwmgr *hwmgr, uint32_t separation_time, + bool cc6_disable, bool pstate_disable, + bool pstate_switch_disable); + int (*get_dal_power_level)(struct pp_hwmgr *hwmgr, + struct amd_pp_dal_clock_info*info); +}; + +struct pp_table_func { + int (*pptable_init)(struct pp_hwmgr *hw_mgr); + int (*pptable_fini)(struct pp_hwmgr *hw_mgr); + int (*pptable_get_number_of_vce_state_table_entries)(struct pp_hwmgr *hw_mgr); + int (*pptable_get_vce_state_table_entry)( + struct pp_hwmgr *hwmgr, + unsigned long i, + struct PP_VCEState *vce_state, + void **clock_info, + unsigned long *flag); +}; + +union phm_cac_leakage_record { + struct { + uint16_t Vddc; /* in CI, we use it for StdVoltageHiSidd */ + uint32_t Leakage; /* in CI, we use it for StdVoltageLoSidd */ + }; + struct { + uint16_t Vddc1; + uint16_t Vddc2; + uint16_t Vddc3; + }; +}; + +struct phm_cac_leakage_table { + uint32_t count; + union phm_cac_leakage_record entries[1]; +}; + +struct phm_samu_clock_voltage_dependency_record { + uint32_t samclk; + uint32_t v; +}; + + +struct phm_samu_clock_voltage_dependency_table { + uint8_t count; + struct phm_samu_clock_voltage_dependency_record entries[1]; +}; + +struct phm_cac_tdp_table { + uint16_t usTDP; + uint16_t usConfigurableTDP; + uint16_t usTDC; + uint16_t usBatteryPowerLimit; + uint16_t usSmallPowerLimit; + uint16_t usLowCACLeakage; + uint16_t usHighCACLeakage; + uint16_t usMaximumPowerDeliveryLimit; + uint16_t usOperatingTempMinLimit; + uint16_t usOperatingTempMaxLimit; + uint16_t usOperatingTempStep; + uint16_t usOperatingTempHyst; + uint16_t usDefaultTargetOperatingTemp; + uint16_t usTargetOperatingTemp; + uint16_t usPowerTuneDataSetID; + uint16_t usSoftwareShutdownTemp; + uint16_t usClockStretchAmount; + uint16_t usTemperatureLimitHotspot; + uint16_t usTemperatureLimitLiquid1; + uint16_t usTemperatureLimitLiquid2; + uint16_t usTemperatureLimitVrVddc; + uint16_t usTemperatureLimitVrMvdd; + uint16_t usTemperatureLimitPlx; + uint8_t ucLiquid1_I2C_address; + uint8_t ucLiquid2_I2C_address; + uint8_t ucLiquid_I2C_Line; + uint8_t ucVr_I2C_address; + uint8_t ucVr_I2C_Line; + uint8_t ucPlx_I2C_address; + uint8_t ucPlx_I2C_Line; +}; + +struct phm_ppm_table { + uint8_t ppm_design; + uint16_t cpu_core_number; + uint32_t platform_tdp; + uint32_t small_ac_platform_tdp; + uint32_t platform_tdc; + uint32_t small_ac_platform_tdc; + uint32_t apu_tdp; + uint32_t dgpu_tdp; + uint32_t dgpu_ulv_power; + uint32_t tj_max; +}; + +struct phm_vq_budgeting_record { + uint32_t ulCUs; + uint32_t ulSustainableSOCPowerLimitLow; + uint32_t ulSustainableSOCPowerLimitHigh; + uint32_t ulMinSclkLow; + uint32_t ulMinSclkHigh; + uint8_t ucDispConfig; + uint32_t ulDClk; + uint32_t ulEClk; + uint32_t ulSustainableSclk; + uint32_t ulSustainableCUs; +}; + +struct phm_vq_budgeting_table { + uint8_t numEntries; + struct phm_vq_budgeting_record entries[1]; +}; + +struct phm_clock_and_voltage_limits { + uint32_t sclk; + uint32_t mclk; + uint16_t vddc; + uint16_t vddci; + uint16_t vddgfx; +}; + +/* Structure to hold PPTable information */ + +struct phm_ppt_v1_information { + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_sclk; + struct phm_ppt_v1_clock_voltage_dependency_table *vdd_dep_on_mclk; + struct phm_clock_array *valid_sclk_values; + struct phm_clock_array *valid_mclk_values; + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; + struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; + struct phm_ppm_table *ppm_parameter_table; + struct phm_cac_tdp_table *cac_dtp_table; + struct phm_ppt_v1_mm_clock_voltage_dependency_table *mm_dep_table; + struct phm_ppt_v1_voltage_lookup_table *vddc_lookup_table; + struct phm_ppt_v1_voltage_lookup_table *vddgfx_lookup_table; + struct phm_ppt_v1_pcie_table *pcie_table; + uint16_t us_ulv_voltage_offset; +}; + +struct phm_dynamic_state_info { + struct phm_clock_voltage_dependency_table *vddc_dependency_on_sclk; + struct phm_clock_voltage_dependency_table *vddci_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *vddc_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *mvdd_dependency_on_mclk; + struct phm_clock_voltage_dependency_table *vddc_dep_on_dal_pwrl; + struct phm_clock_array *valid_sclk_values; + struct phm_clock_array *valid_mclk_values; + struct phm_clock_and_voltage_limits max_clock_voltage_on_dc; + struct phm_clock_and_voltage_limits max_clock_voltage_on_ac; + uint32_t mclk_sclk_ratio; + uint32_t sclk_mclk_delta; + uint32_t vddc_vddci_delta; + uint32_t min_vddc_for_pcie_gen2; + struct phm_cac_leakage_table *cac_leakage_table; + struct phm_phase_shedding_limits_table *vddc_phase_shed_limits_table; + + struct phm_vce_clock_voltage_dependency_table + *vce_clock_voltage_dependency_table; + struct phm_uvd_clock_voltage_dependency_table + *uvd_clock_voltage_dependency_table; + struct phm_acp_clock_voltage_dependency_table + *acp_clock_voltage_dependency_table; + struct phm_samu_clock_voltage_dependency_table + *samu_clock_voltage_dependency_table; + + struct phm_ppm_table *ppm_parameter_table; + struct phm_cac_tdp_table *cac_dtp_table; + struct phm_clock_voltage_dependency_table *vdd_gfx_dependency_on_sclk; + struct phm_vq_budgeting_table *vq_budgeting_table; +}; + +struct pp_fan_info { + bool bNoFan; + uint8_t ucTachometerPulsesPerRevolution; + uint32_t ulMinRPM; + uint32_t ulMaxRPM; +}; + +struct pp_advance_fan_control_parameters { + uint16_t usTMin; /* The temperature, in 0.01 centigrades, below which we just run at a minimal PWM. */ + uint16_t usTMed; /* The middle temperature where we change slopes. */ + uint16_t usTHigh; /* The high temperature for setting the second slope. */ + uint16_t usPWMMin; /* The minimum PWM value in percent (0.01% increments). */ + uint16_t usPWMMed; /* The PWM value (in percent) at TMed. */ + uint16_t usPWMHigh; /* The PWM value at THigh. */ + uint8_t ucTHyst; /* Temperature hysteresis. Integer. */ + uint32_t ulCycleDelay; /* The time between two invocations of the fan control routine in microseconds. */ + uint16_t usTMax; /* The max temperature */ + uint8_t ucFanControlMode; + uint16_t usFanPWMMinLimit; + uint16_t usFanPWMMaxLimit; + uint16_t usFanPWMStep; + uint16_t usDefaultMaxFanPWM; + uint16_t usFanOutputSensitivity; + uint16_t usDefaultFanOutputSensitivity; + uint16_t usMaxFanPWM; /* The max Fan PWM value for Fuzzy Fan Control feature */ + uint16_t usFanRPMMinLimit; /* Minimum limit range in percentage, need to calculate based on minRPM/MaxRpm */ + uint16_t usFanRPMMaxLimit; /* Maximum limit range in percentage, usually set to 100% by default */ + uint16_t usFanRPMStep; /* Step increments/decerements, in percent */ + uint16_t usDefaultMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, default from PPTable */ + uint16_t usMaxFanRPM; /* The max Fan RPM value for Fuzzy Fan Control feature, user defined */ + uint16_t usFanCurrentLow; /* Low current */ + uint16_t usFanCurrentHigh; /* High current */ + uint16_t usFanRPMLow; /* Low RPM */ + uint16_t usFanRPMHigh; /* High RPM */ + uint32_t ulMinFanSCLKAcousticLimit; /* Minimum Fan Controller SCLK Frequency Acoustic Limit. */ + uint8_t ucTargetTemperature; /* Advanced fan controller target temperature. */ + uint8_t ucMinimumPWMLimit; /* The minimum PWM that the advanced fan controller can set. This should be set to the highest PWM that will run the fan at its lowest RPM. */ + uint16_t usFanGainEdge; /* The following is added for Fiji */ + uint16_t usFanGainHotspot; + uint16_t usFanGainLiquid; + uint16_t usFanGainVrVddc; + uint16_t usFanGainVrMvdd; + uint16_t usFanGainPlx; + uint16_t usFanGainHbm; +}; + +struct pp_thermal_controller_info { + uint8_t ucType; + uint8_t ucI2cLine; + uint8_t ucI2cAddress; + struct pp_fan_info fanInfo; + struct pp_advance_fan_control_parameters advanceFanControlParameters; +}; + +struct phm_microcode_version_info { + uint32_t SMC; + uint32_t DMCU; + uint32_t MC; + uint32_t NB; +}; + +/** + * The main hardware manager structure. + */ +struct pp_hwmgr { + uint32_t chip_family; + uint32_t chip_id; + uint32_t hw_revision; + uint32_t sub_sys_id; + uint32_t sub_vendor_id; + + void *device; + struct pp_smumgr *smumgr; + const void *soft_pp_table; + bool need_pp_table_upload; + enum amd_dpm_forced_level dpm_level; + bool block_hw_access; + struct phm_gfx_arbiter gfx_arbiter; + struct phm_acp_arbiter acp_arbiter; + struct phm_uvd_arbiter uvd_arbiter; + struct phm_vce_arbiter vce_arbiter; + uint32_t usec_timeout; + void *pptable; + struct phm_platform_descriptor platform_descriptor; + void *backend; + enum PP_DAL_POWERLEVEL dal_power_level; + struct phm_dynamic_state_info dyn_state; + struct phm_runtime_table_header setup_asic; + struct phm_runtime_table_header disable_dynamic_state_management; + struct phm_runtime_table_header enable_dynamic_state_management; + struct phm_runtime_table_header set_power_state; + struct phm_runtime_table_header enable_clock_power_gatings; + struct phm_runtime_table_header display_configuration_changed; + struct phm_runtime_table_header start_thermal_controller; + struct phm_runtime_table_header set_temperature_range; + const struct pp_hwmgr_func *hwmgr_func; + const struct pp_table_func *pptable_func; + struct pp_power_state *ps; + enum pp_power_source power_source; + uint32_t num_ps; + struct pp_thermal_controller_info thermal_controller; + bool fan_ctrl_is_in_default_mode; + uint32_t fan_ctrl_default_mode; + uint32_t tmin; + struct phm_microcode_version_info microcode_version_info; + uint32_t ps_size; + struct pp_power_state *current_ps; + struct pp_power_state *request_ps; + struct pp_power_state *boot_ps; + struct pp_power_state *uvd_ps; + struct amd_pp_display_configuration display_config; +}; + + +extern int hwmgr_init(struct amd_pp_init *pp_init, + struct pp_instance *handle); + +extern int hwmgr_fini(struct pp_hwmgr *hwmgr); + +extern int hw_init_power_state_table(struct pp_hwmgr *hwmgr); + +extern int phm_wait_on_register(struct pp_hwmgr *hwmgr, uint32_t index, + uint32_t value, uint32_t mask); + +extern int phm_wait_for_register_unequal(struct pp_hwmgr *hwmgr, + uint32_t index, uint32_t value, uint32_t mask); + +extern uint32_t phm_read_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, uint32_t index); + +extern void phm_write_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value); + +extern void phm_wait_on_indirect_register(struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask); + +extern void phm_wait_for_indirect_register_unequal( + struct pp_hwmgr *hwmgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask); + +extern bool phm_cf_want_uvd_power_gating(struct pp_hwmgr *hwmgr); +extern bool phm_cf_want_vce_power_gating(struct pp_hwmgr *hwmgr); +extern bool phm_cf_want_microcode_fan_ctrl(struct pp_hwmgr *hwmgr); + +extern int phm_trim_voltage_table(struct pp_atomctrl_voltage_table *vol_table); +extern int phm_get_svi2_mvdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); +extern int phm_get_svi2_vddci_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_clock_voltage_dependency_table *dep_table); +extern int phm_get_svi2_vdd_voltage_table(struct pp_atomctrl_voltage_table *vol_table, phm_ppt_v1_voltage_lookup_table *lookup_table); +extern void phm_trim_voltage_table_to_fit_state_table(uint32_t max_vol_steps, struct pp_atomctrl_voltage_table *vol_table); +extern int phm_reset_single_dpm_table(void *table, uint32_t count, int max); +extern void phm_setup_pcie_table_entry(void *table, uint32_t index, uint32_t pcie_gen, uint32_t pcie_lanes); +extern int32_t phm_get_dpm_level_enable_mask_value(void *table); +extern uint8_t phm_get_voltage_index(struct phm_ppt_v1_voltage_lookup_table *lookup_table, uint16_t voltage); +extern uint16_t phm_find_closest_vddci(struct pp_atomctrl_voltage_table *vddci_table, uint16_t vddci); +extern int phm_find_boot_level(void *table, uint32_t value, uint32_t *boot_level); +extern int phm_get_sclk_for_voltage_evv(struct pp_hwmgr *hwmgr, phm_ppt_v1_voltage_lookup_table *lookup_table, + uint16_t virtual_voltage_id, int32_t *sclk); +extern int phm_initializa_dynamic_state_adjustment_rule_settings(struct pp_hwmgr *hwmgr); +extern int phm_hwmgr_backend_fini(struct pp_hwmgr *hwmgr); +extern uint32_t phm_get_lowest_enabled_level(struct pp_hwmgr *hwmgr, uint32_t mask); + + +#define PHM_ENTIRE_REGISTER_MASK 0xFFFFFFFFU + +#define PHM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT +#define PHM_FIELD_MASK(reg, field) reg##__##field##_MASK + +#define PHM_SET_FIELD(origval, reg, field, fieldval) \ + (((origval) & ~PHM_FIELD_MASK(reg, field)) | \ + (PHM_FIELD_MASK(reg, field) & ((fieldval) << PHM_FIELD_SHIFT(reg, field)))) + +#define PHM_GET_FIELD(value, reg, field) \ + (((value) & PHM_FIELD_MASK(reg, field)) >> \ + PHM_FIELD_SHIFT(reg, field)) + + +#define PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, index, value, mask) \ + phm_wait_on_register(hwmgr, index, value, mask) + +#define PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, index, value, mask) \ + phm_wait_for_register_unequal(hwmgr, index, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX, index, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_on_indirect_register(hwmgr, mm##port##_INDEX_0, index, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, index, value, mask) \ + phm_wait_for_indirect_register_unequal(hwmgr, mm##port##_INDEX_0, index, value, mask) + +/* Operations on named registers. */ + +#define PHM_WAIT_REGISTER(hwmgr, reg, value, mask) \ + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg, value, mask) + +#define PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, value, mask) \ + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ + PHM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +#define PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, value, mask) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, port, ix##reg, value, mask) + +/* Operations on named fields. */ + +#define PHM_READ_FIELD(device, reg, field) \ + PHM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) + +#define PHM_READ_INDIRECT_FIELD(device, port, reg, field) \ + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field) + +#define PHM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ + PHM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field) + +#define PHM_WRITE_FIELD(device, reg, field, fieldval) \ + cgs_write_register(device, mm##reg, PHM_SET_FIELD( \ + cgs_read_register(device, mm##reg), reg, field, fieldval)) + +#define PHM_WRITE_INDIRECT_FIELD(device, port, reg, field, fieldval) \ + cgs_write_ind_register(device, port, ix##reg, \ + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field, fieldval)) + +#define PHM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ + cgs_write_ind_register(device, port, ix##reg, \ + PHM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field, fieldval)) + +#define PHM_WAIT_FIELD(hwmgr, reg, field, fieldval) \ + PHM_WAIT_REGISTER(hwmgr, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER(hwmgr, port, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_FIELD_UNEQUAL(hwmgr, reg, field, fieldval) \ + PHM_WAIT_REGISTER_UNEQUAL(hwmgr, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(hwmgr, port, reg, field, fieldval) \ + PHM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(hwmgr, port, reg, (fieldval) \ + << PHM_FIELD_SHIFT(reg, field), PHM_FIELD_MASK(reg, field)) + +/* Operations on arrays of registers & fields. */ + +#define PHM_READ_ARRAY_REGISTER(device, reg, offset) \ + cgs_read_register(device, mm##reg + (offset)) + +#define PHM_WRITE_ARRAY_REGISTER(device, reg, offset, value) \ + cgs_write_register(device, mm##reg + (offset), value) + +#define PHM_WAIT_ARRAY_REGISTER(hwmgr, reg, offset, value, mask) \ + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask) + +#define PHM_WAIT_ARRAY_REGISTER_UNEQUAL(hwmgr, reg, offset, value, mask) \ + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset), value, mask) + +#define PHM_READ_ARRAY_FIELD(hwmgr, reg, offset, field) \ + PHM_GET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset), reg, field) + +#define PHM_WRITE_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue) \ + PHM_WRITE_ARRAY_REGISTER(hwmgr->device, reg, offset, \ + PHM_SET_FIELD(PHM_READ_ARRAY_REGISTER(hwmgr->device, reg, offset), \ + reg, field, fieldvalue)) + +#define PHM_WAIT_ARRAY_FIELD(hwmgr, reg, offset, field, fieldvalue) \ + PHM_WAIT_REGISTER_GIVEN_INDEX(hwmgr, mm##reg + (offset), \ + (fieldvalue) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + +#define PHM_WAIT_ARRAY_FIELD_UNEQUAL(hwmgr, reg, offset, field, fieldvalue) \ + PHM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(hwmgr, mm##reg + (offset), \ + (fieldvalue) << PHM_FIELD_SHIFT(reg, field), \ + PHM_FIELD_MASK(reg, field)) + +#endif /* _HWMGR_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/power_state.h b/drivers/gpu/drm/amd/powerplay/inc/power_state.h new file mode 100644 index 000000000000..a3f0ce4d5835 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/power_state.h @@ -0,0 +1,200 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef PP_POWERSTATE_H +#define PP_POWERSTATE_H + +struct pp_hw_power_state { + unsigned int magic; +}; + +struct pp_power_state; + + +#define PP_INVALID_POWER_STATE_ID (0) + + +/* + * An item of a list containing Power States. + */ + +struct PP_StateLinkedList { + struct pp_power_state *next; + struct pp_power_state *prev; +}; + + +enum PP_StateUILabel { + PP_StateUILabel_None, + PP_StateUILabel_Battery, + PP_StateUILabel_MiddleLow, + PP_StateUILabel_Balanced, + PP_StateUILabel_MiddleHigh, + PP_StateUILabel_Performance, + PP_StateUILabel_BACO +}; + +enum PP_StateClassificationFlag { + PP_StateClassificationFlag_Boot = 0x0001, + PP_StateClassificationFlag_Thermal = 0x0002, + PP_StateClassificationFlag_LimitedPowerSource = 0x0004, + PP_StateClassificationFlag_Rest = 0x0008, + PP_StateClassificationFlag_Forced = 0x0010, + PP_StateClassificationFlag_User3DPerformance = 0x0020, + PP_StateClassificationFlag_User2DPerformance = 0x0040, + PP_StateClassificationFlag_3DPerformance = 0x0080, + PP_StateClassificationFlag_ACOverdriveTemplate = 0x0100, + PP_StateClassificationFlag_Uvd = 0x0200, + PP_StateClassificationFlag_3DPerformanceLow = 0x0400, + PP_StateClassificationFlag_ACPI = 0x0800, + PP_StateClassificationFlag_HD2 = 0x1000, + PP_StateClassificationFlag_UvdHD = 0x2000, + PP_StateClassificationFlag_UvdSD = 0x4000, + PP_StateClassificationFlag_UserDCPerformance = 0x8000, + PP_StateClassificationFlag_DCOverdriveTemplate = 0x10000, + PP_StateClassificationFlag_BACO = 0x20000, + PP_StateClassificationFlag_LimitedPowerSource_2 = 0x40000, + PP_StateClassificationFlag_ULV = 0x80000, + PP_StateClassificationFlag_UvdMVC = 0x100000, +}; + +typedef unsigned int PP_StateClassificationFlags; + +struct PP_StateClassificationBlock { + enum PP_StateUILabel ui_label; + enum PP_StateClassificationFlag flags; + int bios_index; + bool temporary_state; + bool to_be_deleted; +}; + +struct PP_StatePcieBlock { + unsigned int lanes; +}; + +enum PP_RefreshrateSource { + PP_RefreshrateSource_EDID, + PP_RefreshrateSource_Explicit +}; + +struct PP_StateDisplayBlock { + bool disableFrameModulation; + bool limitRefreshrate; + enum PP_RefreshrateSource refreshrateSource; + int explicitRefreshrate; + int edidRefreshrateIndex; + bool enableVariBright; +}; + +struct PP_StateMemroyBlock { + bool dllOff; + uint8_t m3arb; + uint8_t unused[3]; +}; + +struct PP_StateSoftwareAlgorithmBlock { + bool disableLoadBalancing; + bool enableSleepForTimestamps; +}; + +#define PP_TEMPERATURE_UNITS_PER_CENTIGRADES 1000 + +/** + * Type to hold a temperature range. + */ +struct PP_TemperatureRange { + uint32_t min; + uint32_t max; +}; + +struct PP_StateValidationBlock { + bool singleDisplayOnly; + bool disallowOnDC; + uint8_t supportedPowerLevels; +}; + +struct PP_UVD_CLOCKS { + uint32_t VCLK; + uint32_t DCLK; +}; + +/** +* Structure to hold a PowerPlay Power State. +*/ +struct pp_power_state { + uint32_t id; + struct PP_StateLinkedList orderedList; + struct PP_StateLinkedList allStatesList; + + struct PP_StateClassificationBlock classification; + struct PP_StateValidationBlock validation; + struct PP_StatePcieBlock pcie; + struct PP_StateDisplayBlock display; + struct PP_StateMemroyBlock memory; + struct PP_TemperatureRange temperatures; + struct PP_StateSoftwareAlgorithmBlock software; + struct PP_UVD_CLOCKS uvd_clocks; + struct pp_hw_power_state hardware; +}; + + +/*Structure to hold a VCE state entry*/ +struct PP_VCEState { + uint32_t evclk; + uint32_t ecclk; + uint32_t sclk; + uint32_t mclk; +}; + +enum PP_MMProfilingState { + PP_MMProfilingState_NA = 0, + PP_MMProfilingState_Started, + PP_MMProfilingState_Stopped +}; + +struct PP_Clock_Engine_Request { + unsigned long clientType; + unsigned long ctxid; + uint64_t context_handle; + unsigned long sclk; + unsigned long sclkHardMin; + unsigned long mclk; + unsigned long iclk; + unsigned long evclk; + unsigned long ecclk; + unsigned long ecclkHardMin; + unsigned long vclk; + unsigned long dclk; + unsigned long samclk; + unsigned long acpclk; + unsigned long sclkOverdrive; + unsigned long mclkOverdrive; + unsigned long sclk_threshold; + unsigned long flag; + unsigned long vclk_ceiling; + unsigned long dclk_ceiling; + unsigned long num_cus; + unsigned long pmflag; + enum PP_MMProfilingState MMProfilingState; +}; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h new file mode 100644 index 000000000000..3bd5e69b9045 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_acpi.h @@ -0,0 +1,28 @@ +/* + * Copyright 2015 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. + * + */ + +extern bool acpi_atcs_functions_supported(void *device, + uint32_t index); +extern int acpi_pcie_perf_request(void *device, + uint8_t perf_req, + bool advertise); diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h new file mode 100644 index 000000000000..0c1593e53654 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_asicblocks.h @@ -0,0 +1,47 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef PP_ASICBLOCKS_H +#define PP_ASICBLOCKS_H + + +enum PHM_AsicBlock { + PHM_AsicBlock_GFX, + PHM_AsicBlock_UVD_MVC, + PHM_AsicBlock_UVD, + PHM_AsicBlock_UVD_HD, + PHM_AsicBlock_UVD_SD, + PHM_AsicBlock_Count +}; + +enum PHM_ClockGateSetting { + PHM_ClockGateSetting_StaticOn, + PHM_ClockGateSetting_StaticOff, + PHM_ClockGateSetting_Dynamic +}; + +struct phm_asic_blocks { + bool gfx : 1; + bool uvd : 1; +}; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h new file mode 100644 index 000000000000..d7d83b7c7f95 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_debug.h @@ -0,0 +1,47 @@ + +/* + * Copyright 2015 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. + * + */ +#ifndef PP_DEBUG_H +#define PP_DEBUG_H + +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> + +#define PP_ASSERT_WITH_CODE(cond, msg, code) \ + do { \ + if (!(cond)) { \ + printk("%s\n", msg); \ + code; \ + } \ + } while (0) + + +#define PP_DBG_LOG(fmt, ...) \ + do { \ + if(0)printk(KERN_INFO "[ pp_dbg ] " fmt, ##__VA_ARGS__); \ + } while (0) + + +#endif /* PP_DEBUG_H */ + diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h b/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h new file mode 100644 index 000000000000..0faf6a25c18b --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_feature.h @@ -0,0 +1,67 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _PP_FEATURE_H_ +#define _PP_FEATURE_H_ + +/** + * PowerPlay feature ids. + */ +enum pp_feature { + PP_Feature_PowerPlay = 0, + PP_Feature_User2DPerformance, + PP_Feature_User3DPerformance, + PP_Feature_VariBright, + PP_Feature_VariBrightOnPowerXpress, + PP_Feature_ReducedRefreshRate, + PP_Feature_GFXClockGating, + PP_Feature_OverdriveTest, + PP_Feature_OverDrive, + PP_Feature_PowerBudgetWaiver, + PP_Feature_PowerControl, + PP_Feature_PowerControl_2, + PP_Feature_MultiUVDState, + PP_Feature_Force3DClock, + PP_Feature_BACO, + PP_Feature_PowerDown, + PP_Feature_DynamicUVDState, + PP_Feature_VCEDPM, + PP_Feature_PPM, + PP_Feature_ACP_POWERGATING, + PP_Feature_FFC, + PP_Feature_FPS, + PP_Feature_ViPG, + PP_Feature_Max +}; + +/** + * Struct for PowerPlay feature info. + */ +struct pp_feature_info { + bool supported; /* feature supported by PowerPlay */ + bool enabled; /* feature enabled in PowerPlay */ + bool enabled_default; /* default enable status of the feature */ + uint32_t version; /* feature version */ +}; + +#endif /* _PP_FEATURE_H_ */ diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h new file mode 100644 index 000000000000..7b60b617dff6 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_instance.h @@ -0,0 +1,36 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _PP_INSTANCE_H_ +#define _PP_INSTANCE_H_ + +#include "smumgr.h" +#include "hwmgr.h" +#include "eventmgr.h" + +struct pp_instance { + struct pp_smumgr *smu_mgr; + struct pp_hwmgr *hwmgr; + struct pp_eventmgr *eventmgr; +}; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h b/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h new file mode 100644 index 000000000000..b43315cc5d58 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/pp_power_source.h @@ -0,0 +1,36 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef PP_POWERSOURCE_H +#define PP_POWERSOURCE_H + +enum pp_power_source { + PP_PowerSource_AC = 0, + PP_PowerSource_DC, + PP_PowerSource_LimitedPower, + PP_PowerSource_LimitedPower_2, + PP_PowerSource_Max +}; + + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h b/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h new file mode 100644 index 000000000000..c067e0925b6b --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/ppinterrupt.h @@ -0,0 +1,46 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _PP_INTERRUPT_H_ +#define _PP_INTERRUPT_H_ + +enum amd_thermal_irq { + AMD_THERMAL_IRQ_LOW_TO_HIGH = 0, + AMD_THERMAL_IRQ_HIGH_TO_LOW, + + AMD_THERMAL_IRQ_LAST +}; + +/* The type of the interrupt callback functions in PowerPlay */ +typedef int (*irq_handler_func_t)(void *private_data, + unsigned src_id, const uint32_t *iv_entry); + +/* Event Manager action chain list information */ +struct pp_interrupt_registration_info { + irq_handler_func_t call_back; /* Pointer to callback function */ + void *context; /* Pointer to callback function context */ + uint32_t src_id; /* Registered interrupt id */ + const uint32_t *iv_entry; +}; + +#endif /* _PP_INTERRUPT_H_ */ diff --git a/drivers/gpu/drm/amd/amdgpu/smu7.h b/drivers/gpu/drm/amd/powerplay/inc/smu7.h index 75a380a15292..75a380a15292 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu7.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu7.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72.h b/drivers/gpu/drm/amd/powerplay/inc/smu72.h new file mode 100644 index 000000000000..b73d6b59ac32 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smu72.h @@ -0,0 +1,664 @@ +#ifndef SMU72_H +#define SMU72_H + +#if !defined(SMC_MICROCODE) +#pragma pack(push, 1) +#endif + +#define SMU__NUM_SCLK_DPM_STATE 8 +#define SMU__NUM_MCLK_DPM_LEVELS 4 +#define SMU__NUM_LCLK_DPM_LEVELS 8 +#define SMU__NUM_PCIE_DPM_LEVELS 8 + +enum SID_OPTION { + SID_OPTION_HI, + SID_OPTION_LO, + SID_OPTION_COUNT +}; + +enum Poly3rdOrderCoeff { + LEAKAGE_TEMPERATURE_SCALAR, + LEAKAGE_VOLTAGE_SCALAR, + DYNAMIC_VOLTAGE_SCALAR, + POLY_3RD_ORDER_COUNT +}; + +struct SMU7_Poly3rdOrder_Data { + int32_t a; + int32_t b; + int32_t c; + int32_t d; + uint8_t a_shift; + uint8_t b_shift; + uint8_t c_shift; + uint8_t x_shift; +}; + +typedef struct SMU7_Poly3rdOrder_Data SMU7_Poly3rdOrder_Data; + +struct Power_Calculator_Data { + uint16_t NoLoadVoltage; + uint16_t LoadVoltage; + uint16_t Resistance; + uint16_t Temperature; + uint16_t BaseLeakage; + uint16_t LkgTempScalar; + uint16_t LkgVoltScalar; + uint16_t LkgAreaScalar; + uint16_t LkgPower; + uint16_t DynVoltScalar; + uint32_t Cac; + uint32_t DynPower; + uint32_t TotalCurrent; + uint32_t TotalPower; +}; + +typedef struct Power_Calculator_Data PowerCalculatorData_t; + +struct Gc_Cac_Weight_Data { + uint8_t index; + uint32_t value; +}; + +typedef struct Gc_Cac_Weight_Data GcCacWeight_Data; + + +typedef struct { + uint32_t high; + uint32_t low; +} data_64_t; + +typedef struct { + data_64_t high; + data_64_t low; +} data_128_t; + +#define SMU7_CONTEXT_ID_SMC 1 +#define SMU7_CONTEXT_ID_VBIOS 2 + +#define SMU72_MAX_LEVELS_VDDC 16 +#define SMU72_MAX_LEVELS_VDDGFX 16 +#define SMU72_MAX_LEVELS_VDDCI 8 +#define SMU72_MAX_LEVELS_MVDD 4 + +#define SMU_MAX_SMIO_LEVELS 4 + +#define SMU72_MAX_LEVELS_GRAPHICS SMU__NUM_SCLK_DPM_STATE /* SCLK + SQ DPM + ULV */ +#define SMU72_MAX_LEVELS_MEMORY SMU__NUM_MCLK_DPM_LEVELS /* MCLK Levels DPM */ +#define SMU72_MAX_LEVELS_GIO SMU__NUM_LCLK_DPM_LEVELS /* LCLK Levels */ +#define SMU72_MAX_LEVELS_LINK SMU__NUM_PCIE_DPM_LEVELS /* PCIe speed and number of lanes. */ +#define SMU72_MAX_LEVELS_UVD 8 /* VCLK/DCLK levels for UVD. */ +#define SMU72_MAX_LEVELS_VCE 8 /* ECLK levels for VCE. */ +#define SMU72_MAX_LEVELS_ACP 8 /* ACLK levels for ACP. */ +#define SMU72_MAX_LEVELS_SAMU 8 /* SAMCLK levels for SAMU. */ +#define SMU72_MAX_ENTRIES_SMIO 32 /* Number of entries in SMIO table. */ + +#define DPM_NO_LIMIT 0 +#define DPM_NO_UP 1 +#define DPM_GO_DOWN 2 +#define DPM_GO_UP 3 + +#define SMU7_FIRST_DPM_GRAPHICS_LEVEL 0 +#define SMU7_FIRST_DPM_MEMORY_LEVEL 0 + +#define GPIO_CLAMP_MODE_VRHOT 1 +#define GPIO_CLAMP_MODE_THERM 2 +#define GPIO_CLAMP_MODE_DC 4 + +#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0 +#define SCRATCH_B_TARG_PCIE_INDEX_MASK (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT) +#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3 +#define SCRATCH_B_CURR_PCIE_INDEX_MASK (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT) +#define SCRATCH_B_TARG_UVD_INDEX_SHIFT 6 +#define SCRATCH_B_TARG_UVD_INDEX_MASK (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT) +#define SCRATCH_B_CURR_UVD_INDEX_SHIFT 9 +#define SCRATCH_B_CURR_UVD_INDEX_MASK (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT) +#define SCRATCH_B_TARG_VCE_INDEX_SHIFT 12 +#define SCRATCH_B_TARG_VCE_INDEX_MASK (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT) +#define SCRATCH_B_CURR_VCE_INDEX_SHIFT 15 +#define SCRATCH_B_CURR_VCE_INDEX_MASK (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT) +#define SCRATCH_B_TARG_ACP_INDEX_SHIFT 18 +#define SCRATCH_B_TARG_ACP_INDEX_MASK (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT) +#define SCRATCH_B_CURR_ACP_INDEX_SHIFT 21 +#define SCRATCH_B_CURR_ACP_INDEX_MASK (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT) +#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24 +#define SCRATCH_B_TARG_SAMU_INDEX_MASK (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT) +#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27 +#define SCRATCH_B_CURR_SAMU_INDEX_MASK (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT) + +/* Virtualization Defines */ +#define CG_XDMA_MASK 0x1 +#define CG_XDMA_SHIFT 0 +#define CG_UVD_MASK 0x2 +#define CG_UVD_SHIFT 1 +#define CG_VCE_MASK 0x4 +#define CG_VCE_SHIFT 2 +#define CG_SAMU_MASK 0x8 +#define CG_SAMU_SHIFT 3 +#define CG_GFX_MASK 0x10 +#define CG_GFX_SHIFT 4 +#define CG_SDMA_MASK 0x20 +#define CG_SDMA_SHIFT 5 +#define CG_HDP_MASK 0x40 +#define CG_HDP_SHIFT 6 +#define CG_MC_MASK 0x80 +#define CG_MC_SHIFT 7 +#define CG_DRM_MASK 0x100 +#define CG_DRM_SHIFT 8 +#define CG_ROM_MASK 0x200 +#define CG_ROM_SHIFT 9 +#define CG_BIF_MASK 0x400 +#define CG_BIF_SHIFT 10 + +#define SMU72_DTE_ITERATIONS 5 +#define SMU72_DTE_SOURCES 3 +#define SMU72_DTE_SINKS 1 +#define SMU72_NUM_CPU_TES 0 +#define SMU72_NUM_GPU_TES 1 +#define SMU72_NUM_NON_TES 2 +#define SMU72_DTE_FAN_SCALAR_MIN 0x100 +#define SMU72_DTE_FAN_SCALAR_MAX 0x166 +#define SMU72_DTE_FAN_TEMP_MAX 93 +#define SMU72_DTE_FAN_TEMP_MIN 83 + +#if defined SMU__FUSION_ONLY +#define SMU7_DTE_ITERATIONS 5 +#define SMU7_DTE_SOURCES 5 +#define SMU7_DTE_SINKS 3 +#define SMU7_NUM_CPU_TES 2 +#define SMU7_NUM_GPU_TES 1 +#define SMU7_NUM_NON_TES 2 +#endif + +struct SMU7_HystController_Data { + uint8_t waterfall_up; + uint8_t waterfall_down; + uint8_t waterfall_limit; + uint8_t spare; + uint16_t release_cnt; + uint16_t release_limit; +}; + +typedef struct SMU7_HystController_Data SMU7_HystController_Data; + +struct SMU72_PIDController { + uint32_t Ki; + int32_t LFWindupUpperLim; + int32_t LFWindupLowerLim; + uint32_t StatePrecision; + uint32_t LfPrecision; + uint32_t LfOffset; + uint32_t MaxState; + uint32_t MaxLfFraction; + uint32_t StateShift; +}; + +typedef struct SMU72_PIDController SMU72_PIDController; + +struct SMU7_LocalDpmScoreboard { + uint32_t PercentageBusy; + + int32_t PIDError; + int32_t PIDIntegral; + int32_t PIDOutput; + + uint32_t SigmaDeltaAccum; + uint32_t SigmaDeltaOutput; + uint32_t SigmaDeltaLevel; + + uint32_t UtilizationSetpoint; + + uint8_t TdpClampMode; + uint8_t TdcClampMode; + uint8_t ThermClampMode; + uint8_t VoltageBusy; + + int8_t CurrLevel; + int8_t TargLevel; + uint8_t LevelChangeInProgress; + uint8_t UpHyst; + + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t DpmEnable; + uint8_t DpmRunning; + + uint8_t DpmForce; + uint8_t DpmForceLevel; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + + uint32_t MinimumPerfSclk; + + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t GfxClkSlow; + uint8_t GpioClampMode; /* bit0 = VRHOT: bit1 = THERM: bit2 = DC */ + + uint8_t FpsFilterWeight; + uint8_t EnabledLevelsChange; + uint8_t DteClampMode; + uint8_t FpsClampMode; + + uint16_t LevelResidencyCounters[SMU72_MAX_LEVELS_GRAPHICS]; + uint16_t LevelSwitchCounters[SMU72_MAX_LEVELS_GRAPHICS]; + + void (*TargetStateCalculator)(uint8_t); + void (*SavedTargetStateCalculator)(uint8_t); + + uint16_t AutoDpmInterval; + uint16_t AutoDpmRange; + + uint8_t FpsEnabled; + uint8_t MaxPerfLevel; + uint8_t AllowLowClkInterruptToHost; + uint8_t FpsRunning; + + uint32_t MaxAllowedFrequency; + + uint32_t FilteredSclkFrequency; + uint32_t LastSclkFrequency; + uint32_t FilteredSclkFrequencyCnt; +}; + +typedef struct SMU7_LocalDpmScoreboard SMU7_LocalDpmScoreboard; + +#define SMU7_MAX_VOLTAGE_CLIENTS 12 + +typedef uint8_t (*VoltageChangeHandler_t)(uint16_t, uint8_t); + +struct SMU_VoltageLevel { + uint8_t Vddc; + uint8_t Vddci; + uint8_t VddGfx; + uint8_t Phases; +}; + +typedef struct SMU_VoltageLevel SMU_VoltageLevel; + +struct SMU7_VoltageScoreboard { + SMU_VoltageLevel CurrentVoltage; + SMU_VoltageLevel TargetVoltage; + uint16_t MaxVid; + uint8_t HighestVidOffset; + uint8_t CurrentVidOffset; + + uint8_t ControllerBusy; + uint8_t CurrentVid; + uint8_t CurrentVddciVid; + uint8_t VddGfxShutdown; /* 0 = normal mode, 1 = shut down */ + + SMU_VoltageLevel RequestedVoltage[SMU7_MAX_VOLTAGE_CLIENTS]; + uint8_t EnabledRequest[SMU7_MAX_VOLTAGE_CLIENTS]; + + uint8_t TargetIndex; + uint8_t Delay; + uint8_t ControllerEnable; + uint8_t ControllerRunning; + uint16_t CurrentStdVoltageHiSidd; + uint16_t CurrentStdVoltageLoSidd; + uint8_t OverrideVoltage; + uint8_t VddcUseUlvOffset; + uint8_t VddGfxUseUlvOffset; + uint8_t padding; + + VoltageChangeHandler_t ChangeVddc; + VoltageChangeHandler_t ChangeVddGfx; + VoltageChangeHandler_t ChangeVddci; + VoltageChangeHandler_t ChangePhase; + VoltageChangeHandler_t ChangeMvdd; + + VoltageChangeHandler_t functionLinks[6]; + + uint8_t *VddcFollower1; + uint8_t *VddcFollower2; + int16_t Driver_OD_RequestedVidOffset1; + int16_t Driver_OD_RequestedVidOffset2; + +}; + +typedef struct SMU7_VoltageScoreboard SMU7_VoltageScoreboard; + +#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */ + +struct SMU7_PCIeLinkSpeedScoreboard { + uint8_t DpmEnable; + uint8_t DpmRunning; + uint8_t DpmForce; + uint8_t DpmForceLevel; + + uint8_t CurrentLinkSpeed; + uint8_t EnabledLevelsChange; + uint16_t AutoDpmInterval; + + uint16_t AutoDpmRange; + uint16_t AutoDpmCount; + + uint8_t DpmMode; + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t CurrentLinkLevel; + +}; + +typedef struct SMU7_PCIeLinkSpeedScoreboard SMU7_PCIeLinkSpeedScoreboard; + +/* -------------------------------------------------------- CAC table ------------------------------------------------------ */ +#define SMU7_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 +#define SMU7_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16 +#define SMU7_SCALE_I 7 +#define SMU7_SCALE_R 12 + +struct SMU7_PowerScoreboard { + PowerCalculatorData_t VddGfxPowerData[SID_OPTION_COUNT]; + PowerCalculatorData_t VddcPowerData[SID_OPTION_COUNT]; + + uint32_t TotalGpuPower; + uint32_t TdcCurrent; + + uint16_t VddciTotalPower; + uint16_t sparesasfsdfd; + uint16_t Vddr1Power; + uint16_t RocPower; + + uint16_t CalcMeasPowerBlend; + uint8_t SidOptionPower; + uint8_t SidOptionCurrent; + + uint32_t WinTime; + + uint16_t Telemetry_1_slope; + uint16_t Telemetry_2_slope; + int32_t Telemetry_1_offset; + int32_t Telemetry_2_offset; + + uint32_t VddcCurrentTelemetry; + uint32_t VddGfxCurrentTelemetry; + uint32_t VddcPowerTelemetry; + uint32_t VddGfxPowerTelemetry; + uint32_t VddciPowerTelemetry; + + uint32_t VddcPower; + uint32_t VddGfxPower; + uint32_t VddciPower; + + uint32_t TelemetryCurrent[2]; + uint32_t TelemetryVoltage[2]; + uint32_t TelemetryPower[2]; +}; + +typedef struct SMU7_PowerScoreboard SMU7_PowerScoreboard; + +struct SMU7_ThermalScoreboard { + int16_t GpuLimit; + int16_t GpuHyst; + uint16_t CurrGnbTemp; + uint16_t FilteredGnbTemp; + + uint8_t ControllerEnable; + uint8_t ControllerRunning; + uint8_t AutoTmonCalInterval; + uint8_t AutoTmonCalEnable; + + uint8_t ThermalDpmEnabled; + uint8_t SclkEnabledMask; + uint8_t spare[2]; + int32_t temperature_gradient; + + SMU7_HystController_Data HystControllerData; + int32_t WeightedSensorTemperature; + uint16_t TemperatureLimit[SMU72_MAX_LEVELS_GRAPHICS]; + uint32_t Alpha; +}; + +typedef struct SMU7_ThermalScoreboard SMU7_ThermalScoreboard; + +/* For FeatureEnables: */ +#define SMU7_SCLK_DPM_CONFIG_MASK 0x01 +#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK 0x02 +#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK 0x04 +#define SMU7_MCLK_DPM_CONFIG_MASK 0x08 +#define SMU7_UVD_DPM_CONFIG_MASK 0x10 +#define SMU7_VCE_DPM_CONFIG_MASK 0x20 +#define SMU7_ACP_DPM_CONFIG_MASK 0x40 +#define SMU7_SAMU_DPM_CONFIG_MASK 0x80 +#define SMU7_PCIEGEN_DPM_CONFIG_MASK 0x100 + +#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE 0x00000001 +#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE 0x00000002 +#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE 0x00000100 +#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE 0x00000200 +#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE 0x00010000 +#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE 0x00020000 + +/* All 'soft registers' should be uint32_t. */ +struct SMU72_SoftRegisters { + uint32_t RefClockFrequency; + uint32_t PmTimerPeriod; + uint32_t FeatureEnables; + + uint32_t PreVBlankGap; + uint32_t VBlankTimeout; + uint32_t TrainTimeGap; + + uint32_t MvddSwitchTime; + uint32_t LongestAcpiTrainTime; + uint32_t AcpiDelay; + uint32_t G5TrainTime; + uint32_t DelayMpllPwron; + uint32_t VoltageChangeTimeout; + + uint32_t HandshakeDisables; + + uint8_t DisplayPhy1Config; + uint8_t DisplayPhy2Config; + uint8_t DisplayPhy3Config; + uint8_t DisplayPhy4Config; + + uint8_t DisplayPhy5Config; + uint8_t DisplayPhy6Config; + uint8_t DisplayPhy7Config; + uint8_t DisplayPhy8Config; + + uint32_t AverageGraphicsActivity; + uint32_t AverageMemoryActivity; + uint32_t AverageGioActivity; + + uint8_t SClkDpmEnabledLevels; + uint8_t MClkDpmEnabledLevels; + uint8_t LClkDpmEnabledLevels; + uint8_t PCIeDpmEnabledLevels; + + uint8_t UVDDpmEnabledLevels; + uint8_t SAMUDpmEnabledLevels; + uint8_t ACPDpmEnabledLevels; + uint8_t VCEDpmEnabledLevels; + + uint32_t DRAM_LOG_ADDR_H; + uint32_t DRAM_LOG_ADDR_L; + uint32_t DRAM_LOG_PHY_ADDR_H; + uint32_t DRAM_LOG_PHY_ADDR_L; + uint32_t DRAM_LOG_BUFF_SIZE; + uint32_t UlvEnterCount; + uint32_t UlvTime; + uint32_t UcodeLoadStatus; + uint32_t Reserved[2]; + +}; + +typedef struct SMU72_SoftRegisters SMU72_SoftRegisters; + +struct SMU72_Firmware_Header { + uint32_t Digest[5]; + uint32_t Version; + uint32_t HeaderSize; + uint32_t Flags; + uint32_t EntryPoint; + uint32_t CodeSize; + uint32_t ImageSize; + + uint32_t Rtos; + uint32_t SoftRegisters; + uint32_t DpmTable; + uint32_t FanTable; + uint32_t CacConfigTable; + uint32_t CacStatusTable; + uint32_t mcRegisterTable; + uint32_t mcArbDramTimingTable; + uint32_t PmFuseTable; + uint32_t Globals; + uint32_t ClockStretcherTable; + uint32_t Reserved[41]; + uint32_t Signature; +}; + +typedef struct SMU72_Firmware_Header SMU72_Firmware_Header; + +#define SMU72_FIRMWARE_HEADER_LOCATION 0x20000 + +enum DisplayConfig { + PowerDown = 1, + DP54x4, + DP54x2, + DP54x1, + DP27x4, + DP27x2, + DP27x1, + HDMI297, + HDMI162, + LVDS, + DP324x4, + DP324x2, + DP324x1 +}; + +#define MC_BLOCK_COUNT 1 +#define CPL_BLOCK_COUNT 5 +#define SE_BLOCK_COUNT 15 +#define GC_BLOCK_COUNT 24 + +struct SMU7_Local_Cac { + uint8_t BlockId; + uint8_t SignalId; + uint8_t Threshold; + uint8_t Padding; +}; + +typedef struct SMU7_Local_Cac SMU7_Local_Cac; + +struct SMU7_Local_Cac_Table { + SMU7_Local_Cac CplLocalCac[CPL_BLOCK_COUNT]; + SMU7_Local_Cac McLocalCac[MC_BLOCK_COUNT]; + SMU7_Local_Cac SeLocalCac[SE_BLOCK_COUNT]; + SMU7_Local_Cac GcLocalCac[GC_BLOCK_COUNT]; +}; + +typedef struct SMU7_Local_Cac_Table SMU7_Local_Cac_Table; + +#if !defined(SMC_MICROCODE) +#pragma pack(pop) +#endif + +/* Description of Clock Gating bitmask for Tonga: */ +/* System Clock Gating */ +#define CG_SYS_BITMASK_FIRST_BIT 0 /* First bit of Sys CG bitmask */ +#define CG_SYS_BITMASK_LAST_BIT 9 /* Last bit of Sys CG bitmask */ +#define CG_SYS_BIF_MGLS_SHIFT 0 +#define CG_SYS_ROM_SHIFT 1 +#define CG_SYS_MC_MGCG_SHIFT 2 +#define CG_SYS_MC_MGLS_SHIFT 3 +#define CG_SYS_SDMA_MGCG_SHIFT 4 +#define CG_SYS_SDMA_MGLS_SHIFT 5 +#define CG_SYS_DRM_MGCG_SHIFT 6 +#define CG_SYS_HDP_MGCG_SHIFT 7 +#define CG_SYS_HDP_MGLS_SHIFT 8 +#define CG_SYS_DRM_MGLS_SHIFT 9 + +#define CG_SYS_BIF_MGLS_MASK 0x1 +#define CG_SYS_ROM_MASK 0x2 +#define CG_SYS_MC_MGCG_MASK 0x4 +#define CG_SYS_MC_MGLS_MASK 0x8 +#define CG_SYS_SDMA_MGCG_MASK 0x10 +#define CG_SYS_SDMA_MGLS_MASK 0x20 +#define CG_SYS_DRM_MGCG_MASK 0x40 +#define CG_SYS_HDP_MGCG_MASK 0x80 +#define CG_SYS_HDP_MGLS_MASK 0x100 +#define CG_SYS_DRM_MGLS_MASK 0x200 + +/* Graphics Clock Gating */ +#define CG_GFX_BITMASK_FIRST_BIT 16 /* First bit of Gfx CG bitmask */ +#define CG_GFX_BITMASK_LAST_BIT 20 /* Last bit of Gfx CG bitmask */ +#define CG_GFX_CGCG_SHIFT 16 +#define CG_GFX_CGLS_SHIFT 17 +#define CG_CPF_MGCG_SHIFT 18 +#define CG_RLC_MGCG_SHIFT 19 +#define CG_GFX_OTHERS_MGCG_SHIFT 20 + +#define CG_GFX_CGCG_MASK 0x00010000 +#define CG_GFX_CGLS_MASK 0x00020000 +#define CG_CPF_MGCG_MASK 0x00040000 +#define CG_RLC_MGCG_MASK 0x00080000 +#define CG_GFX_OTHERS_MGCG_MASK 0x00100000 + +/* Voltage Regulator Configuration */ +/* VR Config info is contained in dpmTable.VRConfig */ + +#define VRCONF_VDDC_MASK 0x000000FF +#define VRCONF_VDDC_SHIFT 0 +#define VRCONF_VDDGFX_MASK 0x0000FF00 +#define VRCONF_VDDGFX_SHIFT 8 +#define VRCONF_VDDCI_MASK 0x00FF0000 +#define VRCONF_VDDCI_SHIFT 16 +#define VRCONF_MVDD_MASK 0xFF000000 +#define VRCONF_MVDD_SHIFT 24 + +#define VR_MERGED_WITH_VDDC 0 +#define VR_SVI2_PLANE_1 1 +#define VR_SVI2_PLANE_2 2 +#define VR_SMIO_PATTERN_1 3 +#define VR_SMIO_PATTERN_2 4 +#define VR_STATIC_VOLTAGE 5 + +/* Clock Stretcher Configuration */ + +#define CLOCK_STRETCHER_MAX_ENTRIES 0x4 +#define CKS_LOOKUPTable_MAX_ENTRIES 0x4 + +/* The 'settings' field is subdivided in the following way: */ +#define CLOCK_STRETCHER_SETTING_DDT_MASK 0x01 +#define CLOCK_STRETCHER_SETTING_DDT_SHIFT 0x0 +#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_MASK 0x1E +#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_SHIFT 0x1 +#define CLOCK_STRETCHER_SETTING_ENABLE_MASK 0x80 +#define CLOCK_STRETCHER_SETTING_ENABLE_SHIFT 0x7 + +struct SMU_ClockStretcherDataTableEntry { + uint8_t minVID; + uint8_t maxVID; + + uint16_t setting; +}; +typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry; + +struct SMU_ClockStretcherDataTable { + SMU_ClockStretcherDataTableEntry ClockStretcherDataTableEntry[CLOCK_STRETCHER_MAX_ENTRIES]; +}; +typedef struct SMU_ClockStretcherDataTable SMU_ClockStretcherDataTable; + +struct SMU_CKS_LOOKUPTableEntry { + uint16_t minFreq; + uint16_t maxFreq; + + uint8_t setting; + uint8_t padding[3]; +}; +typedef struct SMU_CKS_LOOKUPTableEntry SMU_CKS_LOOKUPTableEntry; + +struct SMU_CKS_LOOKUPTable { + SMU_CKS_LOOKUPTableEntry CKS_LOOKUPTableEntry[CKS_LOOKUPTable_MAX_ENTRIES]; +}; +typedef struct SMU_CKS_LOOKUPTable SMU_CKS_LOOKUPTable; + +#endif + + diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h new file mode 100644 index 000000000000..98f76e925e65 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smu72_discrete.h @@ -0,0 +1,760 @@ +#ifndef SMU72_DISCRETE_H +#define SMU72_DISCRETE_H + +#include "smu72.h" + +#if !defined(SMC_MICROCODE) +#pragma pack(push, 1) +#endif + +struct SMIO_Pattern { + uint16_t Voltage; + uint8_t Smio; + uint8_t padding; +}; + +typedef struct SMIO_Pattern SMIO_Pattern; + +struct SMIO_Table { + SMIO_Pattern Pattern[SMU_MAX_SMIO_LEVELS]; +}; + +typedef struct SMIO_Table SMIO_Table; + +struct SMU72_Discrete_GraphicsLevel { + SMU_VoltageLevel MinVoltage; + + uint32_t SclkFrequency; + + uint8_t pcieDpmLevel; + uint8_t DeepSleepDivId; + uint16_t ActivityLevel; + + uint32_t CgSpllFuncCntl3; + uint32_t CgSpllFuncCntl4; + uint32_t SpllSpreadSpectrum; + uint32_t SpllSpreadSpectrum2; + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; + uint8_t SclkDid; + uint8_t DisplayWatermark; + uint8_t EnabledForActivity; + uint8_t EnabledForThrottle; + uint8_t UpHyst; + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t PowerThrottle; +}; + +typedef struct SMU72_Discrete_GraphicsLevel SMU72_Discrete_GraphicsLevel; + +struct SMU72_Discrete_ACPILevel { + uint32_t Flags; + SMU_VoltageLevel MinVoltage; + uint32_t SclkFrequency; + uint8_t SclkDid; + uint8_t DisplayWatermark; + uint8_t DeepSleepDivId; + uint8_t padding; + uint32_t CgSpllFuncCntl; + uint32_t CgSpllFuncCntl2; + uint32_t CgSpllFuncCntl3; + uint32_t CgSpllFuncCntl4; + uint32_t SpllSpreadSpectrum; + uint32_t SpllSpreadSpectrum2; + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; +}; + +typedef struct SMU72_Discrete_ACPILevel SMU72_Discrete_ACPILevel; + +struct SMU72_Discrete_Ulv { + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; + uint16_t VddcOffset; + uint8_t VddcOffsetVid; + uint8_t VddcPhase; + uint32_t Reserved; +}; + +typedef struct SMU72_Discrete_Ulv SMU72_Discrete_Ulv; + +struct SMU72_Discrete_MemoryLevel { + SMU_VoltageLevel MinVoltage; + uint32_t MinMvdd; + + uint32_t MclkFrequency; + + uint8_t EdcReadEnable; + uint8_t EdcWriteEnable; + uint8_t RttEnable; + uint8_t StutterEnable; + + uint8_t StrobeEnable; + uint8_t StrobeRatio; + uint8_t EnabledForThrottle; + uint8_t EnabledForActivity; + + uint8_t UpHyst; + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t padding; + + uint16_t ActivityLevel; + uint8_t DisplayWatermark; + uint8_t padding1; + + uint32_t MpllFuncCntl; + uint32_t MpllFuncCntl_1; + uint32_t MpllFuncCntl_2; + uint32_t MpllAdFuncCntl; + uint32_t MpllDqFuncCntl; + uint32_t MclkPwrmgtCntl; + uint32_t DllCntl; + uint32_t MpllSs1; + uint32_t MpllSs2; +}; + +typedef struct SMU72_Discrete_MemoryLevel SMU72_Discrete_MemoryLevel; + +struct SMU72_Discrete_LinkLevel { + uint8_t PcieGenSpeed; /*< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 */ + uint8_t PcieLaneCount; /*< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 */ + uint8_t EnabledForActivity; + uint8_t SPC; + uint32_t DownThreshold; + uint32_t UpThreshold; + uint32_t Reserved; +}; + +typedef struct SMU72_Discrete_LinkLevel SMU72_Discrete_LinkLevel; + +/* MC ARB DRAM Timing registers. */ +struct SMU72_Discrete_MCArbDramTimingTableEntry { + uint32_t McArbDramTiming; + uint32_t McArbDramTiming2; + uint8_t McArbBurstTime; + uint8_t padding[3]; +}; + +typedef struct SMU72_Discrete_MCArbDramTimingTableEntry SMU72_Discrete_MCArbDramTimingTableEntry; + +struct SMU72_Discrete_MCArbDramTimingTable { + SMU72_Discrete_MCArbDramTimingTableEntry entries[SMU__NUM_SCLK_DPM_STATE][SMU__NUM_MCLK_DPM_LEVELS]; +}; + +typedef struct SMU72_Discrete_MCArbDramTimingTable SMU72_Discrete_MCArbDramTimingTable; + +/* UVD VCLK/DCLK state (level) definition. */ +struct SMU72_Discrete_UvdLevel { + uint32_t VclkFrequency; + uint32_t DclkFrequency; + SMU_VoltageLevel MinVoltage; + uint8_t VclkDivider; + uint8_t DclkDivider; + uint8_t padding[2]; +}; + +typedef struct SMU72_Discrete_UvdLevel SMU72_Discrete_UvdLevel; + +/* Clocks for other external blocks (VCE, ACP, SAMU). */ +struct SMU72_Discrete_ExtClkLevel { + uint32_t Frequency; + SMU_VoltageLevel MinVoltage; + uint8_t Divider; + uint8_t padding[3]; +}; + +typedef struct SMU72_Discrete_ExtClkLevel SMU72_Discrete_ExtClkLevel; + +struct SMU72_Discrete_StateInfo { + uint32_t SclkFrequency; + uint32_t MclkFrequency; + uint32_t VclkFrequency; + uint32_t DclkFrequency; + uint32_t SamclkFrequency; + uint32_t AclkFrequency; + uint32_t EclkFrequency; + uint16_t MvddVoltage; + uint16_t padding16; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + uint8_t McRegIndex; + uint8_t SeqIndex; + uint8_t SclkDid; + int8_t SclkIndex; + int8_t MclkIndex; + uint8_t PCIeGen; + +}; + +typedef struct SMU72_Discrete_StateInfo SMU72_Discrete_StateInfo; + +struct SMU72_Discrete_DpmTable { + /* Multi-DPM controller settings */ + SMU72_PIDController GraphicsPIDController; + SMU72_PIDController MemoryPIDController; + SMU72_PIDController LinkPIDController; + + uint32_t SystemFlags; + + /* SMIO masks for voltage and phase controls */ + uint32_t VRConfig; + uint32_t SmioMask1; + uint32_t SmioMask2; + SMIO_Table SmioTable1; + SMIO_Table SmioTable2; + + uint32_t VddcLevelCount; + uint32_t VddciLevelCount; + uint32_t VddGfxLevelCount; + uint32_t MvddLevelCount; + + uint16_t VddcTable[SMU72_MAX_LEVELS_VDDC]; + uint16_t VddGfxTable[SMU72_MAX_LEVELS_VDDGFX]; + uint16_t VddciTable[SMU72_MAX_LEVELS_VDDCI]; + + uint8_t BapmVddGfxVidHiSidd[SMU72_MAX_LEVELS_VDDGFX]; + uint8_t BapmVddGfxVidLoSidd[SMU72_MAX_LEVELS_VDDGFX]; + uint8_t BapmVddGfxVidHiSidd2[SMU72_MAX_LEVELS_VDDGFX]; + + uint8_t BapmVddcVidHiSidd[SMU72_MAX_LEVELS_VDDC]; + uint8_t BapmVddcVidLoSidd[SMU72_MAX_LEVELS_VDDC]; + uint8_t BapmVddcVidHiSidd2[SMU72_MAX_LEVELS_VDDC]; + + uint8_t GraphicsDpmLevelCount; + uint8_t MemoryDpmLevelCount; + uint8_t LinkLevelCount; + uint8_t MasterDeepSleepControl; + + uint8_t UvdLevelCount; + uint8_t VceLevelCount; + uint8_t AcpLevelCount; + uint8_t SamuLevelCount; + + uint8_t ThermOutGpio; + uint8_t ThermOutPolarity; + uint8_t ThermOutMode; + uint8_t DPMFreezeAndForced; + uint32_t Reserved[4]; + + /* State table entries for each DPM state */ + SMU72_Discrete_GraphicsLevel GraphicsLevel[SMU72_MAX_LEVELS_GRAPHICS]; + SMU72_Discrete_MemoryLevel MemoryACPILevel; + SMU72_Discrete_MemoryLevel MemoryLevel[SMU72_MAX_LEVELS_MEMORY]; + SMU72_Discrete_LinkLevel LinkLevel[SMU72_MAX_LEVELS_LINK]; + SMU72_Discrete_ACPILevel ACPILevel; + SMU72_Discrete_UvdLevel UvdLevel[SMU72_MAX_LEVELS_UVD]; + SMU72_Discrete_ExtClkLevel VceLevel[SMU72_MAX_LEVELS_VCE]; + SMU72_Discrete_ExtClkLevel AcpLevel[SMU72_MAX_LEVELS_ACP]; + SMU72_Discrete_ExtClkLevel SamuLevel[SMU72_MAX_LEVELS_SAMU]; + SMU72_Discrete_Ulv Ulv; + + uint32_t SclkStepSize; + uint32_t Smio[SMU72_MAX_ENTRIES_SMIO]; + + uint8_t UvdBootLevel; + uint8_t VceBootLevel; + uint8_t AcpBootLevel; + uint8_t SamuBootLevel; + + uint8_t GraphicsBootLevel; + uint8_t GraphicsVoltageChangeEnable; + uint8_t GraphicsThermThrottleEnable; + uint8_t GraphicsInterval; + + uint8_t VoltageInterval; + uint8_t ThermalInterval; + uint16_t TemperatureLimitHigh; + + uint16_t TemperatureLimitLow; + uint8_t MemoryBootLevel; + uint8_t MemoryVoltageChangeEnable; + + uint16_t BootMVdd; + uint8_t MemoryInterval; + uint8_t MemoryThermThrottleEnable; + + uint16_t VoltageResponseTime; + uint16_t PhaseResponseTime; + + uint8_t PCIeBootLinkLevel; + uint8_t PCIeGenInterval; + uint8_t DTEInterval; + uint8_t DTEMode; + + uint8_t SVI2Enable; + uint8_t VRHotGpio; + uint8_t AcDcGpio; + uint8_t ThermGpio; + + uint16_t PPM_PkgPwrLimit; + uint16_t PPM_TemperatureLimit; + + uint16_t DefaultTdp; + uint16_t TargetTdp; + + uint16_t FpsHighThreshold; + uint16_t FpsLowThreshold; + + uint16_t BAPMTI_R[SMU72_DTE_ITERATIONS][SMU72_DTE_SOURCES][SMU72_DTE_SINKS]; + uint16_t BAPMTI_RC[SMU72_DTE_ITERATIONS][SMU72_DTE_SOURCES][SMU72_DTE_SINKS]; + + uint8_t DTEAmbientTempBase; + uint8_t DTETjOffset; + uint8_t GpuTjMax; + uint8_t GpuTjHyst; + + SMU_VoltageLevel BootVoltage; + + uint32_t BAPM_TEMP_GRADIENT; + + uint32_t LowSclkInterruptThreshold; + uint32_t VddGfxReChkWait; + + uint8_t ClockStretcherAmount; + + uint8_t Sclk_CKS_masterEn0_7; + uint8_t Sclk_CKS_masterEn8_15; + uint8_t padding[1]; + + uint8_t Sclk_voltageOffset[8]; + + SMU_ClockStretcherDataTable ClockStretcherDataTable; + SMU_CKS_LOOKUPTable CKS_LOOKUPTable; +}; + +typedef struct SMU72_Discrete_DpmTable SMU72_Discrete_DpmTable; + +/* --------------------------------------------------- AC Timing Parameters ------------------------------------------------ */ +#define SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE 16 +#define SMU72_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT SMU72_MAX_LEVELS_MEMORY /* DPM */ + +struct SMU72_Discrete_MCRegisterAddress { + uint16_t s0; + uint16_t s1; +}; + +typedef struct SMU72_Discrete_MCRegisterAddress SMU72_Discrete_MCRegisterAddress; + +struct SMU72_Discrete_MCRegisterSet { + uint32_t value[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; +}; + +typedef struct SMU72_Discrete_MCRegisterSet SMU72_Discrete_MCRegisterSet; + +struct SMU72_Discrete_MCRegisters { + uint8_t last; + uint8_t reserved[3]; + SMU72_Discrete_MCRegisterAddress address[SMU72_DISCRETE_MC_REGISTER_ARRAY_SIZE]; + SMU72_Discrete_MCRegisterSet data[SMU72_DISCRETE_MC_REGISTER_ARRAY_SET_COUNT]; +}; + +typedef struct SMU72_Discrete_MCRegisters SMU72_Discrete_MCRegisters; + + +/* --------------------------------------------------- Fan Table ----------------------------------------------------------- */ + +struct SMU72_Discrete_FanTable { + uint16_t FdoMode; + int16_t TempMin; + int16_t TempMed; + int16_t TempMax; + int16_t Slope1; + int16_t Slope2; + int16_t FdoMin; + int16_t HystUp; + int16_t HystDown; + int16_t HystSlope; + int16_t TempRespLim; + int16_t TempCurr; + int16_t SlopeCurr; + int16_t PwmCurr; + uint32_t RefreshPeriod; + int16_t FdoMax; + uint8_t TempSrc; + int8_t FanControl_GL_Flag; +}; + +typedef struct SMU72_Discrete_FanTable SMU72_Discrete_FanTable; + +#define SMU7_DISCRETE_GPIO_SCLK_DEBUG 4 +#define SMU7_DISCRETE_GPIO_SCLK_DEBUG_BIT (0x1 << SMU7_DISCRETE_GPIO_SCLK_DEBUG) + +struct SMU7_MclkDpmScoreboard { + + uint32_t PercentageBusy; + + int32_t PIDError; + int32_t PIDIntegral; + int32_t PIDOutput; + + uint32_t SigmaDeltaAccum; + uint32_t SigmaDeltaOutput; + uint32_t SigmaDeltaLevel; + + uint32_t UtilizationSetpoint; + + uint8_t TdpClampMode; + uint8_t TdcClampMode; + uint8_t ThermClampMode; + uint8_t VoltageBusy; + + int8_t CurrLevel; + int8_t TargLevel; + uint8_t LevelChangeInProgress; + uint8_t UpHyst; + + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t DpmEnable; + uint8_t DpmRunning; + + uint8_t DpmForce; + uint8_t DpmForceLevel; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + + uint32_t MinimumPerfMclk; + + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t MclkSwitchInProgress; + uint8_t MclkSwitchCritical; + + uint8_t IgnoreVBlank; + uint8_t TargetMclkIndex; + uint8_t TargetMvddIndex; + uint8_t MclkSwitchResult; + + uint16_t VbiFailureCount; + uint8_t VbiWaitCounter; + uint8_t EnabledLevelsChange; + + uint16_t LevelResidencyCountersN[SMU72_MAX_LEVELS_MEMORY]; + uint16_t LevelSwitchCounters[SMU72_MAX_LEVELS_MEMORY]; + + void (*TargetStateCalculator)(uint8_t); + void (*SavedTargetStateCalculator)(uint8_t); + + uint16_t AutoDpmInterval; + uint16_t AutoDpmRange; + + uint16_t VbiTimeoutCount; + uint16_t MclkSwitchingTime; + + uint8_t fastSwitch; + uint8_t Save_PIC_VDDGFX_EXIT; + uint8_t Save_PIC_VDDGFX_ENTER; + uint8_t padding; + +}; + +typedef struct SMU7_MclkDpmScoreboard SMU7_MclkDpmScoreboard; + +struct SMU7_UlvScoreboard { + uint8_t EnterUlv; + uint8_t ExitUlv; + uint8_t UlvActive; + uint8_t WaitingForUlv; + uint8_t UlvEnable; + uint8_t UlvRunning; + uint8_t UlvMasterEnable; + uint8_t padding; + uint32_t UlvAbortedCount; + uint32_t UlvTimeStamp; +}; + +typedef struct SMU7_UlvScoreboard SMU7_UlvScoreboard; + +struct VddgfxSavedRegisters { + uint32_t GPU_DBG[3]; + uint32_t MEC_BaseAddress_Hi; + uint32_t MEC_BaseAddress_Lo; + uint32_t THM_TMON0_CTRL2__RDIR_PRESENT; + uint32_t THM_TMON1_CTRL2__RDIR_PRESENT; + uint32_t CP_INT_CNTL; +}; + +typedef struct VddgfxSavedRegisters VddgfxSavedRegisters; + +struct SMU7_VddGfxScoreboard { + uint8_t VddGfxEnable; + uint8_t VddGfxActive; + uint8_t VPUResetOccured; + uint8_t padding; + + uint32_t VddGfxEnteredCount; + uint32_t VddGfxAbortedCount; + + uint32_t VddGfxVid; + + VddgfxSavedRegisters SavedRegisters; +}; + +typedef struct SMU7_VddGfxScoreboard SMU7_VddGfxScoreboard; + +struct SMU7_TdcLimitScoreboard { + uint8_t Enable; + uint8_t Running; + uint16_t Alpha; + uint32_t FilteredIddc; + uint32_t IddcLimit; + uint32_t IddcHyst; + SMU7_HystController_Data HystControllerData; +}; + +typedef struct SMU7_TdcLimitScoreboard SMU7_TdcLimitScoreboard; + +struct SMU7_PkgPwrLimitScoreboard { + uint8_t Enable; + uint8_t Running; + uint16_t Alpha; + uint32_t FilteredPkgPwr; + uint32_t Limit; + uint32_t Hyst; + uint32_t LimitFromDriver; + SMU7_HystController_Data HystControllerData; +}; + +typedef struct SMU7_PkgPwrLimitScoreboard SMU7_PkgPwrLimitScoreboard; + +struct SMU7_BapmScoreboard { + uint32_t source_powers[SMU72_DTE_SOURCES]; + uint32_t source_powers_last[SMU72_DTE_SOURCES]; + int32_t entity_temperatures[SMU72_NUM_GPU_TES]; + int32_t initial_entity_temperatures[SMU72_NUM_GPU_TES]; + int32_t Limit; + int32_t Hyst; + int32_t therm_influence_coeff_table[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS * 2]; + int32_t therm_node_table[SMU72_DTE_ITERATIONS * SMU72_DTE_SOURCES * SMU72_DTE_SINKS]; + uint16_t ConfigTDPPowerScalar; + uint16_t FanSpeedPowerScalar; + uint16_t OverDrivePowerScalar; + uint16_t OverDriveLimitScalar; + uint16_t FinalPowerScalar; + uint8_t VariantID; + uint8_t spare997; + + SMU7_HystController_Data HystControllerData; + + int32_t temperature_gradient_slope; + int32_t temperature_gradient; + uint32_t measured_temperature; +}; + + +typedef struct SMU7_BapmScoreboard SMU7_BapmScoreboard; + +struct SMU7_AcpiScoreboard { + uint32_t SavedInterruptMask[2]; + uint8_t LastACPIRequest; + uint8_t CgBifResp; + uint8_t RequestType; + uint8_t Padding; + SMU72_Discrete_ACPILevel D0Level; +}; + +typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard; + +struct SMU72_Discrete_PmFuses { + /* dw1 */ + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t SviLoadLineTrimVddC; + uint8_t SviLoadLineOffsetVddC; + + /* dw2 */ + uint16_t TDC_VDDC_PkgLimit; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + + /* dw3 */ + uint8_t TdcWaterfallCtl; + uint8_t LPMLTemperatureMin; + uint8_t LPMLTemperatureMax; + uint8_t Reserved; + + /* dw4-dw7 */ + uint8_t LPMLTemperatureScaler[16]; + + /* dw8-dw9 */ + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t Reserved6; + + /* dw10-dw14 */ + uint8_t GnbLPML[16]; + + /* dw15 */ + uint8_t GnbLPMLMaxVid; + uint8_t GnbLPMLMinVid; + uint8_t Reserved1[2]; + + /* dw16 */ + uint16_t BapmVddCBaseLeakageHiSidd; + uint16_t BapmVddCBaseLeakageLoSidd; +}; + +typedef struct SMU72_Discrete_PmFuses SMU72_Discrete_PmFuses; + +struct SMU7_Discrete_Log_Header_Table { + uint32_t version; + uint32_t asic_id; + uint16_t flags; + uint16_t entry_size; + uint32_t total_size; + uint32_t num_of_entries; + uint8_t type; + uint8_t mode; + uint8_t filler_0[2]; + uint32_t filler_1[2]; +}; + +typedef struct SMU7_Discrete_Log_Header_Table SMU7_Discrete_Log_Header_Table; + +struct SMU7_Discrete_Log_Cntl { + uint8_t Enabled; + uint8_t Type; + uint8_t padding[2]; + uint32_t BufferSize; + uint32_t SamplesLogged; + uint32_t SampleSize; + uint32_t AddrL; + uint32_t AddrH; +}; + +typedef struct SMU7_Discrete_Log_Cntl SMU7_Discrete_Log_Cntl; + +#define CAC_ACC_NW_NUM_OF_SIGNALS 87 + +struct SMU7_Discrete_Cac_Collection_Table { + uint32_t temperature; + uint32_t cac_acc_nw[CAC_ACC_NW_NUM_OF_SIGNALS]; +}; + +typedef struct SMU7_Discrete_Cac_Collection_Table SMU7_Discrete_Cac_Collection_Table; + +struct SMU7_Discrete_Cac_Verification_Table { + uint32_t VddcTotalPower; + uint32_t VddcLeakagePower; + uint32_t VddcConstantPower; + uint32_t VddcGfxDynamicPower; + uint32_t VddcUvdDynamicPower; + uint32_t VddcVceDynamicPower; + uint32_t VddcAcpDynamicPower; + uint32_t VddcPcieDynamicPower; + uint32_t VddcDceDynamicPower; + uint32_t VddcCurrent; + uint32_t VddcVoltage; + uint32_t VddciTotalPower; + uint32_t VddciLeakagePower; + uint32_t VddciConstantPower; + uint32_t VddciDynamicPower; + uint32_t Vddr1TotalPower; + uint32_t Vddr1LeakagePower; + uint32_t Vddr1ConstantPower; + uint32_t Vddr1DynamicPower; + uint32_t spare[4]; + uint32_t temperature; +}; + +typedef struct SMU7_Discrete_Cac_Verification_Table SMU7_Discrete_Cac_Verification_Table; + +struct SMU7_Discrete_Pm_Status_Table { + /* Thermal entities */ + int32_t T_meas_max; + int32_t T_meas_acc; + int32_t T_calc_max; + int32_t T_calc_acc; + uint32_t P_scalar_acc; + uint32_t P_calc_max; + uint32_t P_calc_acc; + + /*Voltage domains */ + uint32_t I_calc_max; + uint32_t I_calc_acc; + uint32_t I_calc_acc_vddci; + uint32_t V_calc_noload_acc; + uint32_t V_calc_load_acc; + uint32_t V_calc_noload_acc_vddci; + uint32_t P_meas_acc; + uint32_t V_meas_noload_acc; + uint32_t V_meas_load_acc; + uint32_t I_meas_acc; + uint32_t P_meas_acc_vddci; + uint32_t V_meas_noload_acc_vddci; + uint32_t V_meas_load_acc_vddci; + uint32_t I_meas_acc_vddci; + + /*Frequency */ + uint16_t Sclk_dpm_residency[8]; + uint16_t Uvd_dpm_residency[8]; + uint16_t Vce_dpm_residency[8]; + uint16_t Mclk_dpm_residency[4]; + + /*Chip */ + uint32_t P_vddci_acc; + uint32_t P_vddr1_acc; + uint32_t P_nte1_acc; + uint32_t PkgPwr_max; + uint32_t PkgPwr_acc; + uint32_t MclkSwitchingTime_max; + uint32_t MclkSwitchingTime_acc; + uint32_t FanPwm_acc; + uint32_t FanRpm_acc; + + uint32_t AccCnt; +}; + +typedef struct SMU7_Discrete_Pm_Status_Table SMU7_Discrete_Pm_Status_Table; + +/*FIXME THESE NEED TO BE UPDATED */ +#define SMU7_SCLK_CAC 0x561 +#define SMU7_MCLK_CAC 0xF9 +#define SMU7_VCLK_CAC 0x2DE +#define SMU7_DCLK_CAC 0x2DE +#define SMU7_ECLK_CAC 0x25E +#define SMU7_ACLK_CAC 0x25E +#define SMU7_SAMCLK_CAC 0x25E +#define SMU7_DISPCLK_CAC 0x100 +#define SMU7_CAC_CONSTANT 0x2EE3430 +#define SMU7_CAC_CONSTANT_SHIFT 18 + +#define SMU7_VDDCI_MCLK_CONST 1765 +#define SMU7_VDDCI_MCLK_CONST_SHIFT 16 +#define SMU7_VDDCI_VDDCI_CONST 50958 +#define SMU7_VDDCI_VDDCI_CONST_SHIFT 14 +#define SMU7_VDDCI_CONST 11781 + +#define SMU7_12C_VDDCI_MCLK_CONST 1623 +#define SMU7_12C_VDDCI_MCLK_CONST_SHIFT 15 +#define SMU7_12C_VDDCI_VDDCI_CONST 40088 +#define SMU7_12C_VDDCI_VDDCI_CONST_SHIFT 13 +#define SMU7_12C_VDDCI_CONST 20856 + +#define SMU7_VDDCI_STROBE_PWR 1331 + +#define SMU7_VDDR1_CONST 693 +#define SMU7_VDDR1_CAC_WEIGHT 20 +#define SMU7_VDDR1_CAC_WEIGHT_SHIFT 19 +#define SMU7_VDDR1_STROBE_PWR 512 + +#define SMU7_AREA_COEFF_UVD 0xA78 +#define SMU7_AREA_COEFF_VCE 0x190A +#define SMU7_AREA_COEFF_ACP 0x22D1 +#define SMU7_AREA_COEFF_SAMU 0x534 + +/*ThermOutMode values */ +#define SMU7_THERM_OUT_MODE_DISABLE 0x0 +#define SMU7_THERM_OUT_MODE_THERM_ONLY 0x1 +#define SMU7_THERM_OUT_MODE_THERM_VRHOT 0x2 + +#if !defined(SMC_MICROCODE) +#pragma pack(pop) +#endif + + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73.h b/drivers/gpu/drm/amd/powerplay/inc/smu73.h new file mode 100644 index 000000000000..c6b12a4c00db --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smu73.h @@ -0,0 +1,720 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _SMU73_H_ +#define _SMU73_H_ + +#pragma pack(push, 1) +enum SID_OPTION { + SID_OPTION_HI, + SID_OPTION_LO, + SID_OPTION_COUNT +}; + +enum Poly3rdOrderCoeff { + LEAKAGE_TEMPERATURE_SCALAR, + LEAKAGE_VOLTAGE_SCALAR, + DYNAMIC_VOLTAGE_SCALAR, + POLY_3RD_ORDER_COUNT +}; + +struct SMU7_Poly3rdOrder_Data +{ + int32_t a; + int32_t b; + int32_t c; + int32_t d; + uint8_t a_shift; + uint8_t b_shift; + uint8_t c_shift; + uint8_t x_shift; +}; + +typedef struct SMU7_Poly3rdOrder_Data SMU7_Poly3rdOrder_Data; + +struct Power_Calculator_Data +{ + uint16_t NoLoadVoltage; + uint16_t LoadVoltage; + uint16_t Resistance; + uint16_t Temperature; + uint16_t BaseLeakage; + uint16_t LkgTempScalar; + uint16_t LkgVoltScalar; + uint16_t LkgAreaScalar; + uint16_t LkgPower; + uint16_t DynVoltScalar; + uint32_t Cac; + uint32_t DynPower; + uint32_t TotalCurrent; + uint32_t TotalPower; +}; + +typedef struct Power_Calculator_Data PowerCalculatorData_t; + +struct Gc_Cac_Weight_Data +{ + uint8_t index; + uint32_t value; +}; + +typedef struct Gc_Cac_Weight_Data GcCacWeight_Data; + + +typedef struct { + uint32_t high; + uint32_t low; +} data_64_t; + +typedef struct { + data_64_t high; + data_64_t low; +} data_128_t; + +#define SMU__NUM_SCLK_DPM_STATE 8 +#define SMU__NUM_MCLK_DPM_LEVELS 4 +#define SMU__NUM_LCLK_DPM_LEVELS 8 +#define SMU__NUM_PCIE_DPM_LEVELS 8 + +#define SMU7_CONTEXT_ID_SMC 1 +#define SMU7_CONTEXT_ID_VBIOS 2 + +#define SMU73_MAX_LEVELS_VDDC 16 +#define SMU73_MAX_LEVELS_VDDGFX 16 +#define SMU73_MAX_LEVELS_VDDCI 8 +#define SMU73_MAX_LEVELS_MVDD 4 + +#define SMU_MAX_SMIO_LEVELS 4 + +#define SMU73_MAX_LEVELS_GRAPHICS SMU__NUM_SCLK_DPM_STATE // SCLK + SQ DPM + ULV +#define SMU73_MAX_LEVELS_MEMORY SMU__NUM_MCLK_DPM_LEVELS // MCLK Levels DPM +#define SMU73_MAX_LEVELS_GIO SMU__NUM_LCLK_DPM_LEVELS // LCLK Levels +#define SMU73_MAX_LEVELS_LINK SMU__NUM_PCIE_DPM_LEVELS // PCIe speed and number of lanes. +#define SMU73_MAX_LEVELS_UVD 8 // VCLK/DCLK levels for UVD. +#define SMU73_MAX_LEVELS_VCE 8 // ECLK levels for VCE. +#define SMU73_MAX_LEVELS_ACP 8 // ACLK levels for ACP. +#define SMU73_MAX_LEVELS_SAMU 8 // SAMCLK levels for SAMU. +#define SMU73_MAX_ENTRIES_SMIO 32 // Number of entries in SMIO table. + +#define DPM_NO_LIMIT 0 +#define DPM_NO_UP 1 +#define DPM_GO_DOWN 2 +#define DPM_GO_UP 3 + +#define SMU7_FIRST_DPM_GRAPHICS_LEVEL 0 +#define SMU7_FIRST_DPM_MEMORY_LEVEL 0 + +#define GPIO_CLAMP_MODE_VRHOT 1 +#define GPIO_CLAMP_MODE_THERM 2 +#define GPIO_CLAMP_MODE_DC 4 + +#define SCRATCH_B_TARG_PCIE_INDEX_SHIFT 0 +#define SCRATCH_B_TARG_PCIE_INDEX_MASK (0x7<<SCRATCH_B_TARG_PCIE_INDEX_SHIFT) +#define SCRATCH_B_CURR_PCIE_INDEX_SHIFT 3 +#define SCRATCH_B_CURR_PCIE_INDEX_MASK (0x7<<SCRATCH_B_CURR_PCIE_INDEX_SHIFT) +#define SCRATCH_B_TARG_UVD_INDEX_SHIFT 6 +#define SCRATCH_B_TARG_UVD_INDEX_MASK (0x7<<SCRATCH_B_TARG_UVD_INDEX_SHIFT) +#define SCRATCH_B_CURR_UVD_INDEX_SHIFT 9 +#define SCRATCH_B_CURR_UVD_INDEX_MASK (0x7<<SCRATCH_B_CURR_UVD_INDEX_SHIFT) +#define SCRATCH_B_TARG_VCE_INDEX_SHIFT 12 +#define SCRATCH_B_TARG_VCE_INDEX_MASK (0x7<<SCRATCH_B_TARG_VCE_INDEX_SHIFT) +#define SCRATCH_B_CURR_VCE_INDEX_SHIFT 15 +#define SCRATCH_B_CURR_VCE_INDEX_MASK (0x7<<SCRATCH_B_CURR_VCE_INDEX_SHIFT) +#define SCRATCH_B_TARG_ACP_INDEX_SHIFT 18 +#define SCRATCH_B_TARG_ACP_INDEX_MASK (0x7<<SCRATCH_B_TARG_ACP_INDEX_SHIFT) +#define SCRATCH_B_CURR_ACP_INDEX_SHIFT 21 +#define SCRATCH_B_CURR_ACP_INDEX_MASK (0x7<<SCRATCH_B_CURR_ACP_INDEX_SHIFT) +#define SCRATCH_B_TARG_SAMU_INDEX_SHIFT 24 +#define SCRATCH_B_TARG_SAMU_INDEX_MASK (0x7<<SCRATCH_B_TARG_SAMU_INDEX_SHIFT) +#define SCRATCH_B_CURR_SAMU_INDEX_SHIFT 27 +#define SCRATCH_B_CURR_SAMU_INDEX_MASK (0x7<<SCRATCH_B_CURR_SAMU_INDEX_SHIFT) + +// Virtualization Defines +#define CG_XDMA_MASK 0x1 +#define CG_XDMA_SHIFT 0 +#define CG_UVD_MASK 0x2 +#define CG_UVD_SHIFT 1 +#define CG_VCE_MASK 0x4 +#define CG_VCE_SHIFT 2 +#define CG_SAMU_MASK 0x8 +#define CG_SAMU_SHIFT 3 +#define CG_GFX_MASK 0x10 +#define CG_GFX_SHIFT 4 +#define CG_SDMA_MASK 0x20 +#define CG_SDMA_SHIFT 5 +#define CG_HDP_MASK 0x40 +#define CG_HDP_SHIFT 6 +#define CG_MC_MASK 0x80 +#define CG_MC_SHIFT 7 +#define CG_DRM_MASK 0x100 +#define CG_DRM_SHIFT 8 +#define CG_ROM_MASK 0x200 +#define CG_ROM_SHIFT 9 +#define CG_BIF_MASK 0x400 +#define CG_BIF_SHIFT 10 + +#define SMU73_DTE_ITERATIONS 5 +#define SMU73_DTE_SOURCES 3 +#define SMU73_DTE_SINKS 1 +#define SMU73_NUM_CPU_TES 0 +#define SMU73_NUM_GPU_TES 1 +#define SMU73_NUM_NON_TES 2 +#define SMU73_DTE_FAN_SCALAR_MIN 0x100 +#define SMU73_DTE_FAN_SCALAR_MAX 0x166 +#define SMU73_DTE_FAN_TEMP_MAX 93 +#define SMU73_DTE_FAN_TEMP_MIN 83 + +#define SMU73_THERMAL_INPUT_LOOP_COUNT 6 +#define SMU73_THERMAL_CLAMP_MODE_COUNT 8 + + +struct SMU7_HystController_Data +{ + uint16_t waterfall_up; + uint16_t waterfall_down; + uint16_t waterfall_limit; + uint16_t release_cnt; + uint16_t release_limit; + uint16_t spare; +}; + +typedef struct SMU7_HystController_Data SMU7_HystController_Data; + +struct SMU73_PIDController +{ + uint32_t Ki; + int32_t LFWindupUpperLim; + int32_t LFWindupLowerLim; + uint32_t StatePrecision; + + uint32_t LfPrecision; + uint32_t LfOffset; + uint32_t MaxState; + uint32_t MaxLfFraction; + uint32_t StateShift; +}; + +typedef struct SMU73_PIDController SMU73_PIDController; + +struct SMU7_LocalDpmScoreboard +{ + uint32_t PercentageBusy; + + int32_t PIDError; + int32_t PIDIntegral; + int32_t PIDOutput; + + uint32_t SigmaDeltaAccum; + uint32_t SigmaDeltaOutput; + uint32_t SigmaDeltaLevel; + + uint32_t UtilizationSetpoint; + + uint8_t TdpClampMode; + uint8_t TdcClampMode; + uint8_t ThermClampMode; + uint8_t VoltageBusy; + + int8_t CurrLevel; + int8_t TargLevel; + uint8_t LevelChangeInProgress; + uint8_t UpHyst; + + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t DpmEnable; + uint8_t DpmRunning; + + uint8_t DpmForce; + uint8_t DpmForceLevel; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + + uint32_t MinimumPerfSclk; + + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t GfxClkSlow; + uint8_t GpioClampMode; + + uint8_t spare2; + uint8_t EnabledLevelsChange; + uint8_t DteClampMode; + uint8_t FpsClampMode; + + uint16_t LevelResidencyCounters [SMU73_MAX_LEVELS_GRAPHICS]; + uint16_t LevelSwitchCounters [SMU73_MAX_LEVELS_GRAPHICS]; + + void (*TargetStateCalculator)(uint8_t); + void (*SavedTargetStateCalculator)(uint8_t); + + uint16_t AutoDpmInterval; + uint16_t AutoDpmRange; + + uint8_t FpsEnabled; + uint8_t MaxPerfLevel; + uint8_t AllowLowClkInterruptToHost; + uint8_t FpsRunning; + + uint32_t MaxAllowedFrequency; + + uint32_t FilteredSclkFrequency; + uint32_t LastSclkFrequency; + uint32_t FilteredSclkFrequencyCnt; + + uint8_t LedEnable; + uint8_t LedPin0; + uint8_t LedPin1; + uint8_t LedPin2; + uint32_t LedAndMask; + + uint16_t FpsAlpha; + uint16_t DeltaTime; + uint32_t CurrentFps; + uint32_t FilteredFps; + uint32_t FrameCount; + uint32_t FrameCountLast; + uint16_t FpsTargetScalar; + uint16_t FpsWaterfallLimitScalar; + uint16_t FpsAlphaScalar; + uint16_t spare8; + SMU7_HystController_Data HystControllerData; +}; + +typedef struct SMU7_LocalDpmScoreboard SMU7_LocalDpmScoreboard; + +#define SMU7_MAX_VOLTAGE_CLIENTS 12 + +typedef uint8_t (*VoltageChangeHandler_t)(uint16_t, uint8_t); + +#define VDDC_MASK 0x00007FFF +#define VDDC_SHIFT 0 +#define VDDCI_MASK 0x3FFF8000 +#define VDDCI_SHIFT 15 +#define PHASES_MASK 0xC0000000 +#define PHASES_SHIFT 30 + +typedef uint32_t SMU_VoltageLevel; + +struct SMU7_VoltageScoreboard +{ + SMU_VoltageLevel TargetVoltage; + uint16_t MaxVid; + uint8_t HighestVidOffset; + uint8_t CurrentVidOffset; + + uint16_t CurrentVddc; + uint16_t CurrentVddci; + + + uint8_t ControllerBusy; + uint8_t CurrentVid; + uint8_t CurrentVddciVid; + uint8_t padding; + + SMU_VoltageLevel RequestedVoltage[SMU7_MAX_VOLTAGE_CLIENTS]; + SMU_VoltageLevel TargetVoltageState; + uint8_t EnabledRequest[SMU7_MAX_VOLTAGE_CLIENTS]; + + uint8_t padding2; + uint8_t padding3; + uint8_t ControllerEnable; + uint8_t ControllerRunning; + uint16_t CurrentStdVoltageHiSidd; + uint16_t CurrentStdVoltageLoSidd; + uint8_t OverrideVoltage; + uint8_t padding4; + uint8_t padding5; + uint8_t CurrentPhases; + + VoltageChangeHandler_t ChangeVddc; + + VoltageChangeHandler_t ChangeVddci; + VoltageChangeHandler_t ChangePhase; + VoltageChangeHandler_t ChangeMvdd; + + VoltageChangeHandler_t functionLinks[6]; + + uint16_t * VddcFollower1; + + int16_t Driver_OD_RequestedVidOffset1; + int16_t Driver_OD_RequestedVidOffset2; + +}; + +typedef struct SMU7_VoltageScoreboard SMU7_VoltageScoreboard; + +// ------------------------------------------------------------------------------------------------------------------------- +#define SMU7_MAX_PCIE_LINK_SPEEDS 3 /* 0:Gen1 1:Gen2 2:Gen3 */ + +struct SMU7_PCIeLinkSpeedScoreboard +{ + uint8_t DpmEnable; + uint8_t DpmRunning; + uint8_t DpmForce; + uint8_t DpmForceLevel; + + uint8_t CurrentLinkSpeed; + uint8_t EnabledLevelsChange; + uint16_t AutoDpmInterval; + + uint16_t AutoDpmRange; + uint16_t AutoDpmCount; + + uint8_t DpmMode; + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t CurrentLinkLevel; + +}; + +typedef struct SMU7_PCIeLinkSpeedScoreboard SMU7_PCIeLinkSpeedScoreboard; + +// -------------------------------------------------------- CAC table ------------------------------------------------------ +#define SMU7_LKGE_LUT_NUM_OF_TEMP_ENTRIES 16 +#define SMU7_LKGE_LUT_NUM_OF_VOLT_ENTRIES 16 + +#define SMU7_SCALE_I 7 +#define SMU7_SCALE_R 12 + +struct SMU7_PowerScoreboard +{ + uint32_t GpuPower; + + uint32_t VddcPower; + uint32_t VddcVoltage; + uint32_t VddcCurrent; + + uint32_t MvddPower; + uint32_t MvddVoltage; + uint32_t MvddCurrent; + + uint32_t RocPower; + + uint16_t Telemetry_1_slope; + uint16_t Telemetry_2_slope; + int32_t Telemetry_1_offset; + int32_t Telemetry_2_offset; +}; +typedef struct SMU7_PowerScoreboard SMU7_PowerScoreboard; + +// For FeatureEnables: +#define SMU7_SCLK_DPM_CONFIG_MASK 0x01 +#define SMU7_VOLTAGE_CONTROLLER_CONFIG_MASK 0x02 +#define SMU7_THERMAL_CONTROLLER_CONFIG_MASK 0x04 +#define SMU7_MCLK_DPM_CONFIG_MASK 0x08 +#define SMU7_UVD_DPM_CONFIG_MASK 0x10 +#define SMU7_VCE_DPM_CONFIG_MASK 0x20 +#define SMU7_ACP_DPM_CONFIG_MASK 0x40 +#define SMU7_SAMU_DPM_CONFIG_MASK 0x80 +#define SMU7_PCIEGEN_DPM_CONFIG_MASK 0x100 + +#define SMU7_ACP_MCLK_HANDSHAKE_DISABLE 0x00000001 +#define SMU7_ACP_SCLK_HANDSHAKE_DISABLE 0x00000002 +#define SMU7_UVD_MCLK_HANDSHAKE_DISABLE 0x00000100 +#define SMU7_UVD_SCLK_HANDSHAKE_DISABLE 0x00000200 +#define SMU7_VCE_MCLK_HANDSHAKE_DISABLE 0x00010000 +#define SMU7_VCE_SCLK_HANDSHAKE_DISABLE 0x00020000 + +// All 'soft registers' should be uint32_t. +struct SMU73_SoftRegisters +{ + uint32_t RefClockFrequency; + uint32_t PmTimerPeriod; + uint32_t FeatureEnables; + + uint32_t PreVBlankGap; + uint32_t VBlankTimeout; + uint32_t TrainTimeGap; + + uint32_t MvddSwitchTime; + uint32_t LongestAcpiTrainTime; + uint32_t AcpiDelay; + uint32_t G5TrainTime; + uint32_t DelayMpllPwron; + uint32_t VoltageChangeTimeout; + + uint32_t HandshakeDisables; + + uint8_t DisplayPhy1Config; + uint8_t DisplayPhy2Config; + uint8_t DisplayPhy3Config; + uint8_t DisplayPhy4Config; + + uint8_t DisplayPhy5Config; + uint8_t DisplayPhy6Config; + uint8_t DisplayPhy7Config; + uint8_t DisplayPhy8Config; + + uint32_t AverageGraphicsActivity; + uint32_t AverageMemoryActivity; + uint32_t AverageGioActivity; + + uint8_t SClkDpmEnabledLevels; + uint8_t MClkDpmEnabledLevels; + uint8_t LClkDpmEnabledLevels; + uint8_t PCIeDpmEnabledLevels; + + uint8_t UVDDpmEnabledLevels; + uint8_t SAMUDpmEnabledLevels; + uint8_t ACPDpmEnabledLevels; + uint8_t VCEDpmEnabledLevels; + + uint32_t DRAM_LOG_ADDR_H; + uint32_t DRAM_LOG_ADDR_L; + uint32_t DRAM_LOG_PHY_ADDR_H; + uint32_t DRAM_LOG_PHY_ADDR_L; + uint32_t DRAM_LOG_BUFF_SIZE; + uint32_t UlvEnterCount; + uint32_t UlvTime; + uint32_t UcodeLoadStatus; + uint32_t Reserved[2]; + +}; + +typedef struct SMU73_SoftRegisters SMU73_SoftRegisters; + +struct SMU73_Firmware_Header +{ + uint32_t Digest[5]; + uint32_t Version; + uint32_t HeaderSize; + uint32_t Flags; + uint32_t EntryPoint; + uint32_t CodeSize; + uint32_t ImageSize; + + uint32_t Rtos; + uint32_t SoftRegisters; + uint32_t DpmTable; + uint32_t FanTable; + uint32_t CacConfigTable; + uint32_t CacStatusTable; + + + uint32_t mcRegisterTable; + + + uint32_t mcArbDramTimingTable; + + + + + uint32_t PmFuseTable; + uint32_t Globals; + uint32_t ClockStretcherTable; + uint32_t Reserved[41]; + uint32_t Signature; +}; + +typedef struct SMU73_Firmware_Header SMU73_Firmware_Header; + +#define SMU7_FIRMWARE_HEADER_LOCATION 0x20000 + +enum DisplayConfig { + PowerDown = 1, + DP54x4, + DP54x2, + DP54x1, + DP27x4, + DP27x2, + DP27x1, + HDMI297, + HDMI162, + LVDS, + DP324x4, + DP324x2, + DP324x1 +}; + + +#define MC_BLOCK_COUNT 1 +#define CPL_BLOCK_COUNT 5 +#define SE_BLOCK_COUNT 15 +#define GC_BLOCK_COUNT 24 + +struct SMU7_Local_Cac { + uint8_t BlockId; + uint8_t SignalId; + uint8_t Threshold; + uint8_t Padding; +}; + +typedef struct SMU7_Local_Cac SMU7_Local_Cac; + +struct SMU7_Local_Cac_Table { + + SMU7_Local_Cac CplLocalCac[CPL_BLOCK_COUNT]; + SMU7_Local_Cac McLocalCac[MC_BLOCK_COUNT]; + SMU7_Local_Cac SeLocalCac[SE_BLOCK_COUNT]; + SMU7_Local_Cac GcLocalCac[GC_BLOCK_COUNT]; +}; + +typedef struct SMU7_Local_Cac_Table SMU7_Local_Cac_Table; + +#if !defined(SMC_MICROCODE) +#pragma pack(pop) +#endif + +// Description of Clock Gating bitmask for Tonga: +// System Clock Gating +#define CG_SYS_BITMASK_FIRST_BIT 0 // First bit of Sys CG bitmask +#define CG_SYS_BITMASK_LAST_BIT 9 // Last bit of Sys CG bitmask +#define CG_SYS_BIF_MGLS_SHIFT 0 +#define CG_SYS_ROM_SHIFT 1 +#define CG_SYS_MC_MGCG_SHIFT 2 +#define CG_SYS_MC_MGLS_SHIFT 3 +#define CG_SYS_SDMA_MGCG_SHIFT 4 +#define CG_SYS_SDMA_MGLS_SHIFT 5 +#define CG_SYS_DRM_MGCG_SHIFT 6 +#define CG_SYS_HDP_MGCG_SHIFT 7 +#define CG_SYS_HDP_MGLS_SHIFT 8 +#define CG_SYS_DRM_MGLS_SHIFT 9 + +#define CG_SYS_BIF_MGLS_MASK 0x1 +#define CG_SYS_ROM_MASK 0x2 +#define CG_SYS_MC_MGCG_MASK 0x4 +#define CG_SYS_MC_MGLS_MASK 0x8 +#define CG_SYS_SDMA_MGCG_MASK 0x10 +#define CG_SYS_SDMA_MGLS_MASK 0x20 +#define CG_SYS_DRM_MGCG_MASK 0x40 +#define CG_SYS_HDP_MGCG_MASK 0x80 +#define CG_SYS_HDP_MGLS_MASK 0x100 +#define CG_SYS_DRM_MGLS_MASK 0x200 + +// Graphics Clock Gating +#define CG_GFX_BITMASK_FIRST_BIT 16 // First bit of Gfx CG bitmask +#define CG_GFX_BITMASK_LAST_BIT 20 // Last bit of Gfx CG bitmask +#define CG_GFX_CGCG_SHIFT 16 +#define CG_GFX_CGLS_SHIFT 17 +#define CG_CPF_MGCG_SHIFT 18 +#define CG_RLC_MGCG_SHIFT 19 +#define CG_GFX_OTHERS_MGCG_SHIFT 20 + +#define CG_GFX_CGCG_MASK 0x00010000 +#define CG_GFX_CGLS_MASK 0x00020000 +#define CG_CPF_MGCG_MASK 0x00040000 +#define CG_RLC_MGCG_MASK 0x00080000 +#define CG_GFX_OTHERS_MGCG_MASK 0x00100000 + + + +// Voltage Regulator Configuration +// VR Config info is contained in dpmTable.VRConfig + +#define VRCONF_VDDC_MASK 0x000000FF +#define VRCONF_VDDC_SHIFT 0 +#define VRCONF_VDDGFX_MASK 0x0000FF00 +#define VRCONF_VDDGFX_SHIFT 8 +#define VRCONF_VDDCI_MASK 0x00FF0000 +#define VRCONF_VDDCI_SHIFT 16 +#define VRCONF_MVDD_MASK 0xFF000000 +#define VRCONF_MVDD_SHIFT 24 + +#define VR_MERGED_WITH_VDDC 0 +#define VR_SVI2_PLANE_1 1 +#define VR_SVI2_PLANE_2 2 +#define VR_SMIO_PATTERN_1 3 +#define VR_SMIO_PATTERN_2 4 +#define VR_STATIC_VOLTAGE 5 + +// Clock Stretcher Configuration + +#define CLOCK_STRETCHER_MAX_ENTRIES 0x4 +#define CKS_LOOKUPTable_MAX_ENTRIES 0x4 + +// The 'settings' field is subdivided in the following way: +#define CLOCK_STRETCHER_SETTING_DDT_MASK 0x01 +#define CLOCK_STRETCHER_SETTING_DDT_SHIFT 0x0 +#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_MASK 0x1E +#define CLOCK_STRETCHER_SETTING_STRETCH_AMOUNT_SHIFT 0x1 +#define CLOCK_STRETCHER_SETTING_ENABLE_MASK 0x80 +#define CLOCK_STRETCHER_SETTING_ENABLE_SHIFT 0x7 + +struct SMU_ClockStretcherDataTableEntry { + uint8_t minVID; + uint8_t maxVID; + + + uint16_t setting; +}; +typedef struct SMU_ClockStretcherDataTableEntry SMU_ClockStretcherDataTableEntry; + +struct SMU_ClockStretcherDataTable { + SMU_ClockStretcherDataTableEntry ClockStretcherDataTableEntry[CLOCK_STRETCHER_MAX_ENTRIES]; +}; +typedef struct SMU_ClockStretcherDataTable SMU_ClockStretcherDataTable; + +struct SMU_CKS_LOOKUPTableEntry { + uint16_t minFreq; + uint16_t maxFreq; + + uint8_t setting; + uint8_t padding[3]; +}; +typedef struct SMU_CKS_LOOKUPTableEntry SMU_CKS_LOOKUPTableEntry; + +struct SMU_CKS_LOOKUPTable { + SMU_CKS_LOOKUPTableEntry CKS_LOOKUPTableEntry[CKS_LOOKUPTable_MAX_ENTRIES]; +}; +typedef struct SMU_CKS_LOOKUPTable SMU_CKS_LOOKUPTable; + +struct AgmAvfsData_t { + uint16_t avgPsmCount[28]; + uint16_t minPsmCount[28]; +}; +typedef struct AgmAvfsData_t AgmAvfsData_t; + +// AVFS DEFINES + +enum VFT_COLUMNS { + SCLK0, + SCLK1, + SCLK2, + SCLK3, + SCLK4, + SCLK5, + SCLK6, + SCLK7, + + NUM_VFT_COLUMNS +}; + +#define TEMP_RANGE_MAXSTEPS 12 +struct VFT_CELL_t { + uint16_t Voltage; +}; + +typedef struct VFT_CELL_t VFT_CELL_t; + +struct VFT_TABLE_t { + VFT_CELL_t Cell[TEMP_RANGE_MAXSTEPS][NUM_VFT_COLUMNS]; + uint16_t AvfsGbv [NUM_VFT_COLUMNS]; + uint16_t BtcGbv [NUM_VFT_COLUMNS]; + uint16_t Temperature [TEMP_RANGE_MAXSTEPS]; + + uint8_t NumTemperatureSteps; + uint8_t padding[3]; +}; +typedef struct VFT_TABLE_t VFT_TABLE_t; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h new file mode 100644 index 000000000000..5916be08a7fe --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smu73_discrete.h @@ -0,0 +1,799 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _SMU73_DISCRETE_H_ +#define _SMU73_DISCRETE_H_ + +#include "smu73.h" + +#pragma pack(push, 1) + +struct SMIO_Pattern +{ + uint16_t Voltage; + uint8_t Smio; + uint8_t padding; +}; + +typedef struct SMIO_Pattern SMIO_Pattern; + +struct SMIO_Table +{ + SMIO_Pattern Pattern[SMU_MAX_SMIO_LEVELS]; +}; + +typedef struct SMIO_Table SMIO_Table; + +struct SMU73_Discrete_GraphicsLevel { + uint32_t MinVoltage; + + uint32_t SclkFrequency; + + uint8_t pcieDpmLevel; + uint8_t DeepSleepDivId; + uint16_t ActivityLevel; + uint32_t CgSpllFuncCntl3; + uint32_t CgSpllFuncCntl4; + uint32_t SpllSpreadSpectrum; + uint32_t SpllSpreadSpectrum2; + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; + uint8_t SclkDid; + uint8_t DisplayWatermark; + uint8_t EnabledForActivity; + uint8_t EnabledForThrottle; + uint8_t UpHyst; + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t PowerThrottle; +}; + +typedef struct SMU73_Discrete_GraphicsLevel SMU73_Discrete_GraphicsLevel; + +struct SMU73_Discrete_ACPILevel { + uint32_t Flags; + uint32_t MinVoltage; + uint32_t SclkFrequency; + uint8_t SclkDid; + uint8_t DisplayWatermark; + uint8_t DeepSleepDivId; + uint8_t padding; + uint32_t CgSpllFuncCntl; + uint32_t CgSpllFuncCntl2; + uint32_t CgSpllFuncCntl3; + uint32_t CgSpllFuncCntl4; + uint32_t SpllSpreadSpectrum; + uint32_t SpllSpreadSpectrum2; + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; +}; + +typedef struct SMU73_Discrete_ACPILevel SMU73_Discrete_ACPILevel; + +struct SMU73_Discrete_Ulv { + uint32_t CcPwrDynRm; + uint32_t CcPwrDynRm1; + uint16_t VddcOffset; + uint8_t VddcOffsetVid; + uint8_t VddcPhase; + uint32_t Reserved; +}; + +typedef struct SMU73_Discrete_Ulv SMU73_Discrete_Ulv; + +struct SMU73_Discrete_MemoryLevel +{ + uint32_t MinVoltage; + uint32_t MinMvdd; + + uint32_t MclkFrequency; + + uint8_t StutterEnable; + uint8_t FreqRange; + uint8_t EnabledForThrottle; + uint8_t EnabledForActivity; + + uint8_t UpHyst; + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t padding; + + uint16_t ActivityLevel; + uint8_t DisplayWatermark; + uint8_t MclkDivider; +}; + +typedef struct SMU73_Discrete_MemoryLevel SMU73_Discrete_MemoryLevel; + +struct SMU73_Discrete_LinkLevel +{ + uint8_t PcieGenSpeed; ///< 0:PciE-gen1 1:PciE-gen2 2:PciE-gen3 + uint8_t PcieLaneCount; ///< 1=x1, 2=x2, 3=x4, 4=x8, 5=x12, 6=x16 + uint8_t EnabledForActivity; + uint8_t SPC; + uint32_t DownThreshold; + uint32_t UpThreshold; + uint32_t Reserved; +}; + +typedef struct SMU73_Discrete_LinkLevel SMU73_Discrete_LinkLevel; + + +// MC ARB DRAM Timing registers. +struct SMU73_Discrete_MCArbDramTimingTableEntry +{ + uint32_t McArbDramTiming; + uint32_t McArbDramTiming2; + uint8_t McArbBurstTime; + uint8_t TRRDS; + uint8_t TRRDL; + uint8_t padding; +}; + +typedef struct SMU73_Discrete_MCArbDramTimingTableEntry SMU73_Discrete_MCArbDramTimingTableEntry; + +struct SMU73_Discrete_MCArbDramTimingTable +{ + SMU73_Discrete_MCArbDramTimingTableEntry entries[SMU__NUM_SCLK_DPM_STATE][SMU__NUM_MCLK_DPM_LEVELS]; +}; + +typedef struct SMU73_Discrete_MCArbDramTimingTable SMU73_Discrete_MCArbDramTimingTable; + +// UVD VCLK/DCLK state (level) definition. +struct SMU73_Discrete_UvdLevel +{ + uint32_t VclkFrequency; + uint32_t DclkFrequency; + uint32_t MinVoltage; + uint8_t VclkDivider; + uint8_t DclkDivider; + uint8_t padding[2]; +}; + +typedef struct SMU73_Discrete_UvdLevel SMU73_Discrete_UvdLevel; + +// Clocks for other external blocks (VCE, ACP, SAMU). +struct SMU73_Discrete_ExtClkLevel +{ + uint32_t Frequency; + uint32_t MinVoltage; + uint8_t Divider; + uint8_t padding[3]; +}; + +typedef struct SMU73_Discrete_ExtClkLevel SMU73_Discrete_ExtClkLevel; + +struct SMU73_Discrete_StateInfo +{ + uint32_t SclkFrequency; + uint32_t MclkFrequency; + uint32_t VclkFrequency; + uint32_t DclkFrequency; + uint32_t SamclkFrequency; + uint32_t AclkFrequency; + uint32_t EclkFrequency; + uint16_t MvddVoltage; + uint16_t padding16; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + uint8_t McRegIndex; + uint8_t SeqIndex; + uint8_t SclkDid; + int8_t SclkIndex; + int8_t MclkIndex; + uint8_t PCIeGen; + +}; + +typedef struct SMU73_Discrete_StateInfo SMU73_Discrete_StateInfo; + +struct SMU73_Discrete_DpmTable +{ + // Multi-DPM controller settings + SMU73_PIDController GraphicsPIDController; + SMU73_PIDController MemoryPIDController; + SMU73_PIDController LinkPIDController; + + uint32_t SystemFlags; + + // SMIO masks for voltage and phase controls + uint32_t VRConfig; + uint32_t SmioMask1; + uint32_t SmioMask2; + SMIO_Table SmioTable1; + SMIO_Table SmioTable2; + + uint32_t MvddLevelCount; + + + uint8_t BapmVddcVidHiSidd [SMU73_MAX_LEVELS_VDDC]; + uint8_t BapmVddcVidLoSidd [SMU73_MAX_LEVELS_VDDC]; + uint8_t BapmVddcVidHiSidd2 [SMU73_MAX_LEVELS_VDDC]; + + uint8_t GraphicsDpmLevelCount; + uint8_t MemoryDpmLevelCount; + uint8_t LinkLevelCount; + uint8_t MasterDeepSleepControl; + + uint8_t UvdLevelCount; + uint8_t VceLevelCount; + uint8_t AcpLevelCount; + uint8_t SamuLevelCount; + + uint8_t ThermOutGpio; + uint8_t ThermOutPolarity; + uint8_t ThermOutMode; + uint8_t BootPhases; + uint32_t Reserved[4]; + + // State table entries for each DPM state + SMU73_Discrete_GraphicsLevel GraphicsLevel [SMU73_MAX_LEVELS_GRAPHICS]; + SMU73_Discrete_MemoryLevel MemoryACPILevel; + SMU73_Discrete_MemoryLevel MemoryLevel [SMU73_MAX_LEVELS_MEMORY]; + SMU73_Discrete_LinkLevel LinkLevel [SMU73_MAX_LEVELS_LINK]; + SMU73_Discrete_ACPILevel ACPILevel; + SMU73_Discrete_UvdLevel UvdLevel [SMU73_MAX_LEVELS_UVD]; + SMU73_Discrete_ExtClkLevel VceLevel [SMU73_MAX_LEVELS_VCE]; + SMU73_Discrete_ExtClkLevel AcpLevel [SMU73_MAX_LEVELS_ACP]; + SMU73_Discrete_ExtClkLevel SamuLevel [SMU73_MAX_LEVELS_SAMU]; + SMU73_Discrete_Ulv Ulv; + + uint32_t SclkStepSize; + uint32_t Smio [SMU73_MAX_ENTRIES_SMIO]; + + uint8_t UvdBootLevel; + uint8_t VceBootLevel; + uint8_t AcpBootLevel; + uint8_t SamuBootLevel; + + uint8_t GraphicsBootLevel; + uint8_t GraphicsVoltageChangeEnable; + uint8_t GraphicsThermThrottleEnable; + uint8_t GraphicsInterval; + + uint8_t VoltageInterval; + uint8_t ThermalInterval; + uint16_t TemperatureLimitHigh; + + uint16_t TemperatureLimitLow; + uint8_t MemoryBootLevel; + uint8_t MemoryVoltageChangeEnable; + + uint16_t BootMVdd; + uint8_t MemoryInterval; + uint8_t MemoryThermThrottleEnable; + + uint16_t VoltageResponseTime; + uint16_t PhaseResponseTime; + + uint8_t PCIeBootLinkLevel; + uint8_t PCIeGenInterval; + uint8_t DTEInterval; + uint8_t DTEMode; + + uint8_t SVI2Enable; + uint8_t VRHotGpio; + uint8_t AcDcGpio; + uint8_t ThermGpio; + + uint16_t PPM_PkgPwrLimit; + uint16_t PPM_TemperatureLimit; + + uint16_t DefaultTdp; + uint16_t TargetTdp; + + uint16_t FpsHighThreshold; + uint16_t FpsLowThreshold; + + uint16_t TemperatureLimitEdge; + uint16_t TemperatureLimitHotspot; + uint16_t TemperatureLimitLiquid1; + uint16_t TemperatureLimitLiquid2; + uint16_t TemperatureLimitVrVddc; + uint16_t TemperatureLimitVrMvdd; + uint16_t TemperatureLimitPlx; + + uint16_t FanGainEdge; + uint16_t FanGainHotspot; + uint16_t FanGainLiquid; + uint16_t FanGainVrVddc; + uint16_t FanGainVrMvdd; + uint16_t FanGainPlx; + uint16_t FanGainHbm; + + uint8_t Liquid1_I2C_address; + uint8_t Liquid2_I2C_address; + uint8_t Vr_I2C_address; + uint8_t Plx_I2C_address; + + uint8_t GeminiMode; + uint8_t spare17[3]; + uint32_t GeminiApertureHigh; + uint32_t GeminiApertureLow; + + uint8_t Liquid_I2C_LineSCL; + uint8_t Liquid_I2C_LineSDA; + uint8_t Vr_I2C_LineSCL; + uint8_t Vr_I2C_LineSDA; + uint8_t Plx_I2C_LineSCL; + uint8_t Plx_I2C_LineSDA; + + uint8_t spare1253[2]; + uint32_t spare123[2]; + + uint8_t DTEAmbientTempBase; + uint8_t DTETjOffset; + uint8_t GpuTjMax; + uint8_t GpuTjHyst; + + uint16_t BootVddc; + uint16_t BootVddci; + + uint32_t BAPM_TEMP_GRADIENT; + + uint32_t LowSclkInterruptThreshold; + uint32_t VddGfxReChkWait; + + uint8_t ClockStretcherAmount; + uint8_t Sclk_CKS_masterEn0_7; + uint8_t Sclk_CKS_masterEn8_15; + uint8_t DPMFreezeAndForced; + + uint8_t Sclk_voltageOffset[8]; + + SMU_ClockStretcherDataTable ClockStretcherDataTable; + SMU_CKS_LOOKUPTable CKS_LOOKUPTable; +}; + +typedef struct SMU73_Discrete_DpmTable SMU73_Discrete_DpmTable; + + +// --------------------------------------------------- Fan Table ----------------------------------------------------------- +struct SMU73_Discrete_FanTable +{ + uint16_t FdoMode; + int16_t TempMin; + int16_t TempMed; + int16_t TempMax; + int16_t Slope1; + int16_t Slope2; + int16_t FdoMin; + int16_t HystUp; + int16_t HystDown; + int16_t HystSlope; + int16_t TempRespLim; + int16_t TempCurr; + int16_t SlopeCurr; + int16_t PwmCurr; + uint32_t RefreshPeriod; + int16_t FdoMax; + uint8_t TempSrc; + int8_t Padding; +}; + +typedef struct SMU73_Discrete_FanTable SMU73_Discrete_FanTable; + +#define SMU7_DISCRETE_GPIO_SCLK_DEBUG 4 +#define SMU7_DISCRETE_GPIO_SCLK_DEBUG_BIT (0x1 << SMU7_DISCRETE_GPIO_SCLK_DEBUG) + + + +struct SMU7_MclkDpmScoreboard +{ + + uint32_t PercentageBusy; + + int32_t PIDError; + int32_t PIDIntegral; + int32_t PIDOutput; + + uint32_t SigmaDeltaAccum; + uint32_t SigmaDeltaOutput; + uint32_t SigmaDeltaLevel; + + uint32_t UtilizationSetpoint; + + uint8_t TdpClampMode; + uint8_t TdcClampMode; + uint8_t ThermClampMode; + uint8_t VoltageBusy; + + int8_t CurrLevel; + int8_t TargLevel; + uint8_t LevelChangeInProgress; + uint8_t UpHyst; + + uint8_t DownHyst; + uint8_t VoltageDownHyst; + uint8_t DpmEnable; + uint8_t DpmRunning; + + uint8_t DpmForce; + uint8_t DpmForceLevel; + uint8_t DisplayWatermark; + uint8_t McArbIndex; + + uint32_t MinimumPerfMclk; + + uint8_t AcpiReq; + uint8_t AcpiAck; + uint8_t MclkSwitchInProgress; + uint8_t MclkSwitchCritical; + + uint8_t IgnoreVBlank; + uint8_t TargetMclkIndex; + uint8_t TargetMvddIndex; + uint8_t MclkSwitchResult; + + uint16_t VbiFailureCount; + uint8_t VbiWaitCounter; + uint8_t EnabledLevelsChange; + + uint16_t LevelResidencyCounters [SMU73_MAX_LEVELS_MEMORY]; + uint16_t LevelSwitchCounters [SMU73_MAX_LEVELS_MEMORY]; + + void (*TargetStateCalculator)(uint8_t); + void (*SavedTargetStateCalculator)(uint8_t); + + uint16_t AutoDpmInterval; + uint16_t AutoDpmRange; + + uint16_t VbiTimeoutCount; + uint16_t MclkSwitchingTime; + + uint8_t fastSwitch; + uint8_t Save_PIC_VDDGFX_EXIT; + uint8_t Save_PIC_VDDGFX_ENTER; + uint8_t padding; + +}; + +typedef struct SMU7_MclkDpmScoreboard SMU7_MclkDpmScoreboard; + +struct SMU7_UlvScoreboard +{ + uint8_t EnterUlv; + uint8_t ExitUlv; + uint8_t UlvActive; + uint8_t WaitingForUlv; + uint8_t UlvEnable; + uint8_t UlvRunning; + uint8_t UlvMasterEnable; + uint8_t padding; + uint32_t UlvAbortedCount; + uint32_t UlvTimeStamp; +}; + +typedef struct SMU7_UlvScoreboard SMU7_UlvScoreboard; + +struct VddgfxSavedRegisters +{ + uint32_t GPU_DBG[3]; + uint32_t MEC_BaseAddress_Hi; + uint32_t MEC_BaseAddress_Lo; + uint32_t THM_TMON0_CTRL2__RDIR_PRESENT; + uint32_t THM_TMON1_CTRL2__RDIR_PRESENT; + uint32_t CP_INT_CNTL; +}; + +typedef struct VddgfxSavedRegisters VddgfxSavedRegisters; + +struct SMU7_VddGfxScoreboard +{ + uint8_t VddGfxEnable; + uint8_t VddGfxActive; + uint8_t VPUResetOccured; + uint8_t padding; + + uint32_t VddGfxEnteredCount; + uint32_t VddGfxAbortedCount; + + uint32_t VddGfxVid; + + VddgfxSavedRegisters SavedRegisters; +}; + +typedef struct SMU7_VddGfxScoreboard SMU7_VddGfxScoreboard; + +struct SMU7_TdcLimitScoreboard { + uint8_t Enable; + uint8_t Running; + uint16_t Alpha; + uint32_t FilteredIddc; + uint32_t IddcLimit; + uint32_t IddcHyst; + SMU7_HystController_Data HystControllerData; +}; + +typedef struct SMU7_TdcLimitScoreboard SMU7_TdcLimitScoreboard; + +struct SMU7_PkgPwrLimitScoreboard { + uint8_t Enable; + uint8_t Running; + uint16_t Alpha; + uint32_t FilteredPkgPwr; + uint32_t Limit; + uint32_t Hyst; + uint32_t LimitFromDriver; + SMU7_HystController_Data HystControllerData; +}; + +typedef struct SMU7_PkgPwrLimitScoreboard SMU7_PkgPwrLimitScoreboard; + +struct SMU7_BapmScoreboard { + uint32_t source_powers[SMU73_DTE_SOURCES]; + uint32_t source_powers_last[SMU73_DTE_SOURCES]; + int32_t entity_temperatures[SMU73_NUM_GPU_TES]; + int32_t initial_entity_temperatures[SMU73_NUM_GPU_TES]; + int32_t Limit; + int32_t Hyst; + int32_t therm_influence_coeff_table[SMU73_DTE_ITERATIONS * SMU73_DTE_SOURCES * SMU73_DTE_SINKS * 2]; + int32_t therm_node_table[SMU73_DTE_ITERATIONS * SMU73_DTE_SOURCES * SMU73_DTE_SINKS]; + uint16_t ConfigTDPPowerScalar; + uint16_t FanSpeedPowerScalar; + uint16_t OverDrivePowerScalar; + uint16_t OverDriveLimitScalar; + uint16_t FinalPowerScalar; + uint8_t VariantID; + uint8_t spare997; + + SMU7_HystController_Data HystControllerData; + + int32_t temperature_gradient_slope; + int32_t temperature_gradient; + uint32_t measured_temperature; +}; + + +typedef struct SMU7_BapmScoreboard SMU7_BapmScoreboard; + +struct SMU7_AcpiScoreboard { + uint32_t SavedInterruptMask[2]; + uint8_t LastACPIRequest; + uint8_t CgBifResp; + uint8_t RequestType; + uint8_t Padding; + SMU73_Discrete_ACPILevel D0Level; +}; + +typedef struct SMU7_AcpiScoreboard SMU7_AcpiScoreboard; + +struct SMU_QuadraticCoeffs { + int32_t m1; + uint32_t b; + + int16_t m2; + uint8_t m1_shift; + uint8_t m2_shift; +}; + +typedef struct SMU_QuadraticCoeffs SMU_QuadraticCoeffs; + +struct SMU73_Discrete_PmFuses { + /* dw0-dw1 */ + uint8_t BapmVddCVidHiSidd[8]; + + /* dw2-dw3 */ + uint8_t BapmVddCVidLoSidd[8]; + + /* dw4-dw5 */ + uint8_t VddCVid[8]; + + /* dw1*/ + uint8_t SviLoadLineEn; + uint8_t SviLoadLineVddC; + uint8_t SviLoadLineTrimVddC; + uint8_t SviLoadLineOffsetVddC; + + /* dw2 */ + uint16_t TDC_VDDC_PkgLimit; + uint8_t TDC_VDDC_ThrottleReleaseLimitPerc; + uint8_t TDC_MAWt; + + /* dw3 */ + uint8_t TdcWaterfallCtl; + uint8_t LPMLTemperatureMin; + uint8_t LPMLTemperatureMax; + uint8_t Reserved; + + /* dw4-dw7 */ + uint8_t LPMLTemperatureScaler[16]; + + /* dw8-dw9 */ + int16_t FuzzyFan_ErrorSetDelta; + int16_t FuzzyFan_ErrorRateSetDelta; + int16_t FuzzyFan_PwmSetDelta; + uint16_t Reserved6; + + /* dw10-dw14 */ + uint8_t GnbLPML[16]; + + /* dw15 */ + uint8_t GnbLPMLMaxVid; + uint8_t GnbLPMLMinVid; + uint8_t Reserved1[2]; + + /* dw16 */ + uint16_t BapmVddCBaseLeakageHiSidd; + uint16_t BapmVddCBaseLeakageLoSidd; + + /* AVFS */ + uint16_t VFT_Temp[3]; + uint16_t padding; + + SMU_QuadraticCoeffs VFT_ATE[3]; + + SMU_QuadraticCoeffs AVFS_GB; + SMU_QuadraticCoeffs ATE_ACBTC_GB; + + SMU_QuadraticCoeffs P2V; + + uint32_t PsmCharzFreq; + + uint16_t InversionVoltage; + uint16_t PsmCharzTemp; + + uint32_t EnabledAvfsModules; +}; + +typedef struct SMU73_Discrete_PmFuses SMU73_Discrete_PmFuses; + +struct SMU7_Discrete_Log_Header_Table { + uint32_t version; + uint32_t asic_id; + uint16_t flags; + uint16_t entry_size; + uint32_t total_size; + uint32_t num_of_entries; + uint8_t type; + uint8_t mode; + uint8_t filler_0[2]; + uint32_t filler_1[2]; +}; + +typedef struct SMU7_Discrete_Log_Header_Table SMU7_Discrete_Log_Header_Table; + +struct SMU7_Discrete_Log_Cntl { + uint8_t Enabled; + uint8_t Type; + uint8_t padding[2]; + uint32_t BufferSize; + uint32_t SamplesLogged; + uint32_t SampleSize; + uint32_t AddrL; + uint32_t AddrH; +}; + +typedef struct SMU7_Discrete_Log_Cntl SMU7_Discrete_Log_Cntl; + +#define CAC_ACC_NW_NUM_OF_SIGNALS 87 + +struct SMU7_Discrete_Cac_Collection_Table { + uint32_t temperature; + uint32_t cac_acc_nw[CAC_ACC_NW_NUM_OF_SIGNALS]; +}; + +typedef struct SMU7_Discrete_Cac_Collection_Table SMU7_Discrete_Cac_Collection_Table; + +struct SMU7_Discrete_Cac_Verification_Table { + uint32_t VddcTotalPower; + uint32_t VddcLeakagePower; + uint32_t VddcConstantPower; + uint32_t VddcGfxDynamicPower; + uint32_t VddcUvdDynamicPower; + uint32_t VddcVceDynamicPower; + uint32_t VddcAcpDynamicPower; + uint32_t VddcPcieDynamicPower; + uint32_t VddcDceDynamicPower; + uint32_t VddcCurrent; + uint32_t VddcVoltage; + uint32_t VddciTotalPower; + uint32_t VddciLeakagePower; + uint32_t VddciConstantPower; + uint32_t VddciDynamicPower; + uint32_t Vddr1TotalPower; + uint32_t Vddr1LeakagePower; + uint32_t Vddr1ConstantPower; + uint32_t Vddr1DynamicPower; + uint32_t spare[4]; + uint32_t temperature; +}; + +typedef struct SMU7_Discrete_Cac_Verification_Table SMU7_Discrete_Cac_Verification_Table; + +struct SMU7_Discrete_Pm_Status_Table { + //Thermal entities + int32_t T_meas_max[SMU73_THERMAL_INPUT_LOOP_COUNT]; + int32_t T_meas_acc[SMU73_THERMAL_INPUT_LOOP_COUNT]; + int32_t T_meas_acc_cnt[SMU73_THERMAL_INPUT_LOOP_COUNT]; + uint32_t T_hbm_acc; + + //Voltage domains + uint32_t I_calc_max; + uint32_t I_calc_acc; + uint32_t P_meas_acc; + uint32_t V_meas_load_acc; + uint32_t I_meas_acc; + uint32_t P_meas_acc_vddci; + uint32_t V_meas_load_acc_vddci; + uint32_t I_meas_acc_vddci; + + //Frequency + uint16_t Sclk_dpm_residency[8]; + uint16_t Uvd_dpm_residency[8]; + uint16_t Vce_dpm_residency[8]; + + //Chip + uint32_t P_roc_acc; + uint32_t PkgPwr_max; + uint32_t PkgPwr_acc; + uint32_t MclkSwitchingTime_max; + uint32_t MclkSwitchingTime_acc; + uint32_t FanPwm_acc; + uint32_t FanRpm_acc; + uint32_t Gfx_busy_acc; + uint32_t Mc_busy_acc; + uint32_t Fps_acc; + + uint32_t AccCnt; +}; + +typedef struct SMU7_Discrete_Pm_Status_Table SMU7_Discrete_Pm_Status_Table; + +//FIXME THESE NEED TO BE UPDATED +#define SMU7_SCLK_CAC 0x561 +#define SMU7_MCLK_CAC 0xF9 +#define SMU7_VCLK_CAC 0x2DE +#define SMU7_DCLK_CAC 0x2DE +#define SMU7_ECLK_CAC 0x25E +#define SMU7_ACLK_CAC 0x25E +#define SMU7_SAMCLK_CAC 0x25E +#define SMU7_DISPCLK_CAC 0x100 +#define SMU7_CAC_CONSTANT 0x2EE3430 +#define SMU7_CAC_CONSTANT_SHIFT 18 + +#define SMU7_VDDCI_MCLK_CONST 1765 +#define SMU7_VDDCI_MCLK_CONST_SHIFT 16 +#define SMU7_VDDCI_VDDCI_CONST 50958 +#define SMU7_VDDCI_VDDCI_CONST_SHIFT 14 +#define SMU7_VDDCI_CONST 11781 +#define SMU7_VDDCI_STROBE_PWR 1331 + +#define SMU7_VDDR1_CONST 693 +#define SMU7_VDDR1_CAC_WEIGHT 20 +#define SMU7_VDDR1_CAC_WEIGHT_SHIFT 19 +#define SMU7_VDDR1_STROBE_PWR 512 + +#define SMU7_AREA_COEFF_UVD 0xA78 +#define SMU7_AREA_COEFF_VCE 0x190A +#define SMU7_AREA_COEFF_ACP 0x22D1 +#define SMU7_AREA_COEFF_SAMU 0x534 + +//ThermOutMode values +#define SMU7_THERM_OUT_MODE_DISABLE 0x0 +#define SMU7_THERM_OUT_MODE_THERM_ONLY 0x1 +#define SMU7_THERM_OUT_MODE_THERM_VRHOT 0x2 + +#pragma pack(pop) + +#endif + diff --git a/drivers/gpu/drm/amd/amdgpu/smu7_discrete.h b/drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h index 0b0b404ff091..0b0b404ff091 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu7_discrete.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu7_discrete.h diff --git a/drivers/gpu/drm/amd/amdgpu/smu7_fusion.h b/drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h index 78ada9ffd508..78ada9ffd508 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu7_fusion.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu7_fusion.h diff --git a/drivers/gpu/drm/amd/amdgpu/smu8.h b/drivers/gpu/drm/amd/powerplay/inc/smu8.h index d758d07b6a31..d758d07b6a31 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu8.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu8.h diff --git a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h index 5c9cc3c0bbfa..0c37c94e9414 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu8_fusion.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu8_fusion.h @@ -48,6 +48,14 @@ struct SMU8_Port80MonitorTable { uint8_t EnableDramShadow; }; +/* Display specific power management parameters */ +#define PWRMGT_SEPARATION_TIME_SHIFT 0 +#define PWRMGT_SEPARATION_TIME_MASK 0xFFFF +#define PWRMGT_DISABLE_CPU_CSTATES_SHIFT 16 +#define PWRMGT_DISABLE_CPU_CSTATES_MASK 0x1 +#define PWRMGT_DISABLE_CPU_PSTATES_SHIFT 24 +#define PWRMGT_DISABLE_CPU_PSTATES_MASK 0x1 + /* Clock Table Definitions */ #define NUM_SCLK_LEVELS 8 #define NUM_LCLK_LEVELS 8 diff --git a/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h index f8ba071f39c8..f8ba071f39c8 100644 --- a/drivers/gpu/drm/amd/amdgpu/smu_ucode_xfer_cz.h +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_cz.h diff --git a/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h new file mode 100644 index 000000000000..c24a81eebc7c --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smu_ucode_xfer_vi.h @@ -0,0 +1,100 @@ +/* + * Copyright 2014 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. + * + */ + +#ifndef SMU_UCODE_XFER_VI_H +#define SMU_UCODE_XFER_VI_H + +#define SMU_DRAMData_TOC_VERSION 1 +#define MAX_IH_REGISTER_COUNT 65535 +#define SMU_DIGEST_SIZE_BYTES 20 +#define SMU_FB_SIZE_BYTES 1048576 +#define SMU_MAX_ENTRIES 12 + +#define UCODE_ID_SMU 0 +#define UCODE_ID_SDMA0 1 +#define UCODE_ID_SDMA1 2 +#define UCODE_ID_CP_CE 3 +#define UCODE_ID_CP_PFP 4 +#define UCODE_ID_CP_ME 5 +#define UCODE_ID_CP_MEC 6 +#define UCODE_ID_CP_MEC_JT1 7 +#define UCODE_ID_CP_MEC_JT2 8 +#define UCODE_ID_GMCON_RENG 9 +#define UCODE_ID_RLC_G 10 +#define UCODE_ID_IH_REG_RESTORE 11 +#define UCODE_ID_VBIOS 12 +#define UCODE_ID_MISC_METADATA 13 +#define UCODE_ID_RLC_SCRATCH 32 +#define UCODE_ID_RLC_SRM_ARAM 33 +#define UCODE_ID_RLC_SRM_DRAM 34 +#define UCODE_ID_MEC_STORAGE 35 +#define UCODE_ID_VBIOS_PARAMETERS 36 +#define UCODE_META_DATA 0xFF + +#define UCODE_ID_SMU_MASK 0x00000001 +#define UCODE_ID_SDMA0_MASK 0x00000002 +#define UCODE_ID_SDMA1_MASK 0x00000004 +#define UCODE_ID_CP_CE_MASK 0x00000008 +#define UCODE_ID_CP_PFP_MASK 0x00000010 +#define UCODE_ID_CP_ME_MASK 0x00000020 +#define UCODE_ID_CP_MEC_MASK 0x00000040 +#define UCODE_ID_CP_MEC_JT1_MASK 0x00000080 +#define UCODE_ID_CP_MEC_JT2_MASK 0x00000100 +#define UCODE_ID_GMCON_RENG_MASK 0x00000200 +#define UCODE_ID_RLC_G_MASK 0x00000400 +#define UCODE_ID_IH_REG_RESTORE_MASK 0x00000800 +#define UCODE_ID_VBIOS_MASK 0x00001000 + +#define UCODE_FLAG_UNHALT_MASK 0x1 + +struct SMU_Entry { +#ifndef __BIG_ENDIAN + uint16_t id; + uint16_t version; + uint32_t image_addr_high; + uint32_t image_addr_low; + uint32_t meta_data_addr_high; + uint32_t meta_data_addr_low; + uint32_t data_size_byte; + uint16_t flags; + uint16_t num_register_entries; +#else + uint16_t version; + uint16_t id; + uint32_t image_addr_high; + uint32_t image_addr_low; + uint32_t meta_data_addr_high; + uint32_t meta_data_addr_low; + uint32_t data_size_byte; + uint16_t num_register_entries; + uint16_t flags; +#endif +}; + +struct SMU_DRAMData_TOC { + uint32_t structure_version; + uint32_t num_entries; + struct SMU_Entry entry[SMU_MAX_ENTRIES]; +}; + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/smumgr.h b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h new file mode 100644 index 000000000000..504f035d1843 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/smumgr.h @@ -0,0 +1,182 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _SMUMGR_H_ +#define _SMUMGR_H_ +#include <linux/types.h> +#include "pp_instance.h" +#include "amd_powerplay.h" + +struct pp_smumgr; +struct pp_instance; + +#define smu_lower_32_bits(n) ((uint32_t)(n)) +#define smu_upper_32_bits(n) ((uint32_t)(((n)>>16)>>16)) + +struct pp_smumgr_func { + int (*smu_init)(struct pp_smumgr *smumgr); + int (*smu_fini)(struct pp_smumgr *smumgr); + int (*start_smu)(struct pp_smumgr *smumgr); + int (*check_fw_load_finish)(struct pp_smumgr *smumgr, + uint32_t firmware); + int (*request_smu_load_fw)(struct pp_smumgr *smumgr); + int (*request_smu_load_specific_fw)(struct pp_smumgr *smumgr, + uint32_t firmware); + int (*get_argument)(struct pp_smumgr *smumgr); + int (*send_msg_to_smc)(struct pp_smumgr *smumgr, uint16_t msg); + int (*send_msg_to_smc_with_parameter)(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter); + int (*download_pptable_settings)(struct pp_smumgr *smumgr, + void **table); + int (*upload_pptable_settings)(struct pp_smumgr *smumgr); +}; + +struct pp_smumgr { + uint32_t chip_family; + uint32_t chip_id; + uint32_t hw_revision; + void *device; + void *backend; + uint32_t usec_timeout; + bool reload_fw; + const struct pp_smumgr_func *smumgr_funcs; +}; + + +extern int smum_init(struct amd_pp_init *pp_init, + struct pp_instance *handle); + +extern int smum_fini(struct pp_smumgr *smumgr); + +extern int smum_get_argument(struct pp_smumgr *smumgr); + +extern int smum_download_powerplay_table(struct pp_smumgr *smumgr, void **table); + +extern int smum_upload_powerplay_table(struct pp_smumgr *smumgr); + +extern int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg); + +extern int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter); + +extern int smum_wait_on_register(struct pp_smumgr *smumgr, + uint32_t index, uint32_t value, uint32_t mask); + +extern int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, + uint32_t index, uint32_t value, uint32_t mask); + +extern int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, + uint32_t indirect_port, uint32_t index, + uint32_t value, uint32_t mask); + + +extern void smum_wait_for_indirect_register_unequal( + struct pp_smumgr *smumgr, + uint32_t indirect_port, uint32_t index, + uint32_t value, uint32_t mask); + +extern int smu_allocate_memory(void *device, uint32_t size, + enum cgs_gpu_mem_type type, + uint32_t byte_align, uint64_t *mc_addr, + void **kptr, void *handle); + +extern int smu_free_memory(void *device, void *handle); + +#define SMUM_FIELD_SHIFT(reg, field) reg##__##field##__SHIFT + +#define SMUM_FIELD_MASK(reg, field) reg##__##field##_MASK + +#define SMUM_WAIT_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ + port, index, value, mask) \ + smum_wait_on_indirect_register(smumgr, \ + mm##port##_INDEX, index, value, mask) + + +#define SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ + index, value, mask) \ + smum_wait_for_register_unequal(smumgr, \ + index, value, mask) + +#define SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, value, mask) \ + SMUM_WAIT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ + mm##reg, value, mask) + +#define SMUM_WAIT_FIELD_UNEQUAL(smumgr, reg, field, fieldval) \ + SMUM_WAIT_REGISTER_UNEQUAL(smumgr, reg, \ + (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ + SMUM_FIELD_MASK(reg, field)) + +#define SMUM_GET_FIELD(value, reg, field) \ + (((value) & SMUM_FIELD_MASK(reg, field)) \ + >> SMUM_FIELD_SHIFT(reg, field)) + +#define SMUM_READ_FIELD(device, reg, field) \ + SMUM_GET_FIELD(cgs_read_register(device, mm##reg), reg, field) + +#define SMUM_SET_FIELD(value, reg, field, field_val) \ + (((value) & ~SMUM_FIELD_MASK(reg, field)) | \ + (SMUM_FIELD_MASK(reg, field) & ((field_val) << \ + SMUM_FIELD_SHIFT(reg, field)))) + +#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, \ + port, index, value, mask) \ + smum_wait_on_indirect_register(smumgr, \ + mm##port##_INDEX_0, index, value, mask) + +#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, \ + port, index, value, mask) \ + smum_wait_for_indirect_register_unequal(smumgr, \ + mm##port##_INDEX_0, index, value, mask) + + +#define SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, value, mask) \ + SMUM_WAIT_VFPF_INDIRECT_REGISTER_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) + +#define SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, value, mask) \ + SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL_GIVEN_INDEX(smumgr, port, ix##reg, value, mask) + + +/*Operations on named fields.*/ + +#define SMUM_READ_VFPF_INDIRECT_FIELD(device, port, reg, field) \ + SMUM_GET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field) + +#define SMUM_WRITE_FIELD(device, reg, field, fieldval) \ + cgs_write_register(device, mm##reg, \ + SMUM_SET_FIELD(cgs_read_register(device, mm##reg), reg, field, fieldval)) + +#define SMUM_WRITE_VFPF_INDIRECT_FIELD(device, port, reg, field, fieldval) \ + cgs_write_ind_register(device, port, ix##reg, \ + SMUM_SET_FIELD(cgs_read_ind_register(device, port, ix##reg), \ + reg, field, fieldval)) + +#define SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, port, reg, field, fieldval) \ + SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, port, reg, \ + (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ + SMUM_FIELD_MASK(reg, field)) + +#define SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, port, reg, field, fieldval) \ + SMUM_WAIT_VFPF_INDIRECT_REGISTER_UNEQUAL(smumgr, port, reg, \ + (fieldval) << SMUM_FIELD_SHIFT(reg, field), \ + SMUM_FIELD_MASK(reg, field)) +#endif diff --git a/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h b/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h new file mode 100644 index 000000000000..63631296d751 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/inc/tonga_ppsmc.h @@ -0,0 +1,420 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef TONGA_PP_SMC_H +#define TONGA_PP_SMC_H + +#pragma pack(push, 1) + +#define PPSMC_SWSTATE_FLAG_DC 0x01 +#define PPSMC_SWSTATE_FLAG_UVD 0x02 +#define PPSMC_SWSTATE_FLAG_VCE 0x04 +#define PPSMC_SWSTATE_FLAG_PCIE_X1 0x08 + +#define PPSMC_THERMAL_PROTECT_TYPE_INTERNAL 0x00 +#define PPSMC_THERMAL_PROTECT_TYPE_EXTERNAL 0x01 +#define PPSMC_THERMAL_PROTECT_TYPE_NONE 0xff + +#define PPSMC_SYSTEMFLAG_GPIO_DC 0x01 +#define PPSMC_SYSTEMFLAG_STEPVDDC 0x02 +#define PPSMC_SYSTEMFLAG_GDDR5 0x04 + +#define PPSMC_SYSTEMFLAG_DISABLE_BABYSTEP 0x08 + +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT 0x10 +#define PPSMC_SYSTEMFLAG_REGULATOR_HOT_ANALOG 0x20 +#define PPSMC_SYSTEMFLAG_12CHANNEL 0x40 + + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_MASK 0x07 +#define PPSMC_EXTRAFLAGS_AC2DC_DONT_WAIT_FOR_VBLANK 0x08 + +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTODPMLOWSTATE 0x00 +#define PPSMC_EXTRAFLAGS_AC2DC_ACTION_GOTOINITIALSTATE 0x01 + +#define PPSMC_EXTRAFLAGS_AC2DC_GPIO5_POLARITY_HIGH 0x10 +#define PPSMC_EXTRAFLAGS_DRIVER_TO_GPIO17 0x20 +#define PPSMC_EXTRAFLAGS_PCC_TO_GPIO17 0x40 + +/* Defines for DPM 2.0 */ +#define PPSMC_DPM2FLAGS_TDPCLMP 0x01 +#define PPSMC_DPM2FLAGS_PWRSHFT 0x02 +#define PPSMC_DPM2FLAGS_OCP 0x04 + +/* Defines for display watermark level */ + +#define PPSMC_DISPLAY_WATERMARK_LOW 0 +#define PPSMC_DISPLAY_WATERMARK_HIGH 1 + +/* In the HW performance level's state flags:*/ +#define PPSMC_STATEFLAG_AUTO_PULSE_SKIP 0x01 +#define PPSMC_STATEFLAG_POWERBOOST 0x02 +#define PPSMC_STATEFLAG_PSKIP_ON_TDP_FAULT 0x04 +#define PPSMC_STATEFLAG_POWERSHIFT 0x08 +#define PPSMC_STATEFLAG_SLOW_READ_MARGIN 0x10 +#define PPSMC_STATEFLAG_DEEPSLEEP_THROTTLE 0x20 +#define PPSMC_STATEFLAG_DEEPSLEEP_BYPASS 0x40 + +/* Fan control algorithm:*/ +#define FDO_MODE_HARDWARE 0 +#define FDO_MODE_PIECE_WISE_LINEAR 1 + +enum FAN_CONTROL { + FAN_CONTROL_FUZZY, + FAN_CONTROL_TABLE +}; + +/* Return codes for driver to SMC communication.*/ + +#define PPSMC_Result_OK ((uint16_t)0x01) +#define PPSMC_Result_NoMore ((uint16_t)0x02) +#define PPSMC_Result_NotNow ((uint16_t)0x03) + +#define PPSMC_Result_Failed ((uint16_t)0xFF) +#define PPSMC_Result_UnknownCmd ((uint16_t)0xFE) +#define PPSMC_Result_UnknownVT ((uint16_t)0xFD) + +typedef uint16_t PPSMC_Result; + +#define PPSMC_isERROR(x) ((uint16_t)0x80 & (x)) + + +#define PPSMC_MSG_Halt ((uint16_t)0x10) +#define PPSMC_MSG_Resume ((uint16_t)0x11) +#define PPSMC_MSG_EnableDPMLevel ((uint16_t)0x12) +#define PPSMC_MSG_ZeroLevelsDisabled ((uint16_t)0x13) +#define PPSMC_MSG_OneLevelsDisabled ((uint16_t)0x14) +#define PPSMC_MSG_TwoLevelsDisabled ((uint16_t)0x15) +#define PPSMC_MSG_EnableThermalInterrupt ((uint16_t)0x16) +#define PPSMC_MSG_RunningOnAC ((uint16_t)0x17) +#define PPSMC_MSG_LevelUp ((uint16_t)0x18) +#define PPSMC_MSG_LevelDown ((uint16_t)0x19) +#define PPSMC_MSG_ResetDPMCounters ((uint16_t)0x1a) +#define PPSMC_MSG_SwitchToSwState ((uint16_t)0x20) + +#define PPSMC_MSG_SwitchToSwStateLast ((uint16_t)0x3f) +#define PPSMC_MSG_SwitchToInitialState ((uint16_t)0x40) +#define PPSMC_MSG_NoForcedLevel ((uint16_t)0x41) +#define PPSMC_MSG_ForceHigh ((uint16_t)0x42) +#define PPSMC_MSG_ForceMediumOrHigh ((uint16_t)0x43) + +#define PPSMC_MSG_SwitchToMinimumPower ((uint16_t)0x51) +#define PPSMC_MSG_ResumeFromMinimumPower ((uint16_t)0x52) +#define PPSMC_MSG_EnableCac ((uint16_t)0x53) +#define PPSMC_MSG_DisableCac ((uint16_t)0x54) +#define PPSMC_DPMStateHistoryStart ((uint16_t)0x55) +#define PPSMC_DPMStateHistoryStop ((uint16_t)0x56) +#define PPSMC_CACHistoryStart ((uint16_t)0x57) +#define PPSMC_CACHistoryStop ((uint16_t)0x58) +#define PPSMC_TDPClampingActive ((uint16_t)0x59) +#define PPSMC_TDPClampingInactive ((uint16_t)0x5A) +#define PPSMC_StartFanControl ((uint16_t)0x5B) +#define PPSMC_StopFanControl ((uint16_t)0x5C) +#define PPSMC_NoDisplay ((uint16_t)0x5D) +#define PPSMC_HasDisplay ((uint16_t)0x5E) +#define PPSMC_MSG_UVDPowerOFF ((uint16_t)0x60) +#define PPSMC_MSG_UVDPowerON ((uint16_t)0x61) +#define PPSMC_MSG_EnableULV ((uint16_t)0x62) +#define PPSMC_MSG_DisableULV ((uint16_t)0x63) +#define PPSMC_MSG_EnterULV ((uint16_t)0x64) +#define PPSMC_MSG_ExitULV ((uint16_t)0x65) +#define PPSMC_PowerShiftActive ((uint16_t)0x6A) +#define PPSMC_PowerShiftInactive ((uint16_t)0x6B) +#define PPSMC_OCPActive ((uint16_t)0x6C) +#define PPSMC_OCPInactive ((uint16_t)0x6D) +#define PPSMC_CACLongTermAvgEnable ((uint16_t)0x6E) +#define PPSMC_CACLongTermAvgDisable ((uint16_t)0x6F) +#define PPSMC_MSG_InferredStateSweep_Start ((uint16_t)0x70) +#define PPSMC_MSG_InferredStateSweep_Stop ((uint16_t)0x71) +#define PPSMC_MSG_SwitchToLowestInfState ((uint16_t)0x72) +#define PPSMC_MSG_SwitchToNonInfState ((uint16_t)0x73) +#define PPSMC_MSG_AllStateSweep_Start ((uint16_t)0x74) +#define PPSMC_MSG_AllStateSweep_Stop ((uint16_t)0x75) +#define PPSMC_MSG_SwitchNextLowerInfState ((uint16_t)0x76) +#define PPSMC_MSG_SwitchNextHigherInfState ((uint16_t)0x77) +#define PPSMC_MSG_MclkRetrainingTest ((uint16_t)0x78) +#define PPSMC_MSG_ForceTDPClamping ((uint16_t)0x79) +#define PPSMC_MSG_CollectCAC_PowerCorreln ((uint16_t)0x7A) +#define PPSMC_MSG_CollectCAC_WeightCalib ((uint16_t)0x7B) +#define PPSMC_MSG_CollectCAC_SQonly ((uint16_t)0x7C) +#define PPSMC_MSG_CollectCAC_TemperaturePwr ((uint16_t)0x7D) + +#define PPSMC_MSG_ExtremitiesTest_Start ((uint16_t)0x7E) +#define PPSMC_MSG_ExtremitiesTest_Stop ((uint16_t)0x7F) +#define PPSMC_FlushDataCache ((uint16_t)0x80) +#define PPSMC_FlushInstrCache ((uint16_t)0x81) + +#define PPSMC_MSG_SetEnabledLevels ((uint16_t)0x82) +#define PPSMC_MSG_SetForcedLevels ((uint16_t)0x83) + +#define PPSMC_MSG_ResetToDefaults ((uint16_t)0x84) + +#define PPSMC_MSG_SetForcedLevelsAndJump ((uint16_t)0x85) +#define PPSMC_MSG_SetCACHistoryMode ((uint16_t)0x86) +#define PPSMC_MSG_EnableDTE ((uint16_t)0x87) +#define PPSMC_MSG_DisableDTE ((uint16_t)0x88) + +#define PPSMC_MSG_SmcSpaceSetAddress ((uint16_t)0x89) +#define PPSMC_MSG_ChangeNearTDPLimit ((uint16_t)0x90) +#define PPSMC_MSG_ChangeSafePowerLimit ((uint16_t)0x91) + +#define PPSMC_MSG_DPMStateSweepStart ((uint16_t)0x92) +#define PPSMC_MSG_DPMStateSweepStop ((uint16_t)0x93) + +#define PPSMC_MSG_OVRDDisableSCLKDS ((uint16_t)0x94) +#define PPSMC_MSG_CancelDisableOVRDSCLKDS ((uint16_t)0x95) +#define PPSMC_MSG_ThrottleOVRDSCLKDS ((uint16_t)0x96) +#define PPSMC_MSG_CancelThrottleOVRDSCLKDS ((uint16_t)0x97) +#define PPSMC_MSG_GPIO17 ((uint16_t)0x98) + +#define PPSMC_MSG_API_SetSvi2Volt_Vddc ((uint16_t)0x99) +#define PPSMC_MSG_API_SetSvi2Volt_Vddci ((uint16_t)0x9A) +#define PPSMC_MSG_API_SetSvi2Volt_Mvdd ((uint16_t)0x9B) +#define PPSMC_MSG_API_GetSvi2Volt_Vddc ((uint16_t)0x9C) +#define PPSMC_MSG_API_GetSvi2Volt_Vddci ((uint16_t)0x9D) +#define PPSMC_MSG_API_GetSvi2Volt_Mvdd ((uint16_t)0x9E) + +#define PPSMC_MSG_BREAK ((uint16_t)0xF8) + +/* Trinity Specific Messages*/ +#define PPSMC_MSG_Test ((uint16_t) 0x100) +#define PPSMC_MSG_DPM_Voltage_Pwrmgt ((uint16_t) 0x101) +#define PPSMC_MSG_DPM_Config ((uint16_t) 0x102) +#define PPSMC_MSG_PM_Controller_Start ((uint16_t) 0x103) +#define PPSMC_MSG_DPM_ForceState ((uint16_t) 0x104) +#define PPSMC_MSG_PG_PowerDownSIMD ((uint16_t) 0x105) +#define PPSMC_MSG_PG_PowerUpSIMD ((uint16_t) 0x106) +#define PPSMC_MSG_PM_Controller_Stop ((uint16_t) 0x107) +#define PPSMC_MSG_PG_SIMD_Config ((uint16_t) 0x108) +#define PPSMC_MSG_Voltage_Cntl_Enable ((uint16_t) 0x109) +#define PPSMC_MSG_Thermal_Cntl_Enable ((uint16_t) 0x10a) +#define PPSMC_MSG_Reset_Service ((uint16_t) 0x10b) +#define PPSMC_MSG_VCEPowerOFF ((uint16_t) 0x10e) +#define PPSMC_MSG_VCEPowerON ((uint16_t) 0x10f) +#define PPSMC_MSG_DPM_Disable_VCE_HS ((uint16_t) 0x110) +#define PPSMC_MSG_DPM_Enable_VCE_HS ((uint16_t) 0x111) +#define PPSMC_MSG_DPM_N_LevelsDisabled ((uint16_t) 0x112) +#define PPSMC_MSG_DCEPowerOFF ((uint16_t) 0x113) +#define PPSMC_MSG_DCEPowerON ((uint16_t) 0x114) +#define PPSMC_MSG_PCIE_DDIPowerDown ((uint16_t) 0x117) +#define PPSMC_MSG_PCIE_DDIPowerUp ((uint16_t) 0x118) +#define PPSMC_MSG_PCIE_CascadePLLPowerDown ((uint16_t) 0x119) +#define PPSMC_MSG_PCIE_CascadePLLPowerUp ((uint16_t) 0x11a) +#define PPSMC_MSG_SYSPLLPowerOff ((uint16_t) 0x11b) +#define PPSMC_MSG_SYSPLLPowerOn ((uint16_t) 0x11c) +#define PPSMC_MSG_DCE_RemoveVoltageAdjustment ((uint16_t) 0x11d) +#define PPSMC_MSG_DCE_AllowVoltageAdjustment ((uint16_t) 0x11e) +#define PPSMC_MSG_DISPLAYPHYStatusNotify ((uint16_t) 0x11f) +#define PPSMC_MSG_EnableBAPM ((uint16_t) 0x120) +#define PPSMC_MSG_DisableBAPM ((uint16_t) 0x121) +#define PPSMC_MSG_PCIE_PHYPowerDown ((uint16_t) 0x122) +#define PPSMC_MSG_PCIE_PHYPowerUp ((uint16_t) 0x123) +#define PPSMC_MSG_UVD_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_Spmi_Enable ((uint16_t) 0x122) +#define PPSMC_MSG_Spmi_Timer ((uint16_t) 0x123) +#define PPSMC_MSG_LCLK_DPM_Config ((uint16_t) 0x124) +#define PPSMC_MSG_NBDPM_Config ((uint16_t) 0x125) +#define PPSMC_MSG_PCIE_DDIPhyPowerDown ((uint16_t) 0x126) +#define PPSMC_MSG_PCIE_DDIPhyPowerUp ((uint16_t) 0x127) +#define PPSMC_MSG_MCLKDPM_Config ((uint16_t) 0x128) + +#define PPSMC_MSG_UVDDPM_Config ((uint16_t) 0x129) +#define PPSMC_MSG_VCEDPM_Config ((uint16_t) 0x12A) +#define PPSMC_MSG_ACPDPM_Config ((uint16_t) 0x12B) +#define PPSMC_MSG_SAMUDPM_Config ((uint16_t) 0x12C) +#define PPSMC_MSG_UVDDPM_SetEnabledMask ((uint16_t) 0x12D) +#define PPSMC_MSG_VCEDPM_SetEnabledMask ((uint16_t) 0x12E) +#define PPSMC_MSG_ACPDPM_SetEnabledMask ((uint16_t) 0x12F) +#define PPSMC_MSG_SAMUDPM_SetEnabledMask ((uint16_t) 0x130) +#define PPSMC_MSG_MCLKDPM_ForceState ((uint16_t) 0x131) +#define PPSMC_MSG_MCLKDPM_NoForcedLevel ((uint16_t) 0x132) +#define PPSMC_MSG_Thermal_Cntl_Disable ((uint16_t) 0x133) +#define PPSMC_MSG_SetTDPLimit ((uint16_t) 0x134) +#define PPSMC_MSG_Voltage_Cntl_Disable ((uint16_t) 0x135) +#define PPSMC_MSG_PCIeDPM_Enable ((uint16_t) 0x136) +#define PPSMC_MSG_ACPPowerOFF ((uint16_t) 0x137) +#define PPSMC_MSG_ACPPowerON ((uint16_t) 0x138) +#define PPSMC_MSG_SAMPowerOFF ((uint16_t) 0x139) +#define PPSMC_MSG_SAMPowerON ((uint16_t) 0x13a) +#define PPSMC_MSG_SDMAPowerOFF ((uint16_t) 0x13b) +#define PPSMC_MSG_SDMAPowerON ((uint16_t) 0x13c) +#define PPSMC_MSG_PCIeDPM_Disable ((uint16_t) 0x13d) +#define PPSMC_MSG_IOMMUPowerOFF ((uint16_t) 0x13e) +#define PPSMC_MSG_IOMMUPowerON ((uint16_t) 0x13f) +#define PPSMC_MSG_NBDPM_Enable ((uint16_t) 0x140) +#define PPSMC_MSG_NBDPM_Disable ((uint16_t) 0x141) +#define PPSMC_MSG_NBDPM_ForceNominal ((uint16_t) 0x142) +#define PPSMC_MSG_NBDPM_ForcePerformance ((uint16_t) 0x143) +#define PPSMC_MSG_NBDPM_UnForce ((uint16_t) 0x144) +#define PPSMC_MSG_SCLKDPM_SetEnabledMask ((uint16_t) 0x145) +#define PPSMC_MSG_MCLKDPM_SetEnabledMask ((uint16_t) 0x146) +#define PPSMC_MSG_PCIeDPM_ForceLevel ((uint16_t) 0x147) +#define PPSMC_MSG_PCIeDPM_UnForceLevel ((uint16_t) 0x148) +#define PPSMC_MSG_EnableACDCGPIOInterrupt ((uint16_t) 0x149) +#define PPSMC_MSG_EnableVRHotGPIOInterrupt ((uint16_t) 0x14a) +#define PPSMC_MSG_SwitchToAC ((uint16_t) 0x14b) + +#define PPSMC_MSG_XDMAPowerOFF ((uint16_t) 0x14c) +#define PPSMC_MSG_XDMAPowerON ((uint16_t) 0x14d) + +#define PPSMC_MSG_DPM_Enable ((uint16_t)0x14e) +#define PPSMC_MSG_DPM_Disable ((uint16_t)0x14f) +#define PPSMC_MSG_MCLKDPM_Enable ((uint16_t)0x150) +#define PPSMC_MSG_MCLKDPM_Disable ((uint16_t)0x151) +#define PPSMC_MSG_LCLKDPM_Enable ((uint16_t)0x152) +#define PPSMC_MSG_LCLKDPM_Disable ((uint16_t)0x153) +#define PPSMC_MSG_UVDDPM_Enable ((uint16_t)0x154) +#define PPSMC_MSG_UVDDPM_Disable ((uint16_t)0x155) +#define PPSMC_MSG_SAMUDPM_Enable ((uint16_t)0x156) +#define PPSMC_MSG_SAMUDPM_Disable ((uint16_t)0x157) +#define PPSMC_MSG_ACPDPM_Enable ((uint16_t)0x158) +#define PPSMC_MSG_ACPDPM_Disable ((uint16_t)0x159) +#define PPSMC_MSG_VCEDPM_Enable ((uint16_t)0x15a) +#define PPSMC_MSG_VCEDPM_Disable ((uint16_t)0x15b) +#define PPSMC_MSG_LCLKDPM_SetEnabledMask ((uint16_t)0x15c) + +#define PPSMC_MSG_DPM_FPS_Mode ((uint16_t) 0x15d) +#define PPSMC_MSG_DPM_Activity_Mode ((uint16_t) 0x15e) +#define PPSMC_MSG_VddC_Request ((uint16_t) 0x15f) +#define PPSMC_MSG_MCLKDPM_GetEnabledMask ((uint16_t) 0x160) +#define PPSMC_MSG_LCLKDPM_GetEnabledMask ((uint16_t) 0x161) +#define PPSMC_MSG_SCLKDPM_GetEnabledMask ((uint16_t) 0x162) +#define PPSMC_MSG_UVDDPM_GetEnabledMask ((uint16_t) 0x163) +#define PPSMC_MSG_SAMUDPM_GetEnabledMask ((uint16_t) 0x164) +#define PPSMC_MSG_ACPDPM_GetEnabledMask ((uint16_t) 0x165) +#define PPSMC_MSG_VCEDPM_GetEnabledMask ((uint16_t) 0x166) +#define PPSMC_MSG_PCIeDPM_SetEnabledMask ((uint16_t) 0x167) +#define PPSMC_MSG_PCIeDPM_GetEnabledMask ((uint16_t) 0x168) +#define PPSMC_MSG_TDCLimitEnable ((uint16_t) 0x169) +#define PPSMC_MSG_TDCLimitDisable ((uint16_t) 0x16a) +#define PPSMC_MSG_DPM_AutoRotate_Mode ((uint16_t) 0x16b) +#define PPSMC_MSG_DISPCLK_FROM_FCH ((uint16_t)0x16c) +#define PPSMC_MSG_DISPCLK_FROM_DFS ((uint16_t)0x16d) +#define PPSMC_MSG_DPREFCLK_FROM_FCH ((uint16_t)0x16e) +#define PPSMC_MSG_DPREFCLK_FROM_DFS ((uint16_t)0x16f) +#define PPSMC_MSG_PmStatusLogStart ((uint16_t)0x170) +#define PPSMC_MSG_PmStatusLogSample ((uint16_t)0x171) +#define PPSMC_MSG_SCLK_AutoDPM_ON ((uint16_t) 0x172) +#define PPSMC_MSG_MCLK_AutoDPM_ON ((uint16_t) 0x173) +#define PPSMC_MSG_LCLK_AutoDPM_ON ((uint16_t) 0x174) +#define PPSMC_MSG_UVD_AutoDPM_ON ((uint16_t) 0x175) +#define PPSMC_MSG_SAMU_AutoDPM_ON ((uint16_t) 0x176) +#define PPSMC_MSG_ACP_AutoDPM_ON ((uint16_t) 0x177) +#define PPSMC_MSG_VCE_AutoDPM_ON ((uint16_t) 0x178) +#define PPSMC_MSG_PCIe_AutoDPM_ON ((uint16_t) 0x179) +#define PPSMC_MSG_MASTER_AutoDPM_ON ((uint16_t) 0x17a) +#define PPSMC_MSG_MASTER_AutoDPM_OFF ((uint16_t) 0x17b) +#define PPSMC_MSG_DYNAMICDISPPHYPOWER ((uint16_t) 0x17c) +#define PPSMC_MSG_CAC_COLLECTION_ON ((uint16_t) 0x17d) +#define PPSMC_MSG_CAC_COLLECTION_OFF ((uint16_t) 0x17e) +#define PPSMC_MSG_CAC_CORRELATION_ON ((uint16_t) 0x17f) +#define PPSMC_MSG_CAC_CORRELATION_OFF ((uint16_t) 0x180) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_ON ((uint16_t) 0x181) +#define PPSMC_MSG_PM_STATUS_TO_DRAM_OFF ((uint16_t) 0x182) +#define PPSMC_MSG_UVD_HANDSHAKE_OFF ((uint16_t) 0x183) +#define PPSMC_MSG_ALLOW_LOWSCLK_INTERRUPT ((uint16_t) 0x184) +#define PPSMC_MSG_PkgPwrLimitEnable ((uint16_t) 0x185) +#define PPSMC_MSG_PkgPwrLimitDisable ((uint16_t) 0x186) +#define PPSMC_MSG_PkgPwrSetLimit ((uint16_t) 0x187) +#define PPSMC_MSG_OverDriveSetTargetTdp ((uint16_t) 0x188) +#define PPSMC_MSG_SCLKDPM_FreezeLevel ((uint16_t) 0x189) +#define PPSMC_MSG_SCLKDPM_UnfreezeLevel ((uint16_t) 0x18A) +#define PPSMC_MSG_MCLKDPM_FreezeLevel ((uint16_t) 0x18B) +#define PPSMC_MSG_MCLKDPM_UnfreezeLevel ((uint16_t) 0x18C) +#define PPSMC_MSG_START_DRAM_LOGGING ((uint16_t) 0x18D) +#define PPSMC_MSG_STOP_DRAM_LOGGING ((uint16_t) 0x18E) +#define PPSMC_MSG_MASTER_DeepSleep_ON ((uint16_t) 0x18F) +#define PPSMC_MSG_MASTER_DeepSleep_OFF ((uint16_t) 0x190) +#define PPSMC_MSG_Remove_DC_Clamp ((uint16_t) 0x191) +#define PPSMC_MSG_DisableACDCGPIOInterrupt ((uint16_t) 0x192) +#define PPSMC_MSG_OverrideVoltageControl_SetVddc ((uint16_t) 0x193) +#define PPSMC_MSG_OverrideVoltageControl_SetVddci ((uint16_t) 0x194) +#define PPSMC_MSG_SetVidOffset_1 ((uint16_t) 0x195) +#define PPSMC_MSG_SetVidOffset_2 ((uint16_t) 0x207) +#define PPSMC_MSG_GetVidOffset_1 ((uint16_t) 0x196) +#define PPSMC_MSG_GetVidOffset_2 ((uint16_t) 0x208) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Enable ((uint16_t) 0x197) +#define PPSMC_MSG_THERMAL_OVERDRIVE_Disable ((uint16_t) 0x198) +#define PPSMC_MSG_SetTjMax ((uint16_t) 0x199) +#define PPSMC_MSG_SetFanPwmMax ((uint16_t) 0x19A) + +#define PPSMC_MSG_WaitForMclkSwitchFinish ((uint16_t) 0x19B) +#define PPSMC_MSG_ENABLE_THERMAL_DPM ((uint16_t) 0x19C) +#define PPSMC_MSG_DISABLE_THERMAL_DPM ((uint16_t) 0x19D) +#define PPSMC_MSG_Enable_PCC ((uint16_t) 0x19E) +#define PPSMC_MSG_Disable_PCC ((uint16_t) 0x19F) + +#define PPSMC_MSG_API_GetSclkFrequency ((uint16_t) 0x200) +#define PPSMC_MSG_API_GetMclkFrequency ((uint16_t) 0x201) +#define PPSMC_MSG_API_GetSclkBusy ((uint16_t) 0x202) +#define PPSMC_MSG_API_GetMclkBusy ((uint16_t) 0x203) +#define PPSMC_MSG_API_GetAsicPower ((uint16_t) 0x204) +#define PPSMC_MSG_SetFanRpmMax ((uint16_t) 0x205) +#define PPSMC_MSG_SetFanSclkTarget ((uint16_t) 0x206) +#define PPSMC_MSG_SetFanMinPwm ((uint16_t) 0x209) +#define PPSMC_MSG_SetFanTemperatureTarget ((uint16_t) 0x20A) + +#define PPSMC_MSG_BACO_StartMonitor ((uint16_t) 0x240) +#define PPSMC_MSG_BACO_Cancel ((uint16_t) 0x241) +#define PPSMC_MSG_EnableVddGfx ((uint16_t) 0x242) +#define PPSMC_MSG_DisableVddGfx ((uint16_t) 0x243) +#define PPSMC_MSG_UcodeAddressLow ((uint16_t) 0x244) +#define PPSMC_MSG_UcodeAddressHigh ((uint16_t) 0x245) +#define PPSMC_MSG_UcodeLoadStatus ((uint16_t) 0x246) + +#define PPSMC_MSG_DRV_DRAM_ADDR_HI ((uint16_t) 0x250) +#define PPSMC_MSG_DRV_DRAM_ADDR_LO ((uint16_t) 0x251) +#define PPSMC_MSG_SMU_DRAM_ADDR_HI ((uint16_t) 0x252) +#define PPSMC_MSG_SMU_DRAM_ADDR_LO ((uint16_t) 0x253) +#define PPSMC_MSG_LoadUcodes ((uint16_t) 0x254) +#define PPSMC_MSG_PowerStateNotify ((uint16_t) 0x255) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_HI ((uint16_t) 0x256) +#define PPSMC_MSG_COND_EXEC_DRAM_ADDR_LO ((uint16_t) 0x257) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_HI ((uint16_t) 0x258) +#define PPSMC_MSG_VBIOS_DRAM_ADDR_LO ((uint16_t) 0x259) +#define PPSMC_MSG_LoadVBios ((uint16_t) 0x25A) +#define PPSMC_MSG_GetUcodeVersion ((uint16_t) 0x25B) +#define DMCUSMC_MSG_PSREntry ((uint16_t) 0x25C) +#define DMCUSMC_MSG_PSRExit ((uint16_t) 0x25D) +#define PPSMC_MSG_EnableClockGatingFeature ((uint16_t) 0x260) +#define PPSMC_MSG_DisableClockGatingFeature ((uint16_t) 0x261) +#define PPSMC_MSG_IsDeviceRunning ((uint16_t) 0x262) +#define PPSMC_MSG_LoadMetaData ((uint16_t) 0x263) +#define PPSMC_MSG_TMON_AutoCaliberate_Enable ((uint16_t) 0x264) +#define PPSMC_MSG_TMON_AutoCaliberate_Disable ((uint16_t) 0x265) +#define PPSMC_MSG_GetTelemetry1Slope ((uint16_t) 0x266) +#define PPSMC_MSG_GetTelemetry1Offset ((uint16_t) 0x267) +#define PPSMC_MSG_GetTelemetry2Slope ((uint16_t) 0x268) +#define PPSMC_MSG_GetTelemetry2Offset ((uint16_t) 0x269) + +typedef uint16_t PPSMC_Msg; + +/* If the SMC firmware has an event status soft register this is what the individual bits mean.*/ +#define PPSMC_EVENT_STATUS_THERMAL 0x00000001 +#define PPSMC_EVENT_STATUS_REGULATORHOT 0x00000002 +#define PPSMC_EVENT_STATUS_DC 0x00000004 +#define PPSMC_EVENT_STATUS_GPIO17 0x00000008 + + +#pragma pack(pop) +#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/Makefile b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile new file mode 100644 index 000000000000..6c4ef135cf01 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/Makefile @@ -0,0 +1,9 @@ +# +# Makefile for the 'smu manager' sub-component of powerplay. +# It provides the smu management services for the driver. + +SMU_MGR = smumgr.o cz_smumgr.o tonga_smumgr.o fiji_smumgr.o + +AMD_PP_SMUMGR = $(addprefix $(AMD_PP_PATH)/smumgr/,$(SMU_MGR)) + +AMD_POWERPLAY_FILES += $(AMD_PP_SMUMGR) diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c new file mode 100644 index 000000000000..e74023bd4e0d --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.c @@ -0,0 +1,858 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/gfp.h> +#include "linux/delay.h" +#include "cgs_common.h" +#include "smu/smu_8_0_d.h" +#include "smu/smu_8_0_sh_mask.h" +#include "smu8.h" +#include "smu8_fusion.h" +#include "cz_smumgr.h" +#include "cz_ppsmc.h" +#include "smu_ucode_xfer_cz.h" +#include "gca/gfx_8_0_d.h" +#include "gca/gfx_8_0_sh_mask.h" +#include "smumgr.h" + +#define SIZE_ALIGN_32(x) (((x) + 31) / 32 * 32) + +static enum cz_scratch_entry firmware_list[] = { + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, +}; + +static int cz_smum_get_argument(struct pp_smumgr *smumgr) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + return cgs_read_register(smumgr->device, + mmSMU_MP1_SRBM2P_ARG_0); +} + +static int cz_send_msg_to_smc_async(struct pp_smumgr *smumgr, + uint16_t msg) +{ + int result = 0; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, + SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); + if (result != 0) { + printk(KERN_ERR "[ powerplay ] cz_send_msg_to_smc_async failed\n"); + return result; + } + + cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_RESP_0, 0); + cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_MSG_0, msg); + + return 0; +} + +/* Send a message to the SMC, and wait for its response.*/ +static int cz_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +{ + int result = 0; + + result = cz_send_msg_to_smc_async(smumgr, msg); + if (result != 0) + return result; + + result = SMUM_WAIT_FIELD_UNEQUAL(smumgr, + SMU_MP1_SRBM2P_RESP_0, CONTENT, 0); + + if (result != 0) + return result; + + return 0; +} + +static int cz_set_smc_sram_address(struct pp_smumgr *smumgr, + uint32_t smc_address, uint32_t limit) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + if (0 != (3 & smc_address)) { + printk(KERN_ERR "[ powerplay ] SMC address must be 4 byte aligned\n"); + return -1; + } + + if (limit <= (smc_address + 3)) { + printk(KERN_ERR "[ powerplay ] SMC address beyond the SMC RAM area\n"); + return -1; + } + + cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX_0, + SMN_MP1_SRAM_START_ADDR + smc_address); + + return 0; +} + +static int cz_write_smc_sram_dword(struct pp_smumgr *smumgr, + uint32_t smc_address, uint32_t value, uint32_t limit) +{ + int result; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + result = cz_set_smc_sram_address(smumgr, smc_address, limit); + cgs_write_register(smumgr->device, mmMP0PUB_IND_DATA_0, value); + + return 0; +} + +static int cz_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + cgs_write_register(smumgr->device, mmSMU_MP1_SRBM2P_ARG_0, parameter); + + return cz_send_msg_to_smc(smumgr, msg); +} + +static int cz_request_smu_load_fw(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)(smumgr->backend); + int result = 0; + uint32_t smc_address; + + if (!smumgr->reload_fw) { + printk(KERN_INFO "[ powerplay ] skip reloading...\n"); + return 0; + } + + smc_address = SMU8_FIRMWARE_HEADER_LOCATION + + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); + + cz_write_smc_sram_dword(smumgr, smc_address, 0, smc_address+4); + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_DriverDramAddrHi, + cz_smu->toc_buffer.mc_addr_high); + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_DriverDramAddrLo, + cz_smu->toc_buffer.mc_addr_low); + + cz_send_msg_to_smc(smumgr, PPSMC_MSG_InitJobs); + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_ExecuteJob, + cz_smu->toc_entry_aram); + cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_smu->toc_entry_power_profiling_index); + + result = cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_ExecuteJob, + cz_smu->toc_entry_initialize_index); + + return result; +} + +static int cz_check_fw_load_finish(struct pp_smumgr *smumgr, + uint32_t firmware) +{ + int i; + uint32_t index = SMN_MP1_SRAM_START_ADDR + + SMU8_FIRMWARE_HEADER_LOCATION + + offsetof(struct SMU8_Firmware_Header, UcodeLoadStatus); + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + return cgs_read_register(smumgr->device, + mmSMU_MP1_SRBM2P_ARG_0); + + cgs_write_register(smumgr->device, mmMP0PUB_IND_INDEX, index); + + for (i = 0; i < smumgr->usec_timeout; i++) { + if (firmware == + (cgs_read_register(smumgr->device, mmMP0PUB_IND_DATA) & firmware)) + break; + udelay(1); + } + + if (i >= smumgr->usec_timeout) { + printk(KERN_ERR "[ powerplay ] SMU check loaded firmware failed.\n"); + return -EINVAL; + } + + return 0; +} + +static int cz_load_mec_firmware(struct pp_smumgr *smumgr) +{ + uint32_t reg_data; + uint32_t tmp; + int ret = 0; + struct cgs_firmware_info info = {0}; + struct cz_smumgr *cz_smu; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + cz_smu = (struct cz_smumgr *)smumgr->backend; + ret = cgs_get_firmware_info(smumgr->device, + CGS_UCODE_ID_CP_MEC, &info); + + if (ret) + return -EINVAL; + + /* Disable MEC parsing/prefetching */ + tmp = cgs_read_register(smumgr->device, + mmCP_MEC_CNTL); + tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME1_HALT, 1); + tmp = SMUM_SET_FIELD(tmp, CP_MEC_CNTL, MEC_ME2_HALT, 1); + cgs_write_register(smumgr->device, mmCP_MEC_CNTL, tmp); + + tmp = cgs_read_register(smumgr->device, + mmCP_CPC_IC_BASE_CNTL); + + tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, VMID, 0); + tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, ATC, 0); + tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, CACHE_POLICY, 0); + tmp = SMUM_SET_FIELD(tmp, CP_CPC_IC_BASE_CNTL, MTYPE, 1); + cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_CNTL, tmp); + + reg_data = smu_lower_32_bits(info.mc_addr) & + SMUM_FIELD_MASK(CP_CPC_IC_BASE_LO, IC_BASE_LO); + cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_LO, reg_data); + + reg_data = smu_upper_32_bits(info.mc_addr) & + SMUM_FIELD_MASK(CP_CPC_IC_BASE_HI, IC_BASE_HI); + cgs_write_register(smumgr->device, mmCP_CPC_IC_BASE_HI, reg_data); + + return 0; +} + +static int cz_start_smu(struct pp_smumgr *smumgr) +{ + int ret = 0; + uint32_t fw_to_check = UCODE_ID_RLC_G_MASK | + UCODE_ID_SDMA0_MASK | + UCODE_ID_SDMA1_MASK | + UCODE_ID_CP_CE_MASK | + UCODE_ID_CP_ME_MASK | + UCODE_ID_CP_PFP_MASK | + UCODE_ID_CP_MEC_JT1_MASK | + UCODE_ID_CP_MEC_JT2_MASK; + + cz_request_smu_load_fw(smumgr); + cz_check_fw_load_finish(smumgr, fw_to_check); + + ret = cz_load_mec_firmware(smumgr); + if (ret) + printk(KERN_ERR "[ powerplay ] Mec Firmware load failed\n"); + + return ret; +} + +static uint8_t cz_translate_firmware_enum_to_arg( + enum cz_scratch_entry firmware_enum) +{ + uint8_t ret = 0; + + switch (firmware_enum) { + case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0: + ret = UCODE_ID_SDMA0; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1: + ret = UCODE_ID_SDMA1; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE: + ret = UCODE_ID_CP_CE; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP: + ret = UCODE_ID_CP_PFP; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME: + ret = UCODE_ID_CP_ME; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1: + ret = UCODE_ID_CP_MEC_JT1; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2: + ret = UCODE_ID_CP_MEC_JT2; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG: + ret = UCODE_ID_GMCON_RENG; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G: + ret = UCODE_ID_RLC_G; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH: + ret = UCODE_ID_RLC_SCRATCH; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM: + ret = UCODE_ID_RLC_SRM_ARAM; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM: + ret = UCODE_ID_RLC_SRM_DRAM; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM: + ret = UCODE_ID_DMCU_ERAM; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM: + ret = UCODE_ID_DMCU_IRAM; + break; + case CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING: + ret = TASK_ARG_INIT_MM_PWR_LOG; + break; + case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT: + case CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING: + case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS: + case CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT: + case CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START: + case CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS: + ret = TASK_ARG_REG_MMIO; + break; + case CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE: + ret = TASK_ARG_INIT_CLK_TABLE; + break; + } + + return ret; +} + +static enum cgs_ucode_id cz_convert_fw_type_to_cgs(uint32_t fw_type) +{ + enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; + + switch (fw_type) { + case UCODE_ID_SDMA0: + result = CGS_UCODE_ID_SDMA0; + break; + case UCODE_ID_SDMA1: + result = CGS_UCODE_ID_SDMA1; + break; + case UCODE_ID_CP_CE: + result = CGS_UCODE_ID_CP_CE; + break; + case UCODE_ID_CP_PFP: + result = CGS_UCODE_ID_CP_PFP; + break; + case UCODE_ID_CP_ME: + result = CGS_UCODE_ID_CP_ME; + break; + case UCODE_ID_CP_MEC_JT1: + result = CGS_UCODE_ID_CP_MEC_JT1; + break; + case UCODE_ID_CP_MEC_JT2: + result = CGS_UCODE_ID_CP_MEC_JT2; + break; + case UCODE_ID_RLC_G: + result = CGS_UCODE_ID_RLC_G; + break; + default: + break; + } + + return result; +} + +static int cz_smu_populate_single_scratch_task( + struct pp_smumgr *smumgr, + enum cz_scratch_entry fw_enum, + uint8_t type, bool is_last) +{ + uint8_t i; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; + struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; + + task->type = type; + task->arg = cz_translate_firmware_enum_to_arg(fw_enum); + task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; + + for (i = 0; i < cz_smu->scratch_buffer_length; i++) + if (cz_smu->scratch_buffer[i].firmware_ID == fw_enum) + break; + + if (i >= cz_smu->scratch_buffer_length) { + printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n"); + return -EINVAL; + } + + task->addr.low = cz_smu->scratch_buffer[i].mc_addr_low; + task->addr.high = cz_smu->scratch_buffer[i].mc_addr_high; + task->size_bytes = cz_smu->scratch_buffer[i].data_size; + + if (CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS == fw_enum) { + struct cz_ih_meta_data *pIHReg_restore = + (struct cz_ih_meta_data *)cz_smu->scratch_buffer[i].kaddr; + pIHReg_restore->command = + METADATA_CMD_MODE0 | METADATA_PERFORM_ON_LOAD; + } + + return 0; +} + +static int cz_smu_populate_single_ucode_load_task( + struct pp_smumgr *smumgr, + enum cz_scratch_entry fw_enum, + bool is_last) +{ + uint8_t i; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; + struct SMU_Task *task = &toc->tasks[cz_smu->toc_entry_used_count++]; + + task->type = TASK_TYPE_UCODE_LOAD; + task->arg = cz_translate_firmware_enum_to_arg(fw_enum); + task->next = is_last ? END_OF_TASK_LIST : cz_smu->toc_entry_used_count; + + for (i = 0; i < cz_smu->driver_buffer_length; i++) + if (cz_smu->driver_buffer[i].firmware_ID == fw_enum) + break; + + if (i >= cz_smu->driver_buffer_length) { + printk(KERN_ERR "[ powerplay ] Invalid Firmware Type\n"); + return -EINVAL; + } + + task->addr.low = cz_smu->driver_buffer[i].mc_addr_low; + task->addr.high = cz_smu->driver_buffer[i].mc_addr_high; + task->size_bytes = cz_smu->driver_buffer[i].data_size; + + return 0; +} + +static int cz_smu_construct_toc_for_rlc_aram_save(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + + cz_smu->toc_entry_aram = cz_smu->toc_entry_used_count; + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + TASK_TYPE_UCODE_SAVE, true); + + return 0; +} + +static int cz_smu_initialize_toc_empty_job_list(struct pp_smumgr *smumgr) +{ + int i; + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; + + for (i = 0; i < NUM_JOBLIST_ENTRIES; i++) + toc->JobList[i] = (uint8_t)IGNORE_JOB; + + return 0; +} + +static int cz_smu_construct_toc_for_vddgfx_enter(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; + + toc->JobList[JOB_GFX_SAVE] = (uint8_t)cz_smu->toc_entry_used_count; + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + TASK_TYPE_UCODE_SAVE, false); + + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + TASK_TYPE_UCODE_SAVE, true); + + return 0; +} + + +static int cz_smu_construct_toc_for_vddgfx_exit(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + struct TOC *toc = (struct TOC *)cz_smu->toc_buffer.kaddr; + + toc->JobList[JOB_GFX_RESTORE] = (uint8_t)cz_smu->toc_entry_used_count; + + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, false); + + /* populate scratch */ + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + TASK_TYPE_UCODE_LOAD, false); + + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + TASK_TYPE_UCODE_LOAD, false); + + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + TASK_TYPE_UCODE_LOAD, true); + + return 0; +} + +static int cz_smu_construct_toc_for_power_profiling( + struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + + cz_smu->toc_entry_power_profiling_index = cz_smu->toc_entry_used_count; + + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + TASK_TYPE_INITIALIZE, true); + return 0; +} + +static int cz_smu_construct_toc_for_bootup(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + + cz_smu->toc_entry_initialize_index = cz_smu->toc_entry_used_count; + + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, false); + cz_smu_populate_single_ucode_load_task(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, true); + + return 0; +} + +static int cz_smu_construct_toc_for_clock_table(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + + cz_smu->toc_entry_clock_table = cz_smu->toc_entry_used_count; + + cz_smu_populate_single_scratch_task(smumgr, + CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, + TASK_TYPE_INITIALIZE, true); + + return 0; +} + +static int cz_smu_construct_toc(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + + cz_smu->toc_entry_used_count = 0; + + cz_smu_initialize_toc_empty_job_list(smumgr); + + cz_smu_construct_toc_for_rlc_aram_save(smumgr); + + cz_smu_construct_toc_for_vddgfx_enter(smumgr); + + cz_smu_construct_toc_for_vddgfx_exit(smumgr); + + cz_smu_construct_toc_for_power_profiling(smumgr); + + cz_smu_construct_toc_for_bootup(smumgr); + + cz_smu_construct_toc_for_clock_table(smumgr); + + return 0; +} + +static int cz_smu_populate_firmware_entries(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + uint32_t firmware_type; + uint32_t i; + int ret; + enum cgs_ucode_id ucode_id; + struct cgs_firmware_info info = {0}; + + cz_smu->driver_buffer_length = 0; + + for (i = 0; i < sizeof(firmware_list)/sizeof(*firmware_list); i++) { + + firmware_type = cz_translate_firmware_enum_to_arg( + firmware_list[i]); + + ucode_id = cz_convert_fw_type_to_cgs(firmware_type); + + ret = cgs_get_firmware_info(smumgr->device, + ucode_id, &info); + + if (ret == 0) { + cz_smu->driver_buffer[i].mc_addr_high = + smu_upper_32_bits(info.mc_addr); + + cz_smu->driver_buffer[i].mc_addr_low = + smu_lower_32_bits(info.mc_addr); + + cz_smu->driver_buffer[i].data_size = info.image_size; + + cz_smu->driver_buffer[i].firmware_ID = firmware_list[i]; + cz_smu->driver_buffer_length++; + } + } + + return 0; +} + +static int cz_smu_populate_single_scratch_entry( + struct pp_smumgr *smumgr, + enum cz_scratch_entry scratch_type, + uint32_t ulsize_byte, + struct cz_buffer_entry *entry) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + long long mc_addr = + ((long long)(cz_smu->smu_buffer.mc_addr_high) << 32) + | cz_smu->smu_buffer.mc_addr_low; + + uint32_t ulsize_aligned = SIZE_ALIGN_32(ulsize_byte); + + mc_addr += cz_smu->smu_buffer_used_bytes; + + entry->data_size = ulsize_byte; + entry->kaddr = (char *) cz_smu->smu_buffer.kaddr + + cz_smu->smu_buffer_used_bytes; + entry->mc_addr_low = smu_lower_32_bits(mc_addr); + entry->mc_addr_high = smu_upper_32_bits(mc_addr); + entry->firmware_ID = scratch_type; + + cz_smu->smu_buffer_used_bytes += ulsize_aligned; + + return 0; +} + +static int cz_download_pptable_settings(struct pp_smumgr *smumgr, void **table) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + unsigned long i; + + for (i = 0; i < cz_smu->scratch_buffer_length; i++) { + if (cz_smu->scratch_buffer[i].firmware_ID + == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) + break; + } + + *table = (struct SMU8_Fusion_ClkTable *)cz_smu->scratch_buffer[i].kaddr; + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SetClkTableAddrHi, + cz_smu->scratch_buffer[i].mc_addr_high); + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SetClkTableAddrLo, + cz_smu->scratch_buffer[i].mc_addr_low); + + cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_smu->toc_entry_clock_table); + + cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToDram); + + return 0; +} + +static int cz_upload_pptable_settings(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + unsigned long i; + + for (i = 0; i < cz_smu->scratch_buffer_length; i++) { + if (cz_smu->scratch_buffer[i].firmware_ID + == CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE) + break; + } + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SetClkTableAddrHi, + cz_smu->scratch_buffer[i].mc_addr_high); + + cz_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SetClkTableAddrLo, + cz_smu->scratch_buffer[i].mc_addr_low); + + cz_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_ExecuteJob, + cz_smu->toc_entry_clock_table); + + cz_send_msg_to_smc(smumgr, PPSMC_MSG_ClkTableXferToSmu); + + return 0; +} + +static int cz_smu_init(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu = (struct cz_smumgr *)smumgr->backend; + uint64_t mc_addr = 0; + int ret = 0; + + cz_smu->toc_buffer.data_size = 4096; + cz_smu->smu_buffer.data_size = + ALIGN(UCODE_ID_RLC_SCRATCH_SIZE_BYTE, 32) + + ALIGN(UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, 32) + + ALIGN(UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, 32) + + ALIGN(sizeof(struct SMU8_MultimediaPowerLogData), 32) + + ALIGN(sizeof(struct SMU8_Fusion_ClkTable), 32); + + ret = smu_allocate_memory(smumgr->device, + cz_smu->toc_buffer.data_size, + CGS_GPU_MEM_TYPE__GART_CACHEABLE, + PAGE_SIZE, + &mc_addr, + &cz_smu->toc_buffer.kaddr, + &cz_smu->toc_buffer.handle); + if (ret != 0) + return -1; + + cz_smu->toc_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); + cz_smu->toc_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); + + ret = smu_allocate_memory(smumgr->device, + cz_smu->smu_buffer.data_size, + CGS_GPU_MEM_TYPE__GART_CACHEABLE, + PAGE_SIZE, + &mc_addr, + &cz_smu->smu_buffer.kaddr, + &cz_smu->smu_buffer.handle); + if (ret != 0) + return -1; + + cz_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); + cz_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); + + cz_smu_populate_firmware_entries(smumgr); + if (0 != cz_smu_populate_single_scratch_entry(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + UCODE_ID_RLC_SCRATCH_SIZE_BYTE, + &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { + printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); + return -1; + } + + if (0 != cz_smu_populate_single_scratch_entry(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + UCODE_ID_RLC_SRM_ARAM_SIZE_BYTE, + &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { + printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); + return -1; + } + if (0 != cz_smu_populate_single_scratch_entry(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + UCODE_ID_RLC_SRM_DRAM_SIZE_BYTE, + &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { + printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); + return -1; + } + + if (0 != cz_smu_populate_single_scratch_entry(smumgr, + CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + sizeof(struct SMU8_MultimediaPowerLogData), + &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { + printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); + return -1; + } + + if (0 != cz_smu_populate_single_scratch_entry(smumgr, + CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE, + sizeof(struct SMU8_Fusion_ClkTable), + &cz_smu->scratch_buffer[cz_smu->scratch_buffer_length++])) { + printk(KERN_ERR "[ powerplay ] Error when Populate Firmware Entry.\n"); + return -1; + } + cz_smu_construct_toc(smumgr); + + return 0; +} + +static int cz_smu_fini(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + cz_smu = (struct cz_smumgr *)smumgr->backend; + if (!cz_smu) { + cgs_free_gpu_mem(smumgr->device, + cz_smu->toc_buffer.handle); + cgs_free_gpu_mem(smumgr->device, + cz_smu->smu_buffer.handle); + kfree(cz_smu); + kfree(smumgr); + } + + return 0; +} + +static const struct pp_smumgr_func cz_smu_funcs = { + .smu_init = cz_smu_init, + .smu_fini = cz_smu_fini, + .start_smu = cz_start_smu, + .check_fw_load_finish = cz_check_fw_load_finish, + .request_smu_load_fw = NULL, + .request_smu_load_specific_fw = NULL, + .get_argument = cz_smum_get_argument, + .send_msg_to_smc = cz_send_msg_to_smc, + .send_msg_to_smc_with_parameter = cz_send_msg_to_smc_with_parameter, + .download_pptable_settings = cz_download_pptable_settings, + .upload_pptable_settings = cz_upload_pptable_settings, +}; + +int cz_smum_init(struct pp_smumgr *smumgr) +{ + struct cz_smumgr *cz_smu; + + cz_smu = kzalloc(sizeof(struct cz_smumgr), GFP_KERNEL); + if (cz_smu == NULL) + return -ENOMEM; + + smumgr->backend = cz_smu; + smumgr->smumgr_funcs = &cz_smu_funcs; + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h new file mode 100644 index 000000000000..883818039248 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/cz_smumgr.h @@ -0,0 +1,102 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _CZ_SMUMGR_H_ +#define _CZ_SMUMGR_H_ + + +#define MAX_NUM_FIRMWARE 8 +#define MAX_NUM_SCRATCH 11 +#define CZ_SCRATCH_SIZE_NONGFX_CLOCKGATING 1024 +#define CZ_SCRATCH_SIZE_NONGFX_GOLDENSETTING 2048 +#define CZ_SCRATCH_SIZE_SDMA_METADATA 1024 +#define CZ_SCRATCH_SIZE_IH ((2*256+1)*4) + +enum cz_scratch_entry { + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA0 = 0, + CZ_SCRATCH_ENTRY_UCODE_ID_SDMA1, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_CE, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_PFP, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_ME, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT1, + CZ_SCRATCH_ENTRY_UCODE_ID_CP_MEC_JT2, + CZ_SCRATCH_ENTRY_UCODE_ID_GMCON_RENG, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_G, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SCRATCH, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_ARAM, + CZ_SCRATCH_ENTRY_UCODE_ID_RLC_SRM_DRAM, + CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_ERAM, + CZ_SCRATCH_ENTRY_UCODE_ID_DMCU_IRAM, + CZ_SCRATCH_ENTRY_UCODE_ID_POWER_PROFILING, + CZ_SCRATCH_ENTRY_DATA_ID_SDMA_HALT, + CZ_SCRATCH_ENTRY_DATA_ID_SYS_CLOCKGATING, + CZ_SCRATCH_ENTRY_DATA_ID_SDMA_RING_REGS, + CZ_SCRATCH_ENTRY_DATA_ID_NONGFX_REINIT, + CZ_SCRATCH_ENTRY_DATA_ID_SDMA_START, + CZ_SCRATCH_ENTRY_DATA_ID_IH_REGISTERS, + CZ_SCRATCH_ENTRY_SMU8_FUSION_CLKTABLE +}; + +struct cz_buffer_entry { + uint32_t data_size; + uint32_t mc_addr_low; + uint32_t mc_addr_high; + void *kaddr; + enum cz_scratch_entry firmware_ID; + unsigned long handle; /* as bo handle used when release bo */ +}; + +struct cz_register_index_data_pair { + uint32_t offset; + uint32_t value; +}; + +struct cz_ih_meta_data { + uint32_t command; + struct cz_register_index_data_pair register_index_value_pair[1]; +}; + +struct cz_smumgr { + uint8_t driver_buffer_length; + uint8_t scratch_buffer_length; + uint16_t toc_entry_used_count; + uint16_t toc_entry_initialize_index; + uint16_t toc_entry_power_profiling_index; + uint16_t toc_entry_aram; + uint16_t toc_entry_ih_register_restore_task_index; + uint16_t toc_entry_clock_table; + uint16_t ih_register_restore_task_size; + uint16_t smu_buffer_used_bytes; + + struct cz_buffer_entry toc_buffer; + struct cz_buffer_entry smu_buffer; + struct cz_buffer_entry firmware_buffer; + struct cz_buffer_entry driver_buffer[MAX_NUM_FIRMWARE]; + struct cz_buffer_entry meta_data_buffer[MAX_NUM_FIRMWARE]; + struct cz_buffer_entry scratch_buffer[MAX_NUM_SCRATCH]; +}; + +struct pp_smumgr; + +extern int cz_smum_init(struct pp_smumgr *smumgr); + +#endif diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c new file mode 100644 index 000000000000..45997e609fd6 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.c @@ -0,0 +1,1042 @@ +/* + * Copyright 2015 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. + * + */ + +#include "smumgr.h" +#include "smu73.h" +#include "smu_ucode_xfer_vi.h" +#include "fiji_smumgr.h" +#include "fiji_ppsmc.h" +#include "smu73_discrete.h" +#include "ppatomctrl.h" +#include "smu/smu_7_1_3_d.h" +#include "smu/smu_7_1_3_sh_mask.h" +#include "gmc/gmc_8_1_d.h" +#include "gmc/gmc_8_1_sh_mask.h" +#include "oss/oss_3_0_d.h" +#include "gca/gfx_8_0_d.h" +#include "bif/bif_5_0_d.h" +#include "bif/bif_5_0_sh_mask.h" +#include "pp_debug.h" +#include "fiji_pwrvirus.h" + +#define AVFS_EN_MSB 1568 +#define AVFS_EN_LSB 1568 + +#define FIJI_SMC_SIZE 0x20000 + +struct SMU73_Discrete_GraphicsLevel avfs_graphics_level[8] = { + /* Min Sclk pcie DeepSleep Activity CgSpll CgSpll spllSpread SpllSpread CcPwr CcPwr Sclk Display Enabled Enabled Voltage Power */ + /* Voltage, Frequency, DpmLevel, DivId, Level, FuncCntl3, FuncCntl4, Spectrum, Spectrum2, DynRm, DynRm1 Did, Watermark, ForActivity, ForThrottle, UpHyst, DownHyst, DownHyst, Throttle */ + { 0x3c0fd047, 0x30750000, 0x00, 0x03, 0x1e00, 0x00200410, 0x87020000, 0x21680000, 0x0c000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xa00fd047, 0x409c0000, 0x01, 0x04, 0x1e00, 0x00800510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x16, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x0410d047, 0x50c30000, 0x01, 0x00, 0x1e00, 0x00600410, 0x87020000, 0x21680000, 0x0d000000, 0, 0, 0x0e, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x6810d047, 0x60ea0000, 0x01, 0x00, 0x1e00, 0x00800410, 0x87020000, 0x21680000, 0x0e000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xcc10d047, 0xe8fd0000, 0x01, 0x00, 0x1e00, 0x00e00410, 0x87020000, 0x21680000, 0x0f000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x3011d047, 0x70110100, 0x01, 0x00, 0x1e00, 0x00400510, 0x87020000, 0x21680000, 0x10000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0x9411d047, 0xf8240100, 0x01, 0x00, 0x1e00, 0x00a00510, 0x87020000, 0x21680000, 0x11000000, 0, 0, 0x0c, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 }, + { 0xf811d047, 0x80380100, 0x01, 0x00, 0x1e00, 0x00000610, 0x87020000, 0x21680000, 0x12000000, 0, 0, 0x0c, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00 } +}; + +static enum cgs_ucode_id fiji_convert_fw_type_to_cgs(uint32_t fw_type) +{ + enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; + + switch (fw_type) { + case UCODE_ID_SMU: + result = CGS_UCODE_ID_SMU; + break; + case UCODE_ID_SDMA0: + result = CGS_UCODE_ID_SDMA0; + break; + case UCODE_ID_SDMA1: + result = CGS_UCODE_ID_SDMA1; + break; + case UCODE_ID_CP_CE: + result = CGS_UCODE_ID_CP_CE; + break; + case UCODE_ID_CP_PFP: + result = CGS_UCODE_ID_CP_PFP; + break; + case UCODE_ID_CP_ME: + result = CGS_UCODE_ID_CP_ME; + break; + case UCODE_ID_CP_MEC: + result = CGS_UCODE_ID_CP_MEC; + break; + case UCODE_ID_CP_MEC_JT1: + result = CGS_UCODE_ID_CP_MEC_JT1; + break; + case UCODE_ID_CP_MEC_JT2: + result = CGS_UCODE_ID_CP_MEC_JT2; + break; + case UCODE_ID_RLC_G: + result = CGS_UCODE_ID_RLC_G; + break; + default: + break; + } + + return result; +} +/** +* Set the address for reading/writing the SMC SRAM space. +* @param smumgr the address of the powerplay hardware manager. +* @param smc_addr the address in the SMC RAM to access. +*/ +static int fiji_set_smc_sram_address(struct pp_smumgr *smumgr, + uint32_t smc_addr, uint32_t limit) +{ + PP_ASSERT_WITH_CODE((0 == (3 & smc_addr)), + "SMC address must be 4 byte aligned.", return -EINVAL;); + PP_ASSERT_WITH_CODE((limit > (smc_addr + 3)), + "SMC address is beyond the SMC RAM area.", return -EINVAL;); + + cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, smc_addr); + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + return 0; +} + +/** +* Copy bytes from an array into the SMC RAM space. +* +* @param smumgr the address of the powerplay SMU manager. +* @param smcStartAddress the start address in the SMC RAM to copy bytes to. +* @param src the byte array to copy the bytes from. +* @param byteCount the number of bytes to copy. +*/ +int fiji_copy_bytes_to_smc(struct pp_smumgr *smumgr, + uint32_t smcStartAddress, const uint8_t *src, + uint32_t byteCount, uint32_t limit) +{ + int result; + uint32_t data, originalData; + uint32_t addr, extraShift; + + PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress)), + "SMC address must be 4 byte aligned.", return -EINVAL;); + PP_ASSERT_WITH_CODE((limit > (smcStartAddress + byteCount)), + "SMC address is beyond the SMC RAM area.", return -EINVAL;); + + addr = smcStartAddress; + + while (byteCount >= 4) { + /* Bytes are written into the SMC addres space with the MSB first. */ + data = src[0] * 0x1000000 + src[1] * 0x10000 + src[2] * 0x100 + src[3]; + + result = fiji_set_smc_sram_address(smumgr, addr, limit); + if (result) + return result; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data); + + src += 4; + byteCount -= 4; + addr += 4; + } + + if (byteCount) { + /* Now write the odd bytes left. + * Do a read modify write cycle. + */ + data = 0; + + result = fiji_set_smc_sram_address(smumgr, addr, limit); + if (result) + return result; + + originalData = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0); + extraShift = 8 * (4 - byteCount); + + while (byteCount > 0) { + /* Bytes are written into the SMC addres + * space with the MSB first. + */ + data = (0x100 * data) + *src++; + byteCount--; + } + data <<= extraShift; + data |= (originalData & ~((~0UL) << extraShift)); + + result = fiji_set_smc_sram_address(smumgr, addr, limit); + if (!result) + return result; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data); + } + return 0; +} + +int fiji_program_jump_on_start(struct pp_smumgr *smumgr) +{ + static unsigned char data[] = { 0xE0, 0x00, 0x80, 0x40 }; + + fiji_copy_bytes_to_smc(smumgr, 0x0, data, 4, sizeof(data) + 1); + + return 0; +} + +/** +* Return if the SMC is currently running. +* +* @param smumgr the address of the powerplay hardware manager. +*/ +bool fiji_is_smc_ram_running(struct pp_smumgr *smumgr) +{ + return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, + CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(smumgr->device, + CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +/** +* Send a message to the SMC, and wait for its response. +* +* @param smumgr the address of the powerplay hardware manager. +* @param msg the message to send. +* @return The response that came from the SMC. +*/ +int fiji_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +{ + if (!fiji_is_smc_ram_running(smumgr)) + return -1; + + if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) { + printk(KERN_ERR "Failed to send Previous Message."); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + } + + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + return 0; +} + +/** + * Send a message to the SMC with parameter + * @param smumgr: the address of the powerplay hardware manager. + * @param msg: the message to send. + * @param parameter: the parameter to send + * @return The response that came from the SMC. + */ +int fiji_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter) +{ + if (!fiji_is_smc_ram_running(smumgr)) + return -1; + + if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) { + printk(KERN_ERR "Failed to send Previous Message."); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + } + + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + return 0; +} + + +/** +* Send a message to the SMC with parameter, do not wait for response +* +* @param smumgr: the address of the powerplay hardware manager. +* @param msg: the message to send. +* @param parameter: the parameter to send +* @return The response that came from the SMC. +*/ +int fiji_send_msg_to_smc_with_parameter_without_waiting( + struct pp_smumgr *smumgr, uint16_t msg, uint32_t parameter) +{ + if (1 != SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP)) { + printk(KERN_ERR "Failed to send Previous Message."); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + } + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + + return 0; +} + +/** +* Uploads the SMU firmware from .hex file +* +* @param smumgr the address of the powerplay SMU manager. +* @return 0 or -1. +*/ + +static int fiji_upload_smu_firmware_image(struct pp_smumgr *smumgr) +{ + const uint8_t *src; + uint32_t byte_count; + uint32_t *data; + struct cgs_firmware_info info = {0}; + + cgs_get_firmware_info(smumgr->device, + fiji_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); + + if (info.image_size & 3) { + printk(KERN_ERR "SMC ucode is not 4 bytes aligned\n"); + return -EINVAL; + } + + if (info.image_size > FIJI_SMC_SIZE) { + printk(KERN_ERR "SMC address is beyond the SMC RAM area\n"); + return -EINVAL; + } + + cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, 0x20000); + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + byte_count = info.image_size; + src = (const uint8_t *)info.kptr; + + data = (uint32_t *)src; + for (; byte_count >= 4; data++, byte_count -= 4) + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data[0]); + + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + return 0; +} + +/** +* Read a 32bit value from the SMC SRAM space. +* ALL PARAMETERS ARE IN HOST BYTE ORDER. +* @param smumgr the address of the powerplay hardware manager. +* @param smc_addr the address in the SMC RAM to access. +* @param value and output parameter for the data read from the SMC SRAM. +*/ +int fiji_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, + uint32_t *value, uint32_t limit) +{ + int result = fiji_set_smc_sram_address(smumgr, smc_addr, limit); + + if (result) + return result; + + *value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0); + return 0; +} + +/** +* Write a 32bit value to the SMC SRAM space. +* ALL PARAMETERS ARE IN HOST BYTE ORDER. +* @param smumgr the address of the powerplay hardware manager. +* @param smc_addr the address in the SMC RAM to access. +* @param value to write to the SMC SRAM. +*/ +int fiji_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, + uint32_t value, uint32_t limit) +{ + int result; + + result = fiji_set_smc_sram_address(smumgr, smc_addr, limit); + + if (result) + return result; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, value); + return 0; +} + +static uint32_t fiji_get_mask_for_firmware_type(uint32_t fw_type) +{ + uint32_t result = 0; + + switch (fw_type) { + case UCODE_ID_SDMA0: + result = UCODE_ID_SDMA0_MASK; + break; + case UCODE_ID_SDMA1: + result = UCODE_ID_SDMA1_MASK; + break; + case UCODE_ID_CP_CE: + result = UCODE_ID_CP_CE_MASK; + break; + case UCODE_ID_CP_PFP: + result = UCODE_ID_CP_PFP_MASK; + break; + case UCODE_ID_CP_ME: + result = UCODE_ID_CP_ME_MASK; + break; + case UCODE_ID_CP_MEC_JT1: + result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT1_MASK; + break; + case UCODE_ID_CP_MEC_JT2: + result = UCODE_ID_CP_MEC_MASK | UCODE_ID_CP_MEC_JT2_MASK; + break; + case UCODE_ID_RLC_G: + result = UCODE_ID_RLC_G_MASK; + break; + default: + printk(KERN_ERR "UCode type is out of range!"); + result = 0; + } + + return result; +} + +/* Populate one firmware image to the data structure */ +static int fiji_populate_single_firmware_entry(struct pp_smumgr *smumgr, + uint32_t fw_type, struct SMU_Entry *entry) +{ + int result; + struct cgs_firmware_info info = {0}; + + result = cgs_get_firmware_info( + smumgr->device, + fiji_convert_fw_type_to_cgs(fw_type), + &info); + + if (!result) { + entry->version = 0; + entry->id = (uint16_t)fw_type; + entry->image_addr_high = smu_upper_32_bits(info.mc_addr); + entry->image_addr_low = smu_lower_32_bits(info.mc_addr); + entry->meta_data_addr_high = 0; + entry->meta_data_addr_low = 0; + entry->data_size_byte = info.image_size; + entry->num_register_entries = 0; + + if (fw_type == UCODE_ID_RLC_G) + entry->flags = 1; + else + entry->flags = 0; + } + + return result; +} + +static int fiji_request_smu_load_fw(struct pp_smumgr *smumgr) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + uint32_t fw_to_load; + struct SMU_DRAMData_TOC *toc; + + if (priv->soft_regs_start) + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + priv->soft_regs_start + + offsetof(SMU73_SoftRegisters, UcodeLoadStatus), + 0x0); + + toc = (struct SMU_DRAMData_TOC *)priv->header; + toc->num_entries = 0; + toc->structure_version = 1; + + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_RLC_G, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_CE, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + PP_ASSERT_WITH_CODE( + 0 == fiji_populate_single_firmware_entry(smumgr, + UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n" , return -1 ); + + fiji_send_msg_to_smc_with_parameter(smumgr, PPSMC_MSG_DRV_DRAM_ADDR_HI, + priv->header_buffer.mc_addr_high); + fiji_send_msg_to_smc_with_parameter(smumgr,PPSMC_MSG_DRV_DRAM_ADDR_LO, + priv->header_buffer.mc_addr_low); + + fw_to_load = UCODE_ID_RLC_G_MASK + + UCODE_ID_SDMA0_MASK + + UCODE_ID_SDMA1_MASK + + UCODE_ID_CP_CE_MASK + + UCODE_ID_CP_ME_MASK + + UCODE_ID_CP_PFP_MASK + + UCODE_ID_CP_MEC_MASK + + UCODE_ID_CP_MEC_JT1_MASK + + UCODE_ID_CP_MEC_JT2_MASK; + + if (fiji_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_LoadUcodes, fw_to_load)) + printk(KERN_ERR "Fail to Request SMU Load uCode"); + + return 0; +} + + +/* Check if the FW has been loaded, SMU will not return + * if loading has not finished. + */ +static int fiji_check_fw_load_finish(struct pp_smumgr *smumgr, + uint32_t fw_type) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + uint32_t mask = fiji_get_mask_for_firmware_type(fw_type); + + /* Check SOFT_REGISTERS_TABLE_28.UcodeLoadStatus */ + if (smum_wait_on_indirect_register(smumgr, mmSMC_IND_INDEX, + priv->soft_regs_start + + offsetof(SMU73_SoftRegisters, UcodeLoadStatus), + mask, mask)) { + printk(KERN_ERR "check firmware loading failed\n"); + return -EINVAL; + } + return 0; +} + + +static int fiji_reload_firmware(struct pp_smumgr *smumgr) +{ + return smumgr->smumgr_funcs->start_smu(smumgr); +} + +static bool fiji_is_hw_virtualization_enabled(struct pp_smumgr *smumgr) +{ + uint32_t value; + + value = cgs_read_register(smumgr->device, mmBIF_IOV_FUNC_IDENTIFIER); + if (value & BIF_IOV_FUNC_IDENTIFIER__IOV_ENABLE_MASK) { + /* driver reads on SR-IOV enabled PF: 0x80000000 + * driver reads on SR-IOV enabled VF: 0x80000001 + * driver reads on SR-IOV disabled: 0x00000000 + */ + return true; + } + return false; +} + +static int fiji_request_smu_specific_fw_load(struct pp_smumgr *smumgr, uint32_t fw_type) +{ + if (fiji_is_hw_virtualization_enabled(smumgr)) { + uint32_t masks = fiji_get_mask_for_firmware_type(fw_type); + if (fiji_send_msg_to_smc_with_parameter_without_waiting(smumgr, + PPSMC_MSG_LoadUcodes, masks)) + printk(KERN_ERR "Fail to Request SMU Load uCode"); + } + /* For non-virtualization cases, + * SMU loads all FWs at once in fiji_request_smu_load_fw. + */ + return 0; +} + +static int fiji_start_smu_in_protection_mode(struct pp_smumgr *smumgr) +{ + int result = 0; + + /* Wait for smc boot up */ + /* SMUM_WAIT_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); */ + + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = fiji_upload_smu_firmware_image(smumgr); + if (result) + return result; + + /* Clear status */ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixSMU_STATUS, 0); + + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for ROM firmware to initialize interrupt hendler */ + /*SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND, + SMC_INTR_CNTL_MASK_0, 0x10040, 0xFFFFFFFF); */ + + /* Set SMU Auto Start */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMU_INPUT_DATA, AUTO_START, 1); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, RCU_UC_EVENTS, + INTERRUPTS_ENABLED, 1); + + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000); + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + /* Wait for done bit to be set */ + SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + SMU_STATUS, SMU_DONE, 0); + + /* Check pass/failed indicator */ + if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMU_STATUS, SMU_PASS)) { + PP_ASSERT_WITH_CODE(false, + "SMU Firmware start failed!", return -1); + } + + /* Wait for firmware to initialize */ + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int fiji_start_smu_in_non_protection_mode(struct pp_smumgr *smumgr) +{ + int result = 0; + + /* wait for smc boot up */ + SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + /* Assert reset */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = fiji_upload_smu_firmware_image(smumgr); + if (result) + return result; + + /* Set smc instruct start point at 0x0 */ + fiji_program_jump_on_start(smumgr); + + /* Enable clock */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +int fiji_setup_pwr_virus(struct pp_smumgr *smumgr) +{ + int i, result = -1; + uint32_t reg, data; + PWR_Command_Table *virus = PwrVirusTable; + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + priv->avfs.AvfsBtcStatus = AVFS_LOAD_VIRUS; + for (i = 0; (i < PWR_VIRUS_TABLE_SIZE); i++) { + switch (virus->command) { + case PwrCmdWrite: + reg = virus->reg; + data = virus->data; + cgs_write_register(smumgr->device, reg, data); + break; + case PwrCmdEnd: + priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_LOADED; + result = 0; + break; + default: + printk(KERN_ERR "Table Exit with Invalid Command!"); + priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL; + result = -1; + break; + } + virus++; + } + return result; +} + +static int fiji_start_avfs_btc(struct pp_smumgr *smumgr) +{ + int result = 0; + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + priv->avfs.AvfsBtcStatus = AVFS_BTC_STARTED; + if (priv->avfs.AvfsBtcParam) { + if (!fiji_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_PerformBtc, priv->avfs.AvfsBtcParam)) { + if (!fiji_send_msg_to_smc(smumgr, PPSMC_MSG_EnableAvfs)) { + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_UNSAVED; + result = 0; + } else { + printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] Attempt" + " to Enable AVFS Failed!"); + fiji_send_msg_to_smc(smumgr, PPSMC_MSG_DisableAvfs); + result = -1; + } + } else { + printk(KERN_ERR "[AVFS][fiji_start_avfs_btc] " + "PerformBTC SMU msg failed"); + result = -1; + } + } + /* Soft-Reset to reset the engine before loading uCode */ + /* halt */ + cgs_write_register(smumgr->device, mmCP_MEC_CNTL, 0x50000000); + /* reset everything */ + cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0xffffffff); + /* clear reset */ + cgs_write_register(smumgr->device, mmGRBM_SOFT_RESET, 0); + + return result; +} + +int fiji_setup_pm_fuse_for_avfs(struct pp_smumgr *smumgr) +{ + int result = 0; + uint32_t table_start; + uint32_t charz_freq_addr, inversion_voltage_addr, charz_freq; + uint16_t inversion_voltage; + + charz_freq = 0x30750000; /* In 10KHz units 0x00007530 Actual value */ + inversion_voltage = 0x1A04; /* mV Q14.2 0x41A Actual value */ + + PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + offsetof(SMU73_Firmware_Header, + PmFuseTable), &table_start, 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not communicate " + "starting address of PmFuse structure", + return -1;); + + charz_freq_addr = table_start + + offsetof(struct SMU73_Discrete_PmFuses, PsmCharzFreq); + inversion_voltage_addr = table_start + + offsetof(struct SMU73_Discrete_PmFuses, InversionVoltage); + + result = fiji_copy_bytes_to_smc(smumgr, charz_freq_addr, + (uint8_t *)(&charz_freq), sizeof(charz_freq), 0x40000); + PP_ASSERT_WITH_CODE(0 == result, + "[AVFS][fiji_setup_pm_fuse_for_avfs] charz_freq could not " + "be populated.", return -1;); + + result = fiji_copy_bytes_to_smc(smumgr, inversion_voltage_addr, + (uint8_t *)(&inversion_voltage), sizeof(inversion_voltage), 0x40000); + PP_ASSERT_WITH_CODE(0 == result, "[AVFS][fiji_setup_pm_fuse_for_avfs] " + "charz_freq could not be populated.", return -1;); + + return result; +} + +int fiji_setup_graphics_level_structure(struct pp_smumgr *smumgr) +{ + int32_t vr_config; + uint32_t table_start; + uint32_t level_addr, vr_config_addr; + uint32_t level_size = sizeof(avfs_graphics_level); + + PP_ASSERT_WITH_CODE(0 == fiji_read_smc_sram_dword(smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, DpmTable), + &table_start, 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] SMU could not " + "communicate starting address of DPM table", + return -1;); + + /* Default value for vr_config = + * VR_MERGED_WITH_VDDC + VR_STATIC_VOLTAGE(VDDCI) */ + vr_config = 0x01000500; /* Real value:0x50001 */ + + vr_config_addr = table_start + + offsetof(SMU73_Discrete_DpmTable, VRConfig); + + PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, vr_config_addr, + (uint8_t *)&vr_config, sizeof(int32_t), 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] Problems copying " + "vr_config value over to SMC", + return -1;); + + level_addr = table_start + offsetof(SMU73_Discrete_DpmTable, GraphicsLevel); + + PP_ASSERT_WITH_CODE(0 == fiji_copy_bytes_to_smc(smumgr, level_addr, + (uint8_t *)(&avfs_graphics_level), level_size, 0x40000), + "[AVFS][Fiji_SetupGfxLvlStruct] Copying of DPM table failed!", + return -1;); + + return 0; +} + +/* Work in Progress */ +int fiji_restore_vft_table(struct pp_smumgr *smumgr) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) { + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; + return 0; + } else + return -EINVAL; +} + +/* Work in Progress */ +int fiji_save_vft_table(struct pp_smumgr *smumgr) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + if (AVFS_BTC_COMPLETED_SAVED == priv->avfs.AvfsBtcStatus) { + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; + return 0; + } else + return -EINVAL; +} + +int fiji_avfs_event_mgr(struct pp_smumgr *smumgr, bool smu_started) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + switch (priv->avfs.AvfsBtcStatus) { + case AVFS_BTC_COMPLETED_SAVED: /*S3 State - Pre SMU Start */ + priv->avfs.AvfsBtcStatus = AVFS_BTC_RESTOREVFT_FAILED; + PP_ASSERT_WITH_CODE(0 == fiji_restore_vft_table(smumgr), + "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics " + "Level table over to SMU", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_RESTORED; + break; + case AVFS_BTC_COMPLETED_RESTORED: /*S3 State - Post SMU Start*/ + priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR; + PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr, + PPSMC_MSG_VftTableIsValid), + "[AVFS][fiji_avfs_event_mgr] SMU did not respond " + "correctly to VftTableIsValid Msg", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_SMUMSG_ERROR; + PP_ASSERT_WITH_CODE(0 == fiji_send_msg_to_smc(smumgr, + PPSMC_MSG_EnableAvfs), + "[AVFS][fiji_avfs_event_mgr] SMU did not respond " + "correctly to EnableAvfs Message Msg", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED; + break; + case AVFS_BTC_BOOT: /*Cold Boot State - Post SMU Start*/ + if (!smu_started) + break; + priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED; + PP_ASSERT_WITH_CODE(0 == fiji_setup_pm_fuse_for_avfs(smumgr), + "[AVFS][fiji_avfs_event_mgr] Failure at " + "fiji_setup_pm_fuse_for_avfs", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_DPMTABLESETUP_FAILED; + PP_ASSERT_WITH_CODE(0 == fiji_setup_graphics_level_structure(smumgr), + "[AVFS][fiji_avfs_event_mgr] Could not Copy Graphics Level" + " table over to SMU", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_VIRUS_FAIL; + PP_ASSERT_WITH_CODE(0 == fiji_setup_pwr_virus(smumgr), + "[AVFS][fiji_avfs_event_mgr] Could not setup " + "Pwr Virus for AVFS ", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_FAILED; + PP_ASSERT_WITH_CODE(0 == fiji_start_avfs_btc(smumgr), + "[AVFS][fiji_avfs_event_mgr] Failure at " + "fiji_start_avfs_btc. AVFS Disabled", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_SAVEVFT_FAILED; + PP_ASSERT_WITH_CODE(0 == fiji_save_vft_table(smumgr), + "[AVFS][fiji_avfs_event_mgr] Could not save VFT Table", + return -1;); + priv->avfs.AvfsBtcStatus = AVFS_BTC_COMPLETED_SAVED; + break; + case AVFS_BTC_DISABLED: /* Do nothing */ + break; + case AVFS_BTC_NOTSUPPORTED: /* Do nothing */ + break; + default: + printk(KERN_ERR "[AVFS] Something is broken. See log!"); + break; + } + return 0; +} + +static int fiji_start_smu(struct pp_smumgr *smumgr) +{ + int result = 0; + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + + /* Only start SMC if SMC RAM is not running */ + if (!fiji_is_smc_ram_running(smumgr)) { + fiji_avfs_event_mgr(smumgr, false); + + /* Check if SMU is running in protected mode */ + if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, + CGS_IND_REG__SMC, + SMU_FIRMWARE, SMU_MODE)) { + result = fiji_start_smu_in_non_protection_mode(smumgr); + if (result) + return result; + } else { + result = fiji_start_smu_in_protection_mode(smumgr); + if (result) + return result; + } + fiji_avfs_event_mgr(smumgr, true); + } + + /* To initialize all clock gating before RLC loaded and running.*/ + cgs_set_clockgating_state(smumgr->device, + AMD_IP_BLOCK_TYPE_GFX, AMD_CG_STATE_GATE); + cgs_set_clockgating_state(smumgr->device, + AMD_IP_BLOCK_TYPE_GMC, AMD_CG_STATE_GATE); + cgs_set_clockgating_state(smumgr->device, + AMD_IP_BLOCK_TYPE_SDMA, AMD_CG_STATE_GATE); + cgs_set_clockgating_state(smumgr->device, + AMD_IP_BLOCK_TYPE_COMMON, AMD_CG_STATE_GATE); + + /* Setup SoftRegsStart here for register lookup in case + * DummyBackEnd is used and ProcessFirmwareHeader is not executed + */ + fiji_read_smc_sram_dword(smumgr, + SMU7_FIRMWARE_HEADER_LOCATION + + offsetof(SMU73_Firmware_Header, SoftRegisters), + &(priv->soft_regs_start), 0x40000); + + result = fiji_request_smu_load_fw(smumgr); + + return result; +} + +static bool fiji_is_hw_avfs_present(struct pp_smumgr *smumgr) +{ + + uint32_t efuse = 0; + uint32_t mask = (1 << ((AVFS_EN_MSB - AVFS_EN_LSB) + 1)) - 1; + + if (!atomctrl_read_efuse(smumgr->device, AVFS_EN_LSB, AVFS_EN_MSB, + mask, &efuse)) { + if (efuse) + return true; + } + return false; +} + +/** +* Write a 32bit value to the SMC SRAM space. +* ALL PARAMETERS ARE IN HOST BYTE ORDER. +* @param smumgr the address of the powerplay hardware manager. +* @param smc_addr the address in the SMC RAM to access. +* @param value to write to the SMC SRAM. +*/ +static int fiji_smu_init(struct pp_smumgr *smumgr) +{ + struct fiji_smumgr *priv = (struct fiji_smumgr *)(smumgr->backend); + uint64_t mc_addr; + + priv->header_buffer.data_size = + ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; + smu_allocate_memory(smumgr->device, + priv->header_buffer.data_size, + CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, + PAGE_SIZE, + &mc_addr, + &priv->header_buffer.kaddr, + &priv->header_buffer.handle); + + priv->header = priv->header_buffer.kaddr; + priv->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); + priv->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); + + PP_ASSERT_WITH_CODE((NULL != priv->header), + "Out of memory.", + kfree(smumgr->backend); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)priv->header_buffer.handle); + return -1); + + priv->avfs.AvfsBtcStatus = AVFS_BTC_BOOT; + if (fiji_is_hw_avfs_present(smumgr)) + /* AVFS Parameter + * 0 - BTC DC disabled, BTC AC disabled + * 1 - BTC DC enabled, BTC AC disabled + * 2 - BTC DC disabled, BTC AC enabled + * 3 - BTC DC enabled, BTC AC enabled + * Default is 0 - BTC DC disabled, BTC AC disabled + */ + priv->avfs.AvfsBtcParam = 0; + else + priv->avfs.AvfsBtcStatus = AVFS_BTC_NOTSUPPORTED; + + priv->acpi_optimization = 1; + + return 0; +} + +static int fiji_smu_fini(struct pp_smumgr *smumgr) +{ + if (smumgr->backend) { + kfree(smumgr->backend); + smumgr->backend = NULL; + } + return 0; +} + +static const struct pp_smumgr_func fiji_smu_funcs = { + .smu_init = &fiji_smu_init, + .smu_fini = &fiji_smu_fini, + .start_smu = &fiji_start_smu, + .check_fw_load_finish = &fiji_check_fw_load_finish, + .request_smu_load_fw = &fiji_reload_firmware, + .request_smu_load_specific_fw = &fiji_request_smu_specific_fw_load, + .send_msg_to_smc = &fiji_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &fiji_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, +}; + +int fiji_smum_init(struct pp_smumgr *smumgr) +{ + struct fiji_smumgr *fiji_smu = NULL; + + fiji_smu = kzalloc(sizeof(struct fiji_smumgr), GFP_KERNEL); + + if (fiji_smu == NULL) + return -1; + + smumgr->backend = fiji_smu; + smumgr->smumgr_funcs = &fiji_smu_funcs; + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h new file mode 100644 index 000000000000..8cd22d9c9140 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/fiji_smumgr.h @@ -0,0 +1,77 @@ +/* + * Copyright 2015 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. + * + */ +#ifndef _FIJI_SMUMANAGER_H_ +#define _FIJI_SMUMANAGER_H_ + +enum AVFS_BTC_STATUS { + AVFS_BTC_BOOT = 0, + AVFS_BTC_BOOT_STARTEDSMU, + AVFS_LOAD_VIRUS, + AVFS_BTC_VIRUS_LOADED, + AVFS_BTC_VIRUS_FAIL, + AVFS_BTC_STARTED, + AVFS_BTC_FAILED, + AVFS_BTC_RESTOREVFT_FAILED, + AVFS_BTC_SAVEVFT_FAILED, + AVFS_BTC_DPMTABLESETUP_FAILED, + AVFS_BTC_COMPLETED_UNSAVED, + AVFS_BTC_COMPLETED_SAVED, + AVFS_BTC_COMPLETED_RESTORED, + AVFS_BTC_DISABLED, + AVFS_BTC_NOTSUPPORTED, + AVFS_BTC_SMUMSG_ERROR +}; + +struct fiji_smu_avfs { + enum AVFS_BTC_STATUS AvfsBtcStatus; + uint32_t AvfsBtcParam; +}; + +struct fiji_buffer_entry { + uint32_t data_size; + uint32_t mc_addr_low; + uint32_t mc_addr_high; + void *kaddr; + unsigned long handle; +}; + +struct fiji_smumgr { + uint8_t *header; + uint8_t *mec_image; + uint32_t soft_regs_start; + struct fiji_smu_avfs avfs; + uint32_t acpi_optimization; + + struct fiji_buffer_entry header_buffer; +}; + +int fiji_smum_init(struct pp_smumgr *smumgr); +int fiji_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress, + uint32_t *value, uint32_t limit); +int fiji_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smc_addr, + uint32_t value, uint32_t limit); +int fiji_copy_bytes_to_smc(struct pp_smumgr *smumgr, uint32_t smcStartAddress, + const uint8_t *src, uint32_t byteCount, uint32_t limit); + +#endif + diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c new file mode 100644 index 000000000000..063ae71c9830 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/smumgr.c @@ -0,0 +1,263 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include "pp_instance.h" +#include "smumgr.h" +#include "cgs_common.h" +#include "linux/delay.h" +#include "cz_smumgr.h" +#include "tonga_smumgr.h" +#include "fiji_smumgr.h" + +int smum_init(struct amd_pp_init *pp_init, struct pp_instance *handle) +{ + struct pp_smumgr *smumgr; + + if ((handle == NULL) || (pp_init == NULL)) + return -EINVAL; + + smumgr = kzalloc(sizeof(struct pp_smumgr), GFP_KERNEL); + if (smumgr == NULL) + return -ENOMEM; + + smumgr->device = pp_init->device; + smumgr->chip_family = pp_init->chip_family; + smumgr->chip_id = pp_init->chip_id; + smumgr->hw_revision = pp_init->rev_id; + smumgr->usec_timeout = AMD_MAX_USEC_TIMEOUT; + smumgr->reload_fw = 1; + handle->smu_mgr = smumgr; + + switch (smumgr->chip_family) { + case AMD_FAMILY_CZ: + cz_smum_init(smumgr); + break; + case AMD_FAMILY_VI: + switch (smumgr->chip_id) { + case CHIP_TONGA: + tonga_smum_init(smumgr); + break; + case CHIP_FIJI: + fiji_smum_init(smumgr); + break; + default: + return -EINVAL; + } + break; + default: + kfree(smumgr); + return -EINVAL; + } + + return 0; +} + +int smum_fini(struct pp_smumgr *smumgr) +{ + kfree(smumgr); + return 0; +} + +int smum_get_argument(struct pp_smumgr *smumgr) +{ + if (NULL != smumgr->smumgr_funcs->get_argument) + return smumgr->smumgr_funcs->get_argument(smumgr); + + return 0; +} + +int smum_download_powerplay_table(struct pp_smumgr *smumgr, + void **table) +{ + if (NULL != smumgr->smumgr_funcs->download_pptable_settings) + return smumgr->smumgr_funcs->download_pptable_settings(smumgr, + table); + + return 0; +} + +int smum_upload_powerplay_table(struct pp_smumgr *smumgr) +{ + if (NULL != smumgr->smumgr_funcs->upload_pptable_settings) + return smumgr->smumgr_funcs->upload_pptable_settings(smumgr); + + return 0; +} + +int smum_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +{ + if (smumgr == NULL || smumgr->smumgr_funcs->send_msg_to_smc == NULL) + return -EINVAL; + + return smumgr->smumgr_funcs->send_msg_to_smc(smumgr, msg); +} + +int smum_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter) +{ + if (smumgr == NULL || + smumgr->smumgr_funcs->send_msg_to_smc_with_parameter == NULL) + return -EINVAL; + return smumgr->smumgr_funcs->send_msg_to_smc_with_parameter( + smumgr, msg, parameter); +} + +/* + * Returns once the part of the register indicated by the mask has + * reached the given value. + */ +int smum_wait_on_register(struct pp_smumgr *smumgr, + uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + for (i = 0; i < smumgr->usec_timeout; i++) { + cur_value = cgs_read_register(smumgr->device, index); + if ((cur_value & mask) == (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic*/ + if (i == smumgr->usec_timeout) + return -1; + + return 0; +} + +int smum_wait_for_register_unequal(struct pp_smumgr *smumgr, + uint32_t index, + uint32_t value, uint32_t mask) +{ + uint32_t i; + uint32_t cur_value; + + if (smumgr == NULL) + return -EINVAL; + + for (i = 0; i < smumgr->usec_timeout; i++) { + cur_value = cgs_read_register(smumgr->device, + index); + if ((cur_value & mask) != (value & mask)) + break; + udelay(1); + } + + /* timeout means wrong logic */ + if (i == smumgr->usec_timeout) + return -1; + + return 0; +} + + +/* + * Returns once the part of the register indicated by the mask + * has reached the given value.The indirect space is described by + * giving the memory-mapped index of the indirect index register. + */ +int smum_wait_on_indirect_register(struct pp_smumgr *smumgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + cgs_write_register(smumgr->device, indirect_port, index); + return smum_wait_on_register(smumgr, indirect_port + 1, + mask, value); +} + +void smum_wait_for_indirect_register_unequal( + struct pp_smumgr *smumgr, + uint32_t indirect_port, + uint32_t index, + uint32_t value, + uint32_t mask) +{ + if (smumgr == NULL || smumgr->device == NULL) + return; + cgs_write_register(smumgr->device, indirect_port, index); + smum_wait_for_register_unequal(smumgr, indirect_port + 1, + value, mask); +} + +int smu_allocate_memory(void *device, uint32_t size, + enum cgs_gpu_mem_type type, + uint32_t byte_align, uint64_t *mc_addr, + void **kptr, void *handle) +{ + int ret = 0; + cgs_handle_t cgs_handle; + + if (device == NULL || handle == NULL || + mc_addr == NULL || kptr == NULL) + return -EINVAL; + + ret = cgs_alloc_gpu_mem(device, type, size, byte_align, + 0, 0, (cgs_handle_t *)handle); + if (ret) + return -ENOMEM; + + cgs_handle = *(cgs_handle_t *)handle; + + ret = cgs_gmap_gpu_mem(device, cgs_handle, mc_addr); + if (ret) + goto error_gmap; + + ret = cgs_kmap_gpu_mem(device, cgs_handle, kptr); + if (ret) + goto error_kmap; + + return 0; + +error_kmap: + cgs_gunmap_gpu_mem(device, cgs_handle); + +error_gmap: + cgs_free_gpu_mem(device, cgs_handle); + return ret; +} + +int smu_free_memory(void *device, void *handle) +{ + cgs_handle_t cgs_handle = (cgs_handle_t)handle; + + if (device == NULL || handle == NULL) + return -EINVAL; + + cgs_kunmap_gpu_mem(device, cgs_handle); + cgs_gunmap_gpu_mem(device, cgs_handle); + cgs_free_gpu_mem(device, cgs_handle); + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c new file mode 100644 index 000000000000..62ff76010aa6 --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.c @@ -0,0 +1,819 @@ +/* + * Copyright 2015 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. + * + */ +#include <linux/types.h> +#include <linux/kernel.h> +#include <linux/slab.h> +#include <linux/gfp.h> + +#include "smumgr.h" +#include "tonga_smumgr.h" +#include "pp_debug.h" +#include "smu_ucode_xfer_vi.h" +#include "tonga_ppsmc.h" +#include "smu/smu_7_1_2_d.h" +#include "smu/smu_7_1_2_sh_mask.h" +#include "cgs_common.h" + +#define TONGA_SMC_SIZE 0x20000 +#define BUFFER_SIZE 80000 +#define MAX_STRING_SIZE 15 +#define BUFFER_SIZETWO 131072 /*128 *1024*/ + +/** +* Set the address for reading/writing the SMC SRAM space. +* @param smumgr the address of the powerplay hardware manager. +* @param smcAddress the address in the SMC RAM to access. +*/ +static int tonga_set_smc_sram_address(struct pp_smumgr *smumgr, + uint32_t smcAddress, uint32_t limit) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + PP_ASSERT_WITH_CODE((0 == (3 & smcAddress)), + "SMC address must be 4 byte aligned.", + return -1;); + + PP_ASSERT_WITH_CODE((limit > (smcAddress + 3)), + "SMC address is beyond the SMC RAM area.", + return -1;); + + cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, smcAddress); + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_11, 0); + + return 0; +} + +/** +* Copy bytes from an array into the SMC RAM space. +* +* @param smumgr the address of the powerplay SMU manager. +* @param smcStartAddress the start address in the SMC RAM to copy bytes to. +* @param src the byte array to copy the bytes from. +* @param byteCount the number of bytes to copy. +*/ +int tonga_copy_bytes_to_smc(struct pp_smumgr *smumgr, + uint32_t smcStartAddress, const uint8_t *src, + uint32_t byteCount, uint32_t limit) +{ + uint32_t addr; + uint32_t data, orig_data; + int result = 0; + uint32_t extra_shift; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + PP_ASSERT_WITH_CODE((0 == (3 & smcStartAddress)), + "SMC address must be 4 byte aligned.", + return 0;); + + PP_ASSERT_WITH_CODE((limit > (smcStartAddress + byteCount)), + "SMC address is beyond the SMC RAM area.", + return 0;); + + addr = smcStartAddress; + + while (byteCount >= 4) { + /* + * Bytes are written into the + * SMC address space with the MSB first + */ + data = (src[0] << 24) + (src[1] << 16) + (src[2] << 8) + src[3]; + + result = tonga_set_smc_sram_address(smumgr, addr, limit); + + if (result) + goto out; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data); + + src += 4; + byteCount -= 4; + addr += 4; + } + + if (0 != byteCount) { + /* Now write odd bytes left, do a read modify write cycle */ + data = 0; + + result = tonga_set_smc_sram_address(smumgr, addr, limit); + if (result) + goto out; + + orig_data = cgs_read_register(smumgr->device, + mmSMC_IND_DATA_0); + extra_shift = 8 * (4 - byteCount); + + while (byteCount > 0) { + data = (data << 8) + *src++; + byteCount--; + } + + data <<= extra_shift; + data |= (orig_data & ~((~0UL) << extra_shift)); + + result = tonga_set_smc_sram_address(smumgr, addr, limit); + if (result) + goto out; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data); + } + +out: + return result; +} + + +int tonga_program_jump_on_start(struct pp_smumgr *smumgr) +{ + static unsigned char pData[] = { 0xE0, 0x00, 0x80, 0x40 }; + + tonga_copy_bytes_to_smc(smumgr, 0x0, pData, 4, sizeof(pData)+1); + + return 0; +} + +/** +* Return if the SMC is currently running. +* +* @param smumgr the address of the powerplay hardware manager. +*/ +static int tonga_is_smc_ram_running(struct pp_smumgr *smumgr) +{ + return ((0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable)) + && (0x20100 <= cgs_read_ind_register(smumgr->device, + CGS_IND_REG__SMC, ixSMC_PC_C))); +} + +static int tonga_send_msg_to_smc_offset(struct pp_smumgr *smumgr) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, 0x20000); + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, PPSMC_MSG_Test); + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + return 0; +} + +/** +* Send a message to the SMC, and wait for its response. +* +* @param smumgr the address of the powerplay hardware manager. +* @param msg the message to send. +* @return The response that came from the SMC. +*/ +static int tonga_send_msg_to_smc(struct pp_smumgr *smumgr, uint16_t msg) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + if (!tonga_is_smc_ram_running(smumgr)) + return -1; + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PP_ASSERT_WITH_CODE( + 1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP), + "Failed to send Previous Message.", + return 1); + + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PP_ASSERT_WITH_CODE( + 1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP), + "Failed to send Message.", + return 1); + + return 0; +} + +/* +* Send a message to the SMC, and do not wait for its response. +* +* @param smumgr the address of the powerplay hardware manager. +* @param msg the message to send. +* @return The response that came from the SMC. +*/ +static int tonga_send_msg_to_smc_without_waiting + (struct pp_smumgr *smumgr, uint16_t msg) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + PP_ASSERT_WITH_CODE( + 1 == SMUM_READ_FIELD(smumgr->device, SMC_RESP_0, SMC_RESP), + "Failed to send Previous Message.", + return 0); + cgs_write_register(smumgr->device, mmSMC_MESSAGE_0, msg); + + return 0; +} + +/* +* Send a message to the SMC with parameter +* +* @param smumgr: the address of the powerplay hardware manager. +* @param msg: the message to send. +* @param parameter: the parameter to send +* @return The response that came from the SMC. +*/ +static int tonga_send_msg_to_smc_with_parameter(struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + if (!tonga_is_smc_ram_running(smumgr)) + return PPSMC_Result_Failed; + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + + return tonga_send_msg_to_smc(smumgr, msg); +} + +/* +* Send a message to the SMC with parameter, do not wait for response +* +* @param smumgr: the address of the powerplay hardware manager. +* @param msg: the message to send. +* @param parameter: the parameter to send +* @return The response that came from the SMC. +*/ +static int tonga_send_msg_to_smc_with_parameter_without_waiting( + struct pp_smumgr *smumgr, + uint16_t msg, uint32_t parameter) +{ + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + SMUM_WAIT_FIELD_UNEQUAL(smumgr, SMC_RESP_0, SMC_RESP, 0); + + cgs_write_register(smumgr->device, mmSMC_MSG_ARG_0, parameter); + + return tonga_send_msg_to_smc_without_waiting(smumgr, msg); +} + +/* + * Read a 32bit value from the SMC SRAM space. + * ALL PARAMETERS ARE IN HOST BYTE ORDER. + * @param smumgr the address of the powerplay hardware manager. + * @param smcAddress the address in the SMC RAM to access. + * @param value and output parameter for the data read from the SMC SRAM. + */ +int tonga_read_smc_sram_dword(struct pp_smumgr *smumgr, + uint32_t smcAddress, uint32_t *value, + uint32_t limit) +{ + int result; + + result = tonga_set_smc_sram_address(smumgr, smcAddress, limit); + + if (0 != result) + return result; + + *value = cgs_read_register(smumgr->device, mmSMC_IND_DATA_0); + + return 0; +} + +/* + * Write a 32bit value to the SMC SRAM space. + * ALL PARAMETERS ARE IN HOST BYTE ORDER. + * @param smumgr the address of the powerplay hardware manager. + * @param smcAddress the address in the SMC RAM to access. + * @param value to write to the SMC SRAM. + */ +int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr, + uint32_t smcAddress, uint32_t value, + uint32_t limit) +{ + int result; + + result = tonga_set_smc_sram_address(smumgr, smcAddress, limit); + + if (0 != result) + return result; + + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, value); + + return 0; +} + +static int tonga_smu_fini(struct pp_smumgr *smumgr) +{ + if (smumgr->backend != NULL) { + kfree(smumgr->backend); + smumgr->backend = NULL; + } + return 0; +} + +static enum cgs_ucode_id tonga_convert_fw_type_to_cgs(uint32_t fw_type) +{ + enum cgs_ucode_id result = CGS_UCODE_ID_MAXIMUM; + + switch (fw_type) { + case UCODE_ID_SMU: + result = CGS_UCODE_ID_SMU; + break; + case UCODE_ID_SDMA0: + result = CGS_UCODE_ID_SDMA0; + break; + case UCODE_ID_SDMA1: + result = CGS_UCODE_ID_SDMA1; + break; + case UCODE_ID_CP_CE: + result = CGS_UCODE_ID_CP_CE; + break; + case UCODE_ID_CP_PFP: + result = CGS_UCODE_ID_CP_PFP; + break; + case UCODE_ID_CP_ME: + result = CGS_UCODE_ID_CP_ME; + break; + case UCODE_ID_CP_MEC: + result = CGS_UCODE_ID_CP_MEC; + break; + case UCODE_ID_CP_MEC_JT1: + result = CGS_UCODE_ID_CP_MEC_JT1; + break; + case UCODE_ID_CP_MEC_JT2: + result = CGS_UCODE_ID_CP_MEC_JT2; + break; + case UCODE_ID_RLC_G: + result = CGS_UCODE_ID_RLC_G; + break; + default: + break; + } + + return result; +} + +/** + * Convert the PPIRI firmware type to SMU type mask. + * For MEC, we need to check all MEC related type +*/ +static uint16_t tonga_get_mask_for_firmware_type(uint16_t firmwareType) +{ + uint16_t result = 0; + + switch (firmwareType) { + case UCODE_ID_SDMA0: + result = UCODE_ID_SDMA0_MASK; + break; + case UCODE_ID_SDMA1: + result = UCODE_ID_SDMA1_MASK; + break; + case UCODE_ID_CP_CE: + result = UCODE_ID_CP_CE_MASK; + break; + case UCODE_ID_CP_PFP: + result = UCODE_ID_CP_PFP_MASK; + break; + case UCODE_ID_CP_ME: + result = UCODE_ID_CP_ME_MASK; + break; + case UCODE_ID_CP_MEC: + case UCODE_ID_CP_MEC_JT1: + case UCODE_ID_CP_MEC_JT2: + result = UCODE_ID_CP_MEC_MASK; + break; + case UCODE_ID_RLC_G: + result = UCODE_ID_RLC_G_MASK; + break; + default: + break; + } + + return result; +} + +/** + * Check if the FW has been loaded, + * SMU will not return if loading has not finished. +*/ +static int tonga_check_fw_load_finish(struct pp_smumgr *smumgr, uint32_t fwType) +{ + uint16_t fwMask = tonga_get_mask_for_firmware_type(fwType); + + if (0 != SMUM_WAIT_VFPF_INDIRECT_REGISTER(smumgr, SMC_IND, + SOFT_REGISTERS_TABLE_28, fwMask, fwMask)) { + printk(KERN_ERR "[ powerplay ] check firmware loading failed\n"); + return -EINVAL; + } + + return 0; +} + +/* Populate one firmware image to the data structure */ +static int tonga_populate_single_firmware_entry(struct pp_smumgr *smumgr, + uint16_t firmware_type, + struct SMU_Entry *pentry) +{ + int result; + struct cgs_firmware_info info = {0}; + + result = cgs_get_firmware_info( + smumgr->device, + tonga_convert_fw_type_to_cgs(firmware_type), + &info); + + if (result == 0) { + pentry->version = 0; + pentry->id = (uint16_t)firmware_type; + pentry->image_addr_high = smu_upper_32_bits(info.mc_addr); + pentry->image_addr_low = smu_lower_32_bits(info.mc_addr); + pentry->meta_data_addr_high = 0; + pentry->meta_data_addr_low = 0; + pentry->data_size_byte = info.image_size; + pentry->num_register_entries = 0; + + if (firmware_type == UCODE_ID_RLC_G) + pentry->flags = 1; + else + pentry->flags = 0; + } else { + return result; + } + + return result; +} + +static int tonga_request_smu_reload_fw(struct pp_smumgr *smumgr) +{ + struct tonga_smumgr *tonga_smu = + (struct tonga_smumgr *)(smumgr->backend); + uint16_t fw_to_load; + int result = 0; + struct SMU_DRAMData_TOC *toc; + /** + * First time this gets called during SmuMgr init, + * we haven't processed SMU header file yet, + * so Soft Register Start offset is unknown. + * However, for this case, UcodeLoadStatus is already 0, + * so we can skip this if the Soft Registers Start offset is 0. + */ + cgs_write_ind_register(smumgr->device, + CGS_IND_REG__SMC, ixSOFT_REGISTERS_TABLE_28, 0); + + tonga_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SMU_DRAM_ADDR_HI, + tonga_smu->smu_buffer.mc_addr_high); + tonga_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_SMU_DRAM_ADDR_LO, + tonga_smu->smu_buffer.mc_addr_low); + + toc = (struct SMU_DRAMData_TOC *)tonga_smu->pHeader; + toc->num_entries = 0; + toc->structure_version = 1; + + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry(smumgr, + UCODE_ID_RLC_G, + &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", + return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry(smumgr, + UCODE_ID_CP_CE, + &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", + return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_CP_PFP, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_CP_ME, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_CP_MEC, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_CP_MEC_JT1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_CP_MEC_JT2, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_SDMA0, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + PP_ASSERT_WITH_CODE( + 0 == tonga_populate_single_firmware_entry + (smumgr, UCODE_ID_SDMA1, &toc->entry[toc->num_entries++]), + "Failed to Get Firmware Entry.\n", return -1); + + tonga_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_DRV_DRAM_ADDR_HI, + tonga_smu->header_buffer.mc_addr_high); + tonga_send_msg_to_smc_with_parameter(smumgr, + PPSMC_MSG_DRV_DRAM_ADDR_LO, + tonga_smu->header_buffer.mc_addr_low); + + fw_to_load = UCODE_ID_RLC_G_MASK + + UCODE_ID_SDMA0_MASK + + UCODE_ID_SDMA1_MASK + + UCODE_ID_CP_CE_MASK + + UCODE_ID_CP_ME_MASK + + UCODE_ID_CP_PFP_MASK + + UCODE_ID_CP_MEC_MASK; + + PP_ASSERT_WITH_CODE( + 0 == tonga_send_msg_to_smc_with_parameter_without_waiting( + smumgr, PPSMC_MSG_LoadUcodes, fw_to_load), + "Fail to Request SMU Load uCode", return 0); + + return result; +} + +static int tonga_request_smu_load_specific_fw(struct pp_smumgr *smumgr, + uint32_t firmwareType) +{ + return 0; +} + +/** + * Upload the SMC firmware to the SMC microcontroller. + * + * @param smumgr the address of the powerplay hardware manager. + * @param pFirmware the data structure containing the various sections of the firmware. + */ +static int tonga_smu_upload_firmware_image(struct pp_smumgr *smumgr) +{ + const uint8_t *src; + uint32_t byte_count; + uint32_t *data; + struct cgs_firmware_info info = {0}; + + if (smumgr == NULL || smumgr->device == NULL) + return -EINVAL; + + cgs_get_firmware_info(smumgr->device, + tonga_convert_fw_type_to_cgs(UCODE_ID_SMU), &info); + + if (info.image_size & 3) { + printk(KERN_ERR "[ powerplay ] SMC ucode is not 4 bytes aligned\n"); + return -EINVAL; + } + + if (info.image_size > TONGA_SMC_SIZE) { + printk(KERN_ERR "[ powerplay ] SMC address is beyond the SMC RAM area\n"); + return -EINVAL; + } + + cgs_write_register(smumgr->device, mmSMC_IND_INDEX_0, 0x20000); + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 1); + + byte_count = info.image_size; + src = (const uint8_t *)info.kptr; + + data = (uint32_t *)src; + for (; byte_count >= 4; data++, byte_count -= 4) + cgs_write_register(smumgr->device, mmSMC_IND_DATA_0, data[0]); + + SMUM_WRITE_FIELD(smumgr->device, SMC_IND_ACCESS_CNTL, AUTO_INCREMENT_IND_0, 0); + + return 0; +} + +static int tonga_start_in_protection_mode(struct pp_smumgr *smumgr) +{ + int result; + + /* Assert reset */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = tonga_smu_upload_firmware_image(smumgr); + if (result) + return result; + + /* Clear status */ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixSMU_STATUS, 0); + + /* Enable clock */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /* De-assert reset */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Set SMU Auto Start */ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMU_INPUT_DATA, AUTO_START, 1); + + /* Clear firmware interrupt enable flag */ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + RCU_UC_EVENTS, INTERRUPTS_ENABLED, 1); + + /** + * Call Test SMU message with 0x20000 offset to trigger SMU start + */ + tonga_send_msg_to_smc_offset(smumgr); + + /* Wait for done bit to be set */ + SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + SMU_STATUS, SMU_DONE, 0); + + /* Check pass/failed indicator */ + if (1 != SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, + CGS_IND_REG__SMC, SMU_STATUS, SMU_PASS)) { + printk(KERN_ERR "[ powerplay ] SMU Firmware start failed\n"); + return -EINVAL; + } + + /* Wait for firmware to initialize */ + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return 0; +} + + +static int tonga_start_in_non_protection_mode(struct pp_smumgr *smumgr) +{ + int result = 0; + + /* wait for smc boot up */ + SMUM_WAIT_VFPF_INDIRECT_FIELD_UNEQUAL(smumgr, SMC_IND, + RCU_UC_EVENTS, boot_seq_done, 0); + + /*Clear firmware interrupt enable flag*/ + cgs_write_ind_register(smumgr->device, CGS_IND_REG__SMC, + ixFIRMWARE_FLAGS, 0); + + + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 1); + + result = tonga_smu_upload_firmware_image(smumgr); + + if (result != 0) + return result; + + /* Set smc instruct start point at 0x0 */ + tonga_program_jump_on_start(smumgr); + + + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_CLOCK_CNTL_0, ck_disable, 0); + + /*De-assert reset*/ + SMUM_WRITE_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMC_SYSCON_RESET_CNTL, rst_reg, 0); + + /* Wait for firmware to initialize */ + SMUM_WAIT_VFPF_INDIRECT_FIELD(smumgr, SMC_IND, + FIRMWARE_FLAGS, INTERRUPTS_ENABLED, 1); + + return result; +} + +static int tonga_start_smu(struct pp_smumgr *smumgr) +{ + int result; + + /* Only start SMC if SMC RAM is not running */ + if (!tonga_is_smc_ram_running(smumgr)) { + /*Check if SMU is running in protected mode*/ + if (0 == SMUM_READ_VFPF_INDIRECT_FIELD(smumgr->device, CGS_IND_REG__SMC, + SMU_FIRMWARE, SMU_MODE)) { + result = tonga_start_in_non_protection_mode(smumgr); + if (result) + return result; + } else { + result = tonga_start_in_protection_mode(smumgr); + if (result) + return result; + } + } + + result = tonga_request_smu_reload_fw(smumgr); + + return result; +} + +/** + * Write a 32bit value to the SMC SRAM space. + * ALL PARAMETERS ARE IN HOST BYTE ORDER. + * @param smumgr the address of the powerplay hardware manager. + * @param smcAddress the address in the SMC RAM to access. + * @param value to write to the SMC SRAM. + */ +static int tonga_smu_init(struct pp_smumgr *smumgr) +{ + struct tonga_smumgr *tonga_smu; + uint8_t *internal_buf; + uint64_t mc_addr = 0; + /* Allocate memory for backend private data */ + tonga_smu = (struct tonga_smumgr *)(smumgr->backend); + tonga_smu->header_buffer.data_size = + ((sizeof(struct SMU_DRAMData_TOC) / 4096) + 1) * 4096; + tonga_smu->smu_buffer.data_size = 200*4096; + + smu_allocate_memory(smumgr->device, + tonga_smu->header_buffer.data_size, + CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, + PAGE_SIZE, + &mc_addr, + &tonga_smu->header_buffer.kaddr, + &tonga_smu->header_buffer.handle); + + tonga_smu->pHeader = tonga_smu->header_buffer.kaddr; + tonga_smu->header_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); + tonga_smu->header_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); + + PP_ASSERT_WITH_CODE((NULL != tonga_smu->pHeader), + "Out of memory.", + kfree(smumgr->backend); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)tonga_smu->header_buffer.handle); + return -1); + + smu_allocate_memory(smumgr->device, + tonga_smu->smu_buffer.data_size, + CGS_GPU_MEM_TYPE__VISIBLE_CONTIG_FB, + PAGE_SIZE, + &mc_addr, + &tonga_smu->smu_buffer.kaddr, + &tonga_smu->smu_buffer.handle); + + internal_buf = tonga_smu->smu_buffer.kaddr; + tonga_smu->smu_buffer.mc_addr_high = smu_upper_32_bits(mc_addr); + tonga_smu->smu_buffer.mc_addr_low = smu_lower_32_bits(mc_addr); + + PP_ASSERT_WITH_CODE((NULL != internal_buf), + "Out of memory.", + kfree(smumgr->backend); + cgs_free_gpu_mem(smumgr->device, + (cgs_handle_t)tonga_smu->smu_buffer.handle); + return -1;); + + return 0; +} + +static const struct pp_smumgr_func tonga_smu_funcs = { + .smu_init = &tonga_smu_init, + .smu_fini = &tonga_smu_fini, + .start_smu = &tonga_start_smu, + .check_fw_load_finish = &tonga_check_fw_load_finish, + .request_smu_load_fw = &tonga_request_smu_reload_fw, + .request_smu_load_specific_fw = &tonga_request_smu_load_specific_fw, + .send_msg_to_smc = &tonga_send_msg_to_smc, + .send_msg_to_smc_with_parameter = &tonga_send_msg_to_smc_with_parameter, + .download_pptable_settings = NULL, + .upload_pptable_settings = NULL, +}; + +int tonga_smum_init(struct pp_smumgr *smumgr) +{ + struct tonga_smumgr *tonga_smu = NULL; + + tonga_smu = kzalloc(sizeof(struct tonga_smumgr), GFP_KERNEL); + + if (tonga_smu == NULL) + return -1; + + smumgr->backend = tonga_smu; + smumgr->smumgr_funcs = &tonga_smu_funcs; + + return 0; +} diff --git a/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h new file mode 100644 index 000000000000..33c788d7f05c --- /dev/null +++ b/drivers/gpu/drm/amd/powerplay/smumgr/tonga_smumgr.h @@ -0,0 +1,53 @@ +/* + * Copyright 2015 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. + * + */ + +#ifndef _TONGA_SMUMGR_H_ +#define _TONGA_SMUMGR_H_ + +struct tonga_buffer_entry { + uint32_t data_size; + uint32_t mc_addr_low; + uint32_t mc_addr_high; + void *kaddr; + unsigned long handle; +}; + +struct tonga_smumgr { + uint8_t *pHeader; + uint8_t *pMecImage; + uint32_t ulSoftRegsStart; + + struct tonga_buffer_entry header_buffer; + struct tonga_buffer_entry smu_buffer; +}; + +extern int tonga_smum_init(struct pp_smumgr *smumgr); +extern int tonga_copy_bytes_to_smc(struct pp_smumgr *smumgr, + uint32_t smcStartAddress, const uint8_t *src, + uint32_t byteCount, uint32_t limit); +extern int tonga_read_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress, + uint32_t *value, uint32_t limit); +extern int tonga_write_smc_sram_dword(struct pp_smumgr *smumgr, uint32_t smcAddress, + uint32_t value, uint32_t limit); + +#endif diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c index 3a4820e863ec..8b2becd1aa07 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.c @@ -47,6 +47,8 @@ static void amd_sched_rq_init(struct amd_sched_rq *rq) static void amd_sched_rq_add_entity(struct amd_sched_rq *rq, struct amd_sched_entity *entity) { + if (!list_empty(&entity->list)) + return; spin_lock(&rq->lock); list_add_tail(&entity->list, &rq->entities); spin_unlock(&rq->lock); @@ -55,6 +57,8 @@ static void amd_sched_rq_add_entity(struct amd_sched_rq *rq, static void amd_sched_rq_remove_entity(struct amd_sched_rq *rq, struct amd_sched_entity *entity) { + if (list_empty(&entity->list)) + return; spin_lock(&rq->lock); list_del_init(&entity->list); if (rq->current_entity == entity) @@ -138,9 +142,6 @@ int amd_sched_entity_init(struct amd_gpu_scheduler *sched, atomic_set(&entity->fence_seq, 0); entity->fence_context = fence_context_alloc(1); - /* Add the entity to the run queue */ - amd_sched_rq_add_entity(rq, entity); - return 0; } @@ -302,9 +303,11 @@ static bool amd_sched_entity_in(struct amd_sched_job *sched_job) spin_unlock(&entity->queue_lock); /* first job wakes up scheduler */ - if (first) + if (first) { + /* Add the entity to the run queue */ + amd_sched_rq_add_entity(entity->rq, entity); amd_sched_wakeup(sched); - + } return added; } @@ -349,14 +352,17 @@ static struct amd_sched_entity * amd_sched_select_entity(struct amd_gpu_scheduler *sched) { struct amd_sched_entity *entity; + int i; if (!amd_sched_ready(sched)) return NULL; /* Kernel run queue has higher priority than normal run queue*/ - entity = amd_sched_rq_select_entity(&sched->kernel_rq); - if (entity == NULL) - entity = amd_sched_rq_select_entity(&sched->sched_rq); + for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++) { + entity = amd_sched_rq_select_entity(&sched->sched_rq[i]); + if (entity) + break; + } return entity; } @@ -478,12 +484,13 @@ int amd_sched_init(struct amd_gpu_scheduler *sched, struct amd_sched_backend_ops *ops, unsigned hw_submission, long timeout, const char *name) { + int i; sched->ops = ops; sched->hw_submission_limit = hw_submission; sched->name = name; sched->timeout = timeout; - amd_sched_rq_init(&sched->sched_rq); - amd_sched_rq_init(&sched->kernel_rq); + for (i = 0; i < AMD_SCHED_MAX_PRIORITY; i++) + amd_sched_rq_init(&sched->sched_rq[i]); init_waitqueue_head(&sched->wake_up_worker); init_waitqueue_head(&sched->job_scheduled); diff --git a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h index a0f0ae53aacd..9403145d7bee 100644 --- a/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h +++ b/drivers/gpu/drm/amd/scheduler/gpu_scheduler.h @@ -104,6 +104,12 @@ struct amd_sched_backend_ops { struct fence *(*run_job)(struct amd_sched_job *sched_job); }; +enum amd_sched_priority { + AMD_SCHED_PRIORITY_KERNEL = 0, + AMD_SCHED_PRIORITY_NORMAL, + AMD_SCHED_MAX_PRIORITY +}; + /** * One scheduler is implemented for each hardware ring */ @@ -112,8 +118,7 @@ struct amd_gpu_scheduler { uint32_t hw_submission_limit; long timeout; const char *name; - struct amd_sched_rq sched_rq; - struct amd_sched_rq kernel_rq; + struct amd_sched_rq sched_rq[AMD_SCHED_MAX_PRIORITY]; wait_queue_head_t wake_up_worker; wait_queue_head_t job_scheduled; atomic_t hw_rq_count; diff --git a/drivers/gpu/drm/drm_pci.c b/drivers/gpu/drm/drm_pci.c index fcd2a86acd2c..a1fff1179a97 100644 --- a/drivers/gpu/drm/drm_pci.c +++ b/drivers/gpu/drm/drm_pci.c @@ -410,6 +410,26 @@ int drm_pcie_get_speed_cap_mask(struct drm_device *dev, u32 *mask) } EXPORT_SYMBOL(drm_pcie_get_speed_cap_mask); +int drm_pcie_get_max_link_width(struct drm_device *dev, u32 *mlw) +{ + struct pci_dev *root; + u32 lnkcap; + + *mlw = 0; + if (!dev->pdev) + return -EINVAL; + + root = dev->pdev->bus->self; + + pcie_capability_read_dword(root, PCI_EXP_LNKCAP, &lnkcap); + + *mlw = (lnkcap & PCI_EXP_LNKCAP_MLW) >> 4; + + DRM_INFO("probing mlw for device %x:%x = %x\n", root->vendor, root->device, lnkcap); + return 0; +} +EXPORT_SYMBOL(drm_pcie_get_max_link_width); + #else int drm_pci_init(struct drm_driver *driver, struct pci_driver *pdriver) diff --git a/drivers/gpu/drm/radeon/Kconfig b/drivers/gpu/drm/radeon/Kconfig index 421ae130809b..9909f5c68d76 100644 --- a/drivers/gpu/drm/radeon/Kconfig +++ b/drivers/gpu/drm/radeon/Kconfig @@ -5,12 +5,3 @@ config DRM_RADEON_USERPTR help This option selects CONFIG_MMU_NOTIFIER if it isn't already selected to enabled full userptr support. - -config DRM_RADEON_UMS - bool "Enable userspace modesetting on radeon (DEPRECATED)" - depends on DRM_RADEON - help - Choose this option if you still need userspace modesetting. - - Userspace modesetting is deprecated for quite some time now, so - enable this only if you have ancient versions of the DDX drivers. diff --git a/drivers/gpu/drm/radeon/Makefile b/drivers/gpu/drm/radeon/Makefile index dea53e36a2ef..08bd17d3925c 100644 --- a/drivers/gpu/drm/radeon/Makefile +++ b/drivers/gpu/drm/radeon/Makefile @@ -58,10 +58,6 @@ $(obj)/evergreen_cs.o: $(obj)/evergreen_reg_safe.h $(obj)/cayman_reg_safe.h radeon-y := radeon_drv.o -# add UMS driver -radeon-$(CONFIG_DRM_RADEON_UMS)+= radeon_cp.o radeon_state.o radeon_mem.o \ - radeon_irq.o r300_cmdbuf.o r600_cp.o r600_blit.o drm_buffer.o - # add KMS driver radeon-y += radeon_device.o radeon_asic.o radeon_kms.o \ radeon_atombios.o radeon_agp.o atombios_crtc.o radeon_combios.o \ diff --git a/drivers/gpu/drm/radeon/atombios_dp.c b/drivers/gpu/drm/radeon/atombios_dp.c index bd73b4069069..44ee72e04df9 100644 --- a/drivers/gpu/drm/radeon/atombios_dp.c +++ b/drivers/gpu/drm/radeon/atombios_dp.c @@ -302,77 +302,31 @@ static int convert_bpc_to_bpp(int bpc) return bpc * 3; } -/* get the max pix clock supported by the link rate and lane num */ -static int dp_get_max_dp_pix_clock(int link_rate, - int lane_num, - int bpp) -{ - return (link_rate * lane_num * 8) / bpp; -} - /***** radeon specific DP functions *****/ -int radeon_dp_get_max_link_rate(struct drm_connector *connector, - const u8 dpcd[DP_DPCD_SIZE]) -{ - int max_link_rate; - - if (radeon_connector_is_dp12_capable(connector)) - max_link_rate = min(drm_dp_max_link_rate(dpcd), 540000); - else - max_link_rate = min(drm_dp_max_link_rate(dpcd), 270000); - - return max_link_rate; -} - -/* First get the min lane# when low rate is used according to pixel clock - * (prefer low rate), second check max lane# supported by DP panel, - * if the max lane# < low rate lane# then use max lane# instead. - */ -static int radeon_dp_get_dp_lane_number(struct drm_connector *connector, - const u8 dpcd[DP_DPCD_SIZE], - int pix_clock) -{ - int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); - int max_link_rate = radeon_dp_get_max_link_rate(connector, dpcd); - int max_lane_num = drm_dp_max_lane_count(dpcd); - int lane_num; - int max_dp_pix_clock; - - for (lane_num = 1; lane_num < max_lane_num; lane_num <<= 1) { - max_dp_pix_clock = dp_get_max_dp_pix_clock(max_link_rate, lane_num, bpp); - if (pix_clock <= max_dp_pix_clock) - break; - } - - return lane_num; -} - -static int radeon_dp_get_dp_link_clock(struct drm_connector *connector, - const u8 dpcd[DP_DPCD_SIZE], - int pix_clock) +int radeon_dp_get_dp_link_config(struct drm_connector *connector, + const u8 dpcd[DP_DPCD_SIZE], + unsigned pix_clock, + unsigned *dp_lanes, unsigned *dp_rate) { int bpp = convert_bpc_to_bpp(radeon_get_monitor_bpc(connector)); - int lane_num, max_pix_clock; - - if (radeon_connector_encoder_get_dp_bridge_encoder_id(connector) == - ENCODER_OBJECT_ID_NUTMEG) - return 270000; - - lane_num = radeon_dp_get_dp_lane_number(connector, dpcd, pix_clock); - max_pix_clock = dp_get_max_dp_pix_clock(162000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 162000; - max_pix_clock = dp_get_max_dp_pix_clock(270000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 270000; - if (radeon_connector_is_dp12_capable(connector)) { - max_pix_clock = dp_get_max_dp_pix_clock(540000, lane_num, bpp); - if (pix_clock <= max_pix_clock) - return 540000; + static const unsigned link_rates[3] = { 162000, 270000, 540000 }; + unsigned max_link_rate = drm_dp_max_link_rate(dpcd); + unsigned max_lane_num = drm_dp_max_lane_count(dpcd); + unsigned lane_num, i, max_pix_clock; + + for (lane_num = 1; lane_num <= max_lane_num; lane_num <<= 1) { + for (i = 0; i < ARRAY_SIZE(link_rates) && link_rates[i] <= max_link_rate; i++) { + max_pix_clock = (lane_num * link_rates[i] * 8) / bpp; + if (max_pix_clock >= pix_clock) { + *dp_lanes = lane_num; + *dp_rate = link_rates[i]; + return 0; + } + } } - return radeon_dp_get_max_link_rate(connector, dpcd); + return -EINVAL; } static u8 radeon_dp_encoder_service(struct radeon_device *rdev, @@ -491,6 +445,7 @@ void radeon_dp_set_link_config(struct drm_connector *connector, { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; + int ret; if (!radeon_connector->con_priv) return; @@ -498,10 +453,14 @@ void radeon_dp_set_link_config(struct drm_connector *connector, if ((dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_DISPLAYPORT) || (dig_connector->dp_sink_type == CONNECTOR_OBJECT_ID_eDP)) { - dig_connector->dp_clock = - radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); - dig_connector->dp_lane_count = - radeon_dp_get_dp_lane_number(connector, dig_connector->dpcd, mode->clock); + ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd, + mode->clock, + &dig_connector->dp_lane_count, + &dig_connector->dp_clock); + if (ret) { + dig_connector->dp_clock = 0; + dig_connector->dp_lane_count = 0; + } } } @@ -510,7 +469,8 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, { struct radeon_connector *radeon_connector = to_radeon_connector(connector); struct radeon_connector_atom_dig *dig_connector; - int dp_clock; + unsigned dp_clock, dp_lanes; + int ret; if ((mode->clock > 340000) && (!radeon_connector_is_dp12_capable(connector))) @@ -520,8 +480,12 @@ int radeon_dp_mode_valid_helper(struct drm_connector *connector, return MODE_CLOCK_HIGH; dig_connector = radeon_connector->con_priv; - dp_clock = - radeon_dp_get_dp_link_clock(connector, dig_connector->dpcd, mode->clock); + ret = radeon_dp_get_dp_link_config(connector, dig_connector->dpcd, + mode->clock, + &dp_lanes, + &dp_clock); + if (ret) + return MODE_CLOCK_HIGH; if ((dp_clock == 540000) && (!radeon_connector_is_dp12_capable(connector))) diff --git a/drivers/gpu/drm/radeon/cik.c b/drivers/gpu/drm/radeon/cik.c index 0154db43860c..1e3a80165309 100644 --- a/drivers/gpu/drm/radeon/cik.c +++ b/drivers/gpu/drm/radeon/cik.c @@ -4132,10 +4132,10 @@ struct radeon_fence *cik_copy_cpdma(struct radeon_device *rdev, * @rdev: radeon_device pointer * @ib: radeon indirect buffer object * - * Emits an DE (drawing engine) or CE (constant engine) IB + * Emits a DE (drawing engine) or CE (constant engine) IB * on the gfx ring. IBs are usually generated by userspace * acceleration drivers and submitted to the kernel for - * sheduling on the ring. This function schedules the IB + * scheduling on the ring. This function schedules the IB * on the gfx ring for execution by the GPU. */ void cik_ring_ib_execute(struct radeon_device *rdev, struct radeon_ib *ib) diff --git a/drivers/gpu/drm/radeon/dce6_afmt.c b/drivers/gpu/drm/radeon/dce6_afmt.c index 752072771388..6bfc46369db1 100644 --- a/drivers/gpu/drm/radeon/dce6_afmt.c +++ b/drivers/gpu/drm/radeon/dce6_afmt.c @@ -301,6 +301,22 @@ void dce6_dp_audio_set_dto(struct radeon_device *rdev, * is the numerator, DCCG_AUDIO_DTOx_MODULE is the denominator */ if (ASIC_IS_DCE8(rdev)) { + unsigned int div = (RREG32(DENTIST_DISPCLK_CNTL) & + DENTIST_DPREFCLK_WDIVIDER_MASK) >> + DENTIST_DPREFCLK_WDIVIDER_SHIFT; + + if (div < 128 && div >= 96) + div -= 64; + else if (div >= 64) + div = div / 2 - 16; + else if (div >= 8) + div /= 4; + else + div = 0; + + if (div) + clock = rdev->clock.gpupll_outputfreq * 10 / div; + WREG32(DCE8_DCCG_AUDIO_DTO1_PHASE, 24000); WREG32(DCE8_DCCG_AUDIO_DTO1_MODULE, clock); } else { diff --git a/drivers/gpu/drm/radeon/drm_buffer.c b/drivers/gpu/drm/radeon/drm_buffer.c deleted file mode 100644 index f4e0f3a3d7b1..000000000000 --- a/drivers/gpu/drm/radeon/drm_buffer.c +++ /dev/null @@ -1,177 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Pauli Nieminen. - * All Rights Reserved. - * - * 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, sub license, 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 (including the - * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. - * - * - **************************************************************************/ -/* - * Multipart buffer for coping data which is larger than the page size. - * - * Authors: - * Pauli Nieminen <suokkos-at-gmail-dot-com> - */ - -#include <linux/export.h> -#include "drm_buffer.h" - -/** - * Allocate the drm buffer object. - * - * buf: Pointer to a pointer where the object is stored. - * size: The number of bytes to allocate. - */ -int drm_buffer_alloc(struct drm_buffer **buf, int size) -{ - int nr_pages = size / PAGE_SIZE + 1; - int idx; - - /* Allocating pointer table to end of structure makes drm_buffer - * variable sized */ - *buf = kzalloc(sizeof(struct drm_buffer) + nr_pages*sizeof(char *), - GFP_KERNEL); - - if (*buf == NULL) { - DRM_ERROR("Failed to allocate drm buffer object to hold" - " %d bytes in %d pages.\n", - size, nr_pages); - return -ENOMEM; - } - - (*buf)->size = size; - - for (idx = 0; idx < nr_pages; ++idx) { - - (*buf)->data[idx] = - kmalloc(min(PAGE_SIZE, size - idx * PAGE_SIZE), - GFP_KERNEL); - - - if ((*buf)->data[idx] == NULL) { - DRM_ERROR("Failed to allocate %dth page for drm" - " buffer with %d bytes and %d pages.\n", - idx + 1, size, nr_pages); - goto error_out; - } - - } - - return 0; - -error_out: - - for (; idx >= 0; --idx) - kfree((*buf)->data[idx]); - - kfree(*buf); - return -ENOMEM; -} - -/** - * Copy the user data to the begin of the buffer and reset the processing - * iterator. - * - * user_data: A pointer the data that is copied to the buffer. - * size: The Number of bytes to copy. - */ -int drm_buffer_copy_from_user(struct drm_buffer *buf, - void __user *user_data, int size) -{ - int nr_pages = size / PAGE_SIZE + 1; - int idx; - - if (size > buf->size) { - DRM_ERROR("Requesting to copy %d bytes to a drm buffer with" - " %d bytes space\n", - size, buf->size); - return -EFAULT; - } - - for (idx = 0; idx < nr_pages; ++idx) { - - if (copy_from_user(buf->data[idx], - user_data + idx * PAGE_SIZE, - min(PAGE_SIZE, size - idx * PAGE_SIZE))) { - DRM_ERROR("Failed to copy user data (%p) to drm buffer" - " (%p) %dth page.\n", - user_data, buf, idx); - return -EFAULT; - - } - } - buf->iterator = 0; - return 0; -} - -/** - * Free the drm buffer object - */ -void drm_buffer_free(struct drm_buffer *buf) -{ - - if (buf != NULL) { - - int nr_pages = buf->size / PAGE_SIZE + 1; - int idx; - for (idx = 0; idx < nr_pages; ++idx) - kfree(buf->data[idx]); - - kfree(buf); - } -} - -/** - * Read an object from buffer that may be split to multiple parts. If object - * is not split function just returns the pointer to object in buffer. But in - * case of split object data is copied to given stack object that is suplied - * by caller. - * - * The processing location of the buffer is also advanced to the next byte - * after the object. - * - * objsize: The size of the objet in bytes. - * stack_obj: A pointer to a memory location where object can be copied. - */ -void *drm_buffer_read_object(struct drm_buffer *buf, - int objsize, void *stack_obj) -{ - int idx = drm_buffer_index(buf); - int page = drm_buffer_page(buf); - void *obj = NULL; - - if (idx + objsize <= PAGE_SIZE) { - obj = &buf->data[page][idx]; - } else { - /* The object is split which forces copy to temporary object.*/ - int beginsz = PAGE_SIZE - idx; - memcpy(stack_obj, &buf->data[page][idx], beginsz); - - memcpy(stack_obj + beginsz, &buf->data[page + 1][0], - objsize - beginsz); - - obj = stack_obj; - } - - drm_buffer_advance(buf, objsize); - return obj; -} diff --git a/drivers/gpu/drm/radeon/drm_buffer.h b/drivers/gpu/drm/radeon/drm_buffer.h deleted file mode 100644 index c80d3a340b94..000000000000 --- a/drivers/gpu/drm/radeon/drm_buffer.h +++ /dev/null @@ -1,148 +0,0 @@ -/************************************************************************** - * - * Copyright 2010 Pauli Nieminen. - * All Rights Reserved. - * - * 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, sub license, 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 (including the - * next paragraph) 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 NON-INFRINGEMENT. IN NO EVENT SHALL - * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS 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. - * - * - **************************************************************************/ -/* - * Multipart buffer for coping data which is larger than the page size. - * - * Authors: - * Pauli Nieminen <suokkos-at-gmail-dot-com> - */ - -#ifndef _DRM_BUFFER_H_ -#define _DRM_BUFFER_H_ - -#include <drm/drmP.h> - -struct drm_buffer { - int iterator; - int size; - char *data[]; -}; - - -/** - * Return the index of page that buffer is currently pointing at. - */ -static inline int drm_buffer_page(struct drm_buffer *buf) -{ - return buf->iterator / PAGE_SIZE; -} -/** - * Return the index of the current byte in the page - */ -static inline int drm_buffer_index(struct drm_buffer *buf) -{ - return buf->iterator & (PAGE_SIZE - 1); -} -/** - * Return number of bytes that is left to process - */ -static inline int drm_buffer_unprocessed(struct drm_buffer *buf) -{ - return buf->size - buf->iterator; -} - -/** - * Advance the buffer iterator number of bytes that is given. - */ -static inline void drm_buffer_advance(struct drm_buffer *buf, int bytes) -{ - buf->iterator += bytes; -} - -/** - * Allocate the drm buffer object. - * - * buf: A pointer to a pointer where the object is stored. - * size: The number of bytes to allocate. - */ -extern int drm_buffer_alloc(struct drm_buffer **buf, int size); - -/** - * Copy the user data to the begin of the buffer and reset the processing - * iterator. - * - * user_data: A pointer the data that is copied to the buffer. - * size: The Number of bytes to copy. - */ -extern int drm_buffer_copy_from_user(struct drm_buffer *buf, - void __user *user_data, int size); - -/** - * Free the drm buffer object - */ -extern void drm_buffer_free(struct drm_buffer *buf); - -/** - * Read an object from buffer that may be split to multiple parts. If object - * is not split function just returns the pointer to object in buffer. But in - * case of split object data is copied to given stack object that is suplied - * by caller. - * - * The processing location of the buffer is also advanced to the next byte - * after the object. - * - * objsize: The size of the objet in bytes. - * stack_obj: A pointer to a memory location where object can be copied. - */ -extern void *drm_buffer_read_object(struct drm_buffer *buf, - int objsize, void *stack_obj); - -/** - * Returns the pointer to the dword which is offset number of elements from the - * current processing location. - * - * Caller must make sure that dword is not split in the buffer. This - * requirement is easily met if all the sizes of objects in buffer are - * multiples of dword and PAGE_SIZE is multiple dword. - * - * Call to this function doesn't change the processing location. - * - * offset: The index of the dword relative to the internat iterator. - */ -static inline void *drm_buffer_pointer_to_dword(struct drm_buffer *buffer, - int offset) -{ - int iter = buffer->iterator + offset * 4; - return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)]; -} -/** - * Returns the pointer to the dword which is offset number of elements from - * the current processing location. - * - * Call to this function doesn't change the processing location. - * - * offset: The index of the byte relative to the internat iterator. - */ -static inline void *drm_buffer_pointer_to_byte(struct drm_buffer *buffer, - int offset) -{ - int iter = buffer->iterator + offset; - return &buffer->data[iter / PAGE_SIZE][iter & (PAGE_SIZE - 1)]; -} - -#endif diff --git a/drivers/gpu/drm/radeon/r300_cmdbuf.c b/drivers/gpu/drm/radeon/r300_cmdbuf.c deleted file mode 100644 index 9418e388b045..000000000000 --- a/drivers/gpu/drm/radeon/r300_cmdbuf.c +++ /dev/null @@ -1,1186 +0,0 @@ -/* r300_cmdbuf.c -- Command buffer emission for R300 -*- linux-c -*- - * - * Copyright (C) The Weather Channel, Inc. 2002. - * Copyright (C) 2004 Nicolai Haehnle. - * All Rights Reserved. - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: - * Nicolai Haehnle <prefect_@gmx.net> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" -#include "r300_reg.h" -#include "drm_buffer.h" - -#include <asm/unaligned.h> - -#define R300_SIMULTANEOUS_CLIPRECTS 4 - -/* Values for R300_RE_CLIPRECT_CNTL depending on the number of cliprects - */ -static const int r300_cliprect_cntl[4] = { - 0xAAAA, - 0xEEEE, - 0xFEFE, - 0xFFFE -}; - -/** - * Emit up to R300_SIMULTANEOUS_CLIPRECTS cliprects from the given command - * buffer, starting with index n. - */ -static int r300_emit_cliprects(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, int n) -{ - struct drm_clip_rect box; - int nr; - int i; - RING_LOCALS; - - nr = cmdbuf->nbox - n; - if (nr > R300_SIMULTANEOUS_CLIPRECTS) - nr = R300_SIMULTANEOUS_CLIPRECTS; - - DRM_DEBUG("%i cliprects\n", nr); - - if (nr) { - BEGIN_RING(6 + nr * 2); - OUT_RING(CP_PACKET0(R300_RE_CLIPRECT_TL_0, nr * 2 - 1)); - - for (i = 0; i < nr; ++i) { - if (copy_from_user - (&box, &cmdbuf->boxes[n + i], sizeof(box))) { - DRM_ERROR("copy cliprect faulted\n"); - return -EFAULT; - } - - box.x2--; /* Hardware expects inclusive bottom-right corner */ - box.y2--; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { - box.x1 = (box.x1) & - R300_CLIPRECT_MASK; - box.y1 = (box.y1) & - R300_CLIPRECT_MASK; - box.x2 = (box.x2) & - R300_CLIPRECT_MASK; - box.y2 = (box.y2) & - R300_CLIPRECT_MASK; - } else { - box.x1 = (box.x1 + R300_CLIPRECT_OFFSET) & - R300_CLIPRECT_MASK; - box.y1 = (box.y1 + R300_CLIPRECT_OFFSET) & - R300_CLIPRECT_MASK; - box.x2 = (box.x2 + R300_CLIPRECT_OFFSET) & - R300_CLIPRECT_MASK; - box.y2 = (box.y2 + R300_CLIPRECT_OFFSET) & - R300_CLIPRECT_MASK; - } - - OUT_RING((box.x1 << R300_CLIPRECT_X_SHIFT) | - (box.y1 << R300_CLIPRECT_Y_SHIFT)); - OUT_RING((box.x2 << R300_CLIPRECT_X_SHIFT) | - (box.y2 << R300_CLIPRECT_Y_SHIFT)); - - } - - OUT_RING_REG(R300_RE_CLIPRECT_CNTL, r300_cliprect_cntl[nr - 1]); - - /* TODO/SECURITY: Force scissors to a safe value, otherwise the - * client might be able to trample over memory. - * The impact should be very limited, but I'd rather be safe than - * sorry. - */ - OUT_RING(CP_PACKET0(R300_RE_SCISSORS_TL, 1)); - OUT_RING(0); - OUT_RING(R300_SCISSORS_X_MASK | R300_SCISSORS_Y_MASK); - ADVANCE_RING(); - } else { - /* Why we allow zero cliprect rendering: - * There are some commands in a command buffer that must be submitted - * even when there are no cliprects, e.g. DMA buffer discard - * or state setting (though state setting could be avoided by - * simulating a loss of context). - * - * Now since the cmdbuf interface is so chaotic right now (and is - * bound to remain that way for a bit until things settle down), - * it is basically impossible to filter out the commands that are - * necessary and those that aren't. - * - * So I choose the safe way and don't do any filtering at all; - * instead, I simply set up the engine so that all rendering - * can't produce any fragments. - */ - BEGIN_RING(2); - OUT_RING_REG(R300_RE_CLIPRECT_CNTL, 0); - ADVANCE_RING(); - } - - /* flus cache and wait idle clean after cliprect change */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - ADVANCE_RING(); - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - - return 0; -} - -static u8 r300_reg_flags[0x10000 >> 2]; - -void r300_init_reg_flags(struct drm_device *dev) -{ - int i; - drm_radeon_private_t *dev_priv = dev->dev_private; - - memset(r300_reg_flags, 0, 0x10000 >> 2); -#define ADD_RANGE_MARK(reg, count,mark) \ - for(i=((reg)>>2);i<((reg)>>2)+(count);i++)\ - r300_reg_flags[i]|=(mark); - -#define MARK_SAFE 1 -#define MARK_CHECK_OFFSET 2 - -#define ADD_RANGE(reg, count) ADD_RANGE_MARK(reg, count, MARK_SAFE) - - /* these match cmducs() command in r300_driver/r300/r300_cmdbuf.c */ - ADD_RANGE(R300_SE_VPORT_XSCALE, 6); - ADD_RANGE(R300_VAP_CNTL, 1); - ADD_RANGE(R300_SE_VTE_CNTL, 2); - ADD_RANGE(0x2134, 2); - ADD_RANGE(R300_VAP_CNTL_STATUS, 1); - ADD_RANGE(R300_VAP_INPUT_CNTL_0, 2); - ADD_RANGE(0x21DC, 1); - ADD_RANGE(R300_VAP_UNKNOWN_221C, 1); - ADD_RANGE(R300_VAP_CLIP_X_0, 4); - ADD_RANGE(R300_VAP_PVS_STATE_FLUSH_REG, 1); - ADD_RANGE(R300_VAP_UNKNOWN_2288, 1); - ADD_RANGE(R300_VAP_OUTPUT_VTX_FMT_0, 2); - ADD_RANGE(R300_VAP_PVS_CNTL_1, 3); - ADD_RANGE(R300_GB_ENABLE, 1); - ADD_RANGE(R300_GB_MSPOS0, 5); - ADD_RANGE(R300_TX_INVALTAGS, 1); - ADD_RANGE(R300_TX_ENABLE, 1); - ADD_RANGE(0x4200, 4); - ADD_RANGE(0x4214, 1); - ADD_RANGE(R300_RE_POINTSIZE, 1); - ADD_RANGE(0x4230, 3); - ADD_RANGE(R300_RE_LINE_CNT, 1); - ADD_RANGE(R300_RE_UNK4238, 1); - ADD_RANGE(0x4260, 3); - ADD_RANGE(R300_RE_SHADE, 4); - ADD_RANGE(R300_RE_POLYGON_MODE, 5); - ADD_RANGE(R300_RE_ZBIAS_CNTL, 1); - ADD_RANGE(R300_RE_ZBIAS_T_FACTOR, 4); - ADD_RANGE(R300_RE_OCCLUSION_CNTL, 1); - ADD_RANGE(R300_RE_CULL_CNTL, 1); - ADD_RANGE(0x42C0, 2); - ADD_RANGE(R300_RS_CNTL_0, 2); - - ADD_RANGE(R300_SU_REG_DEST, 1); - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) - ADD_RANGE(RV530_FG_ZBREG_DEST, 1); - - ADD_RANGE(R300_SC_HYPERZ, 2); - ADD_RANGE(0x43E8, 1); - - ADD_RANGE(0x46A4, 5); - - ADD_RANGE(R300_RE_FOG_STATE, 1); - ADD_RANGE(R300_FOG_COLOR_R, 3); - ADD_RANGE(R300_PP_ALPHA_TEST, 2); - ADD_RANGE(0x4BD8, 1); - ADD_RANGE(R300_PFS_PARAM_0_X, 64); - ADD_RANGE(0x4E00, 1); - ADD_RANGE(R300_RB3D_CBLEND, 2); - ADD_RANGE(R300_RB3D_COLORMASK, 1); - ADD_RANGE(R300_RB3D_BLEND_COLOR, 3); - ADD_RANGE_MARK(R300_RB3D_COLOROFFSET0, 1, MARK_CHECK_OFFSET); /* check offset */ - ADD_RANGE(R300_RB3D_COLORPITCH0, 1); - ADD_RANGE(0x4E50, 9); - ADD_RANGE(0x4E88, 1); - ADD_RANGE(0x4EA0, 2); - ADD_RANGE(R300_ZB_CNTL, 3); - ADD_RANGE(R300_ZB_FORMAT, 4); - ADD_RANGE_MARK(R300_ZB_DEPTHOFFSET, 1, MARK_CHECK_OFFSET); /* check offset */ - ADD_RANGE(R300_ZB_DEPTHPITCH, 1); - ADD_RANGE(R300_ZB_DEPTHCLEARVALUE, 1); - ADD_RANGE(R300_ZB_ZMASK_OFFSET, 13); - ADD_RANGE(R300_ZB_ZPASS_DATA, 2); /* ZB_ZPASS_DATA, ZB_ZPASS_ADDR */ - - ADD_RANGE(R300_TX_FILTER_0, 16); - ADD_RANGE(R300_TX_FILTER1_0, 16); - ADD_RANGE(R300_TX_SIZE_0, 16); - ADD_RANGE(R300_TX_FORMAT_0, 16); - ADD_RANGE(R300_TX_PITCH_0, 16); - /* Texture offset is dangerous and needs more checking */ - ADD_RANGE_MARK(R300_TX_OFFSET_0, 16, MARK_CHECK_OFFSET); - ADD_RANGE(R300_TX_CHROMA_KEY_0, 16); - ADD_RANGE(R300_TX_BORDER_COLOR_0, 16); - - /* Sporadic registers used as primitives are emitted */ - ADD_RANGE(R300_ZB_ZCACHE_CTLSTAT, 1); - ADD_RANGE(R300_RB3D_DSTCACHE_CTLSTAT, 1); - ADD_RANGE(R300_VAP_INPUT_ROUTE_0_0, 8); - ADD_RANGE(R300_VAP_INPUT_ROUTE_1_0, 8); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { - ADD_RANGE(R500_VAP_INDEX_OFFSET, 1); - ADD_RANGE(R500_US_CONFIG, 2); - ADD_RANGE(R500_US_CODE_ADDR, 3); - ADD_RANGE(R500_US_FC_CTRL, 1); - ADD_RANGE(R500_RS_IP_0, 16); - ADD_RANGE(R500_RS_INST_0, 16); - ADD_RANGE(R500_RB3D_COLOR_CLEAR_VALUE_AR, 2); - ADD_RANGE(R500_RB3D_CONSTANT_COLOR_AR, 2); - ADD_RANGE(R500_ZB_FIFO_SIZE, 2); - } else { - ADD_RANGE(R300_PFS_CNTL_0, 3); - ADD_RANGE(R300_PFS_NODE_0, 4); - ADD_RANGE(R300_PFS_TEXI_0, 64); - ADD_RANGE(R300_PFS_INSTR0_0, 64); - ADD_RANGE(R300_PFS_INSTR1_0, 64); - ADD_RANGE(R300_PFS_INSTR2_0, 64); - ADD_RANGE(R300_PFS_INSTR3_0, 64); - ADD_RANGE(R300_RS_INTERP_0, 8); - ADD_RANGE(R300_RS_ROUTE_0, 8); - - } -} - -static __inline__ int r300_check_range(unsigned reg, int count) -{ - int i; - if (reg & ~0xffff) - return -1; - for (i = (reg >> 2); i < (reg >> 2) + count; i++) - if (r300_reg_flags[i] != MARK_SAFE) - return 1; - return 0; -} - -static __inline__ int r300_emit_carefully_checked_packet0(drm_radeon_private_t * - dev_priv, - drm_radeon_kcmd_buffer_t - * cmdbuf, - drm_r300_cmd_header_t - header) -{ - int reg; - int sz; - int i; - u32 *value; - RING_LOCALS; - - sz = header.packet0.count; - reg = (header.packet0.reghi << 8) | header.packet0.reglo; - - if ((sz > 64) || (sz < 0)) { - DRM_ERROR("Cannot emit more than 64 values at a time (reg=%04x sz=%d)\n", - reg, sz); - return -EINVAL; - } - - for (i = 0; i < sz; i++) { - switch (r300_reg_flags[(reg >> 2) + i]) { - case MARK_SAFE: - break; - case MARK_CHECK_OFFSET: - value = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); - if (!radeon_check_offset(dev_priv, *value)) { - DRM_ERROR("Offset failed range check (reg=%04x sz=%d)\n", - reg, sz); - return -EINVAL; - } - break; - default: - DRM_ERROR("Register %04x failed check as flag=%02x\n", - reg + i * 4, r300_reg_flags[(reg >> 2) + i]); - return -EINVAL; - } - } - - BEGIN_RING(1 + sz); - OUT_RING(CP_PACKET0(reg, sz - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - - return 0; -} - -/** - * Emits a packet0 setting arbitrary registers. - * Called by r300_do_cp_cmdbuf. - * - * Note that checks are performed on contents and addresses of the registers - */ -static __inline__ int r300_emit_packet0(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - drm_r300_cmd_header_t header) -{ - int reg; - int sz; - RING_LOCALS; - - sz = header.packet0.count; - reg = (header.packet0.reghi << 8) | header.packet0.reglo; - - if (!sz) - return 0; - - if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - if (reg + sz * 4 >= 0x10000) { - DRM_ERROR("No such registers in hardware reg=%04x sz=%d\n", reg, - sz); - return -EINVAL; - } - - if (r300_check_range(reg, sz)) { - /* go and check everything */ - return r300_emit_carefully_checked_packet0(dev_priv, cmdbuf, - header); - } - /* the rest of the data is safe to emit, whatever the values the user passed */ - - BEGIN_RING(1 + sz); - OUT_RING(CP_PACKET0(reg, sz - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - - return 0; -} - -/** - * Uploads user-supplied vertex program instructions or parameters onto - * the graphics card. - * Called by r300_do_cp_cmdbuf. - */ -static __inline__ int r300_emit_vpu(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - drm_r300_cmd_header_t header) -{ - int sz; - int addr; - RING_LOCALS; - - sz = header.vpu.count; - addr = (header.vpu.adrhi << 8) | header.vpu.adrlo; - - if (!sz) - return 0; - if (sz * 16 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - /* VAP is very sensitive so we purge cache before we program it - * and we also flush its state before & after */ - BEGIN_RING(6); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); - OUT_RING(0); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - - BEGIN_RING(3 + sz * 4); - OUT_RING_REG(R300_VAP_PVS_UPLOAD_ADDRESS, addr); - OUT_RING(CP_PACKET0_TABLE(R300_VAP_PVS_UPLOAD_DATA, sz * 4 - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * 4); - ADVANCE_RING(); - - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_VAP_PVS_STATE_FLUSH_REG, 0)); - OUT_RING(0); - ADVANCE_RING(); - - return 0; -} - -/** - * Emit a clear packet from userspace. - * Called by r300_emit_packet3. - */ -static __inline__ int r300_emit_clear(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - RING_LOCALS; - - if (8 * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - BEGIN_RING(10); - OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 8)); - OUT_RING(R300_PRIM_TYPE_POINT | R300_PRIM_WALK_RING | - (1 << R300_PRIM_NUM_VERTICES_SHIFT)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, 8); - ADVANCE_RING(); - - BEGIN_RING(4); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FLUSH); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* set flush flag */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED; - - return 0; -} - -static __inline__ int r300_emit_3d_load_vbpntr(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - u32 header) -{ - int count, i, k; -#define MAX_ARRAY_PACKET 64 - u32 *data; - u32 narrays; - RING_LOCALS; - - count = (header & RADEON_CP_PACKET_COUNT_MASK) >> 16; - - if ((count + 1) > MAX_ARRAY_PACKET) { - DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", - count); - return -EINVAL; - } - /* carefully check packet contents */ - - /* We have already read the header so advance the buffer. */ - drm_buffer_advance(cmdbuf->buffer, 4); - - narrays = *(u32 *)drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - k = 0; - i = 1; - while ((k < narrays) && (i < (count + 1))) { - i++; /* skip attribute field */ - data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); - if (!radeon_check_offset(dev_priv, *data)) { - DRM_ERROR - ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", - k, i); - return -EINVAL; - } - k++; - i++; - if (k == narrays) - break; - /* have one more to process, they come in pairs */ - data = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); - if (!radeon_check_offset(dev_priv, *data)) { - DRM_ERROR - ("Offset failed range check (k=%d i=%d) while processing 3D_LOAD_VBPNTR packet.\n", - k, i); - return -EINVAL; - } - k++; - i++; - } - /* do the counts match what we expect ? */ - if ((k != narrays) || (i != (count + 1))) { - DRM_ERROR - ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", - k, i, narrays, count + 1); - return -EINVAL; - } - - /* all clear, output packet */ - - BEGIN_RING(count + 2); - OUT_RING(header); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 1); - ADVANCE_RING(); - - return 0; -} - -static __inline__ int r300_emit_bitblt_multi(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - int count, ret; - RING_LOCALS; - - - count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16; - - if (*cmd & 0x8000) { - u32 offset; - u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - if (*cmd1 & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL - | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { - - u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); - offset = *cmd2 << 10; - ret = !radeon_check_offset(dev_priv, offset); - if (ret) { - DRM_ERROR("Invalid bitblt first offset is %08X\n", offset); - return -EINVAL; - } - } - - if ((*cmd1 & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && - (*cmd1 & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { - u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); - offset = *cmd3 << 10; - ret = !radeon_check_offset(dev_priv, offset); - if (ret) { - DRM_ERROR("Invalid bitblt second offset is %08X\n", offset); - return -EINVAL; - } - - } - } - - BEGIN_RING(count+2); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); - ADVANCE_RING(); - - return 0; -} - -static __inline__ int r300_emit_draw_indx_2(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - u32 *cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - int count; - int expected_count; - RING_LOCALS; - - count = (*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16; - - expected_count = *cmd1 >> 16; - if (!(*cmd1 & R300_VAP_VF_CNTL__INDEX_SIZE_32bit)) - expected_count = (expected_count+1)/2; - - if (count && count != expected_count) { - DRM_ERROR("3D_DRAW_INDX_2: packet size %i, expected %i\n", - count, expected_count); - return -EINVAL; - } - - BEGIN_RING(count+2); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); - ADVANCE_RING(); - - if (!count) { - drm_r300_cmd_header_t stack_header, *header; - u32 *cmd1, *cmd2, *cmd3; - - if (drm_buffer_unprocessed(cmdbuf->buffer) - < 4*4 + sizeof(stack_header)) { - DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER, but stream is too short.\n"); - return -EINVAL; - } - - header = drm_buffer_read_object(cmdbuf->buffer, - sizeof(stack_header), &stack_header); - - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - cmd1 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); - cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); - - if (header->header.cmd_type != R300_CMD_PACKET3 || - header->packet3.packet != R300_CMD_PACKET3_RAW || - *cmd != CP_PACKET3(RADEON_CP_INDX_BUFFER, 2)) { - DRM_ERROR("3D_DRAW_INDX_2: expect subsequent INDX_BUFFER.\n"); - return -EINVAL; - } - - if ((*cmd1 & 0x8000ffff) != 0x80000810) { - DRM_ERROR("Invalid indx_buffer reg address %08X\n", - *cmd1); - return -EINVAL; - } - if (!radeon_check_offset(dev_priv, *cmd2)) { - DRM_ERROR("Invalid indx_buffer offset is %08X\n", - *cmd2); - return -EINVAL; - } - if (*cmd3 != expected_count) { - DRM_ERROR("INDX_BUFFER: buffer size %i, expected %i\n", - *cmd3, expected_count); - return -EINVAL; - } - - BEGIN_RING(4); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, 4); - ADVANCE_RING(); - } - - return 0; -} - -static __inline__ int r300_emit_raw_packet3(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - u32 *header; - int count; - RING_LOCALS; - - if (4 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - /* Fixme !! This simply emits a packet without much checking. - We need to be smarter. */ - - /* obtain first word - actual packet3 header */ - header = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - - /* Is it packet 3 ? */ - if ((*header >> 30) != 0x3) { - DRM_ERROR("Not a packet3 header (0x%08x)\n", *header); - return -EINVAL; - } - - count = (*header >> 16) & 0x3fff; - - /* Check again now that we know how much data to expect */ - if ((count + 2) * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) { - DRM_ERROR - ("Expected packet3 of length %d but have only %d bytes left\n", - (count + 2) * 4, drm_buffer_unprocessed(cmdbuf->buffer)); - return -EINVAL; - } - - /* Is it a packet type we know about ? */ - switch (*header & 0xff00) { - case RADEON_3D_LOAD_VBPNTR: /* load vertex array pointers */ - return r300_emit_3d_load_vbpntr(dev_priv, cmdbuf, *header); - - case RADEON_CNTL_BITBLT_MULTI: - return r300_emit_bitblt_multi(dev_priv, cmdbuf); - - case RADEON_CP_INDX_BUFFER: - DRM_ERROR("packet3 INDX_BUFFER without preceding 3D_DRAW_INDX_2 is illegal.\n"); - return -EINVAL; - case RADEON_CP_3D_DRAW_IMMD_2: - /* triggers drawing using in-packet vertex data */ - case RADEON_CP_3D_DRAW_VBUF_2: - /* triggers drawing of vertex buffers setup elsewhere */ - dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | - RADEON_PURGE_EMITED); - break; - case RADEON_CP_3D_DRAW_INDX_2: - /* triggers drawing using indices to vertex buffer */ - /* whenever we send vertex we clear flush & purge */ - dev_priv->track_flush &= ~(RADEON_FLUSH_EMITED | - RADEON_PURGE_EMITED); - return r300_emit_draw_indx_2(dev_priv, cmdbuf); - case RADEON_WAIT_FOR_IDLE: - case RADEON_CP_NOP: - /* these packets are safe */ - break; - default: - DRM_ERROR("Unknown packet3 header (0x%08x)\n", *header); - return -EINVAL; - } - - BEGIN_RING(count + 2); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, count + 2); - ADVANCE_RING(); - - return 0; -} - -/** - * Emit a rendering packet3 from userspace. - * Called by r300_do_cp_cmdbuf. - */ -static __inline__ int r300_emit_packet3(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - drm_r300_cmd_header_t header) -{ - int n; - int ret; - int orig_iter = cmdbuf->buffer->iterator; - - /* This is a do-while-loop so that we run the interior at least once, - * even if cmdbuf->nbox is 0. Compare r300_emit_cliprects for rationale. - */ - n = 0; - do { - if (cmdbuf->nbox > R300_SIMULTANEOUS_CLIPRECTS) { - ret = r300_emit_cliprects(dev_priv, cmdbuf, n); - if (ret) - return ret; - - cmdbuf->buffer->iterator = orig_iter; - } - - switch (header.packet3.packet) { - case R300_CMD_PACKET3_CLEAR: - DRM_DEBUG("R300_CMD_PACKET3_CLEAR\n"); - ret = r300_emit_clear(dev_priv, cmdbuf); - if (ret) { - DRM_ERROR("r300_emit_clear failed\n"); - return ret; - } - break; - - case R300_CMD_PACKET3_RAW: - DRM_DEBUG("R300_CMD_PACKET3_RAW\n"); - ret = r300_emit_raw_packet3(dev_priv, cmdbuf); - if (ret) { - DRM_ERROR("r300_emit_raw_packet3 failed\n"); - return ret; - } - break; - - default: - DRM_ERROR("bad packet3 type %i at byte %d\n", - header.packet3.packet, - cmdbuf->buffer->iterator - (int)sizeof(header)); - return -EINVAL; - } - - n += R300_SIMULTANEOUS_CLIPRECTS; - } while (n < cmdbuf->nbox); - - return 0; -} - -/* Some of the R300 chips seem to be extremely touchy about the two registers - * that are configured in r300_pacify. - * Among the worst offenders seems to be the R300 ND (0x4E44): When userspace - * sends a command buffer that contains only state setting commands and a - * vertex program/parameter upload sequence, this will eventually lead to a - * lockup, unless the sequence is bracketed by calls to r300_pacify. - * So we should take great care to *always* call r300_pacify before - * *anything* 3D related, and again afterwards. This is what the - * call bracket in r300_do_cp_cmdbuf is for. - */ - -/** - * Emit the sequence to pacify R300. - */ -static void r300_pacify(drm_radeon_private_t *dev_priv) -{ - uint32_t cache_z, cache_3d, cache_2d; - RING_LOCALS; - - cache_z = R300_ZC_FLUSH; - cache_2d = R300_RB2D_DC_FLUSH; - cache_3d = R300_RB3D_DC_FLUSH; - if (!(dev_priv->track_flush & RADEON_PURGE_EMITED)) { - /* we can purge, primitive where draw since last purge */ - cache_z |= R300_ZC_FREE; - cache_2d |= R300_RB2D_DC_FREE; - cache_3d |= R300_RB3D_DC_FREE; - } - - /* flush & purge zbuffer */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); - OUT_RING(cache_z); - ADVANCE_RING(); - /* flush & purge 3d */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(cache_3d); - ADVANCE_RING(); - /* flush & purge texture */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_TX_INVALTAGS, 0)); - OUT_RING(0); - ADVANCE_RING(); - /* FIXME: is this one really needed ? */ - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_AARESOLVE_CTL, 0)); - OUT_RING(0); - ADVANCE_RING(); - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_3D_IDLECLEAN); - ADVANCE_RING(); - /* flush & purge 2d through E2 as RB2D will trigger lockup */ - BEGIN_RING(4); - OUT_RING(CP_PACKET0(R300_DSTCACHE_CTLSTAT, 0)); - OUT_RING(cache_2d); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(RADEON_WAIT_2D_IDLECLEAN | - RADEON_WAIT_HOST_IDLECLEAN); - ADVANCE_RING(); - /* set flush & purge flags */ - dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; -} - -/** - * Called by r300_do_cp_cmdbuf to update the internal buffer age and state. - * The actual age emit is done by r300_do_cp_cmdbuf, which is why you must - * be careful about how this function is called. - */ -static void r300_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) -{ - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - - buf_priv->age = ++master_priv->sarea_priv->last_dispatch; - buf->pending = 1; - buf->used = 0; -} - -static void r300_cmd_wait(drm_radeon_private_t * dev_priv, - drm_r300_cmd_header_t header) -{ - u32 wait_until; - RING_LOCALS; - - if (!header.wait.flags) - return; - - wait_until = 0; - - switch(header.wait.flags) { - case R300_WAIT_2D: - wait_until = RADEON_WAIT_2D_IDLE; - break; - case R300_WAIT_3D: - wait_until = RADEON_WAIT_3D_IDLE; - break; - case R300_NEW_WAIT_2D_3D: - wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_3D_IDLE; - break; - case R300_NEW_WAIT_2D_2D_CLEAN: - wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; - break; - case R300_NEW_WAIT_3D_3D_CLEAN: - wait_until = RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; - break; - case R300_NEW_WAIT_2D_2D_CLEAN_3D_3D_CLEAN: - wait_until = RADEON_WAIT_2D_IDLE|RADEON_WAIT_2D_IDLECLEAN; - wait_until |= RADEON_WAIT_3D_IDLE|RADEON_WAIT_3D_IDLECLEAN; - break; - default: - return; - } - - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_WAIT_UNTIL, 0)); - OUT_RING(wait_until); - ADVANCE_RING(); -} - -static int r300_scratch(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - drm_r300_cmd_header_t header) -{ - u32 *ref_age_base; - u32 i, *buf_idx, h_pending; - u64 *ptr_addr; - u64 stack_ptr_addr; - RING_LOCALS; - - if (drm_buffer_unprocessed(cmdbuf->buffer) < - (sizeof(u64) + header.scratch.n_bufs * sizeof(*buf_idx))) { - return -EINVAL; - } - - if (header.scratch.reg >= 5) { - return -EINVAL; - } - - dev_priv->scratch_ages[header.scratch.reg]++; - - ptr_addr = drm_buffer_read_object(cmdbuf->buffer, - sizeof(stack_ptr_addr), &stack_ptr_addr); - ref_age_base = (u32 *)(unsigned long)get_unaligned(ptr_addr); - - for (i=0; i < header.scratch.n_bufs; i++) { - buf_idx = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - *buf_idx *= 2; /* 8 bytes per buf */ - - if (copy_to_user(ref_age_base + *buf_idx, - &dev_priv->scratch_ages[header.scratch.reg], - sizeof(u32))) - return -EINVAL; - - if (copy_from_user(&h_pending, - ref_age_base + *buf_idx + 1, - sizeof(u32))) - return -EINVAL; - - if (h_pending == 0) - return -EINVAL; - - h_pending--; - - if (copy_to_user(ref_age_base + *buf_idx + 1, - &h_pending, - sizeof(u32))) - return -EINVAL; - - drm_buffer_advance(cmdbuf->buffer, sizeof(*buf_idx)); - } - - BEGIN_RING(2); - OUT_RING( CP_PACKET0( RADEON_SCRATCH_REG0 + header.scratch.reg * 4, 0 ) ); - OUT_RING( dev_priv->scratch_ages[header.scratch.reg] ); - ADVANCE_RING(); - - return 0; -} - -/** - * Uploads user-supplied vertex program instructions or parameters onto - * the graphics card. - * Called by r300_do_cp_cmdbuf. - */ -static inline int r300_emit_r500fp(drm_radeon_private_t *dev_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - drm_r300_cmd_header_t header) -{ - int sz; - int addr; - int type; - int isclamp; - int stride; - RING_LOCALS; - - sz = header.r500fp.count; - /* address is 9 bits 0 - 8, bit 1 of flags is part of address */ - addr = ((header.r500fp.adrhi_flags & 1) << 8) | header.r500fp.adrlo; - - type = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_TYPE); - isclamp = !!(header.r500fp.adrhi_flags & R500FP_CONSTANT_CLAMP); - - addr |= (type << 16); - addr |= (isclamp << 17); - - stride = type ? 4 : 6; - - DRM_DEBUG("r500fp %d %d type: %d\n", sz, addr, type); - if (!sz) - return 0; - if (sz * stride * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - BEGIN_RING(3 + sz * stride); - OUT_RING_REG(R500_GA_US_VECTOR_INDEX, addr); - OUT_RING(CP_PACKET0_TABLE(R500_GA_US_VECTOR_DATA, sz * stride - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz * stride); - - ADVANCE_RING(); - - return 0; -} - - -/** - * Parses and validates a user-supplied command buffer and emits appropriate - * commands on the DMA ring buffer. - * Called by the ioctl handler function radeon_cp_cmdbuf. - */ -int r300_do_cp_cmdbuf(struct drm_device *dev, - struct drm_file *file_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf = NULL; - int emit_dispatch_age = 0; - int ret = 0; - - DRM_DEBUG("\n"); - - /* pacify */ - r300_pacify(dev_priv); - - if (cmdbuf->nbox <= R300_SIMULTANEOUS_CLIPRECTS) { - ret = r300_emit_cliprects(dev_priv, cmdbuf, 0); - if (ret) - goto cleanup; - } - - while (drm_buffer_unprocessed(cmdbuf->buffer) - >= sizeof(drm_r300_cmd_header_t)) { - int idx; - drm_r300_cmd_header_t *header, stack_header; - - header = drm_buffer_read_object(cmdbuf->buffer, - sizeof(stack_header), &stack_header); - - switch (header->header.cmd_type) { - case R300_CMD_PACKET0: - DRM_DEBUG("R300_CMD_PACKET0\n"); - ret = r300_emit_packet0(dev_priv, cmdbuf, *header); - if (ret) { - DRM_ERROR("r300_emit_packet0 failed\n"); - goto cleanup; - } - break; - - case R300_CMD_VPU: - DRM_DEBUG("R300_CMD_VPU\n"); - ret = r300_emit_vpu(dev_priv, cmdbuf, *header); - if (ret) { - DRM_ERROR("r300_emit_vpu failed\n"); - goto cleanup; - } - break; - - case R300_CMD_PACKET3: - DRM_DEBUG("R300_CMD_PACKET3\n"); - ret = r300_emit_packet3(dev_priv, cmdbuf, *header); - if (ret) { - DRM_ERROR("r300_emit_packet3 failed\n"); - goto cleanup; - } - break; - - case R300_CMD_END3D: - DRM_DEBUG("R300_CMD_END3D\n"); - /* TODO: - Ideally userspace driver should not need to issue this call, - i.e. the drm driver should issue it automatically and prevent - lockups. - - In practice, we do not understand why this call is needed and what - it does (except for some vague guesses that it has to do with cache - coherence) and so the user space driver does it. - - Once we are sure which uses prevent lockups the code could be moved - into the kernel and the userspace driver will not - need to use this command. - - Note that issuing this command does not hurt anything - except, possibly, performance */ - r300_pacify(dev_priv); - break; - - case R300_CMD_CP_DELAY: - /* simple enough, we can do it here */ - DRM_DEBUG("R300_CMD_CP_DELAY\n"); - { - int i; - RING_LOCALS; - - BEGIN_RING(header->delay.count); - for (i = 0; i < header->delay.count; i++) - OUT_RING(RADEON_CP_PACKET2); - ADVANCE_RING(); - } - break; - - case R300_CMD_DMA_DISCARD: - DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); - idx = header->dma.buf_idx; - if (idx < 0 || idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - idx, dma->buf_count - 1); - ret = -EINVAL; - goto cleanup; - } - - buf = dma->buflist[idx]; - if (buf->file_priv != file_priv || buf->pending) { - DRM_ERROR("bad buffer %p %p %d\n", - buf->file_priv, file_priv, - buf->pending); - ret = -EINVAL; - goto cleanup; - } - - emit_dispatch_age = 1; - r300_discard_buffer(dev, file_priv->master, buf); - break; - - case R300_CMD_WAIT: - DRM_DEBUG("R300_CMD_WAIT\n"); - r300_cmd_wait(dev_priv, *header); - break; - - case R300_CMD_SCRATCH: - DRM_DEBUG("R300_CMD_SCRATCH\n"); - ret = r300_scratch(dev_priv, cmdbuf, *header); - if (ret) { - DRM_ERROR("r300_scratch failed\n"); - goto cleanup; - } - break; - - case R300_CMD_R500FP: - if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV515) { - DRM_ERROR("Calling r500 command on r300 card\n"); - ret = -EINVAL; - goto cleanup; - } - DRM_DEBUG("R300_CMD_R500FP\n"); - ret = r300_emit_r500fp(dev_priv, cmdbuf, *header); - if (ret) { - DRM_ERROR("r300_emit_r500fp failed\n"); - goto cleanup; - } - break; - default: - DRM_ERROR("bad cmd_type %i at byte %d\n", - header->header.cmd_type, - cmdbuf->buffer->iterator - (int)sizeof(*header)); - ret = -EINVAL; - goto cleanup; - } - } - - DRM_DEBUG("END\n"); - - cleanup: - r300_pacify(dev_priv); - - /* We emit the vertex buffer age here, outside the pacifier "brackets" - * for two reasons: - * (1) This may coalesce multiple age emissions into a single one and - * (2) more importantly, some chips lock up hard when scratch registers - * are written inside the pacifier bracket. - */ - if (emit_dispatch_age) { - RING_LOCALS; - - /* Emit the vertex buffer age */ - BEGIN_RING(2); - RADEON_DISPATCH_AGE(master_priv->sarea_priv->last_dispatch); - ADVANCE_RING(); - } - - COMMIT_RING(); - - return ret; -} diff --git a/drivers/gpu/drm/radeon/r600_blit.c b/drivers/gpu/drm/radeon/r600_blit.c deleted file mode 100644 index daf7572be976..000000000000 --- a/drivers/gpu/drm/radeon/r600_blit.c +++ /dev/null @@ -1,874 +0,0 @@ -/* - * Copyright 2009 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 (including the next - * paragraph) 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) AND/OR ITS SUPPLIERS 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 <alexander.deucher@amd.com> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" - -#include "r600_blit_shaders.h" - -/* 23 bits of float fractional data */ -#define I2F_FRAC_BITS 23 -#define I2F_MASK ((1 << I2F_FRAC_BITS) - 1) - -/* - * Converts unsigned integer into 32-bit IEEE floating point representation. - * Will be exact from 0 to 2^24. Above that, we round towards zero - * as the fractional bits will not fit in a float. (It would be better to - * round towards even as the fpu does, but that is slower.) - */ -static __pure uint32_t int2float(uint32_t x) -{ - uint32_t msb, exponent, fraction; - - /* Zero is special */ - if (!x) return 0; - - /* Get location of the most significant bit */ - msb = __fls(x); - - /* - * Use a rotate instead of a shift because that works both leftwards - * and rightwards due to the mod(32) behaviour. This means we don't - * need to check to see if we are above 2^24 or not. - */ - fraction = ror32(x, (msb - I2F_FRAC_BITS) & 0x1f) & I2F_MASK; - exponent = (127 + msb) << I2F_FRAC_BITS; - - return fraction + exponent; -} - -#define DI_PT_RECTLIST 0x11 -#define DI_INDEX_SIZE_16_BIT 0x0 -#define DI_SRC_SEL_AUTO_INDEX 0x2 - -#define FMT_8 0x1 -#define FMT_5_6_5 0x8 -#define FMT_8_8_8_8 0x1a -#define COLOR_8 0x1 -#define COLOR_5_6_5 0x8 -#define COLOR_8_8_8_8 0x1a - -static void -set_render_target(drm_radeon_private_t *dev_priv, int format, int w, int h, u64 gpu_addr) -{ - u32 cb_color_info; - int pitch, slice; - RING_LOCALS; - DRM_DEBUG("\n"); - - h = ALIGN(h, 8); - if (h < 8) - h = 8; - - cb_color_info = ((format << 2) | (1 << 27)); - pitch = (w / 8) - 1; - slice = ((w * h) / 64) - 1; - - if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600) && - ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) { - BEGIN_RING(21 + 2); - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(gpu_addr >> 8); - OUT_RING(CP_PACKET3(R600_IT_SURFACE_BASE_UPDATE, 0)); - OUT_RING(2 << 0); - } else { - BEGIN_RING(21); - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_BASE - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(gpu_addr >> 8); - } - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_SIZE - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING((pitch << 0) | (slice << 10)); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_VIEW - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_INFO - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(cb_color_info); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_TILE - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_FRAG - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_CB_COLOR0_MASK - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - - ADVANCE_RING(); -} - -static void -cp_set_surface_sync(drm_radeon_private_t *dev_priv, - u32 sync_type, u32 size, u64 mc_addr) -{ - u32 cp_coher_size; - RING_LOCALS; - DRM_DEBUG("\n"); - - if (size == 0xffffffff) - cp_coher_size = 0xffffffff; - else - cp_coher_size = ((size + 255) >> 8); - - BEGIN_RING(5); - OUT_RING(CP_PACKET3(R600_IT_SURFACE_SYNC, 3)); - OUT_RING(sync_type); - OUT_RING(cp_coher_size); - OUT_RING((mc_addr >> 8)); - OUT_RING(10); /* poll interval */ - ADVANCE_RING(); -} - -static void -set_shaders(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - u64 gpu_addr; - int i; - u32 *vs, *ps; - uint32_t sq_pgm_resources; - RING_LOCALS; - DRM_DEBUG("\n"); - - /* load shaders */ - vs = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset); - ps = (u32 *) ((char *)dev->agp_buffer_map->handle + dev_priv->blit_vb->offset + 256); - - for (i = 0; i < r6xx_vs_size; i++) - vs[i] = cpu_to_le32(r6xx_vs[i]); - for (i = 0; i < r6xx_ps_size; i++) - ps[i] = cpu_to_le32(r6xx_ps[i]); - - dev_priv->blit_vb->used = 512; - - gpu_addr = dev_priv->gart_buffers_offset + dev_priv->blit_vb->offset; - - /* setup shader regs */ - sq_pgm_resources = (1 << 0); - - BEGIN_RING(9 + 12); - /* VS */ - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_START_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(gpu_addr >> 8); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_RESOURCES_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(sq_pgm_resources); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_CF_OFFSET_VS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - - /* PS */ - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_START_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING((gpu_addr + 256) >> 8); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_RESOURCES_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(sq_pgm_resources | (1 << 28)); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_EXPORTS_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(2); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 1)); - OUT_RING((R600_SQ_PGM_CF_OFFSET_PS - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING(0); - ADVANCE_RING(); - - cp_set_surface_sync(dev_priv, - R600_SH_ACTION_ENA, 512, gpu_addr); -} - -static void -set_vtx_resource(drm_radeon_private_t *dev_priv, u64 gpu_addr) -{ - uint32_t sq_vtx_constant_word2; - RING_LOCALS; - DRM_DEBUG("\n"); - - sq_vtx_constant_word2 = (((gpu_addr >> 32) & 0xff) | (16 << 8)); -#ifdef __BIG_ENDIAN - sq_vtx_constant_word2 |= (2 << 30); -#endif - - BEGIN_RING(9); - OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); - OUT_RING(0x460); - OUT_RING(gpu_addr & 0xffffffff); - OUT_RING(48 - 1); - OUT_RING(sq_vtx_constant_word2); - OUT_RING(1 << 0); - OUT_RING(0); - OUT_RING(0); - OUT_RING(R600_SQ_TEX_VTX_VALID_BUFFER << 30); - ADVANCE_RING(); - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) - cp_set_surface_sync(dev_priv, - R600_TC_ACTION_ENA, 48, gpu_addr); - else - cp_set_surface_sync(dev_priv, - R600_VC_ACTION_ENA, 48, gpu_addr); -} - -static void -set_tex_resource(drm_radeon_private_t *dev_priv, - int format, int w, int h, int pitch, u64 gpu_addr) -{ - uint32_t sq_tex_resource_word0, sq_tex_resource_word1, sq_tex_resource_word4; - RING_LOCALS; - DRM_DEBUG("\n"); - - if (h < 1) - h = 1; - - sq_tex_resource_word0 = (1 << 0); - sq_tex_resource_word0 |= ((((pitch >> 3) - 1) << 8) | - ((w - 1) << 19)); - - sq_tex_resource_word1 = (format << 26); - sq_tex_resource_word1 |= ((h - 1) << 0); - - sq_tex_resource_word4 = ((1 << 14) | - (0 << 16) | - (1 << 19) | - (2 << 22) | - (3 << 25)); - - BEGIN_RING(9); - OUT_RING(CP_PACKET3(R600_IT_SET_RESOURCE, 7)); - OUT_RING(0); - OUT_RING(sq_tex_resource_word0); - OUT_RING(sq_tex_resource_word1); - OUT_RING(gpu_addr >> 8); - OUT_RING(gpu_addr >> 8); - OUT_RING(sq_tex_resource_word4); - OUT_RING(0); - OUT_RING(R600_SQ_TEX_VTX_VALID_TEXTURE << 30); - ADVANCE_RING(); - -} - -static void -set_scissors(drm_radeon_private_t *dev_priv, int x1, int y1, int x2, int y2) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(12); - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); - OUT_RING((R600_PA_SC_SCREEN_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING((x1 << 0) | (y1 << 16)); - OUT_RING((x2 << 0) | (y2 << 16)); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); - OUT_RING((R600_PA_SC_GENERIC_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31)); - OUT_RING((x2 << 0) | (y2 << 16)); - - OUT_RING(CP_PACKET3(R600_IT_SET_CONTEXT_REG, 2)); - OUT_RING((R600_PA_SC_WINDOW_SCISSOR_TL - R600_SET_CONTEXT_REG_OFFSET) >> 2); - OUT_RING((x1 << 0) | (y1 << 16) | (1 << 31)); - OUT_RING((x2 << 0) | (y2 << 16)); - ADVANCE_RING(); -} - -static void -draw_auto(drm_radeon_private_t *dev_priv) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(10); - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); - OUT_RING((R600_VGT_PRIMITIVE_TYPE - R600_SET_CONFIG_REG_OFFSET) >> 2); - OUT_RING(DI_PT_RECTLIST); - - OUT_RING(CP_PACKET3(R600_IT_INDEX_TYPE, 0)); -#ifdef __BIG_ENDIAN - OUT_RING((2 << 2) | DI_INDEX_SIZE_16_BIT); -#else - OUT_RING(DI_INDEX_SIZE_16_BIT); -#endif - - OUT_RING(CP_PACKET3(R600_IT_NUM_INSTANCES, 0)); - OUT_RING(1); - - OUT_RING(CP_PACKET3(R600_IT_DRAW_INDEX_AUTO, 1)); - OUT_RING(3); - OUT_RING(DI_SRC_SEL_AUTO_INDEX); - - ADVANCE_RING(); - COMMIT_RING(); -} - -static void -set_default_state(drm_radeon_private_t *dev_priv) -{ - int i; - u32 sq_config, sq_gpr_resource_mgmt_1, sq_gpr_resource_mgmt_2; - u32 sq_thread_resource_mgmt, sq_stack_resource_mgmt_1, sq_stack_resource_mgmt_2; - int num_ps_gprs, num_vs_gprs, num_temp_gprs, num_gs_gprs, num_es_gprs; - int num_ps_threads, num_vs_threads, num_gs_threads, num_es_threads; - int num_ps_stack_entries, num_vs_stack_entries, num_gs_stack_entries, num_es_stack_entries; - RING_LOCALS; - - switch ((dev_priv->flags & RADEON_FAMILY_MASK)) { - case CHIP_R600: - num_ps_gprs = 192; - num_vs_gprs = 56; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 136; - num_vs_threads = 48; - num_gs_threads = 4; - num_es_threads = 4; - num_ps_stack_entries = 128; - num_vs_stack_entries = 128; - num_gs_stack_entries = 0; - num_es_stack_entries = 0; - break; - case CHIP_RV630: - case CHIP_RV635: - num_ps_gprs = 84; - num_vs_gprs = 36; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 144; - num_vs_threads = 40; - num_gs_threads = 4; - num_es_threads = 4; - num_ps_stack_entries = 40; - num_vs_stack_entries = 40; - num_gs_stack_entries = 32; - num_es_stack_entries = 16; - break; - case CHIP_RV610: - case CHIP_RV620: - case CHIP_RS780: - case CHIP_RS880: - default: - num_ps_gprs = 84; - num_vs_gprs = 36; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 136; - num_vs_threads = 48; - num_gs_threads = 4; - num_es_threads = 4; - num_ps_stack_entries = 40; - num_vs_stack_entries = 40; - num_gs_stack_entries = 32; - num_es_stack_entries = 16; - break; - case CHIP_RV670: - num_ps_gprs = 144; - num_vs_gprs = 40; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 136; - num_vs_threads = 48; - num_gs_threads = 4; - num_es_threads = 4; - num_ps_stack_entries = 40; - num_vs_stack_entries = 40; - num_gs_stack_entries = 32; - num_es_stack_entries = 16; - break; - case CHIP_RV770: - num_ps_gprs = 192; - num_vs_gprs = 56; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 188; - num_vs_threads = 60; - num_gs_threads = 0; - num_es_threads = 0; - num_ps_stack_entries = 256; - num_vs_stack_entries = 256; - num_gs_stack_entries = 0; - num_es_stack_entries = 0; - break; - case CHIP_RV730: - case CHIP_RV740: - num_ps_gprs = 84; - num_vs_gprs = 36; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 188; - num_vs_threads = 60; - num_gs_threads = 0; - num_es_threads = 0; - num_ps_stack_entries = 128; - num_vs_stack_entries = 128; - num_gs_stack_entries = 0; - num_es_stack_entries = 0; - break; - case CHIP_RV710: - num_ps_gprs = 192; - num_vs_gprs = 56; - num_temp_gprs = 4; - num_gs_gprs = 0; - num_es_gprs = 0; - num_ps_threads = 144; - num_vs_threads = 48; - num_gs_threads = 0; - num_es_threads = 0; - num_ps_stack_entries = 128; - num_vs_stack_entries = 128; - num_gs_stack_entries = 0; - num_es_stack_entries = 0; - break; - } - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710)) - sq_config = 0; - else - sq_config = R600_VC_ENABLE; - - sq_config |= (R600_DX9_CONSTS | - R600_ALU_INST_PREFER_VECTOR | - R600_PS_PRIO(0) | - R600_VS_PRIO(1) | - R600_GS_PRIO(2) | - R600_ES_PRIO(3)); - - sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(num_ps_gprs) | - R600_NUM_VS_GPRS(num_vs_gprs) | - R600_NUM_CLAUSE_TEMP_GPRS(num_temp_gprs)); - sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(num_gs_gprs) | - R600_NUM_ES_GPRS(num_es_gprs)); - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(num_ps_threads) | - R600_NUM_VS_THREADS(num_vs_threads) | - R600_NUM_GS_THREADS(num_gs_threads) | - R600_NUM_ES_THREADS(num_es_threads)); - sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(num_ps_stack_entries) | - R600_NUM_VS_STACK_ENTRIES(num_vs_stack_entries)); - sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(num_gs_stack_entries) | - R600_NUM_ES_STACK_ENTRIES(num_es_stack_entries)); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { - BEGIN_RING(r7xx_default_size + 10); - for (i = 0; i < r7xx_default_size; i++) - OUT_RING(r7xx_default_state[i]); - } else { - BEGIN_RING(r6xx_default_size + 10); - for (i = 0; i < r6xx_default_size; i++) - OUT_RING(r6xx_default_state[i]); - } - OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); - OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); - /* SQ config */ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 6)); - OUT_RING((R600_SQ_CONFIG - R600_SET_CONFIG_REG_OFFSET) >> 2); - OUT_RING(sq_config); - OUT_RING(sq_gpr_resource_mgmt_1); - OUT_RING(sq_gpr_resource_mgmt_2); - OUT_RING(sq_thread_resource_mgmt); - OUT_RING(sq_stack_resource_mgmt_1); - OUT_RING(sq_stack_resource_mgmt_2); - ADVANCE_RING(); -} - -static int r600_nomm_get_vb(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - dev_priv->blit_vb = radeon_freelist_get(dev); - if (!dev_priv->blit_vb) { - DRM_ERROR("Unable to allocate vertex buffer for blit\n"); - return -EAGAIN; - } - return 0; -} - -static void r600_nomm_put_vb(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - dev_priv->blit_vb->used = 0; - radeon_cp_discard_buffer(dev, dev_priv->blit_vb->file_priv->master, dev_priv->blit_vb); -} - -static void *r600_nomm_get_vb_ptr(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - return (((char *)dev->agp_buffer_map->handle + - dev_priv->blit_vb->offset + dev_priv->blit_vb->used)); -} - -int -r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - int ret; - DRM_DEBUG("\n"); - - ret = r600_nomm_get_vb(dev); - if (ret) - return ret; - - dev_priv->blit_vb->file_priv = file_priv; - - set_default_state(dev_priv); - set_shaders(dev); - - return 0; -} - - -void -r600_done_blit_copy(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(5); - OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); - OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); - /* wait for 3D idle clean */ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); - OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2); - OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN); - - ADVANCE_RING(); - COMMIT_RING(); - - r600_nomm_put_vb(dev); -} - -void -r600_blit_copy(struct drm_device *dev, - uint64_t src_gpu_addr, uint64_t dst_gpu_addr, - int size_bytes) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - int max_bytes; - u64 vb_addr; - u32 *vb; - - vb = r600_nomm_get_vb_ptr(dev); - - if ((size_bytes & 3) || (src_gpu_addr & 3) || (dst_gpu_addr & 3)) { - max_bytes = 8192; - - while (size_bytes) { - int cur_size = size_bytes; - int src_x = src_gpu_addr & 255; - int dst_x = dst_gpu_addr & 255; - int h = 1; - src_gpu_addr = src_gpu_addr & ~255; - dst_gpu_addr = dst_gpu_addr & ~255; - - if (!src_x && !dst_x) { - h = (cur_size / max_bytes); - if (h > 8192) - h = 8192; - if (h == 0) - h = 1; - else - cur_size = max_bytes; - } else { - if (cur_size > max_bytes) - cur_size = max_bytes; - if (cur_size > (max_bytes - dst_x)) - cur_size = (max_bytes - dst_x); - if (cur_size > (max_bytes - src_x)) - cur_size = (max_bytes - src_x); - } - - if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { - - r600_nomm_put_vb(dev); - r600_nomm_get_vb(dev); - if (!dev_priv->blit_vb) - return; - set_shaders(dev); - vb = r600_nomm_get_vb_ptr(dev); - } - - vb[0] = int2float(dst_x); - vb[1] = 0; - vb[2] = int2float(src_x); - vb[3] = 0; - - vb[4] = int2float(dst_x); - vb[5] = int2float(h); - vb[6] = int2float(src_x); - vb[7] = int2float(h); - - vb[8] = int2float(dst_x + cur_size); - vb[9] = int2float(h); - vb[10] = int2float(src_x + cur_size); - vb[11] = int2float(h); - - /* src */ - set_tex_resource(dev_priv, FMT_8, - src_x + cur_size, h, src_x + cur_size, - src_gpu_addr); - - cp_set_surface_sync(dev_priv, - R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); - - /* dst */ - set_render_target(dev_priv, COLOR_8, - dst_x + cur_size, h, - dst_gpu_addr); - - /* scissors */ - set_scissors(dev_priv, dst_x, 0, dst_x + cur_size, h); - - /* Vertex buffer setup */ - vb_addr = dev_priv->gart_buffers_offset + - dev_priv->blit_vb->offset + - dev_priv->blit_vb->used; - set_vtx_resource(dev_priv, vb_addr); - - /* draw */ - draw_auto(dev_priv); - - cp_set_surface_sync(dev_priv, - R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, - cur_size * h, dst_gpu_addr); - - vb += 12; - dev_priv->blit_vb->used += 12 * 4; - - src_gpu_addr += cur_size * h; - dst_gpu_addr += cur_size * h; - size_bytes -= cur_size * h; - } - } else { - max_bytes = 8192 * 4; - - while (size_bytes) { - int cur_size = size_bytes; - int src_x = (src_gpu_addr & 255); - int dst_x = (dst_gpu_addr & 255); - int h = 1; - src_gpu_addr = src_gpu_addr & ~255; - dst_gpu_addr = dst_gpu_addr & ~255; - - if (!src_x && !dst_x) { - h = (cur_size / max_bytes); - if (h > 8192) - h = 8192; - if (h == 0) - h = 1; - else - cur_size = max_bytes; - } else { - if (cur_size > max_bytes) - cur_size = max_bytes; - if (cur_size > (max_bytes - dst_x)) - cur_size = (max_bytes - dst_x); - if (cur_size > (max_bytes - src_x)) - cur_size = (max_bytes - src_x); - } - - if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { - r600_nomm_put_vb(dev); - r600_nomm_get_vb(dev); - if (!dev_priv->blit_vb) - return; - - set_shaders(dev); - vb = r600_nomm_get_vb_ptr(dev); - } - - vb[0] = int2float(dst_x / 4); - vb[1] = 0; - vb[2] = int2float(src_x / 4); - vb[3] = 0; - - vb[4] = int2float(dst_x / 4); - vb[5] = int2float(h); - vb[6] = int2float(src_x / 4); - vb[7] = int2float(h); - - vb[8] = int2float((dst_x + cur_size) / 4); - vb[9] = int2float(h); - vb[10] = int2float((src_x + cur_size) / 4); - vb[11] = int2float(h); - - /* src */ - set_tex_resource(dev_priv, FMT_8_8_8_8, - (src_x + cur_size) / 4, - h, (src_x + cur_size) / 4, - src_gpu_addr); - - cp_set_surface_sync(dev_priv, - R600_TC_ACTION_ENA, (src_x + cur_size * h), src_gpu_addr); - - /* dst */ - set_render_target(dev_priv, COLOR_8_8_8_8, - (dst_x + cur_size) / 4, h, - dst_gpu_addr); - - /* scissors */ - set_scissors(dev_priv, (dst_x / 4), 0, (dst_x + cur_size / 4), h); - - /* Vertex buffer setup */ - vb_addr = dev_priv->gart_buffers_offset + - dev_priv->blit_vb->offset + - dev_priv->blit_vb->used; - set_vtx_resource(dev_priv, vb_addr); - - /* draw */ - draw_auto(dev_priv); - - cp_set_surface_sync(dev_priv, - R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, - cur_size * h, dst_gpu_addr); - - vb += 12; - dev_priv->blit_vb->used += 12 * 4; - - src_gpu_addr += cur_size * h; - dst_gpu_addr += cur_size * h; - size_bytes -= cur_size * h; - } - } -} - -void -r600_blit_swap(struct drm_device *dev, - uint64_t src_gpu_addr, uint64_t dst_gpu_addr, - int sx, int sy, int dx, int dy, - int w, int h, int src_pitch, int dst_pitch, int cpp) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - int cb_format, tex_format; - int sx2, sy2, dx2, dy2; - u64 vb_addr; - u32 *vb; - - if ((dev_priv->blit_vb->used + 48) > dev_priv->blit_vb->total) { - - r600_nomm_put_vb(dev); - r600_nomm_get_vb(dev); - if (!dev_priv->blit_vb) - return; - - set_shaders(dev); - } - vb = r600_nomm_get_vb_ptr(dev); - - sx2 = sx + w; - sy2 = sy + h; - dx2 = dx + w; - dy2 = dy + h; - - vb[0] = int2float(dx); - vb[1] = int2float(dy); - vb[2] = int2float(sx); - vb[3] = int2float(sy); - - vb[4] = int2float(dx); - vb[5] = int2float(dy2); - vb[6] = int2float(sx); - vb[7] = int2float(sy2); - - vb[8] = int2float(dx2); - vb[9] = int2float(dy2); - vb[10] = int2float(sx2); - vb[11] = int2float(sy2); - - switch(cpp) { - case 4: - cb_format = COLOR_8_8_8_8; - tex_format = FMT_8_8_8_8; - break; - case 2: - cb_format = COLOR_5_6_5; - tex_format = FMT_5_6_5; - break; - default: - cb_format = COLOR_8; - tex_format = FMT_8; - break; - } - - /* src */ - set_tex_resource(dev_priv, tex_format, - src_pitch / cpp, - sy2, src_pitch / cpp, - src_gpu_addr); - - cp_set_surface_sync(dev_priv, - R600_TC_ACTION_ENA, src_pitch * sy2, src_gpu_addr); - - /* dst */ - set_render_target(dev_priv, cb_format, - dst_pitch / cpp, dy2, - dst_gpu_addr); - - /* scissors */ - set_scissors(dev_priv, dx, dy, dx2, dy2); - - /* Vertex buffer setup */ - vb_addr = dev_priv->gart_buffers_offset + - dev_priv->blit_vb->offset + - dev_priv->blit_vb->used; - set_vtx_resource(dev_priv, vb_addr); - - /* draw */ - draw_auto(dev_priv); - - cp_set_surface_sync(dev_priv, - R600_CB_ACTION_ENA | R600_CB0_DEST_BASE_ENA, - dst_pitch * dy2, dst_gpu_addr); - - dev_priv->blit_vb->used += 12 * 4; -} diff --git a/drivers/gpu/drm/radeon/r600_cp.c b/drivers/gpu/drm/radeon/r600_cp.c deleted file mode 100644 index e231eeafef23..000000000000 --- a/drivers/gpu/drm/radeon/r600_cp.c +++ /dev/null @@ -1,2660 +0,0 @@ -/* - * Copyright 2008-2009 Advanced Micro Devices, Inc. - * Copyright 2008 Red Hat 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 (including the next - * paragraph) 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) AND/OR ITS SUPPLIERS 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: - * Dave Airlie <airlied@redhat.com> - * Alex Deucher <alexander.deucher@amd.com> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <linux/module.h> - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" - -#define PFP_UCODE_SIZE 576 -#define PM4_UCODE_SIZE 1792 -#define R700_PFP_UCODE_SIZE 848 -#define R700_PM4_UCODE_SIZE 1360 - -/* Firmware Names */ -MODULE_FIRMWARE("radeon/R600_pfp.bin"); -MODULE_FIRMWARE("radeon/R600_me.bin"); -MODULE_FIRMWARE("radeon/RV610_pfp.bin"); -MODULE_FIRMWARE("radeon/RV610_me.bin"); -MODULE_FIRMWARE("radeon/RV630_pfp.bin"); -MODULE_FIRMWARE("radeon/RV630_me.bin"); -MODULE_FIRMWARE("radeon/RV620_pfp.bin"); -MODULE_FIRMWARE("radeon/RV620_me.bin"); -MODULE_FIRMWARE("radeon/RV635_pfp.bin"); -MODULE_FIRMWARE("radeon/RV635_me.bin"); -MODULE_FIRMWARE("radeon/RV670_pfp.bin"); -MODULE_FIRMWARE("radeon/RV670_me.bin"); -MODULE_FIRMWARE("radeon/RS780_pfp.bin"); -MODULE_FIRMWARE("radeon/RS780_me.bin"); -MODULE_FIRMWARE("radeon/RV770_pfp.bin"); -MODULE_FIRMWARE("radeon/RV770_me.bin"); -MODULE_FIRMWARE("radeon/RV730_pfp.bin"); -MODULE_FIRMWARE("radeon/RV730_me.bin"); -MODULE_FIRMWARE("radeon/RV710_pfp.bin"); -MODULE_FIRMWARE("radeon/RV710_me.bin"); - - -int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, - unsigned family, u32 *ib, int *l); -void r600_cs_legacy_init(void); - - -# define ATI_PCIGART_PAGE_SIZE 4096 /**< PCI GART page size */ -# define ATI_PCIGART_PAGE_MASK (~(ATI_PCIGART_PAGE_SIZE-1)) - -#define R600_PTE_VALID (1 << 0) -#define R600_PTE_SYSTEM (1 << 1) -#define R600_PTE_SNOOPED (1 << 2) -#define R600_PTE_READABLE (1 << 5) -#define R600_PTE_WRITEABLE (1 << 6) - -/* MAX values used for gfx init */ -#define R6XX_MAX_SH_GPRS 256 -#define R6XX_MAX_TEMP_GPRS 16 -#define R6XX_MAX_SH_THREADS 256 -#define R6XX_MAX_SH_STACK_ENTRIES 4096 -#define R6XX_MAX_BACKENDS 8 -#define R6XX_MAX_BACKENDS_MASK 0xff -#define R6XX_MAX_SIMDS 8 -#define R6XX_MAX_SIMDS_MASK 0xff -#define R6XX_MAX_PIPES 8 -#define R6XX_MAX_PIPES_MASK 0xff - -#define R7XX_MAX_SH_GPRS 256 -#define R7XX_MAX_TEMP_GPRS 16 -#define R7XX_MAX_SH_THREADS 256 -#define R7XX_MAX_SH_STACK_ENTRIES 4096 -#define R7XX_MAX_BACKENDS 8 -#define R7XX_MAX_BACKENDS_MASK 0xff -#define R7XX_MAX_SIMDS 16 -#define R7XX_MAX_SIMDS_MASK 0xffff -#define R7XX_MAX_PIPES 8 -#define R7XX_MAX_PIPES_MASK 0xff - -static int r600_do_wait_for_fifo(drm_radeon_private_t *dev_priv, int entries) -{ - int i; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - int slots; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) - slots = (RADEON_READ(R600_GRBM_STATUS) - & R700_CMDFIFO_AVAIL_MASK); - else - slots = (RADEON_READ(R600_GRBM_STATUS) - & R600_CMDFIFO_AVAIL_MASK); - if (slots >= entries) - return 0; - DRM_UDELAY(1); - } - DRM_INFO("wait for fifo failed status : 0x%08X 0x%08X\n", - RADEON_READ(R600_GRBM_STATUS), - RADEON_READ(R600_GRBM_STATUS2)); - - return -EBUSY; -} - -static int r600_do_wait_for_idle(drm_radeon_private_t *dev_priv) -{ - int i, ret; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) - ret = r600_do_wait_for_fifo(dev_priv, 8); - else - ret = r600_do_wait_for_fifo(dev_priv, 16); - if (ret) - return ret; - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(RADEON_READ(R600_GRBM_STATUS) & R600_GUI_ACTIVE)) - return 0; - DRM_UDELAY(1); - } - DRM_INFO("wait idle failed status : 0x%08X 0x%08X\n", - RADEON_READ(R600_GRBM_STATUS), - RADEON_READ(R600_GRBM_STATUS2)); - - return -EBUSY; -} - -void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info) -{ - struct drm_sg_mem *entry = dev->sg; - int max_pages; - int pages; - int i; - - if (!entry) - return; - - if (gart_info->bus_addr) { - max_pages = (gart_info->table_size / sizeof(u64)); - pages = (entry->pages <= max_pages) - ? entry->pages : max_pages; - - for (i = 0; i < pages; i++) { - if (!entry->busaddr[i]) - break; - pci_unmap_page(dev->pdev, entry->busaddr[i], - PAGE_SIZE, PCI_DMA_BIDIRECTIONAL); - } - if (gart_info->gart_table_location == DRM_ATI_GART_MAIN) - gart_info->bus_addr = 0; - } -} - -/* R600 has page table setup */ -int r600_page_table_init(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info; - struct drm_local_map *map = &gart_info->mapping; - struct drm_sg_mem *entry = dev->sg; - int ret = 0; - int i, j; - int pages; - u64 page_base; - dma_addr_t entry_addr; - int max_ati_pages, max_real_pages, gart_idx; - - /* okay page table is available - lets rock */ - max_ati_pages = (gart_info->table_size / sizeof(u64)); - max_real_pages = max_ati_pages / (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); - - pages = (entry->pages <= max_real_pages) ? - entry->pages : max_real_pages; - - memset_io((void __iomem *)map->handle, 0, max_ati_pages * sizeof(u64)); - - gart_idx = 0; - for (i = 0; i < pages; i++) { - entry->busaddr[i] = pci_map_page(dev->pdev, - entry->pagelist[i], 0, - PAGE_SIZE, - PCI_DMA_BIDIRECTIONAL); - if (pci_dma_mapping_error(dev->pdev, entry->busaddr[i])) { - DRM_ERROR("unable to map PCIGART pages!\n"); - r600_page_table_cleanup(dev, gart_info); - goto done; - } - entry_addr = entry->busaddr[i]; - for (j = 0; j < (PAGE_SIZE / ATI_PCIGART_PAGE_SIZE); j++) { - page_base = (u64) entry_addr & ATI_PCIGART_PAGE_MASK; - page_base |= R600_PTE_VALID | R600_PTE_SYSTEM | R600_PTE_SNOOPED; - page_base |= R600_PTE_READABLE | R600_PTE_WRITEABLE; - - DRM_WRITE64(map, gart_idx * sizeof(u64), page_base); - - gart_idx++; - - if ((i % 128) == 0) - DRM_DEBUG("page entry %d: 0x%016llx\n", - i, (unsigned long long)page_base); - entry_addr += ATI_PCIGART_PAGE_SIZE; - } - } - ret = 1; -done: - return ret; -} - -static void r600_vm_flush_gart_range(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - u32 resp, countdown = 1000; - RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR, dev_priv->gart_vm_start >> 12); - RADEON_WRITE(R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); - RADEON_WRITE(R600_VM_CONTEXT0_REQUEST_RESPONSE, 2); - - do { - resp = RADEON_READ(R600_VM_CONTEXT0_REQUEST_RESPONSE); - countdown--; - DRM_UDELAY(1); - } while (((resp & 0xf0) == 0) && countdown); -} - -static void r600_vm_init(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - /* initialise the VM to use the page table we constructed up there */ - u32 vm_c0, i; - u32 mc_rd_a; - u32 vm_l2_cntl, vm_l2_cntl3; - /* okay set up the PCIE aperture type thingo */ - RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12); - RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); - RADEON_WRITE(R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); - - /* setup MC RD a */ - mc_rd_a = R600_MCD_L1_TLB | R600_MCD_L1_FRAG_PROC | R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS | - R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | R600_MCD_EFFECTIVE_L1_TLB_SIZE(5) | - R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(5) | R600_MCD_WAIT_L2_QUERY; - - RADEON_WRITE(R600_MCD_RD_A_CNTL, mc_rd_a); - RADEON_WRITE(R600_MCD_RD_B_CNTL, mc_rd_a); - - RADEON_WRITE(R600_MCD_WR_A_CNTL, mc_rd_a); - RADEON_WRITE(R600_MCD_WR_B_CNTL, mc_rd_a); - - RADEON_WRITE(R600_MCD_RD_GFX_CNTL, mc_rd_a); - RADEON_WRITE(R600_MCD_WR_GFX_CNTL, mc_rd_a); - - RADEON_WRITE(R600_MCD_RD_SYS_CNTL, mc_rd_a); - RADEON_WRITE(R600_MCD_WR_SYS_CNTL, mc_rd_a); - - RADEON_WRITE(R600_MCD_RD_HDP_CNTL, mc_rd_a | R600_MCD_L1_STRICT_ORDERING); - RADEON_WRITE(R600_MCD_WR_HDP_CNTL, mc_rd_a /*| R600_MCD_L1_STRICT_ORDERING*/); - - RADEON_WRITE(R600_MCD_RD_PDMA_CNTL, mc_rd_a); - RADEON_WRITE(R600_MCD_WR_PDMA_CNTL, mc_rd_a); - - RADEON_WRITE(R600_MCD_RD_SEM_CNTL, mc_rd_a | R600_MCD_SEMAPHORE_MODE); - RADEON_WRITE(R600_MCD_WR_SEM_CNTL, mc_rd_a); - - vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W; - vm_l2_cntl |= R600_VM_L2_CNTL_QUEUE_SIZE(7); - RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl); - - RADEON_WRITE(R600_VM_L2_CNTL2, 0); - vm_l2_cntl3 = (R600_VM_L2_CNTL3_BANK_SELECT_0(0) | - R600_VM_L2_CNTL3_BANK_SELECT_1(1) | - R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(2)); - RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3); - - vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT; - - RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0); - - vm_c0 &= ~R600_VM_ENABLE_CONTEXT; - - /* disable all other contexts */ - for (i = 1; i < 8; i++) - RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0); - - RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12); - RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12); - RADEON_WRITE(R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); - - r600_vm_flush_gart_range(dev); -} - -static int r600_cp_init_microcode(drm_radeon_private_t *dev_priv) -{ - struct platform_device *pdev; - const char *chip_name; - size_t pfp_req_size, me_req_size; - char fw_name[30]; - int err; - - pdev = platform_device_register_simple("r600_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "r600_cp: Failed to register firmware\n"); - return -EINVAL; - } - - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_R600: chip_name = "R600"; break; - case CHIP_RV610: chip_name = "RV610"; break; - case CHIP_RV630: chip_name = "RV630"; break; - case CHIP_RV620: chip_name = "RV620"; break; - case CHIP_RV635: chip_name = "RV635"; break; - case CHIP_RV670: chip_name = "RV670"; break; - case CHIP_RS780: - case CHIP_RS880: chip_name = "RS780"; break; - case CHIP_RV770: chip_name = "RV770"; break; - case CHIP_RV730: - case CHIP_RV740: chip_name = "RV730"; break; - case CHIP_RV710: chip_name = "RV710"; break; - default: BUG(); - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { - pfp_req_size = R700_PFP_UCODE_SIZE * 4; - me_req_size = R700_PM4_UCODE_SIZE * 4; - } else { - pfp_req_size = PFP_UCODE_SIZE * 4; - me_req_size = PM4_UCODE_SIZE * 12; - } - - DRM_INFO("Loading %s CP Microcode\n", chip_name); - - snprintf(fw_name, sizeof(fw_name), "radeon/%s_pfp.bin", chip_name); - err = request_firmware(&dev_priv->pfp_fw, fw_name, &pdev->dev); - if (err) - goto out; - if (dev_priv->pfp_fw->size != pfp_req_size) { - printk(KERN_ERR - "r600_cp: Bogus length %zu in firmware \"%s\"\n", - dev_priv->pfp_fw->size, fw_name); - err = -EINVAL; - goto out; - } - - snprintf(fw_name, sizeof(fw_name), "radeon/%s_me.bin", chip_name); - err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev); - if (err) - goto out; - if (dev_priv->me_fw->size != me_req_size) { - printk(KERN_ERR - "r600_cp: Bogus length %zu in firmware \"%s\"\n", - dev_priv->me_fw->size, fw_name); - err = -EINVAL; - } -out: - platform_device_unregister(pdev); - - if (err) { - if (err != -EINVAL) - printk(KERN_ERR - "r600_cp: Failed to load firmware \"%s\"\n", - fw_name); - release_firmware(dev_priv->pfp_fw); - dev_priv->pfp_fw = NULL; - release_firmware(dev_priv->me_fw); - dev_priv->me_fw = NULL; - } - return err; -} - -static void r600_cp_load_microcode(drm_radeon_private_t *dev_priv) -{ - const __be32 *fw_data; - int i; - - if (!dev_priv->me_fw || !dev_priv->pfp_fw) - return; - - r600_do_cp_stop(dev_priv); - - RADEON_WRITE(R600_CP_RB_CNTL, -#ifdef __BIG_ENDIAN - R600_BUF_SWAP_32BIT | -#endif - R600_RB_NO_UPDATE | - R600_RB_BLKSZ(15) | - R600_RB_BUFSZ(3)); - - RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); - RADEON_READ(R600_GRBM_SOFT_RESET); - mdelay(15); - RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); - - fw_data = (const __be32 *)dev_priv->me_fw->data; - RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); - for (i = 0; i < PM4_UCODE_SIZE * 3; i++) - RADEON_WRITE(R600_CP_ME_RAM_DATA, - be32_to_cpup(fw_data++)); - - fw_data = (const __be32 *)dev_priv->pfp_fw->data; - RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); - for (i = 0; i < PFP_UCODE_SIZE; i++) - RADEON_WRITE(R600_CP_PFP_UCODE_DATA, - be32_to_cpup(fw_data++)); - - RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); - RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); - RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); - -} - -static void r700_vm_init(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - /* initialise the VM to use the page table we constructed up there */ - u32 vm_c0, i; - u32 mc_vm_md_l1; - u32 vm_l2_cntl, vm_l2_cntl3; - /* okay set up the PCIE aperture type thingo */ - RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR, dev_priv->gart_vm_start >> 12); - RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); - RADEON_WRITE(R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR, 0); - - mc_vm_md_l1 = R700_ENABLE_L1_TLB | - R700_ENABLE_L1_FRAGMENT_PROCESSING | - R700_SYSTEM_ACCESS_MODE_IN_SYS | - R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU | - R700_EFFECTIVE_L1_TLB_SIZE(5) | - R700_EFFECTIVE_L1_QUEUE_SIZE(5); - - RADEON_WRITE(R700_MC_VM_MD_L1_TLB0_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MD_L1_TLB1_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MD_L1_TLB2_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MB_L1_TLB0_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MB_L1_TLB1_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MB_L1_TLB2_CNTL, mc_vm_md_l1); - RADEON_WRITE(R700_MC_VM_MB_L1_TLB3_CNTL, mc_vm_md_l1); - - vm_l2_cntl = R600_VM_L2_CACHE_EN | R600_VM_L2_FRAG_PROC | R600_VM_ENABLE_PTE_CACHE_LRU_W; - vm_l2_cntl |= R700_VM_L2_CNTL_QUEUE_SIZE(7); - RADEON_WRITE(R600_VM_L2_CNTL, vm_l2_cntl); - - RADEON_WRITE(R600_VM_L2_CNTL2, 0); - vm_l2_cntl3 = R700_VM_L2_CNTL3_BANK_SELECT(0) | R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(2); - RADEON_WRITE(R600_VM_L2_CNTL3, vm_l2_cntl3); - - vm_c0 = R600_VM_ENABLE_CONTEXT | R600_VM_PAGE_TABLE_DEPTH_FLAT; - - RADEON_WRITE(R600_VM_CONTEXT0_CNTL, vm_c0); - - vm_c0 &= ~R600_VM_ENABLE_CONTEXT; - - /* disable all other contexts */ - for (i = 1; i < 8; i++) - RADEON_WRITE(R600_VM_CONTEXT0_CNTL + (i * 4), vm_c0); - - RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR, dev_priv->gart_info.bus_addr >> 12); - RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR, dev_priv->gart_vm_start >> 12); - RADEON_WRITE(R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR, (dev_priv->gart_vm_start + dev_priv->gart_size - 1) >> 12); - - r600_vm_flush_gart_range(dev); -} - -static void r700_cp_load_microcode(drm_radeon_private_t *dev_priv) -{ - const __be32 *fw_data; - int i; - - if (!dev_priv->me_fw || !dev_priv->pfp_fw) - return; - - r600_do_cp_stop(dev_priv); - - RADEON_WRITE(R600_CP_RB_CNTL, -#ifdef __BIG_ENDIAN - R600_BUF_SWAP_32BIT | -#endif - R600_RB_NO_UPDATE | - R600_RB_BLKSZ(15) | - R600_RB_BUFSZ(3)); - - RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); - RADEON_READ(R600_GRBM_SOFT_RESET); - mdelay(15); - RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); - - fw_data = (const __be32 *)dev_priv->pfp_fw->data; - RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); - for (i = 0; i < R700_PFP_UCODE_SIZE; i++) - RADEON_WRITE(R600_CP_PFP_UCODE_DATA, be32_to_cpup(fw_data++)); - RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); - - fw_data = (const __be32 *)dev_priv->me_fw->data; - RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); - for (i = 0; i < R700_PM4_UCODE_SIZE; i++) - RADEON_WRITE(R600_CP_ME_RAM_DATA, be32_to_cpup(fw_data++)); - RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); - - RADEON_WRITE(R600_CP_PFP_UCODE_ADDR, 0); - RADEON_WRITE(R600_CP_ME_RAM_WADDR, 0); - RADEON_WRITE(R600_CP_ME_RAM_RADDR, 0); - -} - -static void r600_test_writeback(drm_radeon_private_t *dev_priv) -{ - u32 tmp; - - /* Start with assuming that writeback doesn't work */ - dev_priv->writeback_works = 0; - - /* Writeback doesn't seem to work everywhere, test it here and possibly - * enable it if it appears to work - */ - radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0); - - RADEON_WRITE(R600_SCRATCH_REG1, 0xdeadbeef); - - for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { - u32 val; - - val = radeon_read_ring_rptr(dev_priv, R600_SCRATCHOFF(1)); - if (val == 0xdeadbeef) - break; - DRM_UDELAY(1); - } - - if (tmp < dev_priv->usec_timeout) { - dev_priv->writeback_works = 1; - DRM_INFO("writeback test succeeded in %d usecs\n", tmp); - } else { - dev_priv->writeback_works = 0; - DRM_INFO("writeback test failed\n"); - } - if (radeon_no_wb == 1) { - dev_priv->writeback_works = 0; - DRM_INFO("writeback forced off\n"); - } - - if (!dev_priv->writeback_works) { - /* Disable writeback to avoid unnecessary bus master transfer */ - RADEON_WRITE(R600_CP_RB_CNTL, -#ifdef __BIG_ENDIAN - R600_BUF_SWAP_32BIT | -#endif - RADEON_READ(R600_CP_RB_CNTL) | - R600_RB_NO_UPDATE); - RADEON_WRITE(R600_SCRATCH_UMSK, 0); - } -} - -int r600_do_engine_reset(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - u32 cp_ptr, cp_me_cntl, cp_rb_cntl; - - DRM_INFO("Resetting GPU\n"); - - cp_ptr = RADEON_READ(R600_CP_RB_WPTR); - cp_me_cntl = RADEON_READ(R600_CP_ME_CNTL); - RADEON_WRITE(R600_CP_ME_CNTL, R600_CP_ME_HALT); - - RADEON_WRITE(R600_GRBM_SOFT_RESET, 0x7fff); - RADEON_READ(R600_GRBM_SOFT_RESET); - DRM_UDELAY(50); - RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); - RADEON_READ(R600_GRBM_SOFT_RESET); - - RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0); - cp_rb_cntl = RADEON_READ(R600_CP_RB_CNTL); - RADEON_WRITE(R600_CP_RB_CNTL, -#ifdef __BIG_ENDIAN - R600_BUF_SWAP_32BIT | -#endif - R600_RB_RPTR_WR_ENA); - - RADEON_WRITE(R600_CP_RB_RPTR_WR, cp_ptr); - RADEON_WRITE(R600_CP_RB_WPTR, cp_ptr); - RADEON_WRITE(R600_CP_RB_CNTL, cp_rb_cntl); - RADEON_WRITE(R600_CP_ME_CNTL, cp_me_cntl); - - /* Reset the CP ring */ - r600_do_cp_reset(dev_priv); - - /* The CP is no longer running after an engine reset */ - dev_priv->cp_running = 0; - - /* Reset any pending vertex, indirect buffers */ - radeon_freelist_reset(dev); - - return 0; - -} - -static u32 r600_get_tile_pipe_to_backend_map(u32 num_tile_pipes, - u32 num_backends, - u32 backend_disable_mask) -{ - u32 backend_map = 0; - u32 enabled_backends_mask; - u32 enabled_backends_count; - u32 cur_pipe; - u32 swizzle_pipe[R6XX_MAX_PIPES]; - u32 cur_backend; - u32 i; - - if (num_tile_pipes > R6XX_MAX_PIPES) - num_tile_pipes = R6XX_MAX_PIPES; - if (num_tile_pipes < 1) - num_tile_pipes = 1; - if (num_backends > R6XX_MAX_BACKENDS) - num_backends = R6XX_MAX_BACKENDS; - if (num_backends < 1) - num_backends = 1; - - enabled_backends_mask = 0; - enabled_backends_count = 0; - for (i = 0; i < R6XX_MAX_BACKENDS; ++i) { - if (((backend_disable_mask >> i) & 1) == 0) { - enabled_backends_mask |= (1 << i); - ++enabled_backends_count; - } - if (enabled_backends_count == num_backends) - break; - } - - if (enabled_backends_count == 0) { - enabled_backends_mask = 1; - enabled_backends_count = 1; - } - - if (enabled_backends_count != num_backends) - num_backends = enabled_backends_count; - - memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R6XX_MAX_PIPES); - switch (num_tile_pipes) { - case 1: - swizzle_pipe[0] = 0; - break; - case 2: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - break; - case 3: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - break; - case 4: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - break; - case 5: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - swizzle_pipe[4] = 4; - break; - case 6: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 5; - swizzle_pipe[4] = 1; - swizzle_pipe[5] = 3; - break; - case 7: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 6; - swizzle_pipe[4] = 1; - swizzle_pipe[5] = 3; - swizzle_pipe[6] = 5; - break; - case 8: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 6; - swizzle_pipe[4] = 1; - swizzle_pipe[5] = 3; - swizzle_pipe[6] = 5; - swizzle_pipe[7] = 7; - break; - } - - cur_backend = 0; - for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { - while (((1 << cur_backend) & enabled_backends_mask) == 0) - cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; - - backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); - - cur_backend = (cur_backend + 1) % R6XX_MAX_BACKENDS; - } - - return backend_map; -} - -static int r600_count_pipe_bits(uint32_t val) -{ - return hweight32(val); -} - -static void r600_gfx_init(struct drm_device *dev, - drm_radeon_private_t *dev_priv) -{ - int i, j, num_qd_pipes; - u32 sx_debug_1; - u32 tc_cntl; - u32 arb_pop; - u32 num_gs_verts_per_thread; - u32 vgt_gs_per_es; - u32 gs_prim_buffer_depth = 0; - u32 sq_ms_fifo_sizes; - u32 sq_config; - u32 sq_gpr_resource_mgmt_1 = 0; - u32 sq_gpr_resource_mgmt_2 = 0; - u32 sq_thread_resource_mgmt = 0; - u32 sq_stack_resource_mgmt_1 = 0; - u32 sq_stack_resource_mgmt_2 = 0; - u32 hdp_host_path_cntl; - u32 backend_map; - u32 gb_tiling_config = 0; - u32 cc_rb_backend_disable; - u32 cc_gc_shader_pipe_config; - u32 ramcfg; - - /* setup chip specs */ - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_R600: - dev_priv->r600_max_pipes = 4; - dev_priv->r600_max_tile_pipes = 8; - dev_priv->r600_max_simds = 4; - dev_priv->r600_max_backends = 4; - dev_priv->r600_max_gprs = 256; - dev_priv->r600_max_threads = 192; - dev_priv->r600_max_stack_entries = 256; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 16; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 128; - dev_priv->r600_sq_num_cf_insts = 2; - break; - case CHIP_RV630: - case CHIP_RV635: - dev_priv->r600_max_pipes = 2; - dev_priv->r600_max_tile_pipes = 2; - dev_priv->r600_max_simds = 3; - dev_priv->r600_max_backends = 1; - dev_priv->r600_max_gprs = 128; - dev_priv->r600_max_threads = 192; - dev_priv->r600_max_stack_entries = 128; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 4; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 128; - dev_priv->r600_sq_num_cf_insts = 2; - break; - case CHIP_RV610: - case CHIP_RS780: - case CHIP_RS880: - case CHIP_RV620: - dev_priv->r600_max_pipes = 1; - dev_priv->r600_max_tile_pipes = 1; - dev_priv->r600_max_simds = 2; - dev_priv->r600_max_backends = 1; - dev_priv->r600_max_gprs = 128; - dev_priv->r600_max_threads = 192; - dev_priv->r600_max_stack_entries = 128; - dev_priv->r600_max_hw_contexts = 4; - dev_priv->r600_max_gs_threads = 4; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 128; - dev_priv->r600_sq_num_cf_insts = 1; - break; - case CHIP_RV670: - dev_priv->r600_max_pipes = 4; - dev_priv->r600_max_tile_pipes = 4; - dev_priv->r600_max_simds = 4; - dev_priv->r600_max_backends = 4; - dev_priv->r600_max_gprs = 192; - dev_priv->r600_max_threads = 192; - dev_priv->r600_max_stack_entries = 256; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 16; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 128; - dev_priv->r600_sq_num_cf_insts = 2; - break; - default: - break; - } - - /* Initialize HDP */ - j = 0; - for (i = 0; i < 32; i++) { - RADEON_WRITE((0x2c14 + j), 0x00000000); - RADEON_WRITE((0x2c18 + j), 0x00000000); - RADEON_WRITE((0x2c1c + j), 0x00000000); - RADEON_WRITE((0x2c20 + j), 0x00000000); - RADEON_WRITE((0x2c24 + j), 0x00000000); - j += 0x18; - } - - RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff)); - - /* setup tiling, simd, pipe config */ - ramcfg = RADEON_READ(R600_RAMCFG); - - switch (dev_priv->r600_max_tile_pipes) { - case 1: - gb_tiling_config |= R600_PIPE_TILING(0); - break; - case 2: - gb_tiling_config |= R600_PIPE_TILING(1); - break; - case 4: - gb_tiling_config |= R600_PIPE_TILING(2); - break; - case 8: - gb_tiling_config |= R600_PIPE_TILING(3); - break; - default: - break; - } - - gb_tiling_config |= R600_BANK_TILING((ramcfg >> R600_NOOFBANK_SHIFT) & R600_NOOFBANK_MASK); - - gb_tiling_config |= R600_GROUP_SIZE(0); - - if (((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK) > 3) { - gb_tiling_config |= R600_ROW_TILING(3); - gb_tiling_config |= R600_SAMPLE_SPLIT(3); - } else { - gb_tiling_config |= - R600_ROW_TILING(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK)); - gb_tiling_config |= - R600_SAMPLE_SPLIT(((ramcfg >> R600_NOOFROWS_SHIFT) & R600_NOOFROWS_MASK)); - } - - gb_tiling_config |= R600_BANK_SWAPS(1); - - cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000; - cc_rb_backend_disable |= - R600_BACKEND_DISABLE((R6XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R6XX_MAX_BACKENDS_MASK); - - cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; - cc_gc_shader_pipe_config |= - R600_INACTIVE_QD_PIPES((R6XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R6XX_MAX_PIPES_MASK); - cc_gc_shader_pipe_config |= - R600_INACTIVE_SIMDS((R6XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R6XX_MAX_SIMDS_MASK); - - backend_map = r600_get_tile_pipe_to_backend_map(dev_priv->r600_max_tile_pipes, - (R6XX_MAX_BACKENDS - - r600_count_pipe_bits((cc_rb_backend_disable & - R6XX_MAX_BACKENDS_MASK) >> 16)), - (cc_rb_backend_disable >> 16)); - gb_tiling_config |= R600_BACKEND_MAP(backend_map); - - RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config); - RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - if (gb_tiling_config & 0xc0) { - dev_priv->r600_group_size = 512; - } else { - dev_priv->r600_group_size = 256; - } - dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7); - if (gb_tiling_config & 0x30) { - dev_priv->r600_nbanks = 8; - } else { - dev_priv->r600_nbanks = 4; - } - - RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); - RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - - num_qd_pipes = - R6XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8); - RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK); - RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK); - - /* set HW defaults for 3D engine */ - RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) | - R600_ROQ_IB2_START(0x2b))); - - RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, (R600_MEQ_END(0x40) | - R600_ROQ_END(0x40))); - - RADEON_WRITE(R600_TA_CNTL_AUX, (R600_DISABLE_CUBE_ANISO | - R600_SYNC_GRADIENT | - R600_SYNC_WALKER | - R600_SYNC_ALIGNER)); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) - RADEON_WRITE(R600_ARB_GDEC_RD_CNTL, 0x00000021); - - sx_debug_1 = RADEON_READ(R600_SX_DEBUG_1); - sx_debug_1 |= R600_SMX_EVENT_RELEASE; - if (((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_R600)) - sx_debug_1 |= R600_ENABLE_NEW_SMX_ADDRESS; - RADEON_WRITE(R600_SX_DEBUG_1, sx_debug_1); - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) - RADEON_WRITE(R600_DB_DEBUG, R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE); - else - RADEON_WRITE(R600_DB_DEBUG, 0); - - RADEON_WRITE(R600_DB_WATERMARKS, (R600_DEPTH_FREE(4) | - R600_DEPTH_FLUSH(16) | - R600_DEPTH_PENDING_FREE(4) | - R600_DEPTH_CACHELINE_FREE(16))); - RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); - RADEON_WRITE(R600_VGT_NUM_INSTANCES, 0); - - RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0)); - RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(0)); - - sq_ms_fifo_sizes = RADEON_READ(R600_SQ_MS_FIFO_SIZES); - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) { - sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(0xa) | - R600_FETCH_FIFO_HIWATER(0xa) | - R600_DONE_FIFO_HIWATER(0xe0) | - R600_ALU_UPDATE_FIFO_HIWATER(0x8)); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630)) { - sq_ms_fifo_sizes &= ~R600_DONE_FIFO_HIWATER(0xff); - sq_ms_fifo_sizes |= R600_DONE_FIFO_HIWATER(0x4); - } - RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); - - /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT - * should be adjusted as needed by the 2D/3D drivers. This just sets default values - */ - sq_config = RADEON_READ(R600_SQ_CONFIG); - sq_config &= ~(R600_PS_PRIO(3) | - R600_VS_PRIO(3) | - R600_GS_PRIO(3) | - R600_ES_PRIO(3)); - sq_config |= (R600_DX9_CONSTS | - R600_VC_ENABLE | - R600_PS_PRIO(0) | - R600_VS_PRIO(1) | - R600_GS_PRIO(2) | - R600_ES_PRIO(3)); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R600) { - sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(124) | - R600_NUM_VS_GPRS(124) | - R600_NUM_CLAUSE_TEMP_GPRS(4)); - sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(0) | - R600_NUM_ES_GPRS(0)); - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(136) | - R600_NUM_VS_THREADS(48) | - R600_NUM_GS_THREADS(4) | - R600_NUM_ES_THREADS(4)); - sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(128) | - R600_NUM_VS_STACK_ENTRIES(128)); - sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(0) | - R600_NUM_ES_STACK_ENTRIES(0)); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) { - /* no vertex cache */ - sq_config &= ~R600_VC_ENABLE; - - sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | - R600_NUM_VS_GPRS(44) | - R600_NUM_CLAUSE_TEMP_GPRS(2)); - sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) | - R600_NUM_ES_GPRS(17)); - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | - R600_NUM_VS_THREADS(78) | - R600_NUM_GS_THREADS(4) | - R600_NUM_ES_THREADS(31)); - sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) | - R600_NUM_VS_STACK_ENTRIES(40)); - sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) | - R600_NUM_ES_STACK_ENTRIES(16)); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV630) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV635)) { - sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | - R600_NUM_VS_GPRS(44) | - R600_NUM_CLAUSE_TEMP_GPRS(2)); - sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(18) | - R600_NUM_ES_GPRS(18)); - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | - R600_NUM_VS_THREADS(78) | - R600_NUM_GS_THREADS(4) | - R600_NUM_ES_THREADS(31)); - sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(40) | - R600_NUM_VS_STACK_ENTRIES(40)); - sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(32) | - R600_NUM_ES_STACK_ENTRIES(16)); - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV670) { - sq_gpr_resource_mgmt_1 = (R600_NUM_PS_GPRS(44) | - R600_NUM_VS_GPRS(44) | - R600_NUM_CLAUSE_TEMP_GPRS(2)); - sq_gpr_resource_mgmt_2 = (R600_NUM_GS_GPRS(17) | - R600_NUM_ES_GPRS(17)); - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS(79) | - R600_NUM_VS_THREADS(78) | - R600_NUM_GS_THREADS(4) | - R600_NUM_ES_THREADS(31)); - sq_stack_resource_mgmt_1 = (R600_NUM_PS_STACK_ENTRIES(64) | - R600_NUM_VS_STACK_ENTRIES(64)); - sq_stack_resource_mgmt_2 = (R600_NUM_GS_STACK_ENTRIES(64) | - R600_NUM_ES_STACK_ENTRIES(64)); - } - - RADEON_WRITE(R600_SQ_CONFIG, sq_config); - RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1, sq_gpr_resource_mgmt_1); - RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2, sq_gpr_resource_mgmt_2); - RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); - RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, sq_stack_resource_mgmt_1); - RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, sq_stack_resource_mgmt_2); - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV610) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV620) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS780) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS880)) - RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_TC_ONLY)); - else - RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, R600_CACHE_INVALIDATION(R600_VC_AND_TC)); - - RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_2S, (R600_S0_X(0xc) | - R600_S0_Y(0x4) | - R600_S1_X(0x4) | - R600_S1_Y(0xc))); - RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_4S, (R600_S0_X(0xe) | - R600_S0_Y(0xe) | - R600_S1_X(0x2) | - R600_S1_Y(0x2) | - R600_S2_X(0xa) | - R600_S2_Y(0x6) | - R600_S3_X(0x6) | - R600_S3_Y(0xa))); - RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0, (R600_S0_X(0xe) | - R600_S0_Y(0xb) | - R600_S1_X(0x4) | - R600_S1_Y(0xc) | - R600_S2_X(0x1) | - R600_S2_Y(0x6) | - R600_S3_X(0xa) | - R600_S3_Y(0xe))); - RADEON_WRITE(R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1, (R600_S4_X(0x6) | - R600_S4_Y(0x1) | - R600_S5_X(0x0) | - R600_S5_Y(0x0) | - R600_S6_X(0xb) | - R600_S6_Y(0x4) | - R600_S7_X(0x7) | - R600_S7_Y(0x8))); - - - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_R600: - case CHIP_RV630: - case CHIP_RV635: - gs_prim_buffer_depth = 0; - break; - case CHIP_RV610: - case CHIP_RS780: - case CHIP_RS880: - case CHIP_RV620: - gs_prim_buffer_depth = 32; - break; - case CHIP_RV670: - gs_prim_buffer_depth = 128; - break; - default: - break; - } - - num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16; - vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; - /* Max value for this is 256 */ - if (vgt_gs_per_es > 256) - vgt_gs_per_es = 256; - - RADEON_WRITE(R600_VGT_ES_PER_GS, 128); - RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es); - RADEON_WRITE(R600_VGT_GS_PER_VS, 2); - RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16); - - /* more default values. 2D/3D driver should adjust as needed */ - RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0); - RADEON_WRITE(R600_VGT_STRMOUT_EN, 0); - RADEON_WRITE(R600_SX_MISC, 0); - RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0); - RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0); - RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0); - RADEON_WRITE(R600_SPI_INPUT_Z, 0); - RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2)); - RADEON_WRITE(R600_CB_COLOR7_FRAG, 0); - - /* clear render buffer base addresses */ - RADEON_WRITE(R600_CB_COLOR0_BASE, 0); - RADEON_WRITE(R600_CB_COLOR1_BASE, 0); - RADEON_WRITE(R600_CB_COLOR2_BASE, 0); - RADEON_WRITE(R600_CB_COLOR3_BASE, 0); - RADEON_WRITE(R600_CB_COLOR4_BASE, 0); - RADEON_WRITE(R600_CB_COLOR5_BASE, 0); - RADEON_WRITE(R600_CB_COLOR6_BASE, 0); - RADEON_WRITE(R600_CB_COLOR7_BASE, 0); - - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV610: - case CHIP_RS780: - case CHIP_RS880: - case CHIP_RV620: - tc_cntl = R600_TC_L2_SIZE(8); - break; - case CHIP_RV630: - case CHIP_RV635: - tc_cntl = R600_TC_L2_SIZE(4); - break; - case CHIP_R600: - tc_cntl = R600_TC_L2_SIZE(0) | R600_L2_DISABLE_LATE_HIT; - break; - default: - tc_cntl = R600_TC_L2_SIZE(0); - break; - } - - RADEON_WRITE(R600_TC_CNTL, tc_cntl); - - hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL); - RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl); - - arb_pop = RADEON_READ(R600_ARB_POP); - arb_pop |= R600_ENABLE_TC128; - RADEON_WRITE(R600_ARB_POP, arb_pop); - - RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); - RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA | - R600_NUM_CLIP_SEQ(3))); - RADEON_WRITE(R600_PA_SC_ENHANCE, R600_FORCE_EOV_MAX_CLK_CNT(4095)); - -} - -static u32 r700_get_tile_pipe_to_backend_map(drm_radeon_private_t *dev_priv, - u32 num_tile_pipes, - u32 num_backends, - u32 backend_disable_mask) -{ - u32 backend_map = 0; - u32 enabled_backends_mask; - u32 enabled_backends_count; - u32 cur_pipe; - u32 swizzle_pipe[R7XX_MAX_PIPES]; - u32 cur_backend; - u32 i; - bool force_no_swizzle; - - if (num_tile_pipes > R7XX_MAX_PIPES) - num_tile_pipes = R7XX_MAX_PIPES; - if (num_tile_pipes < 1) - num_tile_pipes = 1; - if (num_backends > R7XX_MAX_BACKENDS) - num_backends = R7XX_MAX_BACKENDS; - if (num_backends < 1) - num_backends = 1; - - enabled_backends_mask = 0; - enabled_backends_count = 0; - for (i = 0; i < R7XX_MAX_BACKENDS; ++i) { - if (((backend_disable_mask >> i) & 1) == 0) { - enabled_backends_mask |= (1 << i); - ++enabled_backends_count; - } - if (enabled_backends_count == num_backends) - break; - } - - if (enabled_backends_count == 0) { - enabled_backends_mask = 1; - enabled_backends_count = 1; - } - - if (enabled_backends_count != num_backends) - num_backends = enabled_backends_count; - - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV770: - case CHIP_RV730: - force_no_swizzle = false; - break; - case CHIP_RV710: - case CHIP_RV740: - default: - force_no_swizzle = true; - break; - } - - memset((uint8_t *)&swizzle_pipe[0], 0, sizeof(u32) * R7XX_MAX_PIPES); - switch (num_tile_pipes) { - case 1: - swizzle_pipe[0] = 0; - break; - case 2: - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - break; - case 3: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 1; - } - break; - case 4: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 3; - swizzle_pipe[3] = 1; - } - break; - case 5: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - swizzle_pipe[4] = 4; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 1; - swizzle_pipe[4] = 3; - } - break; - case 6: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - swizzle_pipe[4] = 4; - swizzle_pipe[5] = 5; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 5; - swizzle_pipe[4] = 3; - swizzle_pipe[5] = 1; - } - break; - case 7: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - swizzle_pipe[4] = 4; - swizzle_pipe[5] = 5; - swizzle_pipe[6] = 6; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 6; - swizzle_pipe[4] = 3; - swizzle_pipe[5] = 1; - swizzle_pipe[6] = 5; - } - break; - case 8: - if (force_no_swizzle) { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 1; - swizzle_pipe[2] = 2; - swizzle_pipe[3] = 3; - swizzle_pipe[4] = 4; - swizzle_pipe[5] = 5; - swizzle_pipe[6] = 6; - swizzle_pipe[7] = 7; - } else { - swizzle_pipe[0] = 0; - swizzle_pipe[1] = 2; - swizzle_pipe[2] = 4; - swizzle_pipe[3] = 6; - swizzle_pipe[4] = 3; - swizzle_pipe[5] = 1; - swizzle_pipe[6] = 7; - swizzle_pipe[7] = 5; - } - break; - } - - cur_backend = 0; - for (cur_pipe = 0; cur_pipe < num_tile_pipes; ++cur_pipe) { - while (((1 << cur_backend) & enabled_backends_mask) == 0) - cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; - - backend_map |= (u32)(((cur_backend & 3) << (swizzle_pipe[cur_pipe] * 2))); - - cur_backend = (cur_backend + 1) % R7XX_MAX_BACKENDS; - } - - return backend_map; -} - -static void r700_gfx_init(struct drm_device *dev, - drm_radeon_private_t *dev_priv) -{ - int i, j, num_qd_pipes; - u32 ta_aux_cntl; - u32 sx_debug_1; - u32 smx_dc_ctl0; - u32 db_debug3; - u32 num_gs_verts_per_thread; - u32 vgt_gs_per_es; - u32 gs_prim_buffer_depth = 0; - u32 sq_ms_fifo_sizes; - u32 sq_config; - u32 sq_thread_resource_mgmt; - u32 hdp_host_path_cntl; - u32 sq_dyn_gpr_size_simd_ab_0; - u32 backend_map; - u32 gb_tiling_config = 0; - u32 cc_rb_backend_disable; - u32 cc_gc_shader_pipe_config; - u32 mc_arb_ramcfg; - u32 db_debug4; - - /* setup chip specs */ - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV770: - dev_priv->r600_max_pipes = 4; - dev_priv->r600_max_tile_pipes = 8; - dev_priv->r600_max_simds = 10; - dev_priv->r600_max_backends = 4; - dev_priv->r600_max_gprs = 256; - dev_priv->r600_max_threads = 248; - dev_priv->r600_max_stack_entries = 512; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 16 * 2; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 112; - dev_priv->r600_sq_num_cf_insts = 2; - - dev_priv->r700_sx_num_of_sets = 7; - dev_priv->r700_sc_prim_fifo_size = 0xF9; - dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; - dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; - break; - case CHIP_RV730: - dev_priv->r600_max_pipes = 2; - dev_priv->r600_max_tile_pipes = 4; - dev_priv->r600_max_simds = 8; - dev_priv->r600_max_backends = 2; - dev_priv->r600_max_gprs = 128; - dev_priv->r600_max_threads = 248; - dev_priv->r600_max_stack_entries = 256; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 16 * 2; - dev_priv->r600_sx_max_export_size = 256; - dev_priv->r600_sx_max_export_pos_size = 32; - dev_priv->r600_sx_max_export_smx_size = 224; - dev_priv->r600_sq_num_cf_insts = 2; - - dev_priv->r700_sx_num_of_sets = 7; - dev_priv->r700_sc_prim_fifo_size = 0xf9; - dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; - dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; - if (dev_priv->r600_sx_max_export_pos_size > 16) { - dev_priv->r600_sx_max_export_pos_size -= 16; - dev_priv->r600_sx_max_export_smx_size += 16; - } - break; - case CHIP_RV710: - dev_priv->r600_max_pipes = 2; - dev_priv->r600_max_tile_pipes = 2; - dev_priv->r600_max_simds = 2; - dev_priv->r600_max_backends = 1; - dev_priv->r600_max_gprs = 256; - dev_priv->r600_max_threads = 192; - dev_priv->r600_max_stack_entries = 256; - dev_priv->r600_max_hw_contexts = 4; - dev_priv->r600_max_gs_threads = 8 * 2; - dev_priv->r600_sx_max_export_size = 128; - dev_priv->r600_sx_max_export_pos_size = 16; - dev_priv->r600_sx_max_export_smx_size = 112; - dev_priv->r600_sq_num_cf_insts = 1; - - dev_priv->r700_sx_num_of_sets = 7; - dev_priv->r700_sc_prim_fifo_size = 0x40; - dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; - dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; - break; - case CHIP_RV740: - dev_priv->r600_max_pipes = 4; - dev_priv->r600_max_tile_pipes = 4; - dev_priv->r600_max_simds = 8; - dev_priv->r600_max_backends = 4; - dev_priv->r600_max_gprs = 256; - dev_priv->r600_max_threads = 248; - dev_priv->r600_max_stack_entries = 512; - dev_priv->r600_max_hw_contexts = 8; - dev_priv->r600_max_gs_threads = 16 * 2; - dev_priv->r600_sx_max_export_size = 256; - dev_priv->r600_sx_max_export_pos_size = 32; - dev_priv->r600_sx_max_export_smx_size = 224; - dev_priv->r600_sq_num_cf_insts = 2; - - dev_priv->r700_sx_num_of_sets = 7; - dev_priv->r700_sc_prim_fifo_size = 0x100; - dev_priv->r700_sc_hiz_tile_fifo_size = 0x30; - dev_priv->r700_sc_earlyz_tile_fifo_fize = 0x130; - - if (dev_priv->r600_sx_max_export_pos_size > 16) { - dev_priv->r600_sx_max_export_pos_size -= 16; - dev_priv->r600_sx_max_export_smx_size += 16; - } - break; - default: - break; - } - - /* Initialize HDP */ - j = 0; - for (i = 0; i < 32; i++) { - RADEON_WRITE((0x2c14 + j), 0x00000000); - RADEON_WRITE((0x2c18 + j), 0x00000000); - RADEON_WRITE((0x2c1c + j), 0x00000000); - RADEON_WRITE((0x2c20 + j), 0x00000000); - RADEON_WRITE((0x2c24 + j), 0x00000000); - j += 0x18; - } - - RADEON_WRITE(R600_GRBM_CNTL, R600_GRBM_READ_TIMEOUT(0xff)); - - /* setup tiling, simd, pipe config */ - mc_arb_ramcfg = RADEON_READ(R700_MC_ARB_RAMCFG); - - switch (dev_priv->r600_max_tile_pipes) { - case 1: - gb_tiling_config |= R600_PIPE_TILING(0); - break; - case 2: - gb_tiling_config |= R600_PIPE_TILING(1); - break; - case 4: - gb_tiling_config |= R600_PIPE_TILING(2); - break; - case 8: - gb_tiling_config |= R600_PIPE_TILING(3); - break; - default: - break; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV770) - gb_tiling_config |= R600_BANK_TILING(1); - else - gb_tiling_config |= R600_BANK_TILING((mc_arb_ramcfg >> R700_NOOFBANK_SHIFT) & R700_NOOFBANK_MASK); - - gb_tiling_config |= R600_GROUP_SIZE(0); - - if (((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK) > 3) { - gb_tiling_config |= R600_ROW_TILING(3); - gb_tiling_config |= R600_SAMPLE_SPLIT(3); - } else { - gb_tiling_config |= - R600_ROW_TILING(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK)); - gb_tiling_config |= - R600_SAMPLE_SPLIT(((mc_arb_ramcfg >> R700_NOOFROWS_SHIFT) & R700_NOOFROWS_MASK)); - } - - gb_tiling_config |= R600_BANK_SWAPS(1); - - cc_rb_backend_disable = RADEON_READ(R600_CC_RB_BACKEND_DISABLE) & 0x00ff0000; - cc_rb_backend_disable |= - R600_BACKEND_DISABLE((R7XX_MAX_BACKENDS_MASK << dev_priv->r600_max_backends) & R7XX_MAX_BACKENDS_MASK); - - cc_gc_shader_pipe_config = RADEON_READ(R600_CC_GC_SHADER_PIPE_CONFIG) & 0xffffff00; - cc_gc_shader_pipe_config |= - R600_INACTIVE_QD_PIPES((R7XX_MAX_PIPES_MASK << dev_priv->r600_max_pipes) & R7XX_MAX_PIPES_MASK); - cc_gc_shader_pipe_config |= - R600_INACTIVE_SIMDS((R7XX_MAX_SIMDS_MASK << dev_priv->r600_max_simds) & R7XX_MAX_SIMDS_MASK); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV740) - backend_map = 0x28; - else - backend_map = r700_get_tile_pipe_to_backend_map(dev_priv, - dev_priv->r600_max_tile_pipes, - (R7XX_MAX_BACKENDS - - r600_count_pipe_bits((cc_rb_backend_disable & - R7XX_MAX_BACKENDS_MASK) >> 16)), - (cc_rb_backend_disable >> 16)); - gb_tiling_config |= R600_BACKEND_MAP(backend_map); - - RADEON_WRITE(R600_GB_TILING_CONFIG, gb_tiling_config); - RADEON_WRITE(R600_DCP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - RADEON_WRITE(R600_HDP_TILING_CONFIG, (gb_tiling_config & 0xffff)); - if (gb_tiling_config & 0xc0) { - dev_priv->r600_group_size = 512; - } else { - dev_priv->r600_group_size = 256; - } - dev_priv->r600_npipes = 1 << ((gb_tiling_config >> 1) & 0x7); - if (gb_tiling_config & 0x30) { - dev_priv->r600_nbanks = 8; - } else { - dev_priv->r600_nbanks = 4; - } - - RADEON_WRITE(R600_CC_RB_BACKEND_DISABLE, cc_rb_backend_disable); - RADEON_WRITE(R600_CC_GC_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - RADEON_WRITE(R600_GC_USER_SHADER_PIPE_CONFIG, cc_gc_shader_pipe_config); - - RADEON_WRITE(R700_CC_SYS_RB_BACKEND_DISABLE, cc_rb_backend_disable); - RADEON_WRITE(R700_CGTS_SYS_TCC_DISABLE, 0); - RADEON_WRITE(R700_CGTS_TCC_DISABLE, 0); - RADEON_WRITE(R700_CGTS_USER_SYS_TCC_DISABLE, 0); - RADEON_WRITE(R700_CGTS_USER_TCC_DISABLE, 0); - - num_qd_pipes = - R7XX_MAX_PIPES - r600_count_pipe_bits((cc_gc_shader_pipe_config & R600_INACTIVE_QD_PIPES_MASK) >> 8); - RADEON_WRITE(R600_VGT_OUT_DEALLOC_CNTL, (num_qd_pipes * 4) & R600_DEALLOC_DIST_MASK); - RADEON_WRITE(R600_VGT_VERTEX_REUSE_BLOCK_CNTL, ((num_qd_pipes * 4) - 2) & R600_VTX_REUSE_DEPTH_MASK); - - /* set HW defaults for 3D engine */ - RADEON_WRITE(R600_CP_QUEUE_THRESHOLDS, (R600_ROQ_IB1_START(0x16) | - R600_ROQ_IB2_START(0x2b))); - - RADEON_WRITE(R600_CP_MEQ_THRESHOLDS, R700_STQ_SPLIT(0x30)); - - ta_aux_cntl = RADEON_READ(R600_TA_CNTL_AUX); - RADEON_WRITE(R600_TA_CNTL_AUX, ta_aux_cntl | R600_DISABLE_CUBE_ANISO); - - sx_debug_1 = RADEON_READ(R700_SX_DEBUG_1); - sx_debug_1 |= R700_ENABLE_NEW_SMX_ADDRESS; - RADEON_WRITE(R700_SX_DEBUG_1, sx_debug_1); - - smx_dc_ctl0 = RADEON_READ(R600_SMX_DC_CTL0); - smx_dc_ctl0 &= ~R700_CACHE_DEPTH(0x1ff); - smx_dc_ctl0 |= R700_CACHE_DEPTH((dev_priv->r700_sx_num_of_sets * 64) - 1); - RADEON_WRITE(R600_SMX_DC_CTL0, smx_dc_ctl0); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV740) - RADEON_WRITE(R700_SMX_EVENT_CTL, (R700_ES_FLUSH_CTL(4) | - R700_GS_FLUSH_CTL(4) | - R700_ACK_FLUSH_CTL(3) | - R700_SYNC_FLUSH_CTL)); - - db_debug3 = RADEON_READ(R700_DB_DEBUG3); - db_debug3 &= ~R700_DB_CLK_OFF_DELAY(0x1f); - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV770: - case CHIP_RV740: - db_debug3 |= R700_DB_CLK_OFF_DELAY(0x1f); - break; - case CHIP_RV710: - case CHIP_RV730: - default: - db_debug3 |= R700_DB_CLK_OFF_DELAY(2); - break; - } - RADEON_WRITE(R700_DB_DEBUG3, db_debug3); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) != CHIP_RV770) { - db_debug4 = RADEON_READ(RV700_DB_DEBUG4); - db_debug4 |= RV700_DISABLE_TILE_COVERED_FOR_PS_ITER; - RADEON_WRITE(RV700_DB_DEBUG4, db_debug4); - } - - RADEON_WRITE(R600_SX_EXPORT_BUFFER_SIZES, (R600_COLOR_BUFFER_SIZE((dev_priv->r600_sx_max_export_size / 4) - 1) | - R600_POSITION_BUFFER_SIZE((dev_priv->r600_sx_max_export_pos_size / 4) - 1) | - R600_SMX_BUFFER_SIZE((dev_priv->r600_sx_max_export_smx_size / 4) - 1))); - - RADEON_WRITE(R700_PA_SC_FIFO_SIZE_R7XX, (R700_SC_PRIM_FIFO_SIZE(dev_priv->r700_sc_prim_fifo_size) | - R700_SC_HIZ_TILE_FIFO_SIZE(dev_priv->r700_sc_hiz_tile_fifo_size) | - R700_SC_EARLYZ_TILE_FIFO_SIZE(dev_priv->r700_sc_earlyz_tile_fifo_fize))); - - RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); - - RADEON_WRITE(R600_VGT_NUM_INSTANCES, 1); - - RADEON_WRITE(R600_SPI_CONFIG_CNTL, R600_GPR_WRITE_PRIORITY(0)); - - RADEON_WRITE(R600_SPI_CONFIG_CNTL_1, R600_VTX_DONE_DELAY(4)); - - RADEON_WRITE(R600_CP_PERFMON_CNTL, 0); - - sq_ms_fifo_sizes = (R600_CACHE_FIFO_SIZE(16 * dev_priv->r600_sq_num_cf_insts) | - R600_DONE_FIFO_HIWATER(0xe0) | - R600_ALU_UPDATE_FIFO_HIWATER(0x8)); - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV770: - case CHIP_RV730: - case CHIP_RV710: - sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x1); - break; - case CHIP_RV740: - default: - sq_ms_fifo_sizes |= R600_FETCH_FIFO_HIWATER(0x4); - break; - } - RADEON_WRITE(R600_SQ_MS_FIFO_SIZES, sq_ms_fifo_sizes); - - /* SQ_CONFIG, SQ_GPR_RESOURCE_MGMT, SQ_THREAD_RESOURCE_MGMT, SQ_STACK_RESOURCE_MGMT - * should be adjusted as needed by the 2D/3D drivers. This just sets default values - */ - sq_config = RADEON_READ(R600_SQ_CONFIG); - sq_config &= ~(R600_PS_PRIO(3) | - R600_VS_PRIO(3) | - R600_GS_PRIO(3) | - R600_ES_PRIO(3)); - sq_config |= (R600_DX9_CONSTS | - R600_VC_ENABLE | - R600_EXPORT_SRC_C | - R600_PS_PRIO(0) | - R600_VS_PRIO(1) | - R600_GS_PRIO(2) | - R600_ES_PRIO(3)); - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710) - /* no vertex cache */ - sq_config &= ~R600_VC_ENABLE; - - RADEON_WRITE(R600_SQ_CONFIG, sq_config); - - RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_1, (R600_NUM_PS_GPRS((dev_priv->r600_max_gprs * 24)/64) | - R600_NUM_VS_GPRS((dev_priv->r600_max_gprs * 24)/64) | - R600_NUM_CLAUSE_TEMP_GPRS(((dev_priv->r600_max_gprs * 24)/64)/2))); - - RADEON_WRITE(R600_SQ_GPR_RESOURCE_MGMT_2, (R600_NUM_GS_GPRS((dev_priv->r600_max_gprs * 7)/64) | - R600_NUM_ES_GPRS((dev_priv->r600_max_gprs * 7)/64))); - - sq_thread_resource_mgmt = (R600_NUM_PS_THREADS((dev_priv->r600_max_threads * 4)/8) | - R600_NUM_VS_THREADS((dev_priv->r600_max_threads * 2)/8) | - R600_NUM_ES_THREADS((dev_priv->r600_max_threads * 1)/8)); - if (((dev_priv->r600_max_threads * 1) / 8) > dev_priv->r600_max_gs_threads) - sq_thread_resource_mgmt |= R600_NUM_GS_THREADS(dev_priv->r600_max_gs_threads); - else - sq_thread_resource_mgmt |= R600_NUM_GS_THREADS((dev_priv->r600_max_gs_threads * 1)/8); - RADEON_WRITE(R600_SQ_THREAD_RESOURCE_MGMT, sq_thread_resource_mgmt); - - RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_1, (R600_NUM_PS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) | - R600_NUM_VS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4))); - - RADEON_WRITE(R600_SQ_STACK_RESOURCE_MGMT_2, (R600_NUM_GS_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4) | - R600_NUM_ES_STACK_ENTRIES((dev_priv->r600_max_stack_entries * 1)/4))); - - sq_dyn_gpr_size_simd_ab_0 = (R700_SIMDA_RING0((dev_priv->r600_max_gprs * 38)/64) | - R700_SIMDA_RING1((dev_priv->r600_max_gprs * 38)/64) | - R700_SIMDB_RING0((dev_priv->r600_max_gprs * 38)/64) | - R700_SIMDB_RING1((dev_priv->r600_max_gprs * 38)/64)); - - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_0, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_1, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_2, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_3, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_4, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_5, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_6, sq_dyn_gpr_size_simd_ab_0); - RADEON_WRITE(R700_SQ_DYN_GPR_SIZE_SIMD_AB_7, sq_dyn_gpr_size_simd_ab_0); - - RADEON_WRITE(R700_PA_SC_FORCE_EOV_MAX_CNTS, (R700_FORCE_EOV_MAX_CLK_CNT(4095) | - R700_FORCE_EOV_MAX_REZ_CNT(255))); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV710) - RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_TC_ONLY) | - R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO))); - else - RADEON_WRITE(R600_VGT_CACHE_INVALIDATION, (R600_CACHE_INVALIDATION(R600_VC_AND_TC) | - R700_AUTO_INVLD_EN(R700_ES_AND_GS_AUTO))); - - switch (dev_priv->flags & RADEON_FAMILY_MASK) { - case CHIP_RV770: - case CHIP_RV730: - case CHIP_RV740: - gs_prim_buffer_depth = 384; - break; - case CHIP_RV710: - gs_prim_buffer_depth = 128; - break; - default: - break; - } - - num_gs_verts_per_thread = dev_priv->r600_max_pipes * 16; - vgt_gs_per_es = gs_prim_buffer_depth + num_gs_verts_per_thread; - /* Max value for this is 256 */ - if (vgt_gs_per_es > 256) - vgt_gs_per_es = 256; - - RADEON_WRITE(R600_VGT_ES_PER_GS, 128); - RADEON_WRITE(R600_VGT_GS_PER_ES, vgt_gs_per_es); - RADEON_WRITE(R600_VGT_GS_PER_VS, 2); - - /* more default values. 2D/3D driver should adjust as needed */ - RADEON_WRITE(R600_VGT_GS_VERTEX_REUSE, 16); - RADEON_WRITE(R600_PA_SC_LINE_STIPPLE_STATE, 0); - RADEON_WRITE(R600_VGT_STRMOUT_EN, 0); - RADEON_WRITE(R600_SX_MISC, 0); - RADEON_WRITE(R600_PA_SC_MODE_CNTL, 0); - RADEON_WRITE(R700_PA_SC_EDGERULE, 0xaaaaaaaa); - RADEON_WRITE(R600_PA_SC_AA_CONFIG, 0); - RADEON_WRITE(R600_PA_SC_CLIPRECT_RULE, 0xffff); - RADEON_WRITE(R600_PA_SC_LINE_STIPPLE, 0); - RADEON_WRITE(R600_SPI_INPUT_Z, 0); - RADEON_WRITE(R600_SPI_PS_IN_CONTROL_0, R600_NUM_INTERP(2)); - RADEON_WRITE(R600_CB_COLOR7_FRAG, 0); - - /* clear render buffer base addresses */ - RADEON_WRITE(R600_CB_COLOR0_BASE, 0); - RADEON_WRITE(R600_CB_COLOR1_BASE, 0); - RADEON_WRITE(R600_CB_COLOR2_BASE, 0); - RADEON_WRITE(R600_CB_COLOR3_BASE, 0); - RADEON_WRITE(R600_CB_COLOR4_BASE, 0); - RADEON_WRITE(R600_CB_COLOR5_BASE, 0); - RADEON_WRITE(R600_CB_COLOR6_BASE, 0); - RADEON_WRITE(R600_CB_COLOR7_BASE, 0); - - RADEON_WRITE(R700_TCP_CNTL, 0); - - hdp_host_path_cntl = RADEON_READ(R600_HDP_HOST_PATH_CNTL); - RADEON_WRITE(R600_HDP_HOST_PATH_CNTL, hdp_host_path_cntl); - - RADEON_WRITE(R600_PA_SC_MULTI_CHIP_CNTL, 0); - - RADEON_WRITE(R600_PA_CL_ENHANCE, (R600_CLIP_VTX_REORDER_ENA | - R600_NUM_CLIP_SEQ(3))); - -} - -static void r600_cp_init_ring_buffer(struct drm_device *dev, - drm_radeon_private_t *dev_priv, - struct drm_file *file_priv) -{ - struct drm_radeon_master_private *master_priv; - u32 ring_start; - u64 rptr_addr; - - if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) - r700_gfx_init(dev, dev_priv); - else - r600_gfx_init(dev, dev_priv); - - RADEON_WRITE(R600_GRBM_SOFT_RESET, R600_SOFT_RESET_CP); - RADEON_READ(R600_GRBM_SOFT_RESET); - mdelay(15); - RADEON_WRITE(R600_GRBM_SOFT_RESET, 0); - - - /* Set ring buffer size */ -#ifdef __BIG_ENDIAN - RADEON_WRITE(R600_CP_RB_CNTL, - R600_BUF_SWAP_32BIT | - R600_RB_NO_UPDATE | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#else - RADEON_WRITE(R600_CP_RB_CNTL, - RADEON_RB_NO_UPDATE | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#endif - - RADEON_WRITE(R600_CP_SEM_WAIT_TIMER, 0x0); - - /* Set the write pointer delay */ - RADEON_WRITE(R600_CP_RB_WPTR_DELAY, 0); - -#ifdef __BIG_ENDIAN - RADEON_WRITE(R600_CP_RB_CNTL, - R600_BUF_SWAP_32BIT | - R600_RB_NO_UPDATE | - R600_RB_RPTR_WR_ENA | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#else - RADEON_WRITE(R600_CP_RB_CNTL, - R600_RB_NO_UPDATE | - R600_RB_RPTR_WR_ENA | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#endif - - /* Initialize the ring buffer's read and write pointers */ - RADEON_WRITE(R600_CP_RB_RPTR_WR, 0); - RADEON_WRITE(R600_CP_RB_WPTR, 0); - SET_RING_HEAD(dev_priv, 0); - dev_priv->ring.tail = 0; - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - rptr_addr = dev_priv->ring_rptr->offset - - dev->agp->base + - dev_priv->gart_vm_start; - } else -#endif - { - rptr_addr = dev_priv->ring_rptr->offset - - ((unsigned long) dev->sg->virtual) - + dev_priv->gart_vm_start; - } - RADEON_WRITE(R600_CP_RB_RPTR_ADDR, (rptr_addr & 0xfffffffc)); - RADEON_WRITE(R600_CP_RB_RPTR_ADDR_HI, upper_32_bits(rptr_addr)); - -#ifdef __BIG_ENDIAN - RADEON_WRITE(R600_CP_RB_CNTL, - RADEON_BUF_SWAP_32BIT | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#else - RADEON_WRITE(R600_CP_RB_CNTL, - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#endif - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - /* XXX */ - radeon_write_agp_base(dev_priv, dev->agp->base); - - /* XXX */ - radeon_write_agp_location(dev_priv, - (((dev_priv->gart_vm_start - 1 + - dev_priv->gart_size) & 0xffff0000) | - (dev_priv->gart_vm_start >> 16))); - - ring_start = (dev_priv->cp_ring->offset - - dev->agp->base - + dev_priv->gart_vm_start); - } else -#endif - ring_start = (dev_priv->cp_ring->offset - - (unsigned long)dev->sg->virtual - + dev_priv->gart_vm_start); - - RADEON_WRITE(R600_CP_RB_BASE, ring_start >> 8); - - RADEON_WRITE(R600_CP_ME_CNTL, 0xff); - - RADEON_WRITE(R600_CP_DEBUG, (1 << 27) | (1 << 28)); - - /* Initialize the scratch register pointer. This will cause - * the scratch register values to be written out to memory - * whenever they are updated. - * - * We simply put this behind the ring read pointer, this works - * with PCI GART as well as (whatever kind of) AGP GART - */ - { - u64 scratch_addr; - - scratch_addr = RADEON_READ(R600_CP_RB_RPTR_ADDR) & 0xFFFFFFFC; - scratch_addr |= ((u64)RADEON_READ(R600_CP_RB_RPTR_ADDR_HI)) << 32; - scratch_addr += R600_SCRATCH_REG_OFFSET; - scratch_addr >>= 8; - scratch_addr &= 0xffffffff; - - RADEON_WRITE(R600_SCRATCH_ADDR, (uint32_t)scratch_addr); - } - - RADEON_WRITE(R600_SCRATCH_UMSK, 0x7); - - /* Turn on bus mastering */ - radeon_enable_bm(dev_priv); - - radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(0), 0); - RADEON_WRITE(R600_LAST_FRAME_REG, 0); - - radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(1), 0); - RADEON_WRITE(R600_LAST_DISPATCH_REG, 0); - - radeon_write_ring_rptr(dev_priv, R600_SCRATCHOFF(2), 0); - RADEON_WRITE(R600_LAST_CLEAR_REG, 0); - - /* reset sarea copies of these */ - master_priv = file_priv->master->driver_priv; - if (master_priv->sarea_priv) { - master_priv->sarea_priv->last_frame = 0; - master_priv->sarea_priv->last_dispatch = 0; - master_priv->sarea_priv->last_clear = 0; - } - - r600_do_wait_for_idle(dev_priv); - -} - -int r600_do_cleanup_cp(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_irq_uninstall(dev); - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - if (dev_priv->cp_ring != NULL) { - drm_legacy_ioremapfree(dev_priv->cp_ring, dev); - dev_priv->cp_ring = NULL; - } - if (dev_priv->ring_rptr != NULL) { - drm_legacy_ioremapfree(dev_priv->ring_rptr, dev); - dev_priv->ring_rptr = NULL; - } - if (dev->agp_buffer_map != NULL) { - drm_legacy_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; - } - } else -#endif - { - - if (dev_priv->gart_info.bus_addr) - r600_page_table_cleanup(dev, &dev_priv->gart_info); - - if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) { - drm_legacy_ioremapfree(&dev_priv->gart_info.mapping, dev); - dev_priv->gart_info.addr = NULL; - } - } - /* only clear to the start of flags */ - memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); - - return 0; -} - -int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, - struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - - DRM_DEBUG("\n"); - - mutex_init(&dev_priv->cs_mutex); - r600_cs_legacy_init(); - /* if we require new memory map but we don't have it fail */ - if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { - DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { - DRM_DEBUG("Forcing AGP card to PCI mode\n"); - dev_priv->flags &= ~RADEON_IS_AGP; - /* The writeback test succeeds, but when writeback is enabled, - * the ring buffer read ptr update fails after first 128 bytes. - */ - radeon_no_wb = 1; - } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) - && !init->is_pci) { - DRM_DEBUG("Restoring AGP flag\n"); - dev_priv->flags |= RADEON_IS_AGP; - } - - dev_priv->usec_timeout = init->usec_timeout; - if (dev_priv->usec_timeout < 1 || - dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { - DRM_DEBUG("TIMEOUT problem!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - /* Enable vblank on CRTC1 for older X servers - */ - dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; - dev_priv->do_boxes = 0; - dev_priv->cp_mode = init->cp_mode; - - /* We don't support anything other than bus-mastering ring mode, - * but the ring can be in either AGP or PCI space for the ring - * read pointer. - */ - if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && - (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { - DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - switch (init->fb_bpp) { - case 16: - dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; - break; - case 32: - default: - dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; - break; - } - dev_priv->front_offset = init->front_offset; - dev_priv->front_pitch = init->front_pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->back_pitch = init->back_pitch; - - dev_priv->ring_offset = init->ring_offset; - dev_priv->ring_rptr_offset = init->ring_rptr_offset; - dev_priv->buffers_offset = init->buffers_offset; - dev_priv->gart_textures_offset = init->gart_textures_offset; - - master_priv->sarea = drm_legacy_getsarea(dev); - if (!master_priv->sarea) { - DRM_ERROR("could not find sarea!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - dev_priv->cp_ring = drm_legacy_findmap(dev, init->ring_offset); - if (!dev_priv->cp_ring) { - DRM_ERROR("could not find cp ring region!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset); - if (!dev_priv->ring_rptr) { - DRM_ERROR("could not find ring read pointer!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("could not find dma buffer region!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - if (init->gart_textures_offset) { - dev_priv->gart_textures = - drm_legacy_findmap(dev, init->gart_textures_offset); - if (!dev_priv->gart_textures) { - DRM_ERROR("could not find GART texture region!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - } - -#if IS_ENABLED(CONFIG_AGP) - /* XXX */ - if (dev_priv->flags & RADEON_IS_AGP) { - drm_legacy_ioremap_wc(dev_priv->cp_ring, dev); - drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev); - drm_legacy_ioremap_wc(dev->agp_buffer_map, dev); - if (!dev_priv->cp_ring->handle || - !dev_priv->ring_rptr->handle || - !dev->agp_buffer_map->handle) { - DRM_ERROR("could not find ioremap agp regions!\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - } else -#endif - { - dev_priv->cp_ring->handle = (void *)(unsigned long)dev_priv->cp_ring->offset; - dev_priv->ring_rptr->handle = - (void *)(unsigned long)dev_priv->ring_rptr->offset; - dev->agp_buffer_map->handle = - (void *)(unsigned long)dev->agp_buffer_map->offset; - - DRM_DEBUG("dev_priv->cp_ring->handle %p\n", - dev_priv->cp_ring->handle); - DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", - dev_priv->ring_rptr->handle); - DRM_DEBUG("dev->agp_buffer_map->handle %p\n", - dev->agp_buffer_map->handle); - } - - dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 24; - dev_priv->fb_size = - (((radeon_read_fb_location(dev_priv) & 0xffff0000u) << 8) + 0x1000000) - - dev_priv->fb_location; - - dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | - ((dev_priv->front_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | - ((dev_priv->back_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | - ((dev_priv->depth_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->gart_size = init->gart_size; - - /* New let's set the memory map ... */ - if (dev_priv->new_memmap) { - u32 base = 0; - - DRM_INFO("Setting GART location based on new memory map\n"); - - /* If using AGP, try to locate the AGP aperture at the same - * location in the card and on the bus, though we have to - * align it down. - */ -#if IS_ENABLED(CONFIG_AGP) - /* XXX */ - if (dev_priv->flags & RADEON_IS_AGP) { - base = dev->agp->base; - /* Check if valid */ - if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && - base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { - DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", - dev->agp->base); - base = 0; - } - } -#endif - /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ - if (base == 0) { - base = dev_priv->fb_location + dev_priv->fb_size; - if (base < dev_priv->fb_location || - ((base + dev_priv->gart_size) & 0xfffffffful) < base) - base = dev_priv->fb_location - - dev_priv->gart_size; - } - dev_priv->gart_vm_start = base & 0xffc00000u; - if (dev_priv->gart_vm_start != base) - DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", - base, dev_priv->gart_vm_start); - } - -#if IS_ENABLED(CONFIG_AGP) - /* XXX */ - if (dev_priv->flags & RADEON_IS_AGP) - dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - - dev->agp->base - + dev_priv->gart_vm_start); - else -#endif - dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - - (unsigned long)dev->sg->virtual - + dev_priv->gart_vm_start); - - DRM_DEBUG("fb 0x%08x size %d\n", - (unsigned int) dev_priv->fb_location, - (unsigned int) dev_priv->fb_size); - DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); - DRM_DEBUG("dev_priv->gart_vm_start 0x%08x\n", - (unsigned int) dev_priv->gart_vm_start); - DRM_DEBUG("dev_priv->gart_buffers_offset 0x%08lx\n", - dev_priv->gart_buffers_offset); - - dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; - dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle - + init->ring_size / sizeof(u32)); - dev_priv->ring.size = init->ring_size; - dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8); - - dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; - dev_priv->ring.rptr_update_l2qw = order_base_2(/* init->rptr_update */ 4096 / 8); - - dev_priv->ring.fetch_size = /* init->fetch_size */ 32; - dev_priv->ring.fetch_size_l2ow = order_base_2(/* init->fetch_size */ 32 / 16); - - dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; - - dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - /* XXX turn off pcie gart */ - } else -#endif - { - dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); - /* if we have an offset set from userspace */ - if (!dev_priv->pcigart_offset_set) { - DRM_ERROR("Need gart offset from userspace\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - DRM_DEBUG("Using gart offset 0x%08lx\n", dev_priv->pcigart_offset); - - dev_priv->gart_info.bus_addr = - dev_priv->pcigart_offset + dev_priv->fb_location; - dev_priv->gart_info.mapping.offset = - dev_priv->pcigart_offset + dev_priv->fb_aper_offset; - dev_priv->gart_info.mapping.size = - dev_priv->gart_info.table_size; - - drm_legacy_ioremap_wc(&dev_priv->gart_info.mapping, dev); - if (!dev_priv->gart_info.mapping.handle) { - DRM_ERROR("ioremap failed.\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - dev_priv->gart_info.addr = - dev_priv->gart_info.mapping.handle; - - DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", - dev_priv->gart_info.addr, - dev_priv->pcigart_offset); - - if (!r600_page_table_init(dev)) { - DRM_ERROR("Failed to init GART table\n"); - r600_do_cleanup_cp(dev); - return -EINVAL; - } - - if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) - r700_vm_init(dev); - else - r600_vm_init(dev); - } - - if (!dev_priv->me_fw || !dev_priv->pfp_fw) { - int err = r600_cp_init_microcode(dev_priv); - if (err) { - DRM_ERROR("Failed to load firmware!\n"); - r600_do_cleanup_cp(dev); - return err; - } - } - if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) - r700_cp_load_microcode(dev_priv); - else - r600_cp_load_microcode(dev_priv); - - r600_cp_init_ring_buffer(dev, dev_priv, file_priv); - - dev_priv->last_buf = 0; - - r600_do_engine_reset(dev); - r600_test_writeback(dev_priv); - - return 0; -} - -int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - if (((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770)) { - r700_vm_init(dev); - r700_cp_load_microcode(dev_priv); - } else { - r600_vm_init(dev); - r600_cp_load_microcode(dev_priv); - } - r600_cp_init_ring_buffer(dev, dev_priv, file_priv); - r600_do_engine_reset(dev); - - return 0; -} - -/* Wait for the CP to go idle. - */ -int r600_do_cp_idle(drm_radeon_private_t *dev_priv) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(5); - OUT_RING(CP_PACKET3(R600_IT_EVENT_WRITE, 0)); - OUT_RING(R600_CACHE_FLUSH_AND_INV_EVENT); - /* wait for 3D idle clean */ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); - OUT_RING((R600_WAIT_UNTIL - R600_SET_CONFIG_REG_OFFSET) >> 2); - OUT_RING(RADEON_WAIT_3D_IDLE | RADEON_WAIT_3D_IDLECLEAN); - - ADVANCE_RING(); - COMMIT_RING(); - - return r600_do_wait_for_idle(dev_priv); -} - -/* Start the Command Processor. - */ -void r600_do_cp_start(drm_radeon_private_t *dev_priv) -{ - u32 cp_me; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(7); - OUT_RING(CP_PACKET3(R600_IT_ME_INITIALIZE, 5)); - OUT_RING(0x00000001); - if (((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_RV770)) - OUT_RING(0x00000003); - else - OUT_RING(0x00000000); - OUT_RING((dev_priv->r600_max_hw_contexts - 1)); - OUT_RING(R600_ME_INITIALIZE_DEVICE_ID(1)); - OUT_RING(0x00000000); - OUT_RING(0x00000000); - ADVANCE_RING(); - COMMIT_RING(); - - /* set the mux and reset the halt bit */ - cp_me = 0xff; - RADEON_WRITE(R600_CP_ME_CNTL, cp_me); - - dev_priv->cp_running = 1; - -} - -void r600_do_cp_reset(drm_radeon_private_t *dev_priv) -{ - u32 cur_read_ptr; - DRM_DEBUG("\n"); - - cur_read_ptr = RADEON_READ(R600_CP_RB_RPTR); - RADEON_WRITE(R600_CP_RB_WPTR, cur_read_ptr); - SET_RING_HEAD(dev_priv, cur_read_ptr); - dev_priv->ring.tail = cur_read_ptr; -} - -void r600_do_cp_stop(drm_radeon_private_t *dev_priv) -{ - uint32_t cp_me; - - DRM_DEBUG("\n"); - - cp_me = 0xff | R600_CP_ME_HALT; - - RADEON_WRITE(R600_CP_ME_CNTL, cp_me); - - dev_priv->cp_running = 0; -} - -int r600_cp_dispatch_indirect(struct drm_device *dev, - struct drm_buf *buf, int start, int end) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - if (start != end) { - unsigned long offset = (dev_priv->gart_buffers_offset - + buf->offset + start); - int dwords = (end - start + 3) / sizeof(u32); - - DRM_DEBUG("dwords:%d\n", dwords); - DRM_DEBUG("offset 0x%lx\n", offset); - - - /* Indirect buffer data must be a multiple of 16 dwords. - * pad the data with a Type-2 CP packet. - */ - while (dwords & 0xf) { - u32 *data = (u32 *) - ((char *)dev->agp_buffer_map->handle - + buf->offset + start); - data[dwords++] = RADEON_CP_PACKET2; - } - - /* Fire off the indirect buffer */ - BEGIN_RING(4); - OUT_RING(CP_PACKET3(R600_IT_INDIRECT_BUFFER, 2)); - OUT_RING((offset & 0xfffffffc)); - OUT_RING((upper_32_bits(offset) & 0xff)); - OUT_RING(dwords); - ADVANCE_RING(); - } - - return 0; -} - -void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_master *master = file_priv->master; - struct drm_radeon_master_private *master_priv = master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int i, cpp, src_pitch, dst_pitch; - uint64_t src, dst; - RING_LOCALS; - DRM_DEBUG("\n"); - - if (dev_priv->color_fmt == RADEON_COLOR_FORMAT_ARGB8888) - cpp = 4; - else - cpp = 2; - - if (sarea_priv->pfCurrentPage == 0) { - src_pitch = dev_priv->back_pitch; - dst_pitch = dev_priv->front_pitch; - src = dev_priv->back_offset + dev_priv->fb_location; - dst = dev_priv->front_offset + dev_priv->fb_location; - } else { - src_pitch = dev_priv->front_pitch; - dst_pitch = dev_priv->back_pitch; - src = dev_priv->front_offset + dev_priv->fb_location; - dst = dev_priv->back_offset + dev_priv->fb_location; - } - - if (r600_prepare_blit_copy(dev, file_priv)) { - DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); - return; - } - for (i = 0; i < nbox; i++) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; - - DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); - - r600_blit_swap(dev, - src, dst, - x, y, x, y, w, h, - src_pitch, dst_pitch, cpp); - } - r600_done_blit_copy(dev); - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - sarea_priv->last_frame++; - - BEGIN_RING(3); - R600_FRAME_AGE(sarea_priv->last_frame); - ADVANCE_RING(); -} - -int r600_cp_dispatch_texture(struct drm_device *dev, - struct drm_file *file_priv, - drm_radeon_texture_t *tex, - drm_radeon_tex_image_t *image) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_buf *buf; - u32 *buffer; - const u8 __user *data; - unsigned int size, pass_size; - u64 src_offset, dst_offset; - - if (!radeon_check_offset(dev_priv, tex->offset)) { - DRM_ERROR("Invalid destination offset\n"); - return -EINVAL; - } - - /* this might fail for zero-sized uploads - are those illegal? */ - if (!radeon_check_offset(dev_priv, tex->offset + tex->height * tex->pitch - 1)) { - DRM_ERROR("Invalid final destination offset\n"); - return -EINVAL; - } - - size = tex->height * tex->pitch; - - if (size == 0) - return 0; - - dst_offset = tex->offset; - - if (r600_prepare_blit_copy(dev, file_priv)) { - DRM_ERROR("unable to allocate vertex buffer for swap buffer\n"); - return -EAGAIN; - } - do { - data = (const u8 __user *)image->data; - pass_size = size; - - buf = radeon_freelist_get(dev); - if (!buf) { - DRM_DEBUG("EAGAIN\n"); - if (copy_to_user(tex->image, image, sizeof(*image))) - return -EFAULT; - return -EAGAIN; - } - - if (pass_size > buf->total) - pass_size = buf->total; - - /* Dispatch the indirect buffer. - */ - buffer = - (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); - - if (copy_from_user(buffer, data, pass_size)) { - DRM_ERROR("EFAULT on pad, %d bytes\n", pass_size); - return -EFAULT; - } - - buf->file_priv = file_priv; - buf->used = pass_size; - src_offset = dev_priv->gart_buffers_offset + buf->offset; - - r600_blit_copy(dev, src_offset, dst_offset, pass_size); - - radeon_cp_discard_buffer(dev, file_priv->master, buf); - - /* Update the input parameters for next time */ - image->data = (const u8 __user *)image->data + pass_size; - dst_offset += pass_size; - size -= pass_size; - } while (size > 0); - r600_done_blit_copy(dev); - - return 0; -} - -/* - * Legacy cs ioctl - */ -static u32 radeon_cs_id_get(struct drm_radeon_private *radeon) -{ - /* FIXME: check if wrap affect last reported wrap & sequence */ - radeon->cs_id_scnt = (radeon->cs_id_scnt + 1) & 0x00FFFFFF; - if (!radeon->cs_id_scnt) { - /* increment wrap counter */ - radeon->cs_id_wcnt += 0x01000000; - /* valid sequence counter start at 1 */ - radeon->cs_id_scnt = 1; - } - return (radeon->cs_id_scnt | radeon->cs_id_wcnt); -} - -static void r600_cs_id_emit(drm_radeon_private_t *dev_priv, u32 *id) -{ - RING_LOCALS; - - *id = radeon_cs_id_get(dev_priv); - - /* SCRATCH 2 */ - BEGIN_RING(3); - R600_CLEAR_AGE(*id); - ADVANCE_RING(); - COMMIT_RING(); -} - -static int r600_ib_get(struct drm_device *dev, - struct drm_file *fpriv, - struct drm_buf **buffer) -{ - struct drm_buf *buf; - - *buffer = NULL; - buf = radeon_freelist_get(dev); - if (!buf) { - return -EBUSY; - } - buf->file_priv = fpriv; - *buffer = buf; - return 0; -} - -static void r600_ib_free(struct drm_device *dev, struct drm_buf *buf, - struct drm_file *fpriv, int l, int r) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (buf) { - if (!r) - r600_cp_dispatch_indirect(dev, buf, 0, l * 4); - radeon_cp_discard_buffer(dev, fpriv->master, buf); - COMMIT_RING(); - } -} - -int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - struct drm_radeon_cs *cs = data; - struct drm_buf *buf; - unsigned family; - int l, r = 0; - u32 *ib, cs_id = 0; - - if (dev_priv == NULL) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - family = dev_priv->flags & RADEON_FAMILY_MASK; - if (family < CHIP_R600) { - DRM_ERROR("cs ioctl valid only for R6XX & R7XX in legacy mode\n"); - return -EINVAL; - } - mutex_lock(&dev_priv->cs_mutex); - /* get ib */ - r = r600_ib_get(dev, fpriv, &buf); - if (r) { - DRM_ERROR("ib_get failed\n"); - goto out; - } - ib = dev->agp_buffer_map->handle + buf->offset; - /* now parse command stream */ - r = r600_cs_legacy(dev, data, fpriv, family, ib, &l); - if (r) { - goto out; - } - -out: - r600_ib_free(dev, buf, fpriv, l, r); - /* emit cs id sequence */ - r600_cs_id_emit(dev_priv, &cs_id); - cs->cs_id = cs_id; - mutex_unlock(&dev_priv->cs_mutex); - return r; -} - -void r600_cs_legacy_get_tiling_conf(struct drm_device *dev, u32 *npipes, u32 *nbanks, u32 *group_size) -{ - struct drm_radeon_private *dev_priv = dev->dev_private; - - *npipes = dev_priv->r600_npipes; - *nbanks = dev_priv->r600_nbanks; - *group_size = dev_priv->r600_group_size; -} diff --git a/drivers/gpu/drm/radeon/r600_cs.c b/drivers/gpu/drm/radeon/r600_cs.c index acc1f99c84d9..2f36fa1576e0 100644 --- a/drivers/gpu/drm/radeon/r600_cs.c +++ b/drivers/gpu/drm/radeon/r600_cs.c @@ -2328,101 +2328,6 @@ int r600_cs_parse(struct radeon_cs_parser *p) return 0; } -#ifdef CONFIG_DRM_RADEON_UMS - -/** - * cs_parser_fini() - clean parser states - * @parser: parser structure holding parsing context. - * @error: error number - * - * If error is set than unvalidate buffer, otherwise just free memory - * used by parsing context. - **/ -static void r600_cs_parser_fini(struct radeon_cs_parser *parser, int error) -{ - unsigned i; - - kfree(parser->relocs); - for (i = 0; i < parser->nchunks; i++) - drm_free_large(parser->chunks[i].kdata); - kfree(parser->chunks); - kfree(parser->chunks_array); -} - -static int r600_cs_parser_relocs_legacy(struct radeon_cs_parser *p) -{ - if (p->chunk_relocs == NULL) { - return 0; - } - p->relocs = kzalloc(sizeof(struct radeon_bo_list), GFP_KERNEL); - if (p->relocs == NULL) { - return -ENOMEM; - } - return 0; -} - -int r600_cs_legacy(struct drm_device *dev, void *data, struct drm_file *filp, - unsigned family, u32 *ib, int *l) -{ - struct radeon_cs_parser parser; - struct radeon_cs_chunk *ib_chunk; - struct r600_cs_track *track; - int r; - - /* initialize tracker */ - track = kzalloc(sizeof(*track), GFP_KERNEL); - if (track == NULL) - return -ENOMEM; - r600_cs_track_init(track); - r600_cs_legacy_get_tiling_conf(dev, &track->npipes, &track->nbanks, &track->group_size); - /* initialize parser */ - memset(&parser, 0, sizeof(struct radeon_cs_parser)); - parser.filp = filp; - parser.dev = &dev->pdev->dev; - parser.rdev = NULL; - parser.family = family; - parser.track = track; - parser.ib.ptr = ib; - r = radeon_cs_parser_init(&parser, data); - if (r) { - DRM_ERROR("Failed to initialize parser !\n"); - r600_cs_parser_fini(&parser, r); - return r; - } - r = r600_cs_parser_relocs_legacy(&parser); - if (r) { - DRM_ERROR("Failed to parse relocation !\n"); - r600_cs_parser_fini(&parser, r); - return r; - } - /* Copy the packet into the IB, the parser will read from the - * input memory (cached) and write to the IB (which can be - * uncached). */ - ib_chunk = parser.chunk_ib; - parser.ib.length_dw = ib_chunk->length_dw; - *l = parser.ib.length_dw; - if (copy_from_user(ib, ib_chunk->user_ptr, ib_chunk->length_dw * 4)) { - r = -EFAULT; - r600_cs_parser_fini(&parser, r); - return r; - } - r = r600_cs_parse(&parser); - if (r) { - DRM_ERROR("Invalid command stream !\n"); - r600_cs_parser_fini(&parser, r); - return r; - } - r600_cs_parser_fini(&parser, r); - return r; -} - -void r600_cs_legacy_init(void) -{ - r600_nomm = 1; -} - -#endif - /* * DMA */ diff --git a/drivers/gpu/drm/radeon/radeon.h b/drivers/gpu/drm/radeon/radeon.h index 87db64983ea8..5ae6db98aa4d 100644 --- a/drivers/gpu/drm/radeon/radeon.h +++ b/drivers/gpu/drm/radeon/radeon.h @@ -268,6 +268,7 @@ struct radeon_clock { uint32_t current_dispclk; uint32_t dp_extclk; uint32_t max_pixel_clock; + uint32_t gpupll_outputfreq; }; /* @@ -1889,7 +1890,7 @@ struct radeon_asic { void (*pad_ib)(struct radeon_ib *ib); } vm; /* ring specific callbacks */ - struct radeon_asic_ring *ring[RADEON_NUM_RINGS]; + const struct radeon_asic_ring *ring[RADEON_NUM_RINGS]; /* irqs */ struct { int (*set)(struct radeon_device *rdev); diff --git a/drivers/gpu/drm/radeon/radeon_asic.c b/drivers/gpu/drm/radeon/radeon_asic.c index 1d4d4520a0ac..7d5a36dd5094 100644 --- a/drivers/gpu/drm/radeon/radeon_asic.c +++ b/drivers/gpu/drm/radeon/radeon_asic.c @@ -179,7 +179,7 @@ void radeon_agp_disable(struct radeon_device *rdev) * ASIC */ -static struct radeon_asic_ring r100_gfx_ring = { +static const struct radeon_asic_ring r100_gfx_ring = { .ib_execute = &r100_ring_ib_execute, .emit_fence = &r100_fence_ring_emit, .emit_semaphore = &r100_semaphore_ring_emit, @@ -329,7 +329,7 @@ static struct radeon_asic r200_asic = { }, }; -static struct radeon_asic_ring r300_gfx_ring = { +static const struct radeon_asic_ring r300_gfx_ring = { .ib_execute = &r100_ring_ib_execute, .emit_fence = &r300_fence_ring_emit, .emit_semaphore = &r100_semaphore_ring_emit, @@ -343,7 +343,7 @@ static struct radeon_asic_ring r300_gfx_ring = { .set_wptr = &r100_gfx_set_wptr, }; -static struct radeon_asic_ring rv515_gfx_ring = { +static const struct radeon_asic_ring rv515_gfx_ring = { .ib_execute = &r100_ring_ib_execute, .emit_fence = &r300_fence_ring_emit, .emit_semaphore = &r100_semaphore_ring_emit, @@ -901,7 +901,7 @@ static struct radeon_asic r520_asic = { }, }; -static struct radeon_asic_ring r600_gfx_ring = { +static const struct radeon_asic_ring r600_gfx_ring = { .ib_execute = &r600_ring_ib_execute, .emit_fence = &r600_fence_ring_emit, .emit_semaphore = &r600_semaphore_ring_emit, @@ -914,7 +914,7 @@ static struct radeon_asic_ring r600_gfx_ring = { .set_wptr = &r600_gfx_set_wptr, }; -static struct radeon_asic_ring r600_dma_ring = { +static const struct radeon_asic_ring r600_dma_ring = { .ib_execute = &r600_dma_ring_ib_execute, .emit_fence = &r600_dma_fence_ring_emit, .emit_semaphore = &r600_dma_semaphore_ring_emit, @@ -999,7 +999,7 @@ static struct radeon_asic r600_asic = { }, }; -static struct radeon_asic_ring rv6xx_uvd_ring = { +static const struct radeon_asic_ring rv6xx_uvd_ring = { .ib_execute = &uvd_v1_0_ib_execute, .emit_fence = &uvd_v1_0_fence_emit, .emit_semaphore = &uvd_v1_0_semaphore_emit, @@ -1198,7 +1198,7 @@ static struct radeon_asic rs780_asic = { }, }; -static struct radeon_asic_ring rv770_uvd_ring = { +static const struct radeon_asic_ring rv770_uvd_ring = { .ib_execute = &uvd_v1_0_ib_execute, .emit_fence = &uvd_v2_2_fence_emit, .emit_semaphore = &uvd_v2_2_semaphore_emit, @@ -1305,7 +1305,7 @@ static struct radeon_asic rv770_asic = { }, }; -static struct radeon_asic_ring evergreen_gfx_ring = { +static const struct radeon_asic_ring evergreen_gfx_ring = { .ib_execute = &evergreen_ring_ib_execute, .emit_fence = &r600_fence_ring_emit, .emit_semaphore = &r600_semaphore_ring_emit, @@ -1318,7 +1318,7 @@ static struct radeon_asic_ring evergreen_gfx_ring = { .set_wptr = &r600_gfx_set_wptr, }; -static struct radeon_asic_ring evergreen_dma_ring = { +static const struct radeon_asic_ring evergreen_dma_ring = { .ib_execute = &evergreen_dma_ring_ib_execute, .emit_fence = &evergreen_dma_fence_ring_emit, .emit_semaphore = &r600_dma_semaphore_ring_emit, @@ -1612,7 +1612,7 @@ static struct radeon_asic btc_asic = { }, }; -static struct radeon_asic_ring cayman_gfx_ring = { +static const struct radeon_asic_ring cayman_gfx_ring = { .ib_execute = &cayman_ring_ib_execute, .ib_parse = &evergreen_ib_parse, .emit_fence = &cayman_fence_ring_emit, @@ -1627,7 +1627,7 @@ static struct radeon_asic_ring cayman_gfx_ring = { .set_wptr = &cayman_gfx_set_wptr, }; -static struct radeon_asic_ring cayman_dma_ring = { +static const struct radeon_asic_ring cayman_dma_ring = { .ib_execute = &cayman_dma_ring_ib_execute, .ib_parse = &evergreen_dma_ib_parse, .emit_fence = &evergreen_dma_fence_ring_emit, @@ -1642,7 +1642,7 @@ static struct radeon_asic_ring cayman_dma_ring = { .set_wptr = &cayman_dma_set_wptr }; -static struct radeon_asic_ring cayman_uvd_ring = { +static const struct radeon_asic_ring cayman_uvd_ring = { .ib_execute = &uvd_v1_0_ib_execute, .emit_fence = &uvd_v2_2_fence_emit, .emit_semaphore = &uvd_v3_1_semaphore_emit, @@ -1760,7 +1760,7 @@ static struct radeon_asic cayman_asic = { }, }; -static struct radeon_asic_ring trinity_vce_ring = { +static const struct radeon_asic_ring trinity_vce_ring = { .ib_execute = &radeon_vce_ib_execute, .emit_fence = &radeon_vce_fence_emit, .emit_semaphore = &radeon_vce_semaphore_emit, @@ -1881,7 +1881,7 @@ static struct radeon_asic trinity_asic = { }, }; -static struct radeon_asic_ring si_gfx_ring = { +static const struct radeon_asic_ring si_gfx_ring = { .ib_execute = &si_ring_ib_execute, .ib_parse = &si_ib_parse, .emit_fence = &si_fence_ring_emit, @@ -1896,7 +1896,7 @@ static struct radeon_asic_ring si_gfx_ring = { .set_wptr = &cayman_gfx_set_wptr, }; -static struct radeon_asic_ring si_dma_ring = { +static const struct radeon_asic_ring si_dma_ring = { .ib_execute = &cayman_dma_ring_ib_execute, .ib_parse = &evergreen_dma_ib_parse, .emit_fence = &evergreen_dma_fence_ring_emit, @@ -2023,7 +2023,7 @@ static struct radeon_asic si_asic = { }, }; -static struct radeon_asic_ring ci_gfx_ring = { +static const struct radeon_asic_ring ci_gfx_ring = { .ib_execute = &cik_ring_ib_execute, .ib_parse = &cik_ib_parse, .emit_fence = &cik_fence_gfx_ring_emit, @@ -2038,7 +2038,7 @@ static struct radeon_asic_ring ci_gfx_ring = { .set_wptr = &cik_gfx_set_wptr, }; -static struct radeon_asic_ring ci_cp_ring = { +static const struct radeon_asic_ring ci_cp_ring = { .ib_execute = &cik_ring_ib_execute, .ib_parse = &cik_ib_parse, .emit_fence = &cik_fence_compute_ring_emit, @@ -2053,7 +2053,7 @@ static struct radeon_asic_ring ci_cp_ring = { .set_wptr = &cik_compute_set_wptr, }; -static struct radeon_asic_ring ci_dma_ring = { +static const struct radeon_asic_ring ci_dma_ring = { .ib_execute = &cik_sdma_ring_ib_execute, .ib_parse = &cik_ib_parse, .emit_fence = &cik_sdma_fence_ring_emit, @@ -2068,7 +2068,7 @@ static struct radeon_asic_ring ci_dma_ring = { .set_wptr = &cik_sdma_set_wptr, }; -static struct radeon_asic_ring ci_vce_ring = { +static const struct radeon_asic_ring ci_vce_ring = { .ib_execute = &radeon_vce_ib_execute, .emit_fence = &radeon_vce_fence_emit, .emit_semaphore = &radeon_vce_semaphore_emit, diff --git a/drivers/gpu/drm/radeon/radeon_atombios.c b/drivers/gpu/drm/radeon/radeon_atombios.c index 8f285244c839..08fc1b5effa8 100644 --- a/drivers/gpu/drm/radeon/radeon_atombios.c +++ b/drivers/gpu/drm/radeon/radeon_atombios.c @@ -437,7 +437,9 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } /* Fujitsu D3003-S2 board lists DVI-I as DVI-D and VGA */ - if (((dev->pdev->device == 0x9802) || (dev->pdev->device == 0x9806)) && + if (((dev->pdev->device == 0x9802) || + (dev->pdev->device == 0x9805) || + (dev->pdev->device == 0x9806)) && (dev->pdev->subsystem_vendor == 0x1734) && (dev->pdev->subsystem_device == 0x11bd)) { if (*connector_type == DRM_MODE_CONNECTOR_VGA) { @@ -448,14 +450,6 @@ static bool radeon_atom_apply_quirks(struct drm_device *dev, } } - /* Fujitsu D3003-S2 board lists DVI-I as DVI-I and VGA */ - if ((dev->pdev->device == 0x9805) && - (dev->pdev->subsystem_vendor == 0x1734) && - (dev->pdev->subsystem_device == 0x11bd)) { - if (*connector_type == DRM_MODE_CONNECTOR_VGA) - return false; - } - return true; } @@ -1263,6 +1257,13 @@ bool radeon_atom_get_clock_info(struct drm_device *dev) rdev->mode_info.firmware_flags = le16_to_cpu(firmware_info->info.usFirmwareCapability.susAccess); + if (ASIC_IS_DCE8(rdev)) { + rdev->clock.gpupll_outputfreq = + le32_to_cpu(firmware_info->info_22.ulGPUPLL_OutputFreq); + if (rdev->clock.gpupll_outputfreq == 0) + rdev->clock.gpupll_outputfreq = 360000; /* 3.6 GHz */ + } + return true; } diff --git a/drivers/gpu/drm/radeon/radeon_cp.c b/drivers/gpu/drm/radeon/radeon_cp.c deleted file mode 100644 index 500287eff55d..000000000000 --- a/drivers/gpu/drm/radeon/radeon_cp.c +++ /dev/null @@ -1,2243 +0,0 @@ -/* radeon_cp.c -- CP support for Radeon -*- linux-c -*- */ -/* - * Copyright 2000 Precision Insight, Inc., Cedar Park, Texas. - * Copyright 2000 VA Linux Systems, Inc., Fremont, California. - * Copyright 2007 Advanced Micro Devices, Inc. - * All Rights Reserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: - * Kevin E. Martin <martin@valinux.com> - * Gareth Hughes <gareth@valinux.com> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <linux/module.h> - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" -#include "r300_reg.h" - -#define RADEON_FIFO_DEBUG 0 - -/* Firmware Names */ -#define FIRMWARE_R100 "radeon/R100_cp.bin" -#define FIRMWARE_R200 "radeon/R200_cp.bin" -#define FIRMWARE_R300 "radeon/R300_cp.bin" -#define FIRMWARE_R420 "radeon/R420_cp.bin" -#define FIRMWARE_RS690 "radeon/RS690_cp.bin" -#define FIRMWARE_RS600 "radeon/RS600_cp.bin" -#define FIRMWARE_R520 "radeon/R520_cp.bin" - -MODULE_FIRMWARE(FIRMWARE_R100); -MODULE_FIRMWARE(FIRMWARE_R200); -MODULE_FIRMWARE(FIRMWARE_R300); -MODULE_FIRMWARE(FIRMWARE_R420); -MODULE_FIRMWARE(FIRMWARE_RS690); -MODULE_FIRMWARE(FIRMWARE_RS600); -MODULE_FIRMWARE(FIRMWARE_R520); - -static int radeon_do_cleanup_cp(struct drm_device * dev); -static void radeon_do_cp_start(drm_radeon_private_t * dev_priv); - -u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off) -{ - u32 val; - - if (dev_priv->flags & RADEON_IS_AGP) { - val = DRM_READ32(dev_priv->ring_rptr, off); - } else { - val = *(((volatile u32 *) - dev_priv->ring_rptr->handle) + - (off / sizeof(u32))); - val = le32_to_cpu(val); - } - return val; -} - -u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv) -{ - if (dev_priv->writeback_works) - return radeon_read_ring_rptr(dev_priv, 0); - else { - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return RADEON_READ(R600_CP_RB_RPTR); - else - return RADEON_READ(RADEON_CP_RB_RPTR); - } -} - -void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val) -{ - if (dev_priv->flags & RADEON_IS_AGP) - DRM_WRITE32(dev_priv->ring_rptr, off, val); - else - *(((volatile u32 *) dev_priv->ring_rptr->handle) + - (off / sizeof(u32))) = cpu_to_le32(val); -} - -void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val) -{ - radeon_write_ring_rptr(dev_priv, 0, val); -} - -u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index) -{ - if (dev_priv->writeback_works) { - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return radeon_read_ring_rptr(dev_priv, - R600_SCRATCHOFF(index)); - else - return radeon_read_ring_rptr(dev_priv, - RADEON_SCRATCHOFF(index)); - } else { - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return RADEON_READ(R600_SCRATCH_REG0 + 4*index); - else - return RADEON_READ(RADEON_SCRATCH_REG0 + 4*index); - } -} - -static u32 R500_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) -{ - u32 ret; - RADEON_WRITE(R520_MC_IND_INDEX, 0x7f0000 | (addr & 0xff)); - ret = RADEON_READ(R520_MC_IND_DATA); - RADEON_WRITE(R520_MC_IND_INDEX, 0); - return ret; -} - -static u32 RS480_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) -{ - u32 ret; - RADEON_WRITE(RS480_NB_MC_INDEX, addr & 0xff); - ret = RADEON_READ(RS480_NB_MC_DATA); - RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); - return ret; -} - -static u32 RS690_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) -{ - u32 ret; - RADEON_WRITE(RS690_MC_INDEX, (addr & RS690_MC_INDEX_MASK)); - ret = RADEON_READ(RS690_MC_DATA); - RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_MASK); - return ret; -} - -static u32 RS600_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) -{ - u32 ret; - RADEON_WRITE(RS600_MC_INDEX, ((addr & RS600_MC_ADDR_MASK) | - RS600_MC_IND_CITF_ARB0)); - ret = RADEON_READ(RS600_MC_DATA); - return ret; -} - -static u32 IGP_READ_MCIND(drm_radeon_private_t *dev_priv, int addr) -{ - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) - return RS690_READ_MCIND(dev_priv, addr); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - return RS600_READ_MCIND(dev_priv, addr); - else - return RS480_READ_MCIND(dev_priv, addr); -} - -u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv) -{ - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) - return RADEON_READ(R700_MC_VM_FB_LOCATION); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return RADEON_READ(R600_MC_VM_FB_LOCATION); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) - return R500_READ_MCIND(dev_priv, RV515_MC_FB_LOCATION); - else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) - return RS690_READ_MCIND(dev_priv, RS690_MC_FB_LOCATION); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - return RS600_READ_MCIND(dev_priv, RS600_MC_FB_LOCATION); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) - return R500_READ_MCIND(dev_priv, R520_MC_FB_LOCATION); - else - return RADEON_READ(RADEON_MC_FB_LOCATION); -} - -static void radeon_write_fb_location(drm_radeon_private_t *dev_priv, u32 fb_loc) -{ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) - RADEON_WRITE(R700_MC_VM_FB_LOCATION, fb_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - RADEON_WRITE(R600_MC_VM_FB_LOCATION, fb_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) - R500_WRITE_MCIND(RV515_MC_FB_LOCATION, fb_loc); - else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) - RS690_WRITE_MCIND(RS690_MC_FB_LOCATION, fb_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - RS600_WRITE_MCIND(RS600_MC_FB_LOCATION, fb_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) - R500_WRITE_MCIND(R520_MC_FB_LOCATION, fb_loc); - else - RADEON_WRITE(RADEON_MC_FB_LOCATION, fb_loc); -} - -void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc) -{ - /*R6xx/R7xx: AGP_TOP and BOT are actually 18 bits each */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) { - RADEON_WRITE(R700_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */ - RADEON_WRITE(R700_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff); - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { - RADEON_WRITE(R600_MC_VM_AGP_BOT, agp_loc & 0xffff); /* FIX ME */ - RADEON_WRITE(R600_MC_VM_AGP_TOP, (agp_loc >> 16) & 0xffff); - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) - R500_WRITE_MCIND(RV515_MC_AGP_LOCATION, agp_loc); - else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) - RS690_WRITE_MCIND(RS690_MC_AGP_LOCATION, agp_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - RS600_WRITE_MCIND(RS600_MC_AGP_LOCATION, agp_loc); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) - R500_WRITE_MCIND(R520_MC_AGP_LOCATION, agp_loc); - else - RADEON_WRITE(RADEON_MC_AGP_LOCATION, agp_loc); -} - -void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base) -{ - u32 agp_base_hi = upper_32_bits(agp_base); - u32 agp_base_lo = agp_base & 0xffffffff; - u32 r6xx_agp_base = (agp_base >> 22) & 0x3ffff; - - /* R6xx/R7xx must be aligned to a 4MB boundary */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV770) - RADEON_WRITE(R700_MC_VM_AGP_BASE, r6xx_agp_base); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - RADEON_WRITE(R600_MC_VM_AGP_BASE, r6xx_agp_base); - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) { - R500_WRITE_MCIND(RV515_MC_AGP_BASE, agp_base_lo); - R500_WRITE_MCIND(RV515_MC_AGP_BASE_2, agp_base_hi); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { - RS690_WRITE_MCIND(RS690_MC_AGP_BASE, agp_base_lo); - RS690_WRITE_MCIND(RS690_MC_AGP_BASE_2, agp_base_hi); - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { - RS600_WRITE_MCIND(RS600_AGP_BASE, agp_base_lo); - RS600_WRITE_MCIND(RS600_AGP_BASE_2, agp_base_hi); - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) > CHIP_RV515) { - R500_WRITE_MCIND(R520_MC_AGP_BASE, agp_base_lo); - R500_WRITE_MCIND(R520_MC_AGP_BASE_2, agp_base_hi); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { - RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); - RADEON_WRITE(RS480_AGP_BASE_2, agp_base_hi); - } else { - RADEON_WRITE(RADEON_AGP_BASE, agp_base_lo); - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R200) - RADEON_WRITE(RADEON_AGP_BASE_2, agp_base_hi); - } -} - -void radeon_enable_bm(struct drm_radeon_private *dev_priv) -{ - u32 tmp; - /* Turn on bus mastering */ - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { - /* rs600/rs690/rs740 */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RS600_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV350) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { - /* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ - tmp = RADEON_READ(RADEON_BUS_CNTL) & ~RADEON_BUS_MASTER_DIS; - RADEON_WRITE(RADEON_BUS_CNTL, tmp); - } /* PCIE cards appears to not need this */ -} - -static int RADEON_READ_PLL(struct drm_device * dev, int addr) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, addr & 0x1f); - return RADEON_READ(RADEON_CLOCK_CNTL_DATA); -} - -static u32 RADEON_READ_PCIE(drm_radeon_private_t *dev_priv, int addr) -{ - RADEON_WRITE8(RADEON_PCIE_INDEX, addr & 0xff); - return RADEON_READ(RADEON_PCIE_DATA); -} - -#if RADEON_FIFO_DEBUG -static void radeon_status(drm_radeon_private_t * dev_priv) -{ - printk("%s:\n", __func__); - printk("RBBM_STATUS = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_RBBM_STATUS)); - printk("CP_RB_RTPR = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_CP_RB_RPTR)); - printk("CP_RB_WTPR = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_CP_RB_WPTR)); - printk("AIC_CNTL = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_AIC_CNTL)); - printk("AIC_STAT = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_AIC_STAT)); - printk("AIC_PT_BASE = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_AIC_PT_BASE)); - printk("TLB_ADDR = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_AIC_TLB_ADDR)); - printk("TLB_DATA = 0x%08x\n", - (unsigned int)RADEON_READ(RADEON_AIC_TLB_DATA)); -} -#endif - -/* ================================================================ - * Engine, FIFO control - */ - -static int radeon_do_pixcache_flush(drm_radeon_private_t * dev_priv) -{ - u32 tmp; - int i; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { - tmp = RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT); - tmp |= RADEON_RB3D_DC_FLUSH_ALL; - RADEON_WRITE(RADEON_RB3D_DSTCACHE_CTLSTAT, tmp); - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(RADEON_READ(RADEON_RB3D_DSTCACHE_CTLSTAT) - & RADEON_RB3D_DC_BUSY)) { - return 0; - } - DRM_UDELAY(1); - } - } else { - /* don't flush or purge cache here or lockup */ - return 0; - } - -#if RADEON_FIFO_DEBUG - DRM_ERROR("failed!\n"); - radeon_status(dev_priv); -#endif - return -EBUSY; -} - -static int radeon_do_wait_for_fifo(drm_radeon_private_t * dev_priv, int entries) -{ - int i; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - int slots = (RADEON_READ(RADEON_RBBM_STATUS) - & RADEON_RBBM_FIFOCNT_MASK); - if (slots >= entries) - return 0; - DRM_UDELAY(1); - } - DRM_DEBUG("wait for fifo failed status : 0x%08X 0x%08X\n", - RADEON_READ(RADEON_RBBM_STATUS), - RADEON_READ(R300_VAP_CNTL_STATUS)); - -#if RADEON_FIFO_DEBUG - DRM_ERROR("failed!\n"); - radeon_status(dev_priv); -#endif - return -EBUSY; -} - -static int radeon_do_wait_for_idle(drm_radeon_private_t * dev_priv) -{ - int i, ret; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - ret = radeon_do_wait_for_fifo(dev_priv, 64); - if (ret) - return ret; - - for (i = 0; i < dev_priv->usec_timeout; i++) { - if (!(RADEON_READ(RADEON_RBBM_STATUS) - & RADEON_RBBM_ACTIVE)) { - radeon_do_pixcache_flush(dev_priv); - return 0; - } - DRM_UDELAY(1); - } - DRM_DEBUG("wait idle failed status : 0x%08X 0x%08X\n", - RADEON_READ(RADEON_RBBM_STATUS), - RADEON_READ(R300_VAP_CNTL_STATUS)); - -#if RADEON_FIFO_DEBUG - DRM_ERROR("failed!\n"); - radeon_status(dev_priv); -#endif - return -EBUSY; -} - -static void radeon_init_pipes(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - uint32_t gb_tile_config, gb_pipe_sel = 0; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) { - uint32_t z_pipe_sel = RADEON_READ(RV530_GB_PIPE_SELECT2); - if ((z_pipe_sel & 3) == 3) - dev_priv->num_z_pipes = 2; - else - dev_priv->num_z_pipes = 1; - } else - dev_priv->num_z_pipes = 1; - - /* RS4xx/RS6xx/R4xx/R5xx */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R420) { - gb_pipe_sel = RADEON_READ(R400_GB_PIPE_SELECT); - dev_priv->num_gb_pipes = ((gb_pipe_sel >> 12) & 0x3) + 1; - /* SE cards have 1 pipe */ - if ((dev->pdev->device == 0x5e4c) || - (dev->pdev->device == 0x5e4f)) - dev_priv->num_gb_pipes = 1; - } else { - /* R3xx */ - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300 && - dev->pdev->device != 0x4144) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350 && - dev->pdev->device != 0x4148)) { - dev_priv->num_gb_pipes = 2; - } else { - /* RV3xx/R300 AD/R350 AH */ - dev_priv->num_gb_pipes = 1; - } - } - DRM_INFO("Num pipes: %d\n", dev_priv->num_gb_pipes); - - gb_tile_config = (R300_ENABLE_TILING | R300_TILE_SIZE_16 /*| R300_SUBPIXEL_1_16*/); - - switch (dev_priv->num_gb_pipes) { - case 2: gb_tile_config |= R300_PIPE_COUNT_R300; break; - case 3: gb_tile_config |= R300_PIPE_COUNT_R420_3P; break; - case 4: gb_tile_config |= R300_PIPE_COUNT_R420; break; - default: - case 1: gb_tile_config |= R300_PIPE_COUNT_RV350; break; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RV515) { - RADEON_WRITE_PLL(R500_DYN_SCLK_PWMEM_PIPE, (1 | ((gb_pipe_sel >> 8) & 0xf) << 4)); - RADEON_WRITE(R300_SU_REG_DEST, ((1 << dev_priv->num_gb_pipes) - 1)); - } - RADEON_WRITE(R300_GB_TILE_CONFIG, gb_tile_config); - radeon_do_wait_for_idle(dev_priv); - RADEON_WRITE(R300_DST_PIPE_CONFIG, RADEON_READ(R300_DST_PIPE_CONFIG) | R300_PIPE_AUTO_CONFIG); - RADEON_WRITE(R300_RB2D_DSTCACHE_MODE, (RADEON_READ(R300_RB2D_DSTCACHE_MODE) | - R300_DC_AUTOFLUSH_ENABLE | - R300_DC_DC_DISABLE_IGNORE_PE)); - - -} - -/* ================================================================ - * CP control, initialization - */ - -/* Load the microcode for the CP */ -static int radeon_cp_init_microcode(drm_radeon_private_t *dev_priv) -{ - struct platform_device *pdev; - const char *fw_name = NULL; - int err; - - DRM_DEBUG("\n"); - - pdev = platform_device_register_simple("radeon_cp", 0, NULL, 0); - err = IS_ERR(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to register firmware\n"); - return -EINVAL; - } - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R100) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV100) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV200) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS100) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS200)) { - DRM_INFO("Loading R100 Microcode\n"); - fw_name = FIRMWARE_R100; - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R200) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV250) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV280) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS300)) { - DRM_INFO("Loading R200 Microcode\n"); - fw_name = FIRMWARE_R200; - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R300) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R350) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV350) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV380) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS400) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS480)) { - DRM_INFO("Loading R300 Microcode\n"); - fw_name = FIRMWARE_R300; - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R423) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV410)) { - DRM_INFO("Loading R400 Microcode\n"); - fw_name = FIRMWARE_R420; - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) { - DRM_INFO("Loading RS690/RS740 Microcode\n"); - fw_name = FIRMWARE_RS690; - } else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { - DRM_INFO("Loading RS600 Microcode\n"); - fw_name = FIRMWARE_RS600; - } else if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV515) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R520) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV530) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R580) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV560) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RV570)) { - DRM_INFO("Loading R500 Microcode\n"); - fw_name = FIRMWARE_R520; - } - - err = request_firmware(&dev_priv->me_fw, fw_name, &pdev->dev); - platform_device_unregister(pdev); - if (err) { - printk(KERN_ERR "radeon_cp: Failed to load firmware \"%s\"\n", - fw_name); - } else if (dev_priv->me_fw->size % 8) { - printk(KERN_ERR - "radeon_cp: Bogus length %zu in firmware \"%s\"\n", - dev_priv->me_fw->size, fw_name); - err = -EINVAL; - release_firmware(dev_priv->me_fw); - dev_priv->me_fw = NULL; - } - return err; -} - -static void radeon_cp_load_microcode(drm_radeon_private_t *dev_priv) -{ - const __be32 *fw_data; - int i, size; - - radeon_do_wait_for_idle(dev_priv); - - if (dev_priv->me_fw) { - size = dev_priv->me_fw->size / 4; - fw_data = (const __be32 *)&dev_priv->me_fw->data[0]; - RADEON_WRITE(RADEON_CP_ME_RAM_ADDR, 0); - for (i = 0; i < size; i += 2) { - RADEON_WRITE(RADEON_CP_ME_RAM_DATAH, - be32_to_cpup(&fw_data[i])); - RADEON_WRITE(RADEON_CP_ME_RAM_DATAL, - be32_to_cpup(&fw_data[i + 1])); - } - } -} - -/* Flush any pending commands to the CP. This should only be used just - * prior to a wait for idle, as it informs the engine that the command - * stream is ending. - */ -static void radeon_do_cp_flush(drm_radeon_private_t * dev_priv) -{ - DRM_DEBUG("\n"); -#if 0 - u32 tmp; - - tmp = RADEON_READ(RADEON_CP_RB_WPTR) | (1 << 31); - RADEON_WRITE(RADEON_CP_RB_WPTR, tmp); -#endif -} - -/* Wait for the CP to go idle. - */ -int radeon_do_cp_idle(drm_radeon_private_t * dev_priv) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(6); - - RADEON_PURGE_CACHE(); - RADEON_PURGE_ZCACHE(); - RADEON_WAIT_UNTIL_IDLE(); - - ADVANCE_RING(); - COMMIT_RING(); - - return radeon_do_wait_for_idle(dev_priv); -} - -/* Start the Command Processor. - */ -static void radeon_do_cp_start(drm_radeon_private_t * dev_priv) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - radeon_do_wait_for_idle(dev_priv); - - RADEON_WRITE(RADEON_CP_CSQ_CNTL, dev_priv->cp_mode); - - dev_priv->cp_running = 1; - - /* on r420, any DMA from CP to system memory while 2D is active - * can cause a hang. workaround is to queue a CP RESYNC token - */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { - BEGIN_RING(3); - OUT_RING(CP_PACKET0(R300_CP_RESYNC_ADDR, 1)); - OUT_RING(5); /* scratch reg 5 */ - OUT_RING(0xdeadbeef); - ADVANCE_RING(); - COMMIT_RING(); - } - - BEGIN_RING(8); - /* isync can only be written through cp on r5xx write it here */ - OUT_RING(CP_PACKET0(RADEON_ISYNC_CNTL, 0)); - OUT_RING(RADEON_ISYNC_ANY2D_IDLE3D | - RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI); - RADEON_PURGE_CACHE(); - RADEON_PURGE_ZCACHE(); - RADEON_WAIT_UNTIL_IDLE(); - ADVANCE_RING(); - COMMIT_RING(); - - dev_priv->track_flush |= RADEON_FLUSH_EMITED | RADEON_PURGE_EMITED; -} - -/* Reset the Command Processor. This will not flush any pending - * commands, so you must wait for the CP command stream to complete - * before calling this routine. - */ -static void radeon_do_cp_reset(drm_radeon_private_t * dev_priv) -{ - u32 cur_read_ptr; - DRM_DEBUG("\n"); - - cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); - RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); - SET_RING_HEAD(dev_priv, cur_read_ptr); - dev_priv->ring.tail = cur_read_ptr; -} - -/* Stop the Command Processor. This will not flush any pending - * commands, so you must flush the command stream and wait for the CP - * to go idle before calling this routine. - */ -static void radeon_do_cp_stop(drm_radeon_private_t * dev_priv) -{ - RING_LOCALS; - DRM_DEBUG("\n"); - - /* finish the pending CP_RESYNC token */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_R420) { - BEGIN_RING(2); - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); - OUT_RING(R300_RB3D_DC_FINISH); - ADVANCE_RING(); - COMMIT_RING(); - radeon_do_wait_for_idle(dev_priv); - } - - RADEON_WRITE(RADEON_CP_CSQ_CNTL, RADEON_CSQ_PRIDIS_INDDIS); - - dev_priv->cp_running = 0; -} - -/* Reset the engine. This will stop the CP if it is running. - */ -static int radeon_do_engine_reset(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - u32 clock_cntl_index = 0, mclk_cntl = 0, rbbm_soft_reset; - DRM_DEBUG("\n"); - - radeon_do_pixcache_flush(dev_priv); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { - /* may need something similar for newer chips */ - clock_cntl_index = RADEON_READ(RADEON_CLOCK_CNTL_INDEX); - mclk_cntl = RADEON_READ_PLL(dev, RADEON_MCLK_CNTL); - - RADEON_WRITE_PLL(RADEON_MCLK_CNTL, (mclk_cntl | - RADEON_FORCEON_MCLKA | - RADEON_FORCEON_MCLKB | - RADEON_FORCEON_YCLKA | - RADEON_FORCEON_YCLKB | - RADEON_FORCEON_MC | - RADEON_FORCEON_AIC)); - } - - rbbm_soft_reset = RADEON_READ(RADEON_RBBM_SOFT_RESET); - - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset | - RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB)); - RADEON_READ(RADEON_RBBM_SOFT_RESET); - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, (rbbm_soft_reset & - ~(RADEON_SOFT_RESET_CP | - RADEON_SOFT_RESET_HI | - RADEON_SOFT_RESET_SE | - RADEON_SOFT_RESET_RE | - RADEON_SOFT_RESET_PP | - RADEON_SOFT_RESET_E2 | - RADEON_SOFT_RESET_RB))); - RADEON_READ(RADEON_RBBM_SOFT_RESET); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV410) { - RADEON_WRITE_PLL(RADEON_MCLK_CNTL, mclk_cntl); - RADEON_WRITE(RADEON_CLOCK_CNTL_INDEX, clock_cntl_index); - RADEON_WRITE(RADEON_RBBM_SOFT_RESET, rbbm_soft_reset); - } - - /* setup the raster pipes */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R300) - radeon_init_pipes(dev); - - /* Reset the CP ring */ - radeon_do_cp_reset(dev_priv); - - /* The CP is no longer running after an engine reset */ - dev_priv->cp_running = 0; - - /* Reset any pending vertex, indirect buffers */ - radeon_freelist_reset(dev); - - return 0; -} - -static void radeon_cp_init_ring_buffer(struct drm_device * dev, - drm_radeon_private_t *dev_priv, - struct drm_file *file_priv) -{ - struct drm_radeon_master_private *master_priv; - u32 ring_start, cur_read_ptr; - - /* Initialize the memory controller. With new memory map, the fb location - * is not changed, it should have been properly initialized already. Part - * of the problem is that the code below is bogus, assuming the GART is - * always appended to the fb which is not necessarily the case - */ - if (!dev_priv->new_memmap) - radeon_write_fb_location(dev_priv, - ((dev_priv->gart_vm_start - 1) & 0xffff0000) - | (dev_priv->fb_location >> 16)); - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - radeon_write_agp_base(dev_priv, dev->agp->base); - - radeon_write_agp_location(dev_priv, - (((dev_priv->gart_vm_start - 1 + - dev_priv->gart_size) & 0xffff0000) | - (dev_priv->gart_vm_start >> 16))); - - ring_start = (dev_priv->cp_ring->offset - - dev->agp->base - + dev_priv->gart_vm_start); - } else -#endif - ring_start = (dev_priv->cp_ring->offset - - (unsigned long)dev->sg->virtual - + dev_priv->gart_vm_start); - - RADEON_WRITE(RADEON_CP_RB_BASE, ring_start); - - /* Set the write pointer delay */ - RADEON_WRITE(RADEON_CP_RB_WPTR_DELAY, 0); - - /* Initialize the ring buffer's read and write pointers */ - cur_read_ptr = RADEON_READ(RADEON_CP_RB_RPTR); - RADEON_WRITE(RADEON_CP_RB_WPTR, cur_read_ptr); - SET_RING_HEAD(dev_priv, cur_read_ptr); - dev_priv->ring.tail = cur_read_ptr; - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, - dev_priv->ring_rptr->offset - - dev->agp->base + dev_priv->gart_vm_start); - } else -#endif - { - RADEON_WRITE(RADEON_CP_RB_RPTR_ADDR, - dev_priv->ring_rptr->offset - - ((unsigned long) dev->sg->virtual) - + dev_priv->gart_vm_start); - } - - /* Set ring buffer size */ -#ifdef __BIG_ENDIAN - RADEON_WRITE(RADEON_CP_RB_CNTL, - RADEON_BUF_SWAP_32BIT | - (dev_priv->ring.fetch_size_l2ow << 18) | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#else - RADEON_WRITE(RADEON_CP_RB_CNTL, - (dev_priv->ring.fetch_size_l2ow << 18) | - (dev_priv->ring.rptr_update_l2qw << 8) | - dev_priv->ring.size_l2qw); -#endif - - - /* Initialize the scratch register pointer. This will cause - * the scratch register values to be written out to memory - * whenever they are updated. - * - * We simply put this behind the ring read pointer, this works - * with PCI GART as well as (whatever kind of) AGP GART - */ - RADEON_WRITE(RADEON_SCRATCH_ADDR, RADEON_READ(RADEON_CP_RB_RPTR_ADDR) - + RADEON_SCRATCH_REG_OFFSET); - - RADEON_WRITE(RADEON_SCRATCH_UMSK, 0x7); - - radeon_enable_bm(dev_priv); - - radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(0), 0); - RADEON_WRITE(RADEON_LAST_FRAME_REG, 0); - - radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0); - RADEON_WRITE(RADEON_LAST_DISPATCH_REG, 0); - - radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(2), 0); - RADEON_WRITE(RADEON_LAST_CLEAR_REG, 0); - - /* reset sarea copies of these */ - master_priv = file_priv->master->driver_priv; - if (master_priv->sarea_priv) { - master_priv->sarea_priv->last_frame = 0; - master_priv->sarea_priv->last_dispatch = 0; - master_priv->sarea_priv->last_clear = 0; - } - - radeon_do_wait_for_idle(dev_priv); - - /* Sync everything up */ - RADEON_WRITE(RADEON_ISYNC_CNTL, - (RADEON_ISYNC_ANY2D_IDLE3D | - RADEON_ISYNC_ANY3D_IDLE2D | - RADEON_ISYNC_WAIT_IDLEGUI | - RADEON_ISYNC_CPSCRATCH_IDLEGUI)); - -} - -static void radeon_test_writeback(drm_radeon_private_t * dev_priv) -{ - u32 tmp; - - /* Start with assuming that writeback doesn't work */ - dev_priv->writeback_works = 0; - - /* Writeback doesn't seem to work everywhere, test it here and possibly - * enable it if it appears to work - */ - radeon_write_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1), 0); - - RADEON_WRITE(RADEON_SCRATCH_REG1, 0xdeadbeef); - - for (tmp = 0; tmp < dev_priv->usec_timeout; tmp++) { - u32 val; - - val = radeon_read_ring_rptr(dev_priv, RADEON_SCRATCHOFF(1)); - if (val == 0xdeadbeef) - break; - DRM_UDELAY(1); - } - - if (tmp < dev_priv->usec_timeout) { - dev_priv->writeback_works = 1; - DRM_INFO("writeback test succeeded in %d usecs\n", tmp); - } else { - dev_priv->writeback_works = 0; - DRM_INFO("writeback test failed\n"); - } - if (radeon_no_wb == 1) { - dev_priv->writeback_works = 0; - DRM_INFO("writeback forced off\n"); - } - - if (!dev_priv->writeback_works) { - /* Disable writeback to avoid unnecessary bus master transfer */ - RADEON_WRITE(RADEON_CP_RB_CNTL, RADEON_READ(RADEON_CP_RB_CNTL) | - RADEON_RB_NO_UPDATE); - RADEON_WRITE(RADEON_SCRATCH_UMSK, 0); - } -} - -/* Enable or disable IGP GART on the chip */ -static void radeon_set_igpgart(drm_radeon_private_t * dev_priv, int on) -{ - u32 temp; - - if (on) { - DRM_DEBUG("programming igp gart %08X %08lX %08X\n", - dev_priv->gart_vm_start, - (long)dev_priv->gart_info.bus_addr, - dev_priv->gart_size); - - temp = IGP_READ_MCIND(dev_priv, RS480_MC_MISC_CNTL); - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) - IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, (RS480_GART_INDEX_REG_EN | - RS690_BLOCK_GFX_D3_EN)); - else - IGP_WRITE_MCIND(RS480_MC_MISC_CNTL, RS480_GART_INDEX_REG_EN); - - IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | - RS480_VA_SIZE_32MB)); - - temp = IGP_READ_MCIND(dev_priv, RS480_GART_FEATURE_ID); - IGP_WRITE_MCIND(RS480_GART_FEATURE_ID, (RS480_HANG_EN | - RS480_TLB_ENABLE | - RS480_GTW_LAC_EN | - RS480_1LEVEL_GART)); - - temp = dev_priv->gart_info.bus_addr & 0xfffff000; - temp |= (upper_32_bits(dev_priv->gart_info.bus_addr) & 0xff) << 4; - IGP_WRITE_MCIND(RS480_GART_BASE, temp); - - temp = IGP_READ_MCIND(dev_priv, RS480_AGP_MODE_CNTL); - IGP_WRITE_MCIND(RS480_AGP_MODE_CNTL, ((1 << RS480_REQ_TYPE_SNOOP_SHIFT) | - RS480_REQ_TYPE_SNOOP_DIS)); - - radeon_write_agp_base(dev_priv, dev_priv->gart_vm_start); - - dev_priv->gart_size = 32*1024*1024; - temp = (((dev_priv->gart_vm_start - 1 + dev_priv->gart_size) & - 0xffff0000) | (dev_priv->gart_vm_start >> 16)); - - radeon_write_agp_location(dev_priv, temp); - - temp = IGP_READ_MCIND(dev_priv, RS480_AGP_ADDRESS_SPACE_SIZE); - IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, (RS480_GART_EN | - RS480_VA_SIZE_32MB)); - - do { - temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); - if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) - break; - DRM_UDELAY(1); - } while (1); - - IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, - RS480_GART_CACHE_INVALIDATE); - - do { - temp = IGP_READ_MCIND(dev_priv, RS480_GART_CACHE_CNTRL); - if ((temp & RS480_GART_CACHE_INVALIDATE) == 0) - break; - DRM_UDELAY(1); - } while (1); - - IGP_WRITE_MCIND(RS480_GART_CACHE_CNTRL, 0); - } else { - IGP_WRITE_MCIND(RS480_AGP_ADDRESS_SPACE_SIZE, 0); - } -} - -/* Enable or disable IGP GART on the chip */ -static void rs600_set_igpgart(drm_radeon_private_t *dev_priv, int on) -{ - u32 temp; - int i; - - if (on) { - DRM_DEBUG("programming igp gart %08X %08lX %08X\n", - dev_priv->gart_vm_start, - (long)dev_priv->gart_info.bus_addr, - dev_priv->gart_size); - - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (RS600_EFFECTIVE_L2_CACHE_SIZE(6) | - RS600_EFFECTIVE_L2_QUEUE_SIZE(6))); - - for (i = 0; i < 19; i++) - IGP_WRITE_MCIND(RS600_MC_PT0_CLIENT0_CNTL + i, - (RS600_ENABLE_TRANSLATION_MODE_OVERRIDE | - RS600_SYSTEM_ACCESS_MODE_IN_SYS | - RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH | - RS600_EFFECTIVE_L1_CACHE_SIZE(3) | - RS600_ENABLE_FRAGMENT_PROCESSING | - RS600_EFFECTIVE_L1_QUEUE_SIZE(3))); - - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL, (RS600_ENABLE_PAGE_TABLE | - RS600_PAGE_TABLE_TYPE_FLAT)); - - /* disable all other contexts */ - for (i = 1; i < 8; i++) - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_CNTL + i, 0); - - /* setup the page table aperture */ - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR, - dev_priv->gart_info.bus_addr); - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR, - dev_priv->gart_vm_start); - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR, - (dev_priv->gart_vm_start + dev_priv->gart_size - 1)); - IGP_WRITE_MCIND(RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR, 0); - - /* setup the system aperture */ - IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR, - dev_priv->gart_vm_start); - IGP_WRITE_MCIND(RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR, - (dev_priv->gart_vm_start + dev_priv->gart_size - 1)); - - /* enable page tables */ - temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, (temp | RS600_ENABLE_PT)); - - temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); - IGP_WRITE_MCIND(RS600_MC_CNTL1, (temp | RS600_ENABLE_PAGE_TABLES)); - - /* invalidate the cache */ - temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); - - temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); - temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); - - temp |= RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE; - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); - temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); - - temp &= ~(RS600_INVALIDATE_ALL_L1_TLBS | RS600_INVALIDATE_L2_CACHE); - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, temp); - temp = IGP_READ_MCIND(dev_priv, RS600_MC_PT0_CNTL); - - } else { - IGP_WRITE_MCIND(RS600_MC_PT0_CNTL, 0); - temp = IGP_READ_MCIND(dev_priv, RS600_MC_CNTL1); - temp &= ~RS600_ENABLE_PAGE_TABLES; - IGP_WRITE_MCIND(RS600_MC_CNTL1, temp); - } -} - -static void radeon_set_pciegart(drm_radeon_private_t * dev_priv, int on) -{ - u32 tmp = RADEON_READ_PCIE(dev_priv, RADEON_PCIE_TX_GART_CNTL); - if (on) { - - DRM_DEBUG("programming pcie %08X %08lX %08X\n", - dev_priv->gart_vm_start, - (long)dev_priv->gart_info.bus_addr, - dev_priv->gart_size); - RADEON_WRITE_PCIE(RADEON_PCIE_TX_DISCARD_RD_ADDR_LO, - dev_priv->gart_vm_start); - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_BASE, - dev_priv->gart_info.bus_addr); - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_START_LO, - dev_priv->gart_vm_start); - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_END_LO, - dev_priv->gart_vm_start + - dev_priv->gart_size - 1); - - radeon_write_agp_location(dev_priv, 0xffffffc0); /* ?? */ - - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, - RADEON_PCIE_TX_GART_EN); - } else { - RADEON_WRITE_PCIE(RADEON_PCIE_TX_GART_CNTL, - tmp & ~RADEON_PCIE_TX_GART_EN); - } -} - -/* Enable or disable PCI GART on the chip */ -static void radeon_set_pcigart(drm_radeon_private_t * dev_priv, int on) -{ - u32 tmp; - - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740) || - (dev_priv->flags & RADEON_IS_IGPGART)) { - radeon_set_igpgart(dev_priv, on); - return; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) { - rs600_set_igpgart(dev_priv, on); - return; - } - - if (dev_priv->flags & RADEON_IS_PCIE) { - radeon_set_pciegart(dev_priv, on); - return; - } - - tmp = RADEON_READ(RADEON_AIC_CNTL); - - if (on) { - RADEON_WRITE(RADEON_AIC_CNTL, - tmp | RADEON_PCIGART_TRANSLATE_EN); - - /* set PCI GART page-table base address - */ - RADEON_WRITE(RADEON_AIC_PT_BASE, dev_priv->gart_info.bus_addr); - - /* set address range for PCI address translate - */ - RADEON_WRITE(RADEON_AIC_LO_ADDR, dev_priv->gart_vm_start); - RADEON_WRITE(RADEON_AIC_HI_ADDR, dev_priv->gart_vm_start - + dev_priv->gart_size - 1); - - /* Turn off AGP aperture -- is this required for PCI GART? - */ - radeon_write_agp_location(dev_priv, 0xffffffc0); - RADEON_WRITE(RADEON_AGP_COMMAND, 0); /* clear AGP_COMMAND */ - } else { - RADEON_WRITE(RADEON_AIC_CNTL, - tmp & ~RADEON_PCIGART_TRANSLATE_EN); - } -} - -static int radeon_setup_pcigart_surface(drm_radeon_private_t *dev_priv) -{ - struct drm_ati_pcigart_info *gart_info = &dev_priv->gart_info; - struct radeon_virt_surface *vp; - int i; - - for (i = 0; i < RADEON_MAX_SURFACES * 2; i++) { - if (!dev_priv->virt_surfaces[i].file_priv || - dev_priv->virt_surfaces[i].file_priv == PCIGART_FILE_PRIV) - break; - } - if (i >= 2 * RADEON_MAX_SURFACES) - return -ENOMEM; - vp = &dev_priv->virt_surfaces[i]; - - for (i = 0; i < RADEON_MAX_SURFACES; i++) { - struct radeon_surface *sp = &dev_priv->surfaces[i]; - if (sp->refcount) - continue; - - vp->surface_index = i; - vp->lower = gart_info->bus_addr; - vp->upper = vp->lower + gart_info->table_size; - vp->flags = 0; - vp->file_priv = PCIGART_FILE_PRIV; - - sp->refcount = 1; - sp->lower = vp->lower; - sp->upper = vp->upper; - sp->flags = 0; - - RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, sp->flags); - RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * i, sp->lower); - RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * i, sp->upper); - return 0; - } - - return -ENOMEM; -} - -static int radeon_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, - struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - - DRM_DEBUG("\n"); - - /* if we require new memory map but we don't have it fail */ - if ((dev_priv->flags & RADEON_NEW_MEMMAP) && !dev_priv->new_memmap) { - DRM_ERROR("Cannot initialise DRM on this card\nThis card requires a new X.org DDX for 3D\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - if (init->is_pci && (dev_priv->flags & RADEON_IS_AGP)) { - DRM_DEBUG("Forcing AGP card to PCI mode\n"); - dev_priv->flags &= ~RADEON_IS_AGP; - } else if (!(dev_priv->flags & (RADEON_IS_AGP | RADEON_IS_PCI | RADEON_IS_PCIE)) - && !init->is_pci) { - DRM_DEBUG("Restoring AGP flag\n"); - dev_priv->flags |= RADEON_IS_AGP; - } - - if ((!(dev_priv->flags & RADEON_IS_AGP)) && !dev->sg) { - DRM_ERROR("PCI GART memory not allocated!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - dev_priv->usec_timeout = init->usec_timeout; - if (dev_priv->usec_timeout < 1 || - dev_priv->usec_timeout > RADEON_MAX_USEC_TIMEOUT) { - DRM_DEBUG("TIMEOUT problem!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - /* Enable vblank on CRTC1 for older X servers - */ - dev_priv->vblank_crtc = DRM_RADEON_VBLANK_CRTC1; - - switch(init->func) { - case RADEON_INIT_R200_CP: - dev_priv->microcode_version = UCODE_R200; - break; - case RADEON_INIT_R300_CP: - dev_priv->microcode_version = UCODE_R300; - break; - default: - dev_priv->microcode_version = UCODE_R100; - } - - dev_priv->do_boxes = 0; - dev_priv->cp_mode = init->cp_mode; - - /* We don't support anything other than bus-mastering ring mode, - * but the ring can be in either AGP or PCI space for the ring - * read pointer. - */ - if ((init->cp_mode != RADEON_CSQ_PRIBM_INDDIS) && - (init->cp_mode != RADEON_CSQ_PRIBM_INDBM)) { - DRM_DEBUG("BAD cp_mode (%x)!\n", init->cp_mode); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - switch (init->fb_bpp) { - case 16: - dev_priv->color_fmt = RADEON_COLOR_FORMAT_RGB565; - break; - case 32: - default: - dev_priv->color_fmt = RADEON_COLOR_FORMAT_ARGB8888; - break; - } - dev_priv->front_offset = init->front_offset; - dev_priv->front_pitch = init->front_pitch; - dev_priv->back_offset = init->back_offset; - dev_priv->back_pitch = init->back_pitch; - - switch (init->depth_bpp) { - case 16: - dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_16BIT_INT_Z; - break; - case 32: - default: - dev_priv->depth_fmt = RADEON_DEPTH_FORMAT_24BIT_INT_Z; - break; - } - dev_priv->depth_offset = init->depth_offset; - dev_priv->depth_pitch = init->depth_pitch; - - /* Hardware state for depth clears. Remove this if/when we no - * longer clear the depth buffer with a 3D rectangle. Hard-code - * all values to prevent unwanted 3D state from slipping through - * and screwing with the clear operation. - */ - dev_priv->depth_clear.rb3d_cntl = (RADEON_PLANE_MASK_ENABLE | - (dev_priv->color_fmt << 10) | - (dev_priv->microcode_version == - UCODE_R100 ? RADEON_ZBLOCK16 : 0)); - - dev_priv->depth_clear.rb3d_zstencilcntl = - (dev_priv->depth_fmt | - RADEON_Z_TEST_ALWAYS | - RADEON_STENCIL_TEST_ALWAYS | - RADEON_STENCIL_S_FAIL_REPLACE | - RADEON_STENCIL_ZPASS_REPLACE | - RADEON_STENCIL_ZFAIL_REPLACE | RADEON_Z_WRITE_ENABLE); - - dev_priv->depth_clear.se_cntl = (RADEON_FFACE_CULL_CW | - RADEON_BFACE_SOLID | - RADEON_FFACE_SOLID | - RADEON_FLAT_SHADE_VTX_LAST | - RADEON_DIFFUSE_SHADE_FLAT | - RADEON_ALPHA_SHADE_FLAT | - RADEON_SPECULAR_SHADE_FLAT | - RADEON_FOG_SHADE_FLAT | - RADEON_VTX_PIX_CENTER_OGL | - RADEON_ROUND_MODE_TRUNC | - RADEON_ROUND_PREC_8TH_PIX); - - - dev_priv->ring_offset = init->ring_offset; - dev_priv->ring_rptr_offset = init->ring_rptr_offset; - dev_priv->buffers_offset = init->buffers_offset; - dev_priv->gart_textures_offset = init->gart_textures_offset; - - master_priv->sarea = drm_legacy_getsarea(dev); - if (!master_priv->sarea) { - DRM_ERROR("could not find sarea!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - dev_priv->cp_ring = drm_legacy_findmap(dev, init->ring_offset); - if (!dev_priv->cp_ring) { - DRM_ERROR("could not find cp ring region!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - dev_priv->ring_rptr = drm_legacy_findmap(dev, init->ring_rptr_offset); - if (!dev_priv->ring_rptr) { - DRM_ERROR("could not find ring read pointer!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - dev->agp_buffer_token = init->buffers_offset; - dev->agp_buffer_map = drm_legacy_findmap(dev, init->buffers_offset); - if (!dev->agp_buffer_map) { - DRM_ERROR("could not find dma buffer region!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - - if (init->gart_textures_offset) { - dev_priv->gart_textures = - drm_legacy_findmap(dev, init->gart_textures_offset); - if (!dev_priv->gart_textures) { - DRM_ERROR("could not find GART texture region!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - } - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - drm_legacy_ioremap_wc(dev_priv->cp_ring, dev); - drm_legacy_ioremap_wc(dev_priv->ring_rptr, dev); - drm_legacy_ioremap_wc(dev->agp_buffer_map, dev); - if (!dev_priv->cp_ring->handle || - !dev_priv->ring_rptr->handle || - !dev->agp_buffer_map->handle) { - DRM_ERROR("could not find ioremap agp regions!\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - } else -#endif - { - dev_priv->cp_ring->handle = - (void *)(unsigned long)dev_priv->cp_ring->offset; - dev_priv->ring_rptr->handle = - (void *)(unsigned long)dev_priv->ring_rptr->offset; - dev->agp_buffer_map->handle = - (void *)(unsigned long)dev->agp_buffer_map->offset; - - DRM_DEBUG("dev_priv->cp_ring->handle %p\n", - dev_priv->cp_ring->handle); - DRM_DEBUG("dev_priv->ring_rptr->handle %p\n", - dev_priv->ring_rptr->handle); - DRM_DEBUG("dev->agp_buffer_map->handle %p\n", - dev->agp_buffer_map->handle); - } - - dev_priv->fb_location = (radeon_read_fb_location(dev_priv) & 0xffff) << 16; - dev_priv->fb_size = - ((radeon_read_fb_location(dev_priv) & 0xffff0000u) + 0x10000) - - dev_priv->fb_location; - - dev_priv->front_pitch_offset = (((dev_priv->front_pitch / 64) << 22) | - ((dev_priv->front_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->back_pitch_offset = (((dev_priv->back_pitch / 64) << 22) | - ((dev_priv->back_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->depth_pitch_offset = (((dev_priv->depth_pitch / 64) << 22) | - ((dev_priv->depth_offset - + dev_priv->fb_location) >> 10)); - - dev_priv->gart_size = init->gart_size; - - /* New let's set the memory map ... */ - if (dev_priv->new_memmap) { - u32 base = 0; - - DRM_INFO("Setting GART location based on new memory map\n"); - - /* If using AGP, try to locate the AGP aperture at the same - * location in the card and on the bus, though we have to - * align it down. - */ -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - base = dev->agp->base; - /* Check if valid */ - if ((base + dev_priv->gart_size - 1) >= dev_priv->fb_location && - base < (dev_priv->fb_location + dev_priv->fb_size - 1)) { - DRM_INFO("Can't use AGP base @0x%08lx, won't fit\n", - dev->agp->base); - base = 0; - } - } -#endif - /* If not or if AGP is at 0 (Macs), try to put it elsewhere */ - if (base == 0) { - base = dev_priv->fb_location + dev_priv->fb_size; - if (base < dev_priv->fb_location || - ((base + dev_priv->gart_size) & 0xfffffffful) < base) - base = dev_priv->fb_location - - dev_priv->gart_size; - } - dev_priv->gart_vm_start = base & 0xffc00000u; - if (dev_priv->gart_vm_start != base) - DRM_INFO("GART aligned down from 0x%08x to 0x%08x\n", - base, dev_priv->gart_vm_start); - } else { - DRM_INFO("Setting GART location based on old memory map\n"); - dev_priv->gart_vm_start = dev_priv->fb_location + - RADEON_READ(RADEON_CONFIG_APER_SIZE); - } - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) - dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - - dev->agp->base - + dev_priv->gart_vm_start); - else -#endif - dev_priv->gart_buffers_offset = (dev->agp_buffer_map->offset - - (unsigned long)dev->sg->virtual - + dev_priv->gart_vm_start); - - DRM_DEBUG("dev_priv->gart_size %d\n", dev_priv->gart_size); - DRM_DEBUG("dev_priv->gart_vm_start 0x%x\n", dev_priv->gart_vm_start); - DRM_DEBUG("dev_priv->gart_buffers_offset 0x%lx\n", - dev_priv->gart_buffers_offset); - - dev_priv->ring.start = (u32 *) dev_priv->cp_ring->handle; - dev_priv->ring.end = ((u32 *) dev_priv->cp_ring->handle - + init->ring_size / sizeof(u32)); - dev_priv->ring.size = init->ring_size; - dev_priv->ring.size_l2qw = order_base_2(init->ring_size / 8); - - dev_priv->ring.rptr_update = /* init->rptr_update */ 4096; - dev_priv->ring.rptr_update_l2qw = order_base_2( /* init->rptr_update */ 4096 / 8); - - dev_priv->ring.fetch_size = /* init->fetch_size */ 32; - dev_priv->ring.fetch_size_l2ow = order_base_2( /* init->fetch_size */ 32 / 16); - dev_priv->ring.tail_mask = (dev_priv->ring.size / sizeof(u32)) - 1; - - dev_priv->ring.high_mark = RADEON_RING_HIGH_MARK; - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - /* Turn off PCI GART */ - radeon_set_pcigart(dev_priv, 0); - } else -#endif - { - u32 sctrl; - int ret; - - dev_priv->gart_info.table_mask = DMA_BIT_MASK(32); - /* if we have an offset set from userspace */ - if (dev_priv->pcigart_offset_set) { - dev_priv->gart_info.bus_addr = - (resource_size_t)dev_priv->pcigart_offset + dev_priv->fb_location; - dev_priv->gart_info.mapping.offset = - dev_priv->pcigart_offset + dev_priv->fb_aper_offset; - dev_priv->gart_info.mapping.size = - dev_priv->gart_info.table_size; - - drm_legacy_ioremap_wc(&dev_priv->gart_info.mapping, dev); - dev_priv->gart_info.addr = - dev_priv->gart_info.mapping.handle; - - if (dev_priv->flags & RADEON_IS_PCIE) - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCIE; - else - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - dev_priv->gart_info.gart_table_location = - DRM_ATI_GART_FB; - - DRM_DEBUG("Setting phys_pci_gart to %p %08lX\n", - dev_priv->gart_info.addr, - dev_priv->pcigart_offset); - } else { - if (dev_priv->flags & RADEON_IS_IGPGART) - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_IGP; - else - dev_priv->gart_info.gart_reg_if = DRM_ATI_GART_PCI; - dev_priv->gart_info.gart_table_location = - DRM_ATI_GART_MAIN; - dev_priv->gart_info.addr = NULL; - dev_priv->gart_info.bus_addr = 0; - if (dev_priv->flags & RADEON_IS_PCIE) { - DRM_ERROR - ("Cannot use PCI Express without GART in FB memory\n"); - radeon_do_cleanup_cp(dev); - return -EINVAL; - } - } - - sctrl = RADEON_READ(RADEON_SURFACE_CNTL); - RADEON_WRITE(RADEON_SURFACE_CNTL, 0); - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - ret = r600_page_table_init(dev); - else - ret = drm_ati_pcigart_init(dev, &dev_priv->gart_info); - RADEON_WRITE(RADEON_SURFACE_CNTL, sctrl); - - if (!ret) { - DRM_ERROR("failed to init PCI GART!\n"); - radeon_do_cleanup_cp(dev); - return -ENOMEM; - } - - ret = radeon_setup_pcigart_surface(dev_priv); - if (ret) { - DRM_ERROR("failed to setup GART surface!\n"); - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - r600_page_table_cleanup(dev, &dev_priv->gart_info); - else - drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info); - radeon_do_cleanup_cp(dev); - return ret; - } - - /* Turn on PCI GART */ - radeon_set_pcigart(dev_priv, 1); - } - - if (!dev_priv->me_fw) { - int err = radeon_cp_init_microcode(dev_priv); - if (err) { - DRM_ERROR("Failed to load firmware!\n"); - radeon_do_cleanup_cp(dev); - return err; - } - } - radeon_cp_load_microcode(dev_priv); - radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); - - dev_priv->last_buf = 0; - - radeon_do_engine_reset(dev); - radeon_test_writeback(dev_priv); - - return 0; -} - -static int radeon_do_cleanup_cp(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - /* Make sure interrupts are disabled here because the uninstall ioctl - * may not have been called from userspace and after dev_private - * is freed, it's too late. - */ - if (dev->irq_enabled) - drm_irq_uninstall(dev); - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - if (dev_priv->cp_ring != NULL) { - drm_legacy_ioremapfree(dev_priv->cp_ring, dev); - dev_priv->cp_ring = NULL; - } - if (dev_priv->ring_rptr != NULL) { - drm_legacy_ioremapfree(dev_priv->ring_rptr, dev); - dev_priv->ring_rptr = NULL; - } - if (dev->agp_buffer_map != NULL) { - drm_legacy_ioremapfree(dev->agp_buffer_map, dev); - dev->agp_buffer_map = NULL; - } - } else -#endif - { - - if (dev_priv->gart_info.bus_addr) { - /* Turn off PCI GART */ - radeon_set_pcigart(dev_priv, 0); - if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) - r600_page_table_cleanup(dev, &dev_priv->gart_info); - else { - if (!drm_ati_pcigart_cleanup(dev, &dev_priv->gart_info)) - DRM_ERROR("failed to cleanup PCI GART!\n"); - } - } - - if (dev_priv->gart_info.gart_table_location == DRM_ATI_GART_FB) - { - drm_legacy_ioremapfree(&dev_priv->gart_info.mapping, dev); - dev_priv->gart_info.addr = NULL; - } - } - /* only clear to the start of flags */ - memset(dev_priv, 0, offsetof(drm_radeon_private_t, flags)); - - return 0; -} - -/* This code will reinit the Radeon CP hardware after a resume from disc. - * AFAIK, it would be very difficult to pickle the state at suspend time, so - * here we make sure that all Radeon hardware initialisation is re-done without - * affecting running applications. - * - * Charl P. Botha <http://cpbotha.net> - */ -static int radeon_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (!dev_priv) { - DRM_ERROR("Called with no initialization\n"); - return -EINVAL; - } - - DRM_DEBUG("Starting radeon_do_resume_cp()\n"); - -#if IS_ENABLED(CONFIG_AGP) - if (dev_priv->flags & RADEON_IS_AGP) { - /* Turn off PCI GART */ - radeon_set_pcigart(dev_priv, 0); - } else -#endif - { - /* Turn on PCI GART */ - radeon_set_pcigart(dev_priv, 1); - } - - radeon_cp_load_microcode(dev_priv); - radeon_cp_init_ring_buffer(dev, dev_priv, file_priv); - - dev_priv->have_z_offset = 0; - radeon_do_engine_reset(dev); - radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); - - DRM_DEBUG("radeon_do_resume_cp() complete\n"); - - return 0; -} - -int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_init_t *init = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (init->func == RADEON_INIT_R300_CP) - r300_init_reg_flags(dev); - - switch (init->func) { - case RADEON_INIT_CP: - case RADEON_INIT_R200_CP: - case RADEON_INIT_R300_CP: - return radeon_do_init_cp(dev, init, file_priv); - case RADEON_INIT_R600_CP: - return r600_do_init_cp(dev, init, file_priv); - case RADEON_CLEANUP_CP: - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return r600_do_cleanup_cp(dev); - else - return radeon_do_cleanup_cp(dev); - } - - return -EINVAL; -} - -int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (dev_priv->cp_running) { - DRM_DEBUG("while CP running\n"); - return 0; - } - if (dev_priv->cp_mode == RADEON_CSQ_PRIDIS_INDDIS) { - DRM_DEBUG("called with bogus CP mode (%d)\n", - dev_priv->cp_mode); - return 0; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_do_cp_start(dev_priv); - else - radeon_do_cp_start(dev_priv); - - return 0; -} - -/* Stop the CP. The engine must have been idled before calling this - * routine. - */ -int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_cp_stop_t *stop = data; - int ret; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (!dev_priv->cp_running) - return 0; - - /* Flush any pending CP commands. This ensures any outstanding - * commands are exectuted by the engine before we turn it off. - */ - if (stop->flush) { - radeon_do_cp_flush(dev_priv); - } - - /* If we fail to make the engine go idle, we return an error - * code so that the DRM ioctl wrapper can try again. - */ - if (stop->idle) { - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - ret = r600_do_cp_idle(dev_priv); - else - ret = radeon_do_cp_idle(dev_priv); - if (ret) - return ret; - } - - /* Finally, we can turn off the CP. If the engine isn't idle, - * we will get some dropped triangles as they won't be fully - * rendered before the CP is shut down. - */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_do_cp_stop(dev_priv); - else - radeon_do_cp_stop(dev_priv); - - /* Reset the engine */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_do_engine_reset(dev); - else - radeon_do_engine_reset(dev); - - return 0; -} - -void radeon_do_release(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - int i, ret; - - if (dev_priv) { - if (dev_priv->cp_running) { - /* Stop the cp */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { - while ((ret = r600_do_cp_idle(dev_priv)) != 0) { - DRM_DEBUG("radeon_do_cp_idle %d\n", ret); -#ifdef __linux__ - schedule(); -#else - tsleep(&ret, PZERO, "rdnrel", 1); -#endif - } - } else { - while ((ret = radeon_do_cp_idle(dev_priv)) != 0) { - DRM_DEBUG("radeon_do_cp_idle %d\n", ret); -#ifdef __linux__ - schedule(); -#else - tsleep(&ret, PZERO, "rdnrel", 1); -#endif - } - } - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { - r600_do_cp_stop(dev_priv); - r600_do_engine_reset(dev); - } else { - radeon_do_cp_stop(dev_priv); - radeon_do_engine_reset(dev); - } - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) < CHIP_R600) { - /* Disable *all* interrupts */ - if (dev_priv->mmio) /* remove this after permanent addmaps */ - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); - - if (dev_priv->mmio) { /* remove all surfaces */ - for (i = 0; i < RADEON_MAX_SURFACES; i++) { - RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * i, 0); - RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + - 16 * i, 0); - RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + - 16 * i, 0); - } - } - } - - /* Free memory heap structures */ - radeon_mem_takedown(&(dev_priv->gart_heap)); - radeon_mem_takedown(&(dev_priv->fb_heap)); - - /* deallocate kernel resources */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_do_cleanup_cp(dev); - else - radeon_do_cleanup_cp(dev); - release_firmware(dev_priv->me_fw); - dev_priv->me_fw = NULL; - release_firmware(dev_priv->pfp_fw); - dev_priv->pfp_fw = NULL; - } -} - -/* Just reset the CP ring. Called as part of an X Server engine reset. - */ -int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (!dev_priv) { - DRM_DEBUG("called before init done\n"); - return -EINVAL; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_do_cp_reset(dev_priv); - else - radeon_do_cp_reset(dev_priv); - - /* The CP is no longer running after an engine reset */ - dev_priv->cp_running = 0; - - return 0; -} - -int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return r600_do_cp_idle(dev_priv); - else - return radeon_do_cp_idle(dev_priv); -} - -/* Added by Charl P. Botha to call radeon_do_resume_cp(). - */ -int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return r600_do_resume_cp(dev, file_priv); - else - return radeon_do_resume_cp(dev, file_priv); -} - -int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return r600_do_engine_reset(dev); - else - return radeon_do_engine_reset(dev); -} - -/* ================================================================ - * Fullscreen mode - */ - -/* KW: Deprecated to say the least: - */ -int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - return 0; -} - -/* ================================================================ - * Freelist management - */ - -/* Original comment: FIXME: ROTATE_BUFS is a hack to cycle through - * bufs until freelist code is used. Note this hides a problem with - * the scratch register * (used to keep track of last buffer - * completed) being written to before * the last buffer has actually - * completed rendering. - * - * KW: It's also a good way to find free buffers quickly. - * - * KW: Ideally this loop wouldn't exist, and freelist_get wouldn't - * sleep. However, bugs in older versions of radeon_accel.c mean that - * we essentially have to do this, else old clients will break. - * - * However, it does leave open a potential deadlock where all the - * buffers are held by other clients, which can't release them because - * they can't get the lock. - */ - -struct drm_buf *radeon_freelist_get(struct drm_device * dev) -{ - struct drm_device_dma *dma = dev->dma; - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_buf_priv_t *buf_priv; - struct drm_buf *buf; - int i, t; - int start; - - if (++dev_priv->last_buf >= dma->buf_count) - dev_priv->last_buf = 0; - - start = dev_priv->last_buf; - - for (t = 0; t < dev_priv->usec_timeout; t++) { - u32 done_age = GET_SCRATCH(dev_priv, 1); - DRM_DEBUG("done_age = %d\n", done_age); - for (i = 0; i < dma->buf_count; i++) { - buf = dma->buflist[start]; - buf_priv = buf->dev_private; - if (buf->file_priv == NULL || (buf->pending && - buf_priv->age <= - done_age)) { - dev_priv->stats.requested_bufs++; - buf->pending = 0; - return buf; - } - if (++start >= dma->buf_count) - start = 0; - } - - if (t) { - DRM_UDELAY(1); - dev_priv->stats.freelist_loops++; - } - } - - return NULL; -} - -void radeon_freelist_reset(struct drm_device * dev) -{ - struct drm_device_dma *dma = dev->dma; - drm_radeon_private_t *dev_priv = dev->dev_private; - int i; - - dev_priv->last_buf = 0; - for (i = 0; i < dma->buf_count; i++) { - struct drm_buf *buf = dma->buflist[i]; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; - buf_priv->age = 0; - } -} - -/* ================================================================ - * CP command submission - */ - -int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n) -{ - drm_radeon_ring_buffer_t *ring = &dev_priv->ring; - int i; - u32 last_head = GET_RING_HEAD(dev_priv); - - for (i = 0; i < dev_priv->usec_timeout; i++) { - u32 head = GET_RING_HEAD(dev_priv); - - ring->space = (head - ring->tail) * sizeof(u32); - if (ring->space <= 0) - ring->space += ring->size; - if (ring->space > n) - return 0; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - if (head != last_head) - i = 0; - last_head = head; - - DRM_UDELAY(1); - } - - /* FIXME: This return value is ignored in the BEGIN_RING macro! */ -#if RADEON_FIFO_DEBUG - radeon_status(dev_priv); - DRM_ERROR("failed!\n"); -#endif - return -EBUSY; -} - -static int radeon_cp_get_buffers(struct drm_device *dev, - struct drm_file *file_priv, - struct drm_dma * d) -{ - int i; - struct drm_buf *buf; - - for (i = d->granted_count; i < d->request_count; i++) { - buf = radeon_freelist_get(dev); - if (!buf) - return -EBUSY; /* NOTE: broken client */ - - buf->file_priv = file_priv; - - if (copy_to_user(&d->request_indices[i], &buf->idx, - sizeof(buf->idx))) - return -EFAULT; - if (copy_to_user(&d->request_sizes[i], &buf->total, - sizeof(buf->total))) - return -EFAULT; - - d->granted_count++; - } - return 0; -} - -int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - struct drm_device_dma *dma = dev->dma; - int ret = 0; - struct drm_dma *d = data; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - /* Please don't send us buffers. - */ - if (d->send_count != 0) { - DRM_ERROR("Process %d trying to send %d buffers via drmDMA\n", - DRM_CURRENTPID, d->send_count); - return -EINVAL; - } - - /* We'll send you buffers. - */ - if (d->request_count < 0 || d->request_count > dma->buf_count) { - DRM_ERROR("Process %d trying to get %d buffers (of %d max)\n", - DRM_CURRENTPID, d->request_count, dma->buf_count); - return -EINVAL; - } - - d->granted_count = 0; - - if (d->request_count) { - ret = radeon_cp_get_buffers(dev, file_priv, d); - } - - return ret; -} - -int radeon_driver_load(struct drm_device *dev, unsigned long flags) -{ - drm_radeon_private_t *dev_priv; - int ret = 0; - - dev_priv = kzalloc(sizeof(drm_radeon_private_t), GFP_KERNEL); - if (dev_priv == NULL) - return -ENOMEM; - - dev->dev_private = (void *)dev_priv; - dev_priv->flags = flags; - - switch (flags & RADEON_FAMILY_MASK) { - case CHIP_R100: - case CHIP_RV200: - case CHIP_R200: - case CHIP_R300: - case CHIP_R350: - case CHIP_R420: - case CHIP_R423: - case CHIP_RV410: - case CHIP_RV515: - case CHIP_R520: - case CHIP_RV570: - case CHIP_R580: - dev_priv->flags |= RADEON_HAS_HIERZ; - break; - default: - /* all other chips have no hierarchical z buffer */ - break; - } - - pci_set_master(dev->pdev); - - if (drm_pci_device_is_agp(dev)) - dev_priv->flags |= RADEON_IS_AGP; - else if (pci_is_pcie(dev->pdev)) - dev_priv->flags |= RADEON_IS_PCIE; - else - dev_priv->flags |= RADEON_IS_PCI; - - ret = drm_legacy_addmap(dev, pci_resource_start(dev->pdev, 2), - pci_resource_len(dev->pdev, 2), _DRM_REGISTERS, - _DRM_READ_ONLY | _DRM_DRIVER, &dev_priv->mmio); - if (ret != 0) - return ret; - - ret = drm_vblank_init(dev, 2); - if (ret) { - radeon_driver_unload(dev); - return ret; - } - - DRM_DEBUG("%s card detected\n", - ((dev_priv->flags & RADEON_IS_AGP) ? "AGP" : (((dev_priv->flags & RADEON_IS_PCIE) ? "PCIE" : "PCI")))); - return ret; -} - -int radeon_master_create(struct drm_device *dev, struct drm_master *master) -{ - struct drm_radeon_master_private *master_priv; - unsigned long sareapage; - int ret; - - master_priv = kzalloc(sizeof(*master_priv), GFP_KERNEL); - if (!master_priv) - return -ENOMEM; - - /* prebuild the SAREA */ - sareapage = max_t(unsigned long, SAREA_MAX, PAGE_SIZE); - ret = drm_legacy_addmap(dev, 0, sareapage, _DRM_SHM, _DRM_CONTAINS_LOCK, - &master_priv->sarea); - if (ret) { - DRM_ERROR("SAREA setup failed\n"); - kfree(master_priv); - return ret; - } - master_priv->sarea_priv = master_priv->sarea->handle + sizeof(struct drm_sarea); - master_priv->sarea_priv->pfCurrentPage = 0; - - master->driver_priv = master_priv; - return 0; -} - -void radeon_master_destroy(struct drm_device *dev, struct drm_master *master) -{ - struct drm_radeon_master_private *master_priv = master->driver_priv; - - if (!master_priv) - return; - - if (master_priv->sarea_priv && - master_priv->sarea_priv->pfCurrentPage != 0) - radeon_cp_dispatch_flip(dev, master); - - master_priv->sarea_priv = NULL; - if (master_priv->sarea) - drm_legacy_rmmap_locked(dev, master_priv->sarea); - - kfree(master_priv); - - master->driver_priv = NULL; -} - -/* Create mappings for registers and framebuffer so userland doesn't necessarily - * have to find them. - */ -int radeon_driver_firstopen(struct drm_device *dev) -{ - int ret; - drm_local_map_t *map; - drm_radeon_private_t *dev_priv = dev->dev_private; - - dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - - dev_priv->fb_aper_offset = pci_resource_start(dev->pdev, 0); - ret = drm_legacy_addmap(dev, dev_priv->fb_aper_offset, - pci_resource_len(dev->pdev, 0), - _DRM_FRAME_BUFFER, _DRM_WRITE_COMBINING, &map); - if (ret != 0) - return ret; - - return 0; -} - -int radeon_driver_unload(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - DRM_DEBUG("\n"); - - drm_legacy_rmmap(dev, dev_priv->mmio); - - kfree(dev_priv); - - dev->dev_private = NULL; - return 0; -} - -void radeon_commit_ring(drm_radeon_private_t *dev_priv) -{ - int i; - u32 *ring; - int tail_aligned; - - /* check if the ring is padded out to 16-dword alignment */ - - tail_aligned = dev_priv->ring.tail & (RADEON_RING_ALIGN-1); - if (tail_aligned) { - int num_p2 = RADEON_RING_ALIGN - tail_aligned; - - ring = dev_priv->ring.start; - /* pad with some CP_PACKET2 */ - for (i = 0; i < num_p2; i++) - ring[dev_priv->ring.tail + i] = CP_PACKET2(); - - dev_priv->ring.tail += i; - - dev_priv->ring.space -= num_p2 * sizeof(u32); - } - - dev_priv->ring.tail &= dev_priv->ring.tail_mask; - - mb(); - GET_RING_HEAD( dev_priv ); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { - RADEON_WRITE(R600_CP_RB_WPTR, dev_priv->ring.tail); - /* read from PCI bus to ensure correct posting */ - RADEON_READ(R600_CP_RB_RPTR); - } else { - RADEON_WRITE(RADEON_CP_RB_WPTR, dev_priv->ring.tail); - /* read from PCI bus to ensure correct posting */ - RADEON_READ(RADEON_CP_RB_RPTR); - } -} diff --git a/drivers/gpu/drm/radeon/radeon_device.c b/drivers/gpu/drm/radeon/radeon_device.c index c566993a2ec3..d690df545b4d 100644 --- a/drivers/gpu/drm/radeon/radeon_device.c +++ b/drivers/gpu/drm/radeon/radeon_device.c @@ -1744,6 +1744,7 @@ int radeon_resume_kms(struct drm_device *dev, bool resume, bool fbcon) } drm_kms_helper_poll_enable(dev); + drm_helper_hpd_irq_event(dev); /* set the power state here in case we are a PX system or headless */ if ((rdev->pm.pm_method == PM_METHOD_DPM) && rdev->pm.dpm_enabled) diff --git a/drivers/gpu/drm/radeon/radeon_dp_mst.c b/drivers/gpu/drm/radeon/radeon_dp_mst.c index 94323f51ffcf..c236f6fec245 100644 --- a/drivers/gpu/drm/radeon/radeon_dp_mst.c +++ b/drivers/gpu/drm/radeon/radeon_dp_mst.c @@ -525,11 +525,17 @@ static bool radeon_mst_mode_fixup(struct drm_encoder *encoder, drm_mode_set_crtcinfo(adjusted_mode, 0); { struct radeon_connector_atom_dig *dig_connector; + int ret; dig_connector = mst_enc->connector->con_priv; - dig_connector->dp_lane_count = drm_dp_max_lane_count(dig_connector->dpcd); - dig_connector->dp_clock = radeon_dp_get_max_link_rate(&mst_enc->connector->base, - dig_connector->dpcd); + ret = radeon_dp_get_dp_link_config(&mst_enc->connector->base, + dig_connector->dpcd, adjusted_mode->clock, + &dig_connector->dp_lane_count, + &dig_connector->dp_clock); + if (ret) { + dig_connector->dp_lane_count = 0; + dig_connector->dp_clock = 0; + } DRM_DEBUG_KMS("dig clock %p %d %d\n", dig_connector, dig_connector->dp_lane_count, dig_connector->dp_clock); } diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c index 5b6a6f5b3619..e266ffc520d2 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.c +++ b/drivers/gpu/drm/radeon/radeon_drv.c @@ -291,88 +291,6 @@ static struct pci_device_id pciidlist[] = { MODULE_DEVICE_TABLE(pci, pciidlist); -#ifdef CONFIG_DRM_RADEON_UMS - -static int radeon_suspend(struct drm_device *dev, pm_message_t state) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return 0; - - /* Disable *all* interrupts */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) - RADEON_WRITE(R500_DxMODE_INT_MASK, 0); - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); - return 0; -} - -static int radeon_resume(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return 0; - - /* Restore interrupt registers */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) - RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); - RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); - return 0; -} - - -static const struct file_operations radeon_driver_old_fops = { - .owner = THIS_MODULE, - .open = drm_open, - .release = drm_release, - .unlocked_ioctl = drm_ioctl, - .mmap = drm_legacy_mmap, - .poll = drm_poll, - .read = drm_read, -#ifdef CONFIG_COMPAT - .compat_ioctl = radeon_compat_ioctl, -#endif - .llseek = noop_llseek, -}; - -static struct drm_driver driver_old = { - .driver_features = - DRIVER_USE_AGP | DRIVER_PCI_DMA | DRIVER_SG | - DRIVER_HAVE_IRQ | DRIVER_HAVE_DMA | DRIVER_IRQ_SHARED, - .dev_priv_size = sizeof(drm_radeon_buf_priv_t), - .load = radeon_driver_load, - .firstopen = radeon_driver_firstopen, - .open = radeon_driver_open, - .preclose = radeon_driver_preclose, - .postclose = radeon_driver_postclose, - .lastclose = radeon_driver_lastclose, - .set_busid = drm_pci_set_busid, - .unload = radeon_driver_unload, - .suspend = radeon_suspend, - .resume = radeon_resume, - .get_vblank_counter = radeon_get_vblank_counter, - .enable_vblank = radeon_enable_vblank, - .disable_vblank = radeon_disable_vblank, - .master_create = radeon_master_create, - .master_destroy = radeon_master_destroy, - .irq_preinstall = radeon_driver_irq_preinstall, - .irq_postinstall = radeon_driver_irq_postinstall, - .irq_uninstall = radeon_driver_irq_uninstall, - .irq_handler = radeon_driver_irq_handler, - .ioctls = radeon_ioctls, - .dma_ioctl = radeon_cp_buffers, - .fops = &radeon_driver_old_fops, - .name = DRIVER_NAME, - .desc = DRIVER_DESC, - .date = DRIVER_DATE, - .major = DRIVER_MAJOR, - .minor = DRIVER_MINOR, - .patchlevel = DRIVER_PATCHLEVEL, -}; - -#endif - static struct drm_driver kms_driver; static int radeon_kick_out_firmware_fb(struct pci_dev *pdev) @@ -619,13 +537,6 @@ static struct drm_driver kms_driver = { static struct drm_driver *driver; static struct pci_driver *pdriver; -#ifdef CONFIG_DRM_RADEON_UMS -static struct pci_driver radeon_pci_driver = { - .name = DRIVER_NAME, - .id_table = pciidlist, -}; -#endif - static struct pci_driver radeon_kms_pci_driver = { .name = DRIVER_NAME, .id_table = pciidlist, @@ -655,16 +566,8 @@ static int __init radeon_init(void) radeon_register_atpx_handler(); } else { -#ifdef CONFIG_DRM_RADEON_UMS - DRM_INFO("radeon userspace modesetting enabled.\n"); - driver = &driver_old; - pdriver = &radeon_pci_driver; - driver->driver_features &= ~DRIVER_MODESET; - driver->num_ioctls = radeon_max_ioctl; -#else DRM_ERROR("No UMS support in radeon module!\n"); return -EINVAL; -#endif } radeon_kfd_init(); diff --git a/drivers/gpu/drm/radeon/radeon_drv.h b/drivers/gpu/drm/radeon/radeon_drv.h index 0caafc7a6e17..afef2d9fccd8 100644 --- a/drivers/gpu/drm/radeon/radeon_drv.h +++ b/drivers/gpu/drm/radeon/radeon_drv.h @@ -119,2052 +119,4 @@ long radeon_drm_ioctl(struct file *filp, unsigned int cmd, unsigned long arg); -/* The rest of the file is DEPRECATED! */ -#ifdef CONFIG_DRM_RADEON_UMS - -enum radeon_cp_microcode_version { - UCODE_R100, - UCODE_R200, - UCODE_R300, -}; - -typedef struct drm_radeon_freelist { - unsigned int age; - struct drm_buf *buf; - struct drm_radeon_freelist *next; - struct drm_radeon_freelist *prev; -} drm_radeon_freelist_t; - -typedef struct drm_radeon_ring_buffer { - u32 *start; - u32 *end; - int size; - int size_l2qw; - - int rptr_update; /* Double Words */ - int rptr_update_l2qw; /* log2 Quad Words */ - - int fetch_size; /* Double Words */ - int fetch_size_l2ow; /* log2 Oct Words */ - - u32 tail; - u32 tail_mask; - int space; - - int high_mark; -} drm_radeon_ring_buffer_t; - -typedef struct drm_radeon_depth_clear_t { - u32 rb3d_cntl; - u32 rb3d_zstencilcntl; - u32 se_cntl; -} drm_radeon_depth_clear_t; - -struct drm_radeon_driver_file_fields { - int64_t radeon_fb_delta; -}; - -struct mem_block { - struct mem_block *next; - struct mem_block *prev; - int start; - int size; - struct drm_file *file_priv; /* NULL: free, -1: heap, other: real files */ -}; - -struct radeon_surface { - int refcount; - u32 lower; - u32 upper; - u32 flags; -}; - -struct radeon_virt_surface { - int surface_index; - u32 lower; - u32 upper; - u32 flags; - struct drm_file *file_priv; -#define PCIGART_FILE_PRIV ((void *) -1L) -}; - -#define RADEON_FLUSH_EMITED (1 << 0) -#define RADEON_PURGE_EMITED (1 << 1) - -struct drm_radeon_master_private { - drm_local_map_t *sarea; - drm_radeon_sarea_t *sarea_priv; -}; - -typedef struct drm_radeon_private { - drm_radeon_ring_buffer_t ring; - - u32 fb_location; - u32 fb_size; - int new_memmap; - - int gart_size; - u32 gart_vm_start; - unsigned long gart_buffers_offset; - - int cp_mode; - int cp_running; - - drm_radeon_freelist_t *head; - drm_radeon_freelist_t *tail; - int last_buf; - int writeback_works; - - int usec_timeout; - - int microcode_version; - - struct { - u32 boxes; - int freelist_timeouts; - int freelist_loops; - int requested_bufs; - int last_frame_reads; - int last_clear_reads; - int clears; - int texture_uploads; - } stats; - - int do_boxes; - int page_flipping; - - u32 color_fmt; - unsigned int front_offset; - unsigned int front_pitch; - unsigned int back_offset; - unsigned int back_pitch; - - u32 depth_fmt; - unsigned int depth_offset; - unsigned int depth_pitch; - - u32 front_pitch_offset; - u32 back_pitch_offset; - u32 depth_pitch_offset; - - drm_radeon_depth_clear_t depth_clear; - - unsigned long ring_offset; - unsigned long ring_rptr_offset; - unsigned long buffers_offset; - unsigned long gart_textures_offset; - - drm_local_map_t *sarea; - drm_local_map_t *cp_ring; - drm_local_map_t *ring_rptr; - drm_local_map_t *gart_textures; - - struct mem_block *gart_heap; - struct mem_block *fb_heap; - - /* SW interrupt */ - wait_queue_head_t swi_queue; - atomic_t swi_emitted; - int vblank_crtc; - uint32_t irq_enable_reg; - uint32_t r500_disp_irq_reg; - - struct radeon_surface surfaces[RADEON_MAX_SURFACES]; - struct radeon_virt_surface virt_surfaces[2 * RADEON_MAX_SURFACES]; - - unsigned long pcigart_offset; - unsigned int pcigart_offset_set; - struct drm_ati_pcigart_info gart_info; - - u32 scratch_ages[5]; - - int have_z_offset; - - /* starting from here on, data is preserved across an open */ - uint32_t flags; /* see radeon_chip_flags */ - resource_size_t fb_aper_offset; - - int num_gb_pipes; - int num_z_pipes; - int track_flush; - drm_local_map_t *mmio; - - /* r6xx/r7xx pipe/shader config */ - int r600_max_pipes; - int r600_max_tile_pipes; - int r600_max_simds; - int r600_max_backends; - int r600_max_gprs; - int r600_max_threads; - int r600_max_stack_entries; - int r600_max_hw_contexts; - int r600_max_gs_threads; - int r600_sx_max_export_size; - int r600_sx_max_export_pos_size; - int r600_sx_max_export_smx_size; - int r600_sq_num_cf_insts; - int r700_sx_num_of_sets; - int r700_sc_prim_fifo_size; - int r700_sc_hiz_tile_fifo_size; - int r700_sc_earlyz_tile_fifo_fize; - int r600_group_size; - int r600_npipes; - int r600_nbanks; - - struct mutex cs_mutex; - u32 cs_id_scnt; - u32 cs_id_wcnt; - /* r6xx/r7xx drm blit vertex buffer */ - struct drm_buf *blit_vb; - - /* firmware */ - const struct firmware *me_fw, *pfp_fw; -} drm_radeon_private_t; - -typedef struct drm_radeon_buf_priv { - u32 age; -} drm_radeon_buf_priv_t; - -struct drm_buffer; - -typedef struct drm_radeon_kcmd_buffer { - int bufsz; - struct drm_buffer *buffer; - int nbox; - struct drm_clip_rect __user *boxes; -} drm_radeon_kcmd_buffer_t; - -extern int radeon_no_wb; -extern struct drm_ioctl_desc radeon_ioctls[]; -extern int radeon_max_ioctl; - -extern u32 radeon_get_ring_head(drm_radeon_private_t *dev_priv); -extern void radeon_set_ring_head(drm_radeon_private_t *dev_priv, u32 val); - -#define GET_RING_HEAD(dev_priv) radeon_get_ring_head(dev_priv) -#define SET_RING_HEAD(dev_priv, val) radeon_set_ring_head(dev_priv, val) - -/* Check whether the given hardware address is inside the framebuffer or the - * GART area. - */ -static __inline__ int radeon_check_offset(drm_radeon_private_t *dev_priv, - u64 off) -{ - u32 fb_start = dev_priv->fb_location; - u32 fb_end = fb_start + dev_priv->fb_size - 1; - u32 gart_start = dev_priv->gart_vm_start; - u32 gart_end = gart_start + dev_priv->gart_size - 1; - - return ((off >= fb_start && off <= fb_end) || - (off >= gart_start && off <= gart_end)); -} - -/* radeon_state.c */ -extern void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf); - - /* radeon_cp.c */ -extern int radeon_cp_init(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_start(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_stop(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_idle(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_resume(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_engine_reset(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_fullscreen(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_cp_buffers(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern u32 radeon_read_fb_location(drm_radeon_private_t *dev_priv); -extern void radeon_write_agp_location(drm_radeon_private_t *dev_priv, u32 agp_loc); -extern void radeon_write_agp_base(drm_radeon_private_t *dev_priv, u64 agp_base); - -extern void radeon_freelist_reset(struct drm_device * dev); -extern struct drm_buf *radeon_freelist_get(struct drm_device * dev); - -extern int radeon_wait_ring(drm_radeon_private_t * dev_priv, int n); - -extern int radeon_do_cp_idle(drm_radeon_private_t * dev_priv); - -extern int radeon_driver_preinit(struct drm_device *dev, unsigned long flags); -extern int radeon_presetup(struct drm_device *dev); -extern int radeon_driver_postcleanup(struct drm_device *dev); - -extern int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern void radeon_mem_takedown(struct mem_block **heap); -extern void radeon_mem_release(struct drm_file *file_priv, - struct mem_block *heap); - -extern void radeon_enable_bm(struct drm_radeon_private *dev_priv); -extern u32 radeon_read_ring_rptr(drm_radeon_private_t *dev_priv, u32 off); -extern void radeon_write_ring_rptr(drm_radeon_private_t *dev_priv, u32 off, u32 val); - - /* radeon_irq.c */ -extern void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state); -extern int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv); -extern int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv); - -extern void radeon_do_release(struct drm_device * dev); -extern u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe); -extern int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe); -extern void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe); -extern irqreturn_t radeon_driver_irq_handler(int irq, void *arg); -extern void radeon_driver_irq_preinstall(struct drm_device * dev); -extern int radeon_driver_irq_postinstall(struct drm_device *dev); -extern void radeon_driver_irq_uninstall(struct drm_device * dev); -extern void radeon_enable_interrupt(struct drm_device *dev); -extern int radeon_vblank_crtc_get(struct drm_device *dev); -extern int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value); - -extern int radeon_driver_load(struct drm_device *dev, unsigned long flags); -extern int radeon_driver_unload(struct drm_device *dev); -extern int radeon_driver_firstopen(struct drm_device *dev); -extern void radeon_driver_preclose(struct drm_device *dev, - struct drm_file *file_priv); -extern void radeon_driver_postclose(struct drm_device *dev, - struct drm_file *file_priv); -extern void radeon_driver_lastclose(struct drm_device * dev); -extern int radeon_driver_open(struct drm_device *dev, - struct drm_file *file_priv); -extern long radeon_compat_ioctl(struct file *filp, unsigned int cmd, - unsigned long arg); - -extern int radeon_master_create(struct drm_device *dev, struct drm_master *master); -extern void radeon_master_destroy(struct drm_device *dev, struct drm_master *master); -extern void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master); -/* r300_cmdbuf.c */ -extern void r300_init_reg_flags(struct drm_device *dev); - -extern int r300_do_cp_cmdbuf(struct drm_device *dev, - struct drm_file *file_priv, - drm_radeon_kcmd_buffer_t *cmdbuf); - -/* r600_cp.c */ -extern int r600_do_engine_reset(struct drm_device *dev); -extern int r600_do_cleanup_cp(struct drm_device *dev); -extern int r600_do_init_cp(struct drm_device *dev, drm_radeon_init_t *init, - struct drm_file *file_priv); -extern int r600_do_resume_cp(struct drm_device *dev, struct drm_file *file_priv); -extern int r600_do_cp_idle(drm_radeon_private_t *dev_priv); -extern void r600_do_cp_start(drm_radeon_private_t *dev_priv); -extern void r600_do_cp_reset(drm_radeon_private_t *dev_priv); -extern void r600_do_cp_stop(drm_radeon_private_t *dev_priv); -extern int r600_cp_dispatch_indirect(struct drm_device *dev, - struct drm_buf *buf, int start, int end); -extern int r600_page_table_init(struct drm_device *dev); -extern void r600_page_table_cleanup(struct drm_device *dev, struct drm_ati_pcigart_info *gart_info); -extern int r600_cs_legacy_ioctl(struct drm_device *dev, void *data, struct drm_file *fpriv); -extern void r600_cp_dispatch_swap(struct drm_device *dev, struct drm_file *file_priv); -extern int r600_cp_dispatch_texture(struct drm_device *dev, - struct drm_file *file_priv, - drm_radeon_texture_t *tex, - drm_radeon_tex_image_t *image); -/* r600_blit.c */ -extern int r600_prepare_blit_copy(struct drm_device *dev, struct drm_file *file_priv); -extern void r600_done_blit_copy(struct drm_device *dev); -extern void r600_blit_copy(struct drm_device *dev, - uint64_t src_gpu_addr, uint64_t dst_gpu_addr, - int size_bytes); -extern void r600_blit_swap(struct drm_device *dev, - uint64_t src_gpu_addr, uint64_t dst_gpu_addr, - int sx, int sy, int dx, int dy, - int w, int h, int src_pitch, int dst_pitch, int cpp); - -/* Flags for stats.boxes - */ -#define RADEON_BOX_DMA_IDLE 0x1 -#define RADEON_BOX_RING_FULL 0x2 -#define RADEON_BOX_FLIP 0x4 -#define RADEON_BOX_WAIT_IDLE 0x8 -#define RADEON_BOX_TEXTURE_LOAD 0x10 - -/* Register definitions, register access macros and drmAddMap constants - * for Radeon kernel driver. - */ -#define RADEON_MM_INDEX 0x0000 -#define RADEON_MM_DATA 0x0004 - -#define RADEON_AGP_COMMAND 0x0f60 -#define RADEON_AGP_COMMAND_PCI_CONFIG 0x0060 /* offset in PCI config */ -# define RADEON_AGP_ENABLE (1<<8) -#define RADEON_AUX_SCISSOR_CNTL 0x26f0 -# define RADEON_EXCLUSIVE_SCISSOR_0 (1 << 24) -# define RADEON_EXCLUSIVE_SCISSOR_1 (1 << 25) -# define RADEON_EXCLUSIVE_SCISSOR_2 (1 << 26) -# define RADEON_SCISSOR_0_ENABLE (1 << 28) -# define RADEON_SCISSOR_1_ENABLE (1 << 29) -# define RADEON_SCISSOR_2_ENABLE (1 << 30) - -/* - * PCIE radeons (rv370/rv380, rv410, r423/r430/r480, r5xx) - * don't have an explicit bus mastering disable bit. It's handled - * by the PCI D-states. PMI_BM_DIS disables D-state bus master - * handling, not bus mastering itself. - */ -#define RADEON_BUS_CNTL 0x0030 -/* r1xx, r2xx, r300, r(v)350, r420/r481, rs400/rs480 */ -# define RADEON_BUS_MASTER_DIS (1 << 6) -/* rs600/rs690/rs740 */ -# define RS600_BUS_MASTER_DIS (1 << 14) -# define RS600_MSI_REARM (1 << 20) -/* see RS400_MSI_REARM in AIC_CNTL for rs480 */ - -#define RADEON_BUS_CNTL1 0x0034 -# define RADEON_PMI_BM_DIS (1 << 2) -# define RADEON_PMI_INT_DIS (1 << 3) - -#define RV370_BUS_CNTL 0x004c -# define RV370_PMI_BM_DIS (1 << 5) -# define RV370_PMI_INT_DIS (1 << 6) - -#define RADEON_MSI_REARM_EN 0x0160 -/* rv370/rv380, rv410, r423/r430/r480, r5xx */ -# define RV370_MSI_REARM_EN (1 << 0) - -#define RADEON_CLOCK_CNTL_DATA 0x000c -# define RADEON_PLL_WR_EN (1 << 7) -#define RADEON_CLOCK_CNTL_INDEX 0x0008 -#define RADEON_CONFIG_APER_SIZE 0x0108 -#define RADEON_CONFIG_MEMSIZE 0x00f8 -#define RADEON_CRTC_OFFSET 0x0224 -#define RADEON_CRTC_OFFSET_CNTL 0x0228 -# define RADEON_CRTC_TILE_EN (1 << 15) -# define RADEON_CRTC_OFFSET_FLIP_CNTL (1 << 16) -#define RADEON_CRTC2_OFFSET 0x0324 -#define RADEON_CRTC2_OFFSET_CNTL 0x0328 - -#define RADEON_PCIE_INDEX 0x0030 -#define RADEON_PCIE_DATA 0x0034 -#define RADEON_PCIE_TX_GART_CNTL 0x10 -# define RADEON_PCIE_TX_GART_EN (1 << 0) -# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_PASS_THRU (0 << 1) -# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_CLAMP_LO (1 << 1) -# define RADEON_PCIE_TX_GART_UNMAPPED_ACCESS_DISCARD (3 << 1) -# define RADEON_PCIE_TX_GART_MODE_32_128_CACHE (0 << 3) -# define RADEON_PCIE_TX_GART_MODE_8_4_128_CACHE (1 << 3) -# define RADEON_PCIE_TX_GART_CHK_RW_VALID_EN (1 << 5) -# define RADEON_PCIE_TX_GART_INVALIDATE_TLB (1 << 8) -#define RADEON_PCIE_TX_DISCARD_RD_ADDR_LO 0x11 -#define RADEON_PCIE_TX_DISCARD_RD_ADDR_HI 0x12 -#define RADEON_PCIE_TX_GART_BASE 0x13 -#define RADEON_PCIE_TX_GART_START_LO 0x14 -#define RADEON_PCIE_TX_GART_START_HI 0x15 -#define RADEON_PCIE_TX_GART_END_LO 0x16 -#define RADEON_PCIE_TX_GART_END_HI 0x17 - -#define RS480_NB_MC_INDEX 0x168 -# define RS480_NB_MC_IND_WR_EN (1 << 8) -#define RS480_NB_MC_DATA 0x16c - -#define RS690_MC_INDEX 0x78 -# define RS690_MC_INDEX_MASK 0x1ff -# define RS690_MC_INDEX_WR_EN (1 << 9) -# define RS690_MC_INDEX_WR_ACK 0x7f -#define RS690_MC_DATA 0x7c - -/* MC indirect registers */ -#define RS480_MC_MISC_CNTL 0x18 -# define RS480_DISABLE_GTW (1 << 1) -/* switch between MCIND GART and MM GART registers. 0 = mmgart, 1 = mcind gart */ -# define RS480_GART_INDEX_REG_EN (1 << 12) -# define RS690_BLOCK_GFX_D3_EN (1 << 14) -#define RS480_K8_FB_LOCATION 0x1e -#define RS480_GART_FEATURE_ID 0x2b -# define RS480_HANG_EN (1 << 11) -# define RS480_TLB_ENABLE (1 << 18) -# define RS480_P2P_ENABLE (1 << 19) -# define RS480_GTW_LAC_EN (1 << 25) -# define RS480_2LEVEL_GART (0 << 30) -# define RS480_1LEVEL_GART (1 << 30) -# define RS480_PDC_EN (1 << 31) -#define RS480_GART_BASE 0x2c -#define RS480_GART_CACHE_CNTRL 0x2e -# define RS480_GART_CACHE_INVALIDATE (1 << 0) /* wait for it to clear */ -#define RS480_AGP_ADDRESS_SPACE_SIZE 0x38 -# define RS480_GART_EN (1 << 0) -# define RS480_VA_SIZE_32MB (0 << 1) -# define RS480_VA_SIZE_64MB (1 << 1) -# define RS480_VA_SIZE_128MB (2 << 1) -# define RS480_VA_SIZE_256MB (3 << 1) -# define RS480_VA_SIZE_512MB (4 << 1) -# define RS480_VA_SIZE_1GB (5 << 1) -# define RS480_VA_SIZE_2GB (6 << 1) -#define RS480_AGP_MODE_CNTL 0x39 -# define RS480_POST_GART_Q_SIZE (1 << 18) -# define RS480_NONGART_SNOOP (1 << 19) -# define RS480_AGP_RD_BUF_SIZE (1 << 20) -# define RS480_REQ_TYPE_SNOOP_SHIFT 22 -# define RS480_REQ_TYPE_SNOOP_MASK 0x3 -# define RS480_REQ_TYPE_SNOOP_DIS (1 << 24) -#define RS480_MC_MISC_UMA_CNTL 0x5f -#define RS480_MC_MCLK_CNTL 0x7a -#define RS480_MC_UMA_DUALCH_CNTL 0x86 - -#define RS690_MC_FB_LOCATION 0x100 -#define RS690_MC_AGP_LOCATION 0x101 -#define RS690_MC_AGP_BASE 0x102 -#define RS690_MC_AGP_BASE_2 0x103 - -#define RS600_MC_INDEX 0x70 -# define RS600_MC_ADDR_MASK 0xffff -# define RS600_MC_IND_SEQ_RBS_0 (1 << 16) -# define RS600_MC_IND_SEQ_RBS_1 (1 << 17) -# define RS600_MC_IND_SEQ_RBS_2 (1 << 18) -# define RS600_MC_IND_SEQ_RBS_3 (1 << 19) -# define RS600_MC_IND_AIC_RBS (1 << 20) -# define RS600_MC_IND_CITF_ARB0 (1 << 21) -# define RS600_MC_IND_CITF_ARB1 (1 << 22) -# define RS600_MC_IND_WR_EN (1 << 23) -#define RS600_MC_DATA 0x74 - -#define RS600_MC_STATUS 0x0 -# define RS600_MC_IDLE (1 << 1) -#define RS600_MC_FB_LOCATION 0x4 -#define RS600_MC_AGP_LOCATION 0x5 -#define RS600_AGP_BASE 0x6 -#define RS600_AGP_BASE_2 0x7 -#define RS600_MC_CNTL1 0x9 -# define RS600_ENABLE_PAGE_TABLES (1 << 26) -#define RS600_MC_PT0_CNTL 0x100 -# define RS600_ENABLE_PT (1 << 0) -# define RS600_EFFECTIVE_L2_CACHE_SIZE(x) ((x) << 15) -# define RS600_EFFECTIVE_L2_QUEUE_SIZE(x) ((x) << 21) -# define RS600_INVALIDATE_ALL_L1_TLBS (1 << 28) -# define RS600_INVALIDATE_L2_CACHE (1 << 29) -#define RS600_MC_PT0_CONTEXT0_CNTL 0x102 -# define RS600_ENABLE_PAGE_TABLE (1 << 0) -# define RS600_PAGE_TABLE_TYPE_FLAT (0 << 1) -#define RS600_MC_PT0_SYSTEM_APERTURE_LOW_ADDR 0x112 -#define RS600_MC_PT0_SYSTEM_APERTURE_HIGH_ADDR 0x114 -#define RS600_MC_PT0_CONTEXT0_DEFAULT_READ_ADDR 0x11c -#define RS600_MC_PT0_CONTEXT0_FLAT_BASE_ADDR 0x12c -#define RS600_MC_PT0_CONTEXT0_FLAT_START_ADDR 0x13c -#define RS600_MC_PT0_CONTEXT0_FLAT_END_ADDR 0x14c -#define RS600_MC_PT0_CLIENT0_CNTL 0x16c -# define RS600_ENABLE_TRANSLATION_MODE_OVERRIDE (1 << 0) -# define RS600_TRANSLATION_MODE_OVERRIDE (1 << 1) -# define RS600_SYSTEM_ACCESS_MODE_MASK (3 << 8) -# define RS600_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 8) -# define RS600_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 8) -# define RS600_SYSTEM_ACCESS_MODE_IN_SYS (2 << 8) -# define RS600_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 8) -# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASSTHROUGH (0 << 10) -# define RS600_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 10) -# define RS600_EFFECTIVE_L1_CACHE_SIZE(x) ((x) << 11) -# define RS600_ENABLE_FRAGMENT_PROCESSING (1 << 14) -# define RS600_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) -# define RS600_INVALIDATE_L1_TLB (1 << 20) - -#define R520_MC_IND_INDEX 0x70 -#define R520_MC_IND_WR_EN (1 << 24) -#define R520_MC_IND_DATA 0x74 - -#define RV515_MC_FB_LOCATION 0x01 -#define RV515_MC_AGP_LOCATION 0x02 -#define RV515_MC_AGP_BASE 0x03 -#define RV515_MC_AGP_BASE_2 0x04 - -#define R520_MC_FB_LOCATION 0x04 -#define R520_MC_AGP_LOCATION 0x05 -#define R520_MC_AGP_BASE 0x06 -#define R520_MC_AGP_BASE_2 0x07 - -#define RADEON_MPP_TB_CONFIG 0x01c0 -#define RADEON_MEM_CNTL 0x0140 -#define RADEON_MEM_SDRAM_MODE_REG 0x0158 -#define RADEON_AGP_BASE_2 0x015c /* r200+ only */ -#define RS480_AGP_BASE_2 0x0164 -#define RADEON_AGP_BASE 0x0170 - -/* pipe config regs */ -#define R400_GB_PIPE_SELECT 0x402c -#define RV530_GB_PIPE_SELECT2 0x4124 -#define R500_DYN_SCLK_PWMEM_PIPE 0x000d /* PLL */ -#define R300_GB_TILE_CONFIG 0x4018 -# define R300_ENABLE_TILING (1 << 0) -# define R300_PIPE_COUNT_RV350 (0 << 1) -# define R300_PIPE_COUNT_R300 (3 << 1) -# define R300_PIPE_COUNT_R420_3P (6 << 1) -# define R300_PIPE_COUNT_R420 (7 << 1) -# define R300_TILE_SIZE_8 (0 << 4) -# define R300_TILE_SIZE_16 (1 << 4) -# define R300_TILE_SIZE_32 (2 << 4) -# define R300_SUBPIXEL_1_12 (0 << 16) -# define R300_SUBPIXEL_1_16 (1 << 16) -#define R300_DST_PIPE_CONFIG 0x170c -# define R300_PIPE_AUTO_CONFIG (1 << 31) -#define R300_RB2D_DSTCACHE_MODE 0x3428 -# define R300_DC_AUTOFLUSH_ENABLE (1 << 8) -# define R300_DC_DC_DISABLE_IGNORE_PE (1 << 17) - -#define RADEON_RB3D_COLOROFFSET 0x1c40 -#define RADEON_RB3D_COLORPITCH 0x1c48 - -#define RADEON_SRC_X_Y 0x1590 - -#define RADEON_DP_GUI_MASTER_CNTL 0x146c -# define RADEON_GMC_SRC_PITCH_OFFSET_CNTL (1 << 0) -# define RADEON_GMC_DST_PITCH_OFFSET_CNTL (1 << 1) -# define RADEON_GMC_BRUSH_SOLID_COLOR (13 << 4) -# define RADEON_GMC_BRUSH_NONE (15 << 4) -# define RADEON_GMC_DST_16BPP (4 << 8) -# define RADEON_GMC_DST_24BPP (5 << 8) -# define RADEON_GMC_DST_32BPP (6 << 8) -# define RADEON_GMC_DST_DATATYPE_SHIFT 8 -# define RADEON_GMC_SRC_DATATYPE_COLOR (3 << 12) -# define RADEON_DP_SRC_SOURCE_MEMORY (2 << 24) -# define RADEON_DP_SRC_SOURCE_HOST_DATA (3 << 24) -# define RADEON_GMC_CLR_CMP_CNTL_DIS (1 << 28) -# define RADEON_GMC_WR_MSK_DIS (1 << 30) -# define RADEON_ROP3_S 0x00cc0000 -# define RADEON_ROP3_P 0x00f00000 -#define RADEON_DP_WRITE_MASK 0x16cc -#define RADEON_SRC_PITCH_OFFSET 0x1428 -#define RADEON_DST_PITCH_OFFSET 0x142c -#define RADEON_DST_PITCH_OFFSET_C 0x1c80 -# define RADEON_DST_TILE_LINEAR (0 << 30) -# define RADEON_DST_TILE_MACRO (1 << 30) -# define RADEON_DST_TILE_MICRO (2 << 30) -# define RADEON_DST_TILE_BOTH (3 << 30) - -#define RADEON_SCRATCH_REG0 0x15e0 -#define RADEON_SCRATCH_REG1 0x15e4 -#define RADEON_SCRATCH_REG2 0x15e8 -#define RADEON_SCRATCH_REG3 0x15ec -#define RADEON_SCRATCH_REG4 0x15f0 -#define RADEON_SCRATCH_REG5 0x15f4 -#define RADEON_SCRATCH_UMSK 0x0770 -#define RADEON_SCRATCH_ADDR 0x0774 - -#define RADEON_SCRATCHOFF( x ) (RADEON_SCRATCH_REG_OFFSET + 4*(x)) - -extern u32 radeon_get_scratch(drm_radeon_private_t *dev_priv, int index); - -#define GET_SCRATCH(dev_priv, x) radeon_get_scratch(dev_priv, x) - -#define R600_SCRATCH_REG0 0x8500 -#define R600_SCRATCH_REG1 0x8504 -#define R600_SCRATCH_REG2 0x8508 -#define R600_SCRATCH_REG3 0x850c -#define R600_SCRATCH_REG4 0x8510 -#define R600_SCRATCH_REG5 0x8514 -#define R600_SCRATCH_REG6 0x8518 -#define R600_SCRATCH_REG7 0x851c -#define R600_SCRATCH_UMSK 0x8540 -#define R600_SCRATCH_ADDR 0x8544 - -#define R600_SCRATCHOFF(x) (R600_SCRATCH_REG_OFFSET + 4*(x)) - -#define RADEON_GEN_INT_CNTL 0x0040 -# define RADEON_CRTC_VBLANK_MASK (1 << 0) -# define RADEON_CRTC2_VBLANK_MASK (1 << 9) -# define RADEON_GUI_IDLE_INT_ENABLE (1 << 19) -# define RADEON_SW_INT_ENABLE (1 << 25) - -#define RADEON_GEN_INT_STATUS 0x0044 -# define RADEON_CRTC_VBLANK_STAT (1 << 0) -# define RADEON_CRTC_VBLANK_STAT_ACK (1 << 0) -# define RADEON_CRTC2_VBLANK_STAT (1 << 9) -# define RADEON_CRTC2_VBLANK_STAT_ACK (1 << 9) -# define RADEON_GUI_IDLE_INT_TEST_ACK (1 << 19) -# define RADEON_SW_INT_TEST (1 << 25) -# define RADEON_SW_INT_TEST_ACK (1 << 25) -# define RADEON_SW_INT_FIRE (1 << 26) -# define R500_DISPLAY_INT_STATUS (1 << 0) - -#define RADEON_HOST_PATH_CNTL 0x0130 -# define RADEON_HDP_SOFT_RESET (1 << 26) -# define RADEON_HDP_WC_TIMEOUT_MASK (7 << 28) -# define RADEON_HDP_WC_TIMEOUT_28BCLK (7 << 28) - -#define RADEON_ISYNC_CNTL 0x1724 -# define RADEON_ISYNC_ANY2D_IDLE3D (1 << 0) -# define RADEON_ISYNC_ANY3D_IDLE2D (1 << 1) -# define RADEON_ISYNC_TRIG2D_IDLE3D (1 << 2) -# define RADEON_ISYNC_TRIG3D_IDLE2D (1 << 3) -# define RADEON_ISYNC_WAIT_IDLEGUI (1 << 4) -# define RADEON_ISYNC_CPSCRATCH_IDLEGUI (1 << 5) - -#define RADEON_RBBM_GUICNTL 0x172c -# define RADEON_HOST_DATA_SWAP_NONE (0 << 0) -# define RADEON_HOST_DATA_SWAP_16BIT (1 << 0) -# define RADEON_HOST_DATA_SWAP_32BIT (2 << 0) -# define RADEON_HOST_DATA_SWAP_HDW (3 << 0) - -#define RADEON_MC_AGP_LOCATION 0x014c -#define RADEON_MC_FB_LOCATION 0x0148 -#define RADEON_MCLK_CNTL 0x0012 -# define RADEON_FORCEON_MCLKA (1 << 16) -# define RADEON_FORCEON_MCLKB (1 << 17) -# define RADEON_FORCEON_YCLKA (1 << 18) -# define RADEON_FORCEON_YCLKB (1 << 19) -# define RADEON_FORCEON_MC (1 << 20) -# define RADEON_FORCEON_AIC (1 << 21) - -#define RADEON_PP_BORDER_COLOR_0 0x1d40 -#define RADEON_PP_BORDER_COLOR_1 0x1d44 -#define RADEON_PP_BORDER_COLOR_2 0x1d48 -#define RADEON_PP_CNTL 0x1c38 -# define RADEON_SCISSOR_ENABLE (1 << 1) -#define RADEON_PP_LUM_MATRIX 0x1d00 -#define RADEON_PP_MISC 0x1c14 -#define RADEON_PP_ROT_MATRIX_0 0x1d58 -#define RADEON_PP_TXFILTER_0 0x1c54 -#define RADEON_PP_TXOFFSET_0 0x1c5c -#define RADEON_PP_TXFILTER_1 0x1c6c -#define RADEON_PP_TXFILTER_2 0x1c84 - -#define R300_RB2D_DSTCACHE_CTLSTAT 0x342c /* use R300_DSTCACHE_CTLSTAT */ -#define R300_DSTCACHE_CTLSTAT 0x1714 -# define R300_RB2D_DC_FLUSH (3 << 0) -# define R300_RB2D_DC_FREE (3 << 2) -# define R300_RB2D_DC_FLUSH_ALL 0xf -# define R300_RB2D_DC_BUSY (1 << 31) -#define RADEON_RB3D_CNTL 0x1c3c -# define RADEON_ALPHA_BLEND_ENABLE (1 << 0) -# define RADEON_PLANE_MASK_ENABLE (1 << 1) -# define RADEON_DITHER_ENABLE (1 << 2) -# define RADEON_ROUND_ENABLE (1 << 3) -# define RADEON_SCALE_DITHER_ENABLE (1 << 4) -# define RADEON_DITHER_INIT (1 << 5) -# define RADEON_ROP_ENABLE (1 << 6) -# define RADEON_STENCIL_ENABLE (1 << 7) -# define RADEON_Z_ENABLE (1 << 8) -# define RADEON_ZBLOCK16 (1 << 15) -#define RADEON_RB3D_DEPTHOFFSET 0x1c24 -#define RADEON_RB3D_DEPTHCLEARVALUE 0x3230 -#define RADEON_RB3D_DEPTHPITCH 0x1c28 -#define RADEON_RB3D_PLANEMASK 0x1d84 -#define RADEON_RB3D_STENCILREFMASK 0x1d7c -#define RADEON_RB3D_ZCACHE_MODE 0x3250 -#define RADEON_RB3D_ZCACHE_CTLSTAT 0x3254 -# define RADEON_RB3D_ZC_FLUSH (1 << 0) -# define RADEON_RB3D_ZC_FREE (1 << 2) -# define RADEON_RB3D_ZC_FLUSH_ALL 0x5 -# define RADEON_RB3D_ZC_BUSY (1 << 31) -#define R300_ZB_ZCACHE_CTLSTAT 0x4f18 -# define R300_ZC_FLUSH (1 << 0) -# define R300_ZC_FREE (1 << 1) -# define R300_ZC_BUSY (1 << 31) -#define RADEON_RB3D_DSTCACHE_CTLSTAT 0x325c -# define RADEON_RB3D_DC_FLUSH (3 << 0) -# define RADEON_RB3D_DC_FREE (3 << 2) -# define RADEON_RB3D_DC_FLUSH_ALL 0xf -# define RADEON_RB3D_DC_BUSY (1 << 31) -#define R300_RB3D_DSTCACHE_CTLSTAT 0x4e4c -# define R300_RB3D_DC_FLUSH (2 << 0) -# define R300_RB3D_DC_FREE (2 << 2) -# define R300_RB3D_DC_FINISH (1 << 4) -#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c -# define RADEON_Z_TEST_MASK (7 << 4) -# define RADEON_Z_TEST_ALWAYS (7 << 4) -# define RADEON_Z_HIERARCHY_ENABLE (1 << 8) -# define RADEON_STENCIL_TEST_ALWAYS (7 << 12) -# define RADEON_STENCIL_S_FAIL_REPLACE (2 << 16) -# define RADEON_STENCIL_ZPASS_REPLACE (2 << 20) -# define RADEON_STENCIL_ZFAIL_REPLACE (2 << 24) -# define RADEON_Z_COMPRESSION_ENABLE (1 << 28) -# define RADEON_FORCE_Z_DIRTY (1 << 29) -# define RADEON_Z_WRITE_ENABLE (1 << 30) -# define RADEON_Z_DECOMPRESSION_ENABLE (1 << 31) -#define RADEON_RBBM_SOFT_RESET 0x00f0 -# define RADEON_SOFT_RESET_CP (1 << 0) -# define RADEON_SOFT_RESET_HI (1 << 1) -# define RADEON_SOFT_RESET_SE (1 << 2) -# define RADEON_SOFT_RESET_RE (1 << 3) -# define RADEON_SOFT_RESET_PP (1 << 4) -# define RADEON_SOFT_RESET_E2 (1 << 5) -# define RADEON_SOFT_RESET_RB (1 << 6) -# define RADEON_SOFT_RESET_HDP (1 << 7) -/* - * 6:0 Available slots in the FIFO - * 8 Host Interface active - * 9 CP request active - * 10 FIFO request active - * 11 Host Interface retry active - * 12 CP retry active - * 13 FIFO retry active - * 14 FIFO pipeline busy - * 15 Event engine busy - * 16 CP command stream busy - * 17 2D engine busy - * 18 2D portion of render backend busy - * 20 3D setup engine busy - * 26 GA engine busy - * 27 CBA 2D engine busy - * 31 2D engine busy or 3D engine busy or FIFO not empty or CP busy or - * command stream queue not empty or Ring Buffer not empty - */ -#define RADEON_RBBM_STATUS 0x0e40 -/* Same as the previous RADEON_RBBM_STATUS; this is a mirror of that register. */ -/* #define RADEON_RBBM_STATUS 0x1740 */ -/* bits 6:0 are dword slots available in the cmd fifo */ -# define RADEON_RBBM_FIFOCNT_MASK 0x007f -# define RADEON_HIRQ_ON_RBB (1 << 8) -# define RADEON_CPRQ_ON_RBB (1 << 9) -# define RADEON_CFRQ_ON_RBB (1 << 10) -# define RADEON_HIRQ_IN_RTBUF (1 << 11) -# define RADEON_CPRQ_IN_RTBUF (1 << 12) -# define RADEON_CFRQ_IN_RTBUF (1 << 13) -# define RADEON_PIPE_BUSY (1 << 14) -# define RADEON_ENG_EV_BUSY (1 << 15) -# define RADEON_CP_CMDSTRM_BUSY (1 << 16) -# define RADEON_E2_BUSY (1 << 17) -# define RADEON_RB2D_BUSY (1 << 18) -# define RADEON_RB3D_BUSY (1 << 19) /* not used on r300 */ -# define RADEON_VAP_BUSY (1 << 20) -# define RADEON_RE_BUSY (1 << 21) /* not used on r300 */ -# define RADEON_TAM_BUSY (1 << 22) /* not used on r300 */ -# define RADEON_TDM_BUSY (1 << 23) /* not used on r300 */ -# define RADEON_PB_BUSY (1 << 24) /* not used on r300 */ -# define RADEON_TIM_BUSY (1 << 25) /* not used on r300 */ -# define RADEON_GA_BUSY (1 << 26) -# define RADEON_CBA2D_BUSY (1 << 27) -# define RADEON_RBBM_ACTIVE (1 << 31) -#define RADEON_RE_LINE_PATTERN 0x1cd0 -#define RADEON_RE_MISC 0x26c4 -#define RADEON_RE_TOP_LEFT 0x26c0 -#define RADEON_RE_WIDTH_HEIGHT 0x1c44 -#define RADEON_RE_STIPPLE_ADDR 0x1cc8 -#define RADEON_RE_STIPPLE_DATA 0x1ccc - -#define RADEON_SCISSOR_TL_0 0x1cd8 -#define RADEON_SCISSOR_BR_0 0x1cdc -#define RADEON_SCISSOR_TL_1 0x1ce0 -#define RADEON_SCISSOR_BR_1 0x1ce4 -#define RADEON_SCISSOR_TL_2 0x1ce8 -#define RADEON_SCISSOR_BR_2 0x1cec -#define RADEON_SE_COORD_FMT 0x1c50 -#define RADEON_SE_CNTL 0x1c4c -# define RADEON_FFACE_CULL_CW (0 << 0) -# define RADEON_BFACE_SOLID (3 << 1) -# define RADEON_FFACE_SOLID (3 << 3) -# define RADEON_FLAT_SHADE_VTX_LAST (3 << 6) -# define RADEON_DIFFUSE_SHADE_FLAT (1 << 8) -# define RADEON_DIFFUSE_SHADE_GOURAUD (2 << 8) -# define RADEON_ALPHA_SHADE_FLAT (1 << 10) -# define RADEON_ALPHA_SHADE_GOURAUD (2 << 10) -# define RADEON_SPECULAR_SHADE_FLAT (1 << 12) -# define RADEON_SPECULAR_SHADE_GOURAUD (2 << 12) -# define RADEON_FOG_SHADE_FLAT (1 << 14) -# define RADEON_FOG_SHADE_GOURAUD (2 << 14) -# define RADEON_VPORT_XY_XFORM_ENABLE (1 << 24) -# define RADEON_VPORT_Z_XFORM_ENABLE (1 << 25) -# define RADEON_VTX_PIX_CENTER_OGL (1 << 27) -# define RADEON_ROUND_MODE_TRUNC (0 << 28) -# define RADEON_ROUND_PREC_8TH_PIX (1 << 30) -#define RADEON_SE_CNTL_STATUS 0x2140 -#define RADEON_SE_LINE_WIDTH 0x1db8 -#define RADEON_SE_VPORT_XSCALE 0x1d98 -#define RADEON_SE_ZBIAS_FACTOR 0x1db0 -#define RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED 0x2210 -#define RADEON_SE_TCL_OUTPUT_VTX_FMT 0x2254 -#define RADEON_SE_TCL_VECTOR_INDX_REG 0x2200 -# define RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT 16 -# define RADEON_VEC_INDX_DWORD_COUNT_SHIFT 28 -#define RADEON_SE_TCL_VECTOR_DATA_REG 0x2204 -#define RADEON_SE_TCL_SCALAR_INDX_REG 0x2208 -# define RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT 16 -#define RADEON_SE_TCL_SCALAR_DATA_REG 0x220C -#define RADEON_SURFACE_ACCESS_FLAGS 0x0bf8 -#define RADEON_SURFACE_ACCESS_CLR 0x0bfc -#define RADEON_SURFACE_CNTL 0x0b00 -# define RADEON_SURF_TRANSLATION_DIS (1 << 8) -# define RADEON_NONSURF_AP0_SWP_MASK (3 << 20) -# define RADEON_NONSURF_AP0_SWP_LITTLE (0 << 20) -# define RADEON_NONSURF_AP0_SWP_BIG16 (1 << 20) -# define RADEON_NONSURF_AP0_SWP_BIG32 (2 << 20) -# define RADEON_NONSURF_AP1_SWP_MASK (3 << 22) -# define RADEON_NONSURF_AP1_SWP_LITTLE (0 << 22) -# define RADEON_NONSURF_AP1_SWP_BIG16 (1 << 22) -# define RADEON_NONSURF_AP1_SWP_BIG32 (2 << 22) -#define RADEON_SURFACE0_INFO 0x0b0c -# define RADEON_SURF_PITCHSEL_MASK (0x1ff << 0) -# define RADEON_SURF_TILE_MODE_MASK (3 << 16) -# define RADEON_SURF_TILE_MODE_MACRO (0 << 16) -# define RADEON_SURF_TILE_MODE_MICRO (1 << 16) -# define RADEON_SURF_TILE_MODE_32BIT_Z (2 << 16) -# define RADEON_SURF_TILE_MODE_16BIT_Z (3 << 16) -#define RADEON_SURFACE0_LOWER_BOUND 0x0b04 -#define RADEON_SURFACE0_UPPER_BOUND 0x0b08 -# define RADEON_SURF_ADDRESS_FIXED_MASK (0x3ff << 0) -#define RADEON_SURFACE1_INFO 0x0b1c -#define RADEON_SURFACE1_LOWER_BOUND 0x0b14 -#define RADEON_SURFACE1_UPPER_BOUND 0x0b18 -#define RADEON_SURFACE2_INFO 0x0b2c -#define RADEON_SURFACE2_LOWER_BOUND 0x0b24 -#define RADEON_SURFACE2_UPPER_BOUND 0x0b28 -#define RADEON_SURFACE3_INFO 0x0b3c -#define RADEON_SURFACE3_LOWER_BOUND 0x0b34 -#define RADEON_SURFACE3_UPPER_BOUND 0x0b38 -#define RADEON_SURFACE4_INFO 0x0b4c -#define RADEON_SURFACE4_LOWER_BOUND 0x0b44 -#define RADEON_SURFACE4_UPPER_BOUND 0x0b48 -#define RADEON_SURFACE5_INFO 0x0b5c -#define RADEON_SURFACE5_LOWER_BOUND 0x0b54 -#define RADEON_SURFACE5_UPPER_BOUND 0x0b58 -#define RADEON_SURFACE6_INFO 0x0b6c -#define RADEON_SURFACE6_LOWER_BOUND 0x0b64 -#define RADEON_SURFACE6_UPPER_BOUND 0x0b68 -#define RADEON_SURFACE7_INFO 0x0b7c -#define RADEON_SURFACE7_LOWER_BOUND 0x0b74 -#define RADEON_SURFACE7_UPPER_BOUND 0x0b78 -#define RADEON_SW_SEMAPHORE 0x013c - -#define RADEON_WAIT_UNTIL 0x1720 -# define RADEON_WAIT_CRTC_PFLIP (1 << 0) -# define RADEON_WAIT_2D_IDLE (1 << 14) -# define RADEON_WAIT_3D_IDLE (1 << 15) -# define RADEON_WAIT_2D_IDLECLEAN (1 << 16) -# define RADEON_WAIT_3D_IDLECLEAN (1 << 17) -# define RADEON_WAIT_HOST_IDLECLEAN (1 << 18) - -#define RADEON_RB3D_ZMASKOFFSET 0x3234 -#define RADEON_RB3D_ZSTENCILCNTL 0x1c2c -# define RADEON_DEPTH_FORMAT_16BIT_INT_Z (0 << 0) -# define RADEON_DEPTH_FORMAT_24BIT_INT_Z (2 << 0) - -/* CP registers */ -#define RADEON_CP_ME_RAM_ADDR 0x07d4 -#define RADEON_CP_ME_RAM_RADDR 0x07d8 -#define RADEON_CP_ME_RAM_DATAH 0x07dc -#define RADEON_CP_ME_RAM_DATAL 0x07e0 - -#define RADEON_CP_RB_BASE 0x0700 -#define RADEON_CP_RB_CNTL 0x0704 -# define RADEON_BUF_SWAP_32BIT (2 << 16) -# define RADEON_RB_NO_UPDATE (1 << 27) -# define RADEON_RB_RPTR_WR_ENA (1 << 31) -#define RADEON_CP_RB_RPTR_ADDR 0x070c -#define RADEON_CP_RB_RPTR 0x0710 -#define RADEON_CP_RB_WPTR 0x0714 - -#define RADEON_CP_RB_WPTR_DELAY 0x0718 -# define RADEON_PRE_WRITE_TIMER_SHIFT 0 -# define RADEON_PRE_WRITE_LIMIT_SHIFT 23 - -#define RADEON_CP_IB_BASE 0x0738 - -#define RADEON_CP_CSQ_CNTL 0x0740 -# define RADEON_CSQ_CNT_PRIMARY_MASK (0xff << 0) -# define RADEON_CSQ_PRIDIS_INDDIS (0 << 28) -# define RADEON_CSQ_PRIPIO_INDDIS (1 << 28) -# define RADEON_CSQ_PRIBM_INDDIS (2 << 28) -# define RADEON_CSQ_PRIPIO_INDBM (3 << 28) -# define RADEON_CSQ_PRIBM_INDBM (4 << 28) -# define RADEON_CSQ_PRIPIO_INDPIO (15 << 28) - -#define R300_CP_RESYNC_ADDR 0x0778 -#define R300_CP_RESYNC_DATA 0x077c - -#define RADEON_AIC_CNTL 0x01d0 -# define RADEON_PCIGART_TRANSLATE_EN (1 << 0) -# define RS400_MSI_REARM (1 << 3) -#define RADEON_AIC_STAT 0x01d4 -#define RADEON_AIC_PT_BASE 0x01d8 -#define RADEON_AIC_LO_ADDR 0x01dc -#define RADEON_AIC_HI_ADDR 0x01e0 -#define RADEON_AIC_TLB_ADDR 0x01e4 -#define RADEON_AIC_TLB_DATA 0x01e8 - -/* CP command packets */ -#define RADEON_CP_PACKET0 0x00000000 -# define RADEON_ONE_REG_WR (1 << 15) -#define RADEON_CP_PACKET1 0x40000000 -#define RADEON_CP_PACKET2 0x80000000 -#define RADEON_CP_PACKET3 0xC0000000 -# define RADEON_CP_NOP 0x00001000 -# define RADEON_CP_NEXT_CHAR 0x00001900 -# define RADEON_CP_PLY_NEXTSCAN 0x00001D00 -# define RADEON_CP_SET_SCISSORS 0x00001E00 - /* GEN_INDX_PRIM is unsupported starting with R300 */ -# define RADEON_3D_RNDR_GEN_INDX_PRIM 0x00002300 -# define RADEON_WAIT_FOR_IDLE 0x00002600 -# define RADEON_3D_DRAW_VBUF 0x00002800 -# define RADEON_3D_DRAW_IMMD 0x00002900 -# define RADEON_3D_DRAW_INDX 0x00002A00 -# define RADEON_CP_LOAD_PALETTE 0x00002C00 -# define RADEON_3D_LOAD_VBPNTR 0x00002F00 -# define RADEON_MPEG_IDCT_MACROBLOCK 0x00003000 -# define RADEON_MPEG_IDCT_MACROBLOCK_REV 0x00003100 -# define RADEON_3D_CLEAR_ZMASK 0x00003200 -# define RADEON_CP_INDX_BUFFER 0x00003300 -# define RADEON_CP_3D_DRAW_VBUF_2 0x00003400 -# define RADEON_CP_3D_DRAW_IMMD_2 0x00003500 -# define RADEON_CP_3D_DRAW_INDX_2 0x00003600 -# define RADEON_3D_CLEAR_HIZ 0x00003700 -# define RADEON_CP_3D_CLEAR_CMASK 0x00003802 -# define RADEON_CNTL_HOSTDATA_BLT 0x00009400 -# define RADEON_CNTL_PAINT_MULTI 0x00009A00 -# define RADEON_CNTL_BITBLT_MULTI 0x00009B00 -# define RADEON_CNTL_SET_SCISSORS 0xC0001E00 - -# define R600_IT_INDIRECT_BUFFER_END 0x00001700 -# define R600_IT_SET_PREDICATION 0x00002000 -# define R600_IT_REG_RMW 0x00002100 -# define R600_IT_COND_EXEC 0x00002200 -# define R600_IT_PRED_EXEC 0x00002300 -# define R600_IT_START_3D_CMDBUF 0x00002400 -# define R600_IT_DRAW_INDEX_2 0x00002700 -# define R600_IT_CONTEXT_CONTROL 0x00002800 -# define R600_IT_DRAW_INDEX_IMMD_BE 0x00002900 -# define R600_IT_INDEX_TYPE 0x00002A00 -# define R600_IT_DRAW_INDEX 0x00002B00 -# define R600_IT_DRAW_INDEX_AUTO 0x00002D00 -# define R600_IT_DRAW_INDEX_IMMD 0x00002E00 -# define R600_IT_NUM_INSTANCES 0x00002F00 -# define R600_IT_STRMOUT_BUFFER_UPDATE 0x00003400 -# define R600_IT_INDIRECT_BUFFER_MP 0x00003800 -# define R600_IT_MEM_SEMAPHORE 0x00003900 -# define R600_IT_MPEG_INDEX 0x00003A00 -# define R600_IT_WAIT_REG_MEM 0x00003C00 -# define R600_IT_MEM_WRITE 0x00003D00 -# define R600_IT_INDIRECT_BUFFER 0x00003200 -# define R600_IT_SURFACE_SYNC 0x00004300 -# define R600_CB0_DEST_BASE_ENA (1 << 6) -# define R600_TC_ACTION_ENA (1 << 23) -# define R600_VC_ACTION_ENA (1 << 24) -# define R600_CB_ACTION_ENA (1 << 25) -# define R600_DB_ACTION_ENA (1 << 26) -# define R600_SH_ACTION_ENA (1 << 27) -# define R600_SMX_ACTION_ENA (1 << 28) -# define R600_IT_ME_INITIALIZE 0x00004400 -# define R600_ME_INITIALIZE_DEVICE_ID(x) ((x) << 16) -# define R600_IT_COND_WRITE 0x00004500 -# define R600_IT_EVENT_WRITE 0x00004600 -# define R600_IT_EVENT_WRITE_EOP 0x00004700 -# define R600_IT_ONE_REG_WRITE 0x00005700 -# define R600_IT_SET_CONFIG_REG 0x00006800 -# define R600_SET_CONFIG_REG_OFFSET 0x00008000 -# define R600_SET_CONFIG_REG_END 0x0000ac00 -# define R600_IT_SET_CONTEXT_REG 0x00006900 -# define R600_SET_CONTEXT_REG_OFFSET 0x00028000 -# define R600_SET_CONTEXT_REG_END 0x00029000 -# define R600_IT_SET_ALU_CONST 0x00006A00 -# define R600_SET_ALU_CONST_OFFSET 0x00030000 -# define R600_SET_ALU_CONST_END 0x00032000 -# define R600_IT_SET_BOOL_CONST 0x00006B00 -# define R600_SET_BOOL_CONST_OFFSET 0x0003e380 -# define R600_SET_BOOL_CONST_END 0x00040000 -# define R600_IT_SET_LOOP_CONST 0x00006C00 -# define R600_SET_LOOP_CONST_OFFSET 0x0003e200 -# define R600_SET_LOOP_CONST_END 0x0003e380 -# define R600_IT_SET_RESOURCE 0x00006D00 -# define R600_SET_RESOURCE_OFFSET 0x00038000 -# define R600_SET_RESOURCE_END 0x0003c000 -# define R600_SQ_TEX_VTX_INVALID_TEXTURE 0x0 -# define R600_SQ_TEX_VTX_INVALID_BUFFER 0x1 -# define R600_SQ_TEX_VTX_VALID_TEXTURE 0x2 -# define R600_SQ_TEX_VTX_VALID_BUFFER 0x3 -# define R600_IT_SET_SAMPLER 0x00006E00 -# define R600_SET_SAMPLER_OFFSET 0x0003c000 -# define R600_SET_SAMPLER_END 0x0003cff0 -# define R600_IT_SET_CTL_CONST 0x00006F00 -# define R600_SET_CTL_CONST_OFFSET 0x0003cff0 -# define R600_SET_CTL_CONST_END 0x0003e200 -# define R600_IT_SURFACE_BASE_UPDATE 0x00007300 - -#define RADEON_CP_PACKET_MASK 0xC0000000 -#define RADEON_CP_PACKET_COUNT_MASK 0x3fff0000 -#define RADEON_CP_PACKET0_REG_MASK 0x000007ff -#define RADEON_CP_PACKET1_REG0_MASK 0x000007ff -#define RADEON_CP_PACKET1_REG1_MASK 0x003ff800 - -#define RADEON_VTX_Z_PRESENT (1 << 31) -#define RADEON_VTX_PKCOLOR_PRESENT (1 << 3) - -#define RADEON_PRIM_TYPE_NONE (0 << 0) -#define RADEON_PRIM_TYPE_POINT (1 << 0) -#define RADEON_PRIM_TYPE_LINE (2 << 0) -#define RADEON_PRIM_TYPE_LINE_STRIP (3 << 0) -#define RADEON_PRIM_TYPE_TRI_LIST (4 << 0) -#define RADEON_PRIM_TYPE_TRI_FAN (5 << 0) -#define RADEON_PRIM_TYPE_TRI_STRIP (6 << 0) -#define RADEON_PRIM_TYPE_TRI_TYPE2 (7 << 0) -#define RADEON_PRIM_TYPE_RECT_LIST (8 << 0) -#define RADEON_PRIM_TYPE_3VRT_POINT_LIST (9 << 0) -#define RADEON_PRIM_TYPE_3VRT_LINE_LIST (10 << 0) -#define RADEON_PRIM_TYPE_MASK 0xf -#define RADEON_PRIM_WALK_IND (1 << 4) -#define RADEON_PRIM_WALK_LIST (2 << 4) -#define RADEON_PRIM_WALK_RING (3 << 4) -#define RADEON_COLOR_ORDER_BGRA (0 << 6) -#define RADEON_COLOR_ORDER_RGBA (1 << 6) -#define RADEON_MAOS_ENABLE (1 << 7) -#define RADEON_VTX_FMT_R128_MODE (0 << 8) -#define RADEON_VTX_FMT_RADEON_MODE (1 << 8) -#define RADEON_NUM_VERTICES_SHIFT 16 - -#define RADEON_COLOR_FORMAT_CI8 2 -#define RADEON_COLOR_FORMAT_ARGB1555 3 -#define RADEON_COLOR_FORMAT_RGB565 4 -#define RADEON_COLOR_FORMAT_ARGB8888 6 -#define RADEON_COLOR_FORMAT_RGB332 7 -#define RADEON_COLOR_FORMAT_RGB8 9 -#define RADEON_COLOR_FORMAT_ARGB4444 15 - -#define RADEON_TXFORMAT_I8 0 -#define RADEON_TXFORMAT_AI88 1 -#define RADEON_TXFORMAT_RGB332 2 -#define RADEON_TXFORMAT_ARGB1555 3 -#define RADEON_TXFORMAT_RGB565 4 -#define RADEON_TXFORMAT_ARGB4444 5 -#define RADEON_TXFORMAT_ARGB8888 6 -#define RADEON_TXFORMAT_RGBA8888 7 -#define RADEON_TXFORMAT_Y8 8 -#define RADEON_TXFORMAT_VYUY422 10 -#define RADEON_TXFORMAT_YVYU422 11 -#define RADEON_TXFORMAT_DXT1 12 -#define RADEON_TXFORMAT_DXT23 14 -#define RADEON_TXFORMAT_DXT45 15 - -#define R200_PP_TXCBLEND_0 0x2f00 -#define R200_PP_TXCBLEND_1 0x2f10 -#define R200_PP_TXCBLEND_2 0x2f20 -#define R200_PP_TXCBLEND_3 0x2f30 -#define R200_PP_TXCBLEND_4 0x2f40 -#define R200_PP_TXCBLEND_5 0x2f50 -#define R200_PP_TXCBLEND_6 0x2f60 -#define R200_PP_TXCBLEND_7 0x2f70 -#define R200_SE_TCL_LIGHT_MODEL_CTL_0 0x2268 -#define R200_PP_TFACTOR_0 0x2ee0 -#define R200_SE_VTX_FMT_0 0x2088 -#define R200_SE_VAP_CNTL 0x2080 -#define R200_SE_TCL_MATRIX_SEL_0 0x2230 -#define R200_SE_TCL_TEX_PROC_CTL_2 0x22a8 -#define R200_SE_TCL_UCP_VERT_BLEND_CTL 0x22c0 -#define R200_PP_TXFILTER_5 0x2ca0 -#define R200_PP_TXFILTER_4 0x2c80 -#define R200_PP_TXFILTER_3 0x2c60 -#define R200_PP_TXFILTER_2 0x2c40 -#define R200_PP_TXFILTER_1 0x2c20 -#define R200_PP_TXFILTER_0 0x2c00 -#define R200_PP_TXOFFSET_5 0x2d78 -#define R200_PP_TXOFFSET_4 0x2d60 -#define R200_PP_TXOFFSET_3 0x2d48 -#define R200_PP_TXOFFSET_2 0x2d30 -#define R200_PP_TXOFFSET_1 0x2d18 -#define R200_PP_TXOFFSET_0 0x2d00 - -#define R200_PP_CUBIC_FACES_0 0x2c18 -#define R200_PP_CUBIC_FACES_1 0x2c38 -#define R200_PP_CUBIC_FACES_2 0x2c58 -#define R200_PP_CUBIC_FACES_3 0x2c78 -#define R200_PP_CUBIC_FACES_4 0x2c98 -#define R200_PP_CUBIC_FACES_5 0x2cb8 -#define R200_PP_CUBIC_OFFSET_F1_0 0x2d04 -#define R200_PP_CUBIC_OFFSET_F2_0 0x2d08 -#define R200_PP_CUBIC_OFFSET_F3_0 0x2d0c -#define R200_PP_CUBIC_OFFSET_F4_0 0x2d10 -#define R200_PP_CUBIC_OFFSET_F5_0 0x2d14 -#define R200_PP_CUBIC_OFFSET_F1_1 0x2d1c -#define R200_PP_CUBIC_OFFSET_F2_1 0x2d20 -#define R200_PP_CUBIC_OFFSET_F3_1 0x2d24 -#define R200_PP_CUBIC_OFFSET_F4_1 0x2d28 -#define R200_PP_CUBIC_OFFSET_F5_1 0x2d2c -#define R200_PP_CUBIC_OFFSET_F1_2 0x2d34 -#define R200_PP_CUBIC_OFFSET_F2_2 0x2d38 -#define R200_PP_CUBIC_OFFSET_F3_2 0x2d3c -#define R200_PP_CUBIC_OFFSET_F4_2 0x2d40 -#define R200_PP_CUBIC_OFFSET_F5_2 0x2d44 -#define R200_PP_CUBIC_OFFSET_F1_3 0x2d4c -#define R200_PP_CUBIC_OFFSET_F2_3 0x2d50 -#define R200_PP_CUBIC_OFFSET_F3_3 0x2d54 -#define R200_PP_CUBIC_OFFSET_F4_3 0x2d58 -#define R200_PP_CUBIC_OFFSET_F5_3 0x2d5c -#define R200_PP_CUBIC_OFFSET_F1_4 0x2d64 -#define R200_PP_CUBIC_OFFSET_F2_4 0x2d68 -#define R200_PP_CUBIC_OFFSET_F3_4 0x2d6c -#define R200_PP_CUBIC_OFFSET_F4_4 0x2d70 -#define R200_PP_CUBIC_OFFSET_F5_4 0x2d74 -#define R200_PP_CUBIC_OFFSET_F1_5 0x2d7c -#define R200_PP_CUBIC_OFFSET_F2_5 0x2d80 -#define R200_PP_CUBIC_OFFSET_F3_5 0x2d84 -#define R200_PP_CUBIC_OFFSET_F4_5 0x2d88 -#define R200_PP_CUBIC_OFFSET_F5_5 0x2d8c - -#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 -#define R200_SE_VTE_CNTL 0x20b0 -#define R200_SE_TCL_OUTPUT_VTX_COMP_SEL 0x2250 -#define R200_PP_TAM_DEBUG3 0x2d9c -#define R200_PP_CNTL_X 0x2cc4 -#define R200_SE_VAP_CNTL_STATUS 0x2140 -#define R200_RE_SCISSOR_TL_0 0x1cd8 -#define R200_RE_SCISSOR_TL_1 0x1ce0 -#define R200_RE_SCISSOR_TL_2 0x1ce8 -#define R200_RB3D_DEPTHXY_OFFSET 0x1d60 -#define R200_RE_AUX_SCISSOR_CNTL 0x26f0 -#define R200_SE_VTX_STATE_CNTL 0x2180 -#define R200_RE_POINTSIZE 0x2648 -#define R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0 0x2254 - -#define RADEON_PP_TEX_SIZE_0 0x1d04 /* NPOT */ -#define RADEON_PP_TEX_SIZE_1 0x1d0c -#define RADEON_PP_TEX_SIZE_2 0x1d14 - -#define RADEON_PP_CUBIC_FACES_0 0x1d24 -#define RADEON_PP_CUBIC_FACES_1 0x1d28 -#define RADEON_PP_CUBIC_FACES_2 0x1d2c -#define RADEON_PP_CUBIC_OFFSET_T0_0 0x1dd0 /* bits [31:5] */ -#define RADEON_PP_CUBIC_OFFSET_T1_0 0x1e00 -#define RADEON_PP_CUBIC_OFFSET_T2_0 0x1e14 - -#define RADEON_SE_TCL_STATE_FLUSH 0x2284 - -#define SE_VAP_CNTL__TCL_ENA_MASK 0x00000001 -#define SE_VAP_CNTL__FORCE_W_TO_ONE_MASK 0x00010000 -#define SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT 0x00000012 -#define SE_VTE_CNTL__VTX_XY_FMT_MASK 0x00000100 -#define SE_VTE_CNTL__VTX_Z_FMT_MASK 0x00000200 -#define SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK 0x00000001 -#define SE_VTX_FMT_0__VTX_W0_PRESENT_MASK 0x00000002 -#define SE_VTX_FMT_0__VTX_COLOR_0_FMT__SHIFT 0x0000000b -#define R200_3D_DRAW_IMMD_2 0xC0003500 -#define R200_SE_VTX_FMT_1 0x208c -#define R200_RE_CNTL 0x1c50 - -#define R200_RB3D_BLENDCOLOR 0x3218 - -#define R200_SE_TCL_POINT_SPRITE_CNTL 0x22c4 - -#define R200_PP_TRI_PERF 0x2cf8 - -#define R200_PP_AFS_0 0x2f80 -#define R200_PP_AFS_1 0x2f00 /* same as txcblend_0 */ - -#define R200_VAP_PVS_CNTL_1 0x22D0 - -#define RADEON_CRTC_CRNT_FRAME 0x0214 -#define RADEON_CRTC2_CRNT_FRAME 0x0314 - -#define R500_D1CRTC_STATUS 0x609c -#define R500_D2CRTC_STATUS 0x689c -#define R500_CRTC_V_BLANK (1<<0) - -#define R500_D1CRTC_FRAME_COUNT 0x60a4 -#define R500_D2CRTC_FRAME_COUNT 0x68a4 - -#define R500_D1MODE_V_COUNTER 0x6530 -#define R500_D2MODE_V_COUNTER 0x6d30 - -#define R500_D1MODE_VBLANK_STATUS 0x6534 -#define R500_D2MODE_VBLANK_STATUS 0x6d34 -#define R500_VBLANK_OCCURED (1<<0) -#define R500_VBLANK_ACK (1<<4) -#define R500_VBLANK_STAT (1<<12) -#define R500_VBLANK_INT (1<<16) - -#define R500_DxMODE_INT_MASK 0x6540 -#define R500_D1MODE_INT_MASK (1<<0) -#define R500_D2MODE_INT_MASK (1<<8) - -#define R500_DISP_INTERRUPT_STATUS 0x7edc -#define R500_D1_VBLANK_INTERRUPT (1 << 4) -#define R500_D2_VBLANK_INTERRUPT (1 << 5) - -/* R6xx/R7xx registers */ -#define R600_MC_VM_FB_LOCATION 0x2180 -#define R600_MC_VM_AGP_TOP 0x2184 -#define R600_MC_VM_AGP_BOT 0x2188 -#define R600_MC_VM_AGP_BASE 0x218c -#define R600_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2190 -#define R600_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2194 -#define R600_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x2198 - -#define R700_MC_VM_FB_LOCATION 0x2024 -#define R700_MC_VM_AGP_TOP 0x2028 -#define R700_MC_VM_AGP_BOT 0x202c -#define R700_MC_VM_AGP_BASE 0x2030 -#define R700_MC_VM_SYSTEM_APERTURE_LOW_ADDR 0x2034 -#define R700_MC_VM_SYSTEM_APERTURE_HIGH_ADDR 0x2038 -#define R700_MC_VM_SYSTEM_APERTURE_DEFAULT_ADDR 0x203c - -#define R600_MCD_RD_A_CNTL 0x219c -#define R600_MCD_RD_B_CNTL 0x21a0 - -#define R600_MCD_WR_A_CNTL 0x21a4 -#define R600_MCD_WR_B_CNTL 0x21a8 - -#define R600_MCD_RD_SYS_CNTL 0x2200 -#define R600_MCD_WR_SYS_CNTL 0x2214 - -#define R600_MCD_RD_GFX_CNTL 0x21fc -#define R600_MCD_RD_HDP_CNTL 0x2204 -#define R600_MCD_RD_PDMA_CNTL 0x2208 -#define R600_MCD_RD_SEM_CNTL 0x220c -#define R600_MCD_WR_GFX_CNTL 0x2210 -#define R600_MCD_WR_HDP_CNTL 0x2218 -#define R600_MCD_WR_PDMA_CNTL 0x221c -#define R600_MCD_WR_SEM_CNTL 0x2220 - -# define R600_MCD_L1_TLB (1 << 0) -# define R600_MCD_L1_FRAG_PROC (1 << 1) -# define R600_MCD_L1_STRICT_ORDERING (1 << 2) - -# define R600_MCD_SYSTEM_ACCESS_MODE_MASK (3 << 6) -# define R600_MCD_SYSTEM_ACCESS_MODE_PA_ONLY (0 << 6) -# define R600_MCD_SYSTEM_ACCESS_MODE_USE_SYS_MAP (1 << 6) -# define R600_MCD_SYSTEM_ACCESS_MODE_IN_SYS (2 << 6) -# define R600_MCD_SYSTEM_ACCESS_MODE_NOT_IN_SYS (3 << 6) - -# define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 8) -# define R600_MCD_SYSTEM_APERTURE_UNMAPPED_ACCESS_DEFAULT_PAGE (1 << 8) - -# define R600_MCD_SEMAPHORE_MODE (1 << 10) -# define R600_MCD_WAIT_L2_QUERY (1 << 11) -# define R600_MCD_EFFECTIVE_L1_TLB_SIZE(x) ((x) << 12) -# define R600_MCD_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 15) - -#define R700_MC_VM_MD_L1_TLB0_CNTL 0x2654 -#define R700_MC_VM_MD_L1_TLB1_CNTL 0x2658 -#define R700_MC_VM_MD_L1_TLB2_CNTL 0x265c - -#define R700_MC_VM_MB_L1_TLB0_CNTL 0x2234 -#define R700_MC_VM_MB_L1_TLB1_CNTL 0x2238 -#define R700_MC_VM_MB_L1_TLB2_CNTL 0x223c -#define R700_MC_VM_MB_L1_TLB3_CNTL 0x2240 - -# define R700_ENABLE_L1_TLB (1 << 0) -# define R700_ENABLE_L1_FRAGMENT_PROCESSING (1 << 1) -# define R700_SYSTEM_ACCESS_MODE_IN_SYS (2 << 3) -# define R700_SYSTEM_APERTURE_UNMAPPED_ACCESS_PASS_THRU (0 << 5) -# define R700_EFFECTIVE_L1_TLB_SIZE(x) ((x) << 15) -# define R700_EFFECTIVE_L1_QUEUE_SIZE(x) ((x) << 18) - -#define R700_MC_ARB_RAMCFG 0x2760 -# define R700_NOOFBANK_SHIFT 0 -# define R700_NOOFBANK_MASK 0x3 -# define R700_NOOFRANK_SHIFT 2 -# define R700_NOOFRANK_MASK 0x1 -# define R700_NOOFROWS_SHIFT 3 -# define R700_NOOFROWS_MASK 0x7 -# define R700_NOOFCOLS_SHIFT 6 -# define R700_NOOFCOLS_MASK 0x3 -# define R700_CHANSIZE_SHIFT 8 -# define R700_CHANSIZE_MASK 0x1 -# define R700_BURSTLENGTH_SHIFT 9 -# define R700_BURSTLENGTH_MASK 0x1 -#define R600_RAMCFG 0x2408 -# define R600_NOOFBANK_SHIFT 0 -# define R600_NOOFBANK_MASK 0x1 -# define R600_NOOFRANK_SHIFT 1 -# define R600_NOOFRANK_MASK 0x1 -# define R600_NOOFROWS_SHIFT 2 -# define R600_NOOFROWS_MASK 0x7 -# define R600_NOOFCOLS_SHIFT 5 -# define R600_NOOFCOLS_MASK 0x3 -# define R600_CHANSIZE_SHIFT 7 -# define R600_CHANSIZE_MASK 0x1 -# define R600_BURSTLENGTH_SHIFT 8 -# define R600_BURSTLENGTH_MASK 0x1 - -#define R600_VM_L2_CNTL 0x1400 -# define R600_VM_L2_CACHE_EN (1 << 0) -# define R600_VM_L2_FRAG_PROC (1 << 1) -# define R600_VM_ENABLE_PTE_CACHE_LRU_W (1 << 9) -# define R600_VM_L2_CNTL_QUEUE_SIZE(x) ((x) << 13) -# define R700_VM_L2_CNTL_QUEUE_SIZE(x) ((x) << 14) - -#define R600_VM_L2_CNTL2 0x1404 -# define R600_VM_L2_CNTL2_INVALIDATE_ALL_L1_TLBS (1 << 0) -# define R600_VM_L2_CNTL2_INVALIDATE_L2_CACHE (1 << 1) -#define R600_VM_L2_CNTL3 0x1408 -# define R600_VM_L2_CNTL3_BANK_SELECT_0(x) ((x) << 0) -# define R600_VM_L2_CNTL3_BANK_SELECT_1(x) ((x) << 5) -# define R600_VM_L2_CNTL3_CACHE_UPDATE_MODE(x) ((x) << 10) -# define R700_VM_L2_CNTL3_BANK_SELECT(x) ((x) << 0) -# define R700_VM_L2_CNTL3_CACHE_UPDATE_MODE(x) ((x) << 6) - -#define R600_VM_L2_STATUS 0x140c - -#define R600_VM_CONTEXT0_CNTL 0x1410 -# define R600_VM_ENABLE_CONTEXT (1 << 0) -# define R600_VM_PAGE_TABLE_DEPTH_FLAT (0 << 1) - -#define R600_VM_CONTEXT0_CNTL2 0x1430 -#define R600_VM_CONTEXT0_REQUEST_RESPONSE 0x1470 -#define R600_VM_CONTEXT0_INVALIDATION_LOW_ADDR 0x1490 -#define R600_VM_CONTEXT0_INVALIDATION_HIGH_ADDR 0x14b0 -#define R600_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x1574 -#define R600_VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x1594 -#define R600_VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x15b4 - -#define R700_VM_CONTEXT0_PAGE_TABLE_BASE_ADDR 0x153c -#define R700_VM_CONTEXT0_PAGE_TABLE_START_ADDR 0x155c -#define R700_VM_CONTEXT0_PAGE_TABLE_END_ADDR 0x157c - -#define R600_HDP_HOST_PATH_CNTL 0x2c00 - -#define R600_GRBM_CNTL 0x8000 -# define R600_GRBM_READ_TIMEOUT(x) ((x) << 0) - -#define R600_GRBM_STATUS 0x8010 -# define R600_CMDFIFO_AVAIL_MASK 0x1f -# define R700_CMDFIFO_AVAIL_MASK 0xf -# define R600_GUI_ACTIVE (1 << 31) -#define R600_GRBM_STATUS2 0x8014 -#define R600_GRBM_SOFT_RESET 0x8020 -# define R600_SOFT_RESET_CP (1 << 0) -#define R600_WAIT_UNTIL 0x8040 - -#define R600_CP_SEM_WAIT_TIMER 0x85bc -#define R600_CP_ME_CNTL 0x86d8 -# define R600_CP_ME_HALT (1 << 28) -#define R600_CP_QUEUE_THRESHOLDS 0x8760 -# define R600_ROQ_IB1_START(x) ((x) << 0) -# define R600_ROQ_IB2_START(x) ((x) << 8) -#define R600_CP_MEQ_THRESHOLDS 0x8764 -# define R700_STQ_SPLIT(x) ((x) << 0) -# define R600_MEQ_END(x) ((x) << 16) -# define R600_ROQ_END(x) ((x) << 24) -#define R600_CP_PERFMON_CNTL 0x87fc -#define R600_CP_RB_BASE 0xc100 -#define R600_CP_RB_CNTL 0xc104 -# define R600_RB_BUFSZ(x) ((x) << 0) -# define R600_RB_BLKSZ(x) ((x) << 8) -# define R600_BUF_SWAP_32BIT (2 << 16) -# define R600_RB_NO_UPDATE (1 << 27) -# define R600_RB_RPTR_WR_ENA (1 << 31) -#define R600_CP_RB_RPTR_WR 0xc108 -#define R600_CP_RB_RPTR_ADDR 0xc10c -#define R600_CP_RB_RPTR_ADDR_HI 0xc110 -#define R600_CP_RB_WPTR 0xc114 -#define R600_CP_RB_WPTR_ADDR 0xc118 -#define R600_CP_RB_WPTR_ADDR_HI 0xc11c -#define R600_CP_RB_RPTR 0x8700 -#define R600_CP_RB_WPTR_DELAY 0x8704 -#define R600_CP_PFP_UCODE_ADDR 0xc150 -#define R600_CP_PFP_UCODE_DATA 0xc154 -#define R600_CP_ME_RAM_RADDR 0xc158 -#define R600_CP_ME_RAM_WADDR 0xc15c -#define R600_CP_ME_RAM_DATA 0xc160 -#define R600_CP_DEBUG 0xc1fc - -#define R600_PA_CL_ENHANCE 0x8a14 -# define R600_CLIP_VTX_REORDER_ENA (1 << 0) -# define R600_NUM_CLIP_SEQ(x) ((x) << 1) -#define R600_PA_SC_LINE_STIPPLE_STATE 0x8b10 -#define R600_PA_SC_MULTI_CHIP_CNTL 0x8b20 -#define R700_PA_SC_FORCE_EOV_MAX_CNTS 0x8b24 -# define R700_FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) -# define R700_FORCE_EOV_MAX_REZ_CNT(x) ((x) << 16) -#define R600_PA_SC_AA_SAMPLE_LOCS_2S 0x8b40 -#define R600_PA_SC_AA_SAMPLE_LOCS_4S 0x8b44 -#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD0 0x8b48 -#define R600_PA_SC_AA_SAMPLE_LOCS_8S_WD1 0x8b4c -# define R600_S0_X(x) ((x) << 0) -# define R600_S0_Y(x) ((x) << 4) -# define R600_S1_X(x) ((x) << 8) -# define R600_S1_Y(x) ((x) << 12) -# define R600_S2_X(x) ((x) << 16) -# define R600_S2_Y(x) ((x) << 20) -# define R600_S3_X(x) ((x) << 24) -# define R600_S3_Y(x) ((x) << 28) -# define R600_S4_X(x) ((x) << 0) -# define R600_S4_Y(x) ((x) << 4) -# define R600_S5_X(x) ((x) << 8) -# define R600_S5_Y(x) ((x) << 12) -# define R600_S6_X(x) ((x) << 16) -# define R600_S6_Y(x) ((x) << 20) -# define R600_S7_X(x) ((x) << 24) -# define R600_S7_Y(x) ((x) << 28) -#define R600_PA_SC_FIFO_SIZE 0x8bd0 -# define R600_SC_PRIM_FIFO_SIZE(x) ((x) << 0) -# define R600_SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 8) -# define R600_SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 16) -#define R700_PA_SC_FIFO_SIZE_R7XX 0x8bcc -# define R700_SC_PRIM_FIFO_SIZE(x) ((x) << 0) -# define R700_SC_HIZ_TILE_FIFO_SIZE(x) ((x) << 12) -# define R700_SC_EARLYZ_TILE_FIFO_SIZE(x) ((x) << 20) -#define R600_PA_SC_ENHANCE 0x8bf0 -# define R600_FORCE_EOV_MAX_CLK_CNT(x) ((x) << 0) -# define R600_FORCE_EOV_MAX_TILE_CNT(x) ((x) << 12) -#define R600_PA_SC_CLIPRECT_RULE 0x2820c -#define R700_PA_SC_EDGERULE 0x28230 -#define R600_PA_SC_LINE_STIPPLE 0x28a0c -#define R600_PA_SC_MODE_CNTL 0x28a4c -#define R600_PA_SC_AA_CONFIG 0x28c04 - -#define R600_SX_EXPORT_BUFFER_SIZES 0x900c -# define R600_COLOR_BUFFER_SIZE(x) ((x) << 0) -# define R600_POSITION_BUFFER_SIZE(x) ((x) << 8) -# define R600_SMX_BUFFER_SIZE(x) ((x) << 16) -#define R600_SX_DEBUG_1 0x9054 -# define R600_SMX_EVENT_RELEASE (1 << 0) -# define R600_ENABLE_NEW_SMX_ADDRESS (1 << 16) -#define R700_SX_DEBUG_1 0x9058 -# define R700_ENABLE_NEW_SMX_ADDRESS (1 << 16) -#define R600_SX_MISC 0x28350 - -#define R600_DB_DEBUG 0x9830 -# define R600_PREZ_MUST_WAIT_FOR_POSTZ_DONE (1 << 31) -#define R600_DB_WATERMARKS 0x9838 -# define R600_DEPTH_FREE(x) ((x) << 0) -# define R600_DEPTH_FLUSH(x) ((x) << 5) -# define R600_DEPTH_PENDING_FREE(x) ((x) << 15) -# define R600_DEPTH_CACHELINE_FREE(x) ((x) << 20) -#define R700_DB_DEBUG3 0x98b0 -# define R700_DB_CLK_OFF_DELAY(x) ((x) << 11) -#define RV700_DB_DEBUG4 0x9b8c -# define RV700_DISABLE_TILE_COVERED_FOR_PS_ITER (1 << 6) - -#define R600_VGT_CACHE_INVALIDATION 0x88c4 -# define R600_CACHE_INVALIDATION(x) ((x) << 0) -# define R600_VC_ONLY 0 -# define R600_TC_ONLY 1 -# define R600_VC_AND_TC 2 -# define R700_AUTO_INVLD_EN(x) ((x) << 6) -# define R700_NO_AUTO 0 -# define R700_ES_AUTO 1 -# define R700_GS_AUTO 2 -# define R700_ES_AND_GS_AUTO 3 -#define R600_VGT_GS_PER_ES 0x88c8 -#define R600_VGT_ES_PER_GS 0x88cc -#define R600_VGT_GS_PER_VS 0x88e8 -#define R600_VGT_GS_VERTEX_REUSE 0x88d4 -#define R600_VGT_NUM_INSTANCES 0x8974 -#define R600_VGT_STRMOUT_EN 0x28ab0 -#define R600_VGT_EVENT_INITIATOR 0x28a90 -# define R600_CACHE_FLUSH_AND_INV_EVENT (0x16 << 0) -#define R600_VGT_VERTEX_REUSE_BLOCK_CNTL 0x28c58 -# define R600_VTX_REUSE_DEPTH_MASK 0xff -#define R600_VGT_OUT_DEALLOC_CNTL 0x28c5c -# define R600_DEALLOC_DIST_MASK 0x7f - -#define R600_CB_COLOR0_BASE 0x28040 -#define R600_CB_COLOR1_BASE 0x28044 -#define R600_CB_COLOR2_BASE 0x28048 -#define R600_CB_COLOR3_BASE 0x2804c -#define R600_CB_COLOR4_BASE 0x28050 -#define R600_CB_COLOR5_BASE 0x28054 -#define R600_CB_COLOR6_BASE 0x28058 -#define R600_CB_COLOR7_BASE 0x2805c -#define R600_CB_COLOR7_FRAG 0x280fc - -#define R600_CB_COLOR0_SIZE 0x28060 -#define R600_CB_COLOR0_VIEW 0x28080 -#define R600_CB_COLOR0_INFO 0x280a0 -#define R600_CB_COLOR0_TILE 0x280c0 -#define R600_CB_COLOR0_FRAG 0x280e0 -#define R600_CB_COLOR0_MASK 0x28100 - -#define AVIVO_D1MODE_VLINE_START_END 0x6538 -#define AVIVO_D2MODE_VLINE_START_END 0x6d38 -#define R600_CP_COHER_BASE 0x85f8 -#define R600_DB_DEPTH_BASE 0x2800c -#define R600_SQ_PGM_START_FS 0x28894 -#define R600_SQ_PGM_START_ES 0x28880 -#define R600_SQ_PGM_START_VS 0x28858 -#define R600_SQ_PGM_RESOURCES_VS 0x28868 -#define R600_SQ_PGM_CF_OFFSET_VS 0x288d0 -#define R600_SQ_PGM_START_GS 0x2886c -#define R600_SQ_PGM_START_PS 0x28840 -#define R600_SQ_PGM_RESOURCES_PS 0x28850 -#define R600_SQ_PGM_EXPORTS_PS 0x28854 -#define R600_SQ_PGM_CF_OFFSET_PS 0x288cc -#define R600_VGT_DMA_BASE 0x287e8 -#define R600_VGT_DMA_BASE_HI 0x287e4 -#define R600_VGT_STRMOUT_BASE_OFFSET_0 0x28b10 -#define R600_VGT_STRMOUT_BASE_OFFSET_1 0x28b14 -#define R600_VGT_STRMOUT_BASE_OFFSET_2 0x28b18 -#define R600_VGT_STRMOUT_BASE_OFFSET_3 0x28b1c -#define R600_VGT_STRMOUT_BASE_OFFSET_HI_0 0x28b44 -#define R600_VGT_STRMOUT_BASE_OFFSET_HI_1 0x28b48 -#define R600_VGT_STRMOUT_BASE_OFFSET_HI_2 0x28b4c -#define R600_VGT_STRMOUT_BASE_OFFSET_HI_3 0x28b50 -#define R600_VGT_STRMOUT_BUFFER_BASE_0 0x28ad8 -#define R600_VGT_STRMOUT_BUFFER_BASE_1 0x28ae8 -#define R600_VGT_STRMOUT_BUFFER_BASE_2 0x28af8 -#define R600_VGT_STRMOUT_BUFFER_BASE_3 0x28b08 -#define R600_VGT_STRMOUT_BUFFER_OFFSET_0 0x28adc -#define R600_VGT_STRMOUT_BUFFER_OFFSET_1 0x28aec -#define R600_VGT_STRMOUT_BUFFER_OFFSET_2 0x28afc -#define R600_VGT_STRMOUT_BUFFER_OFFSET_3 0x28b0c - -#define R600_VGT_PRIMITIVE_TYPE 0x8958 - -#define R600_PA_SC_SCREEN_SCISSOR_TL 0x28030 -#define R600_PA_SC_GENERIC_SCISSOR_TL 0x28240 -#define R600_PA_SC_WINDOW_SCISSOR_TL 0x28204 - -#define R600_TC_CNTL 0x9608 -# define R600_TC_L2_SIZE(x) ((x) << 5) -# define R600_L2_DISABLE_LATE_HIT (1 << 9) - -#define R600_ARB_POP 0x2418 -# define R600_ENABLE_TC128 (1 << 30) -#define R600_ARB_GDEC_RD_CNTL 0x246c - -#define R600_TA_CNTL_AUX 0x9508 -# define R600_DISABLE_CUBE_WRAP (1 << 0) -# define R600_DISABLE_CUBE_ANISO (1 << 1) -# define R700_GETLOD_SELECT(x) ((x) << 2) -# define R600_SYNC_GRADIENT (1 << 24) -# define R600_SYNC_WALKER (1 << 25) -# define R600_SYNC_ALIGNER (1 << 26) -# define R600_BILINEAR_PRECISION_6_BIT (0 << 31) -# define R600_BILINEAR_PRECISION_8_BIT (1 << 31) - -#define R700_TCP_CNTL 0x9610 - -#define R600_SMX_DC_CTL0 0xa020 -# define R700_USE_HASH_FUNCTION (1 << 0) -# define R700_CACHE_DEPTH(x) ((x) << 1) -# define R700_FLUSH_ALL_ON_EVENT (1 << 10) -# define R700_STALL_ON_EVENT (1 << 11) -#define R700_SMX_EVENT_CTL 0xa02c -# define R700_ES_FLUSH_CTL(x) ((x) << 0) -# define R700_GS_FLUSH_CTL(x) ((x) << 3) -# define R700_ACK_FLUSH_CTL(x) ((x) << 6) -# define R700_SYNC_FLUSH_CTL (1 << 8) - -#define R600_SQ_CONFIG 0x8c00 -# define R600_VC_ENABLE (1 << 0) -# define R600_EXPORT_SRC_C (1 << 1) -# define R600_DX9_CONSTS (1 << 2) -# define R600_ALU_INST_PREFER_VECTOR (1 << 3) -# define R600_DX10_CLAMP (1 << 4) -# define R600_CLAUSE_SEQ_PRIO(x) ((x) << 8) -# define R600_PS_PRIO(x) ((x) << 24) -# define R600_VS_PRIO(x) ((x) << 26) -# define R600_GS_PRIO(x) ((x) << 28) -# define R600_ES_PRIO(x) ((x) << 30) -#define R600_SQ_GPR_RESOURCE_MGMT_1 0x8c04 -# define R600_NUM_PS_GPRS(x) ((x) << 0) -# define R600_NUM_VS_GPRS(x) ((x) << 16) -# define R700_DYN_GPR_ENABLE (1 << 27) -# define R600_NUM_CLAUSE_TEMP_GPRS(x) ((x) << 28) -#define R600_SQ_GPR_RESOURCE_MGMT_2 0x8c08 -# define R600_NUM_GS_GPRS(x) ((x) << 0) -# define R600_NUM_ES_GPRS(x) ((x) << 16) -#define R600_SQ_THREAD_RESOURCE_MGMT 0x8c0c -# define R600_NUM_PS_THREADS(x) ((x) << 0) -# define R600_NUM_VS_THREADS(x) ((x) << 8) -# define R600_NUM_GS_THREADS(x) ((x) << 16) -# define R600_NUM_ES_THREADS(x) ((x) << 24) -#define R600_SQ_STACK_RESOURCE_MGMT_1 0x8c10 -# define R600_NUM_PS_STACK_ENTRIES(x) ((x) << 0) -# define R600_NUM_VS_STACK_ENTRIES(x) ((x) << 16) -#define R600_SQ_STACK_RESOURCE_MGMT_2 0x8c14 -# define R600_NUM_GS_STACK_ENTRIES(x) ((x) << 0) -# define R600_NUM_ES_STACK_ENTRIES(x) ((x) << 16) -#define R600_SQ_MS_FIFO_SIZES 0x8cf0 -# define R600_CACHE_FIFO_SIZE(x) ((x) << 0) -# define R600_FETCH_FIFO_HIWATER(x) ((x) << 8) -# define R600_DONE_FIFO_HIWATER(x) ((x) << 16) -# define R600_ALU_UPDATE_FIFO_HIWATER(x) ((x) << 24) -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_0 0x8db0 -# define R700_SIMDA_RING0(x) ((x) << 0) -# define R700_SIMDA_RING1(x) ((x) << 8) -# define R700_SIMDB_RING0(x) ((x) << 16) -# define R700_SIMDB_RING1(x) ((x) << 24) -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_1 0x8db4 -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_2 0x8db8 -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_3 0x8dbc -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_4 0x8dc0 -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_5 0x8dc4 -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_6 0x8dc8 -#define R700_SQ_DYN_GPR_SIZE_SIMD_AB_7 0x8dcc - -#define R600_SPI_PS_IN_CONTROL_0 0x286cc -# define R600_NUM_INTERP(x) ((x) << 0) -# define R600_POSITION_ENA (1 << 8) -# define R600_POSITION_CENTROID (1 << 9) -# define R600_POSITION_ADDR(x) ((x) << 10) -# define R600_PARAM_GEN(x) ((x) << 15) -# define R600_PARAM_GEN_ADDR(x) ((x) << 19) -# define R600_BARYC_SAMPLE_CNTL(x) ((x) << 26) -# define R600_PERSP_GRADIENT_ENA (1 << 28) -# define R600_LINEAR_GRADIENT_ENA (1 << 29) -# define R600_POSITION_SAMPLE (1 << 30) -# define R600_BARYC_AT_SAMPLE_ENA (1 << 31) -#define R600_SPI_PS_IN_CONTROL_1 0x286d0 -# define R600_GEN_INDEX_PIX (1 << 0) -# define R600_GEN_INDEX_PIX_ADDR(x) ((x) << 1) -# define R600_FRONT_FACE_ENA (1 << 8) -# define R600_FRONT_FACE_CHAN(x) ((x) << 9) -# define R600_FRONT_FACE_ALL_BITS (1 << 11) -# define R600_FRONT_FACE_ADDR(x) ((x) << 12) -# define R600_FOG_ADDR(x) ((x) << 17) -# define R600_FIXED_PT_POSITION_ENA (1 << 24) -# define R600_FIXED_PT_POSITION_ADDR(x) ((x) << 25) -# define R700_POSITION_ULC (1 << 30) -#define R600_SPI_INPUT_Z 0x286d8 - -#define R600_SPI_CONFIG_CNTL 0x9100 -# define R600_GPR_WRITE_PRIORITY(x) ((x) << 0) -# define R600_DISABLE_INTERP_1 (1 << 5) -#define R600_SPI_CONFIG_CNTL_1 0x913c -# define R600_VTX_DONE_DELAY(x) ((x) << 0) -# define R600_INTERP_ONE_PRIM_PER_ROW (1 << 4) - -#define R600_GB_TILING_CONFIG 0x98f0 -# define R600_PIPE_TILING(x) ((x) << 1) -# define R600_BANK_TILING(x) ((x) << 4) -# define R600_GROUP_SIZE(x) ((x) << 6) -# define R600_ROW_TILING(x) ((x) << 8) -# define R600_BANK_SWAPS(x) ((x) << 11) -# define R600_SAMPLE_SPLIT(x) ((x) << 14) -# define R600_BACKEND_MAP(x) ((x) << 16) -#define R600_DCP_TILING_CONFIG 0x6ca0 -#define R600_HDP_TILING_CONFIG 0x2f3c - -#define R600_CC_RB_BACKEND_DISABLE 0x98f4 -#define R700_CC_SYS_RB_BACKEND_DISABLE 0x3f88 -# define R600_BACKEND_DISABLE(x) ((x) << 16) - -#define R600_CC_GC_SHADER_PIPE_CONFIG 0x8950 -#define R600_GC_USER_SHADER_PIPE_CONFIG 0x8954 -# define R600_INACTIVE_QD_PIPES(x) ((x) << 8) -# define R600_INACTIVE_QD_PIPES_MASK (0xff << 8) -# define R600_INACTIVE_SIMDS(x) ((x) << 16) -# define R600_INACTIVE_SIMDS_MASK (0xff << 16) - -#define R700_CGTS_SYS_TCC_DISABLE 0x3f90 -#define R700_CGTS_USER_SYS_TCC_DISABLE 0x3f94 -#define R700_CGTS_TCC_DISABLE 0x9148 -#define R700_CGTS_USER_TCC_DISABLE 0x914c - -/* Constants */ -#define RADEON_MAX_USEC_TIMEOUT 100000 /* 100 ms */ - -#define RADEON_LAST_FRAME_REG RADEON_SCRATCH_REG0 -#define RADEON_LAST_DISPATCH_REG RADEON_SCRATCH_REG1 -#define RADEON_LAST_CLEAR_REG RADEON_SCRATCH_REG2 -#define RADEON_LAST_SWI_REG RADEON_SCRATCH_REG3 -#define RADEON_LAST_DISPATCH 1 - -#define R600_LAST_FRAME_REG R600_SCRATCH_REG0 -#define R600_LAST_DISPATCH_REG R600_SCRATCH_REG1 -#define R600_LAST_CLEAR_REG R600_SCRATCH_REG2 -#define R600_LAST_SWI_REG R600_SCRATCH_REG3 - -#define RADEON_MAX_VB_AGE 0x7fffffff -#define RADEON_MAX_VB_VERTS (0xffff) - -#define RADEON_RING_HIGH_MARK 128 - -#define RADEON_PCIGART_TABLE_SIZE (32*1024) - -#define RADEON_READ(reg) DRM_READ32( dev_priv->mmio, (reg) ) -#define RADEON_WRITE(reg, val) \ -do { \ - if (reg < 0x10000) { \ - DRM_WRITE32(dev_priv->mmio, (reg), (val)); \ - } else { \ - DRM_WRITE32(dev_priv->mmio, RADEON_MM_INDEX, (reg)); \ - DRM_WRITE32(dev_priv->mmio, RADEON_MM_DATA, (val)); \ - } \ -} while (0) -#define RADEON_READ8(reg) DRM_READ8( dev_priv->mmio, (reg) ) -#define RADEON_WRITE8(reg,val) DRM_WRITE8( dev_priv->mmio, (reg), (val) ) - -#define RADEON_WRITE_PLL(addr, val) \ -do { \ - RADEON_WRITE8(RADEON_CLOCK_CNTL_INDEX, \ - ((addr) & 0x1f) | RADEON_PLL_WR_EN ); \ - RADEON_WRITE(RADEON_CLOCK_CNTL_DATA, (val)); \ -} while (0) - -#define RADEON_WRITE_PCIE(addr, val) \ -do { \ - RADEON_WRITE8(RADEON_PCIE_INDEX, \ - ((addr) & 0xff)); \ - RADEON_WRITE(RADEON_PCIE_DATA, (val)); \ -} while (0) - -#define R500_WRITE_MCIND(addr, val) \ -do { \ - RADEON_WRITE(R520_MC_IND_INDEX, 0xff0000 | ((addr) & 0xff)); \ - RADEON_WRITE(R520_MC_IND_DATA, (val)); \ - RADEON_WRITE(R520_MC_IND_INDEX, 0); \ -} while (0) - -#define RS480_WRITE_MCIND(addr, val) \ -do { \ - RADEON_WRITE(RS480_NB_MC_INDEX, \ - ((addr) & 0xff) | RS480_NB_MC_IND_WR_EN); \ - RADEON_WRITE(RS480_NB_MC_DATA, (val)); \ - RADEON_WRITE(RS480_NB_MC_INDEX, 0xff); \ -} while (0) - -#define RS690_WRITE_MCIND(addr, val) \ -do { \ - RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_EN | ((addr) & RS690_MC_INDEX_MASK)); \ - RADEON_WRITE(RS690_MC_DATA, val); \ - RADEON_WRITE(RS690_MC_INDEX, RS690_MC_INDEX_WR_ACK); \ -} while (0) - -#define RS600_WRITE_MCIND(addr, val) \ -do { \ - RADEON_WRITE(RS600_MC_INDEX, RS600_MC_IND_WR_EN | RS600_MC_IND_CITF_ARB0 | ((addr) & RS600_MC_ADDR_MASK)); \ - RADEON_WRITE(RS600_MC_DATA, val); \ -} while (0) - -#define IGP_WRITE_MCIND(addr, val) \ -do { \ - if (((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS690) || \ - ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS740)) \ - RS690_WRITE_MCIND(addr, val); \ - else if ((dev_priv->flags & RADEON_FAMILY_MASK) == CHIP_RS600) \ - RS600_WRITE_MCIND(addr, val); \ - else \ - RS480_WRITE_MCIND(addr, val); \ -} while (0) - -#define CP_PACKET0( reg, n ) \ - (RADEON_CP_PACKET0 | ((n) << 16) | ((reg) >> 2)) -#define CP_PACKET0_TABLE( reg, n ) \ - (RADEON_CP_PACKET0 | RADEON_ONE_REG_WR | ((n) << 16) | ((reg) >> 2)) -#define CP_PACKET1( reg0, reg1 ) \ - (RADEON_CP_PACKET1 | (((reg1) >> 2) << 15) | ((reg0) >> 2)) -#define CP_PACKET2() \ - (RADEON_CP_PACKET2) -#define CP_PACKET3( pkt, n ) \ - (RADEON_CP_PACKET3 | (pkt) | ((n) << 16)) - -/* ================================================================ - * Engine control helper macros - */ - -#define RADEON_WAIT_UNTIL_2D_IDLE() do { \ - OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ - OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ - RADEON_WAIT_HOST_IDLECLEAN) ); \ -} while (0) - -#define RADEON_WAIT_UNTIL_3D_IDLE() do { \ - OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ - OUT_RING( (RADEON_WAIT_3D_IDLECLEAN | \ - RADEON_WAIT_HOST_IDLECLEAN) ); \ -} while (0) - -#define RADEON_WAIT_UNTIL_IDLE() do { \ - OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ - OUT_RING( (RADEON_WAIT_2D_IDLECLEAN | \ - RADEON_WAIT_3D_IDLECLEAN | \ - RADEON_WAIT_HOST_IDLECLEAN) ); \ -} while (0) - -#define RADEON_WAIT_UNTIL_PAGE_FLIPPED() do { \ - OUT_RING( CP_PACKET0( RADEON_WAIT_UNTIL, 0 ) ); \ - OUT_RING( RADEON_WAIT_CRTC_PFLIP ); \ -} while (0) - -#define RADEON_FLUSH_CACHE() do { \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH); \ - } else { \ - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_RB3D_DC_FLUSH); \ - } \ -} while (0) - -#define RADEON_PURGE_CACHE() do { \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING(CP_PACKET0(RADEON_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_DC_FLUSH | RADEON_RB3D_DC_FREE); \ - } else { \ - OUT_RING(CP_PACKET0(R300_RB3D_DSTCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_RB3D_DC_FLUSH | R300_RB3D_DC_FREE); \ - } \ -} while (0) - -#define RADEON_FLUSH_ZCACHE() do { \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_ZC_FLUSH); \ - } else { \ - OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_ZC_FLUSH); \ - } \ -} while (0) - -#define RADEON_PURGE_ZCACHE() do { \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) <= CHIP_RV280) { \ - OUT_RING(CP_PACKET0(RADEON_RB3D_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(RADEON_RB3D_ZC_FLUSH | RADEON_RB3D_ZC_FREE); \ - } else { \ - OUT_RING(CP_PACKET0(R300_ZB_ZCACHE_CTLSTAT, 0)); \ - OUT_RING(R300_ZC_FLUSH | R300_ZC_FREE); \ - } \ -} while (0) - -/* ================================================================ - * Misc helper macros - */ - -/* Perfbox functionality only. - */ -#define RING_SPACE_TEST_WITH_RETURN( dev_priv ) \ -do { \ - if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) { \ - u32 head = GET_RING_HEAD( dev_priv ); \ - if (head == dev_priv->ring.tail) \ - dev_priv->stats.boxes |= RADEON_BOX_DMA_IDLE; \ - } \ -} while (0) - -#define VB_AGE_TEST_WITH_RETURN( dev_priv ) \ -do { \ - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; \ - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; \ - if ( sarea_priv->last_dispatch >= RADEON_MAX_VB_AGE ) { \ - int __ret; \ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) \ - __ret = r600_do_cp_idle(dev_priv); \ - else \ - __ret = radeon_do_cp_idle(dev_priv); \ - if ( __ret ) return __ret; \ - sarea_priv->last_dispatch = 0; \ - radeon_freelist_reset( dev ); \ - } \ -} while (0) - -#define RADEON_DISPATCH_AGE( age ) do { \ - OUT_RING( CP_PACKET0( RADEON_LAST_DISPATCH_REG, 0 ) ); \ - OUT_RING( age ); \ -} while (0) - -#define RADEON_FRAME_AGE( age ) do { \ - OUT_RING( CP_PACKET0( RADEON_LAST_FRAME_REG, 0 ) ); \ - OUT_RING( age ); \ -} while (0) - -#define RADEON_CLEAR_AGE( age ) do { \ - OUT_RING( CP_PACKET0( RADEON_LAST_CLEAR_REG, 0 ) ); \ - OUT_RING( age ); \ -} while (0) - -#define R600_DISPATCH_AGE(age) do { \ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ - OUT_RING((R600_LAST_DISPATCH_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ - OUT_RING(age); \ -} while (0) - -#define R600_FRAME_AGE(age) do { \ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ - OUT_RING((R600_LAST_FRAME_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ - OUT_RING(age); \ -} while (0) - -#define R600_CLEAR_AGE(age) do { \ - OUT_RING(CP_PACKET3(R600_IT_SET_CONFIG_REG, 1)); \ - OUT_RING((R600_LAST_CLEAR_REG - R600_SET_CONFIG_REG_OFFSET) >> 2); \ - OUT_RING(age); \ -} while (0) - -/* ================================================================ - * Ring control - */ - -#define RADEON_VERBOSE 0 - -#define RING_LOCALS int write, _nr, _align_nr; unsigned int mask; u32 *ring; - -#define RADEON_RING_ALIGN 16 - -#define BEGIN_RING( n ) do { \ - if ( RADEON_VERBOSE ) { \ - DRM_INFO( "BEGIN_RING( %d )\n", (n)); \ - } \ - _align_nr = RADEON_RING_ALIGN - ((dev_priv->ring.tail + n) & (RADEON_RING_ALIGN-1)); \ - _align_nr += n; \ - if (dev_priv->ring.space <= (_align_nr * sizeof(u32))) { \ - COMMIT_RING(); \ - radeon_wait_ring( dev_priv, _align_nr * sizeof(u32)); \ - } \ - _nr = n; dev_priv->ring.space -= (n) * sizeof(u32); \ - ring = dev_priv->ring.start; \ - write = dev_priv->ring.tail; \ - mask = dev_priv->ring.tail_mask; \ -} while (0) - -#define ADVANCE_RING() do { \ - if ( RADEON_VERBOSE ) { \ - DRM_INFO( "ADVANCE_RING() wr=0x%06x tail=0x%06x\n", \ - write, dev_priv->ring.tail ); \ - } \ - if (((dev_priv->ring.tail + _nr) & mask) != write) { \ - DRM_ERROR( \ - "ADVANCE_RING(): mismatch: nr: %x write: %x line: %d\n", \ - ((dev_priv->ring.tail + _nr) & mask), \ - write, __LINE__); \ - } else \ - dev_priv->ring.tail = write; \ -} while (0) - -extern void radeon_commit_ring(drm_radeon_private_t *dev_priv); - -#define COMMIT_RING() do { \ - radeon_commit_ring(dev_priv); \ - } while(0) - -#define OUT_RING( x ) do { \ - if ( RADEON_VERBOSE ) { \ - DRM_INFO( " OUT_RING( 0x%08x ) at 0x%x\n", \ - (unsigned int)(x), write ); \ - } \ - ring[write++] = (x); \ - write &= mask; \ -} while (0) - -#define OUT_RING_REG( reg, val ) do { \ - OUT_RING( CP_PACKET0( reg, 0 ) ); \ - OUT_RING( val ); \ -} while (0) - -#define OUT_RING_TABLE( tab, sz ) do { \ - int _size = (sz); \ - int *_tab = (int *)(tab); \ - \ - if (write + _size > mask) { \ - int _i = (mask+1) - write; \ - _size -= _i; \ - while (_i > 0 ) { \ - *(int *)(ring + write) = *_tab++; \ - write++; \ - _i--; \ - } \ - write = 0; \ - _tab += _i; \ - } \ - while (_size > 0) { \ - *(ring + write) = *_tab++; \ - write++; \ - _size--; \ - } \ - write &= mask; \ -} while (0) - -/** - * Copy given number of dwords from drm buffer to the ring buffer. - */ -#define OUT_RING_DRM_BUFFER(buf, sz) do { \ - int _size = (sz) * 4; \ - struct drm_buffer *_buf = (buf); \ - int _part_size; \ - while (_size > 0) { \ - _part_size = _size; \ - \ - if (write + _part_size/4 > mask) \ - _part_size = ((mask + 1) - write)*4; \ - \ - if (drm_buffer_index(_buf) + _part_size > PAGE_SIZE) \ - _part_size = PAGE_SIZE - drm_buffer_index(_buf);\ - \ - \ - \ - memcpy(ring + write, &_buf->data[drm_buffer_page(_buf)] \ - [drm_buffer_index(_buf)], _part_size); \ - \ - _size -= _part_size; \ - write = (write + _part_size/4) & mask; \ - drm_buffer_advance(_buf, _part_size); \ - } \ -} while (0) - - -#endif /* CONFIG_DRM_RADEON_UMS */ - #endif /* __RADEON_DRV_H__ */ diff --git a/drivers/gpu/drm/radeon/radeon_fb.c b/drivers/gpu/drm/radeon/radeon_fb.c index adc44bbc81a9..d2e628eea53d 100644 --- a/drivers/gpu/drm/radeon/radeon_fb.c +++ b/drivers/gpu/drm/radeon/radeon_fb.c @@ -282,7 +282,7 @@ out_unref: } if (fb && ret) { - drm_gem_object_unreference(gobj); + drm_gem_object_unreference_unlocked(gobj); drm_framebuffer_unregister_private(fb); drm_framebuffer_cleanup(fb); kfree(fb); diff --git a/drivers/gpu/drm/radeon/radeon_fence.c b/drivers/gpu/drm/radeon/radeon_fence.c index df09ca7c4889..05815c47b246 100644 --- a/drivers/gpu/drm/radeon/radeon_fence.c +++ b/drivers/gpu/drm/radeon/radeon_fence.c @@ -130,7 +130,7 @@ int radeon_fence_emit(struct radeon_device *rdev, struct radeon_fence **fence, int ring) { - u64 seq = ++rdev->fence_drv[ring].sync_seq[ring]; + u64 seq; /* we are protected by the ring emission mutex */ *fence = kmalloc(sizeof(struct radeon_fence), GFP_KERNEL); @@ -138,7 +138,7 @@ int radeon_fence_emit(struct radeon_device *rdev, return -ENOMEM; } (*fence)->rdev = rdev; - (*fence)->seq = seq; + (*fence)->seq = seq = ++rdev->fence_drv[ring].sync_seq[ring]; (*fence)->ring = ring; (*fence)->is_vm_update = false; fence_init(&(*fence)->base, &radeon_fence_ops, diff --git a/drivers/gpu/drm/radeon/radeon_irq.c b/drivers/gpu/drm/radeon/radeon_irq.c deleted file mode 100644 index 688afb62f7c4..000000000000 --- a/drivers/gpu/drm/radeon/radeon_irq.c +++ /dev/null @@ -1,402 +0,0 @@ -/* radeon_irq.c -- IRQ handling for radeon -*- linux-c -*- */ -/* - * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: - * Keith Whitwell <keith@tungstengraphics.com> - * Michel D�zer <michel@daenzer.net> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" - -void radeon_irq_set_state(struct drm_device *dev, u32 mask, int state) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (state) - dev_priv->irq_enable_reg |= mask; - else - dev_priv->irq_enable_reg &= ~mask; - - if (dev->irq_enabled) - RADEON_WRITE(RADEON_GEN_INT_CNTL, dev_priv->irq_enable_reg); -} - -static void r500_vbl_irq_set_state(struct drm_device *dev, u32 mask, int state) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (state) - dev_priv->r500_disp_irq_reg |= mask; - else - dev_priv->r500_disp_irq_reg &= ~mask; - - if (dev->irq_enabled) - RADEON_WRITE(R500_DxMODE_INT_MASK, dev_priv->r500_disp_irq_reg); -} - -int radeon_enable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { - switch (pipe) { - case 0: - r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 1); - break; - case 1: - r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 1); - break; - default: - DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", - pipe); - return -EINVAL; - } - } else { - switch (pipe) { - case 0: - radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 1); - break; - case 1: - radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 1); - break; - default: - DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", - pipe); - return -EINVAL; - } - } - - return 0; -} - -void radeon_disable_vblank(struct drm_device *dev, unsigned int pipe) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { - switch (pipe) { - case 0: - r500_vbl_irq_set_state(dev, R500_D1MODE_INT_MASK, 0); - break; - case 1: - r500_vbl_irq_set_state(dev, R500_D2MODE_INT_MASK, 0); - break; - default: - DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", - pipe); - break; - } - } else { - switch (pipe) { - case 0: - radeon_irq_set_state(dev, RADEON_CRTC_VBLANK_MASK, 0); - break; - case 1: - radeon_irq_set_state(dev, RADEON_CRTC2_VBLANK_MASK, 0); - break; - default: - DRM_ERROR("tried to enable vblank on non-existent crtc %u\n", - pipe); - break; - } - } -} - -static u32 radeon_acknowledge_irqs(drm_radeon_private_t *dev_priv, u32 *r500_disp_int) -{ - u32 irqs = RADEON_READ(RADEON_GEN_INT_STATUS); - u32 irq_mask = RADEON_SW_INT_TEST; - - *r500_disp_int = 0; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { - /* vbl interrupts in a different place */ - - if (irqs & R500_DISPLAY_INT_STATUS) { - /* if a display interrupt */ - u32 disp_irq; - - disp_irq = RADEON_READ(R500_DISP_INTERRUPT_STATUS); - - *r500_disp_int = disp_irq; - if (disp_irq & R500_D1_VBLANK_INTERRUPT) - RADEON_WRITE(R500_D1MODE_VBLANK_STATUS, R500_VBLANK_ACK); - if (disp_irq & R500_D2_VBLANK_INTERRUPT) - RADEON_WRITE(R500_D2MODE_VBLANK_STATUS, R500_VBLANK_ACK); - } - irq_mask |= R500_DISPLAY_INT_STATUS; - } else - irq_mask |= RADEON_CRTC_VBLANK_STAT | RADEON_CRTC2_VBLANK_STAT; - - irqs &= irq_mask; - - if (irqs) - RADEON_WRITE(RADEON_GEN_INT_STATUS, irqs); - - return irqs; -} - -/* Interrupts - Used for device synchronization and flushing in the - * following circumstances: - * - * - Exclusive FB access with hw idle: - * - Wait for GUI Idle (?) interrupt, then do normal flush. - * - * - Frame throttling, NV_fence: - * - Drop marker irq's into command stream ahead of time. - * - Wait on irq's with lock *not held* - * - Check each for termination condition - * - * - Internally in cp_getbuffer, etc: - * - as above, but wait with lock held??? - * - * NOTE: These functions are misleadingly named -- the irq's aren't - * tied to dma at all, this is just a hangover from dri prehistory. - */ - -irqreturn_t radeon_driver_irq_handler(int irq, void *arg) -{ - struct drm_device *dev = (struct drm_device *) arg; - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - u32 stat; - u32 r500_disp_int; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return IRQ_NONE; - - /* Only consider the bits we're interested in - others could be used - * outside the DRM - */ - stat = radeon_acknowledge_irqs(dev_priv, &r500_disp_int); - if (!stat) - return IRQ_NONE; - - stat &= dev_priv->irq_enable_reg; - - /* SW interrupt */ - if (stat & RADEON_SW_INT_TEST) - wake_up(&dev_priv->swi_queue); - - /* VBLANK interrupt */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { - if (r500_disp_int & R500_D1_VBLANK_INTERRUPT) - drm_handle_vblank(dev, 0); - if (r500_disp_int & R500_D2_VBLANK_INTERRUPT) - drm_handle_vblank(dev, 1); - } else { - if (stat & RADEON_CRTC_VBLANK_STAT) - drm_handle_vblank(dev, 0); - if (stat & RADEON_CRTC2_VBLANK_STAT) - drm_handle_vblank(dev, 1); - } - return IRQ_HANDLED; -} - -static int radeon_emit_irq(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - unsigned int ret; - RING_LOCALS; - - atomic_inc(&dev_priv->swi_emitted); - ret = atomic_read(&dev_priv->swi_emitted); - - BEGIN_RING(4); - OUT_RING_REG(RADEON_LAST_SWI_REG, ret); - OUT_RING_REG(RADEON_GEN_INT_STATUS, RADEON_SW_INT_FIRE); - ADVANCE_RING(); - COMMIT_RING(); - - return ret; -} - -static int radeon_wait_irq(struct drm_device * dev, int swi_nr) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - int ret = 0; - - if (RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr) - return 0; - - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - - DRM_WAIT_ON(ret, dev_priv->swi_queue, 3 * HZ, - RADEON_READ(RADEON_LAST_SWI_REG) >= swi_nr); - - return ret; -} - -u32 radeon_get_vblank_counter(struct drm_device *dev, unsigned int pipe) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - if (pipe > 1) { - DRM_ERROR("Invalid crtc %u\n", pipe); - return -EINVAL; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) { - if (pipe == 0) - return RADEON_READ(R500_D1CRTC_FRAME_COUNT); - else - return RADEON_READ(R500_D2CRTC_FRAME_COUNT); - } else { - if (pipe == 0) - return RADEON_READ(RADEON_CRTC_CRNT_FRAME); - else - return RADEON_READ(RADEON_CRTC2_CRNT_FRAME); - } -} - -/* Needs the lock as it touches the ring. - */ -int radeon_irq_emit(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_emit_t *emit = data; - int result; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return -EINVAL; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - result = radeon_emit_irq(dev); - - if (copy_to_user(emit->irq_seq, &result, sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -/* Doesn't need the hardware lock. - */ -int radeon_irq_wait(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_irq_wait_t *irqwait = data; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return -EINVAL; - - return radeon_wait_irq(dev, irqwait->irq_seq); -} - -/* drm_dma.h hooks -*/ -void radeon_driver_irq_preinstall(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - u32 dummy; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return; - - /* Disable *all* interrupts */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) - RADEON_WRITE(R500_DxMODE_INT_MASK, 0); - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); - - /* Clear bits if they're already high */ - radeon_acknowledge_irqs(dev_priv, &dummy); -} - -int radeon_driver_irq_postinstall(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - - atomic_set(&dev_priv->swi_emitted, 0); - init_waitqueue_head(&dev_priv->swi_queue); - - dev->max_vblank_count = 0x001fffff; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return 0; - - radeon_irq_set_state(dev, RADEON_SW_INT_ENABLE, 1); - - return 0; -} - -void radeon_driver_irq_uninstall(struct drm_device * dev) -{ - drm_radeon_private_t *dev_priv = - (drm_radeon_private_t *) dev->dev_private; - if (!dev_priv) - return; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - return; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_RS600) - RADEON_WRITE(R500_DxMODE_INT_MASK, 0); - /* Disable *all* interrupts */ - RADEON_WRITE(RADEON_GEN_INT_CNTL, 0); -} - - -int radeon_vblank_crtc_get(struct drm_device *dev) -{ - drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - - return dev_priv->vblank_crtc; -} - -int radeon_vblank_crtc_set(struct drm_device *dev, int64_t value) -{ - drm_radeon_private_t *dev_priv = (drm_radeon_private_t *) dev->dev_private; - if (value & ~(DRM_RADEON_VBLANK_CRTC1 | DRM_RADEON_VBLANK_CRTC2)) { - DRM_ERROR("called with invalid crtc 0x%x\n", (unsigned int)value); - return -EINVAL; - } - dev_priv->vblank_crtc = (unsigned int)value; - return 0; -} diff --git a/drivers/gpu/drm/radeon/radeon_kms.c b/drivers/gpu/drm/radeon/radeon_kms.c index d290a8a09036..4fab44e0f36b 100644 --- a/drivers/gpu/drm/radeon/radeon_kms.c +++ b/drivers/gpu/drm/radeon/radeon_kms.c @@ -748,19 +748,19 @@ void radeon_driver_preclose_kms(struct drm_device *dev, * radeon_get_vblank_counter_kms - get frame count * * @dev: drm dev pointer - * @crtc: crtc to get the frame count from + * @pipe: crtc to get the frame count from * * Gets the frame count on the requested crtc (all asics). * Returns frame count on success, -EINVAL on failure. */ -u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) +u32 radeon_get_vblank_counter_kms(struct drm_device *dev, unsigned int pipe) { int vpos, hpos, stat; u32 count; struct radeon_device *rdev = dev->dev_private; - if (crtc < 0 || crtc >= rdev->num_crtc) { - DRM_ERROR("Invalid crtc %d\n", crtc); + if (pipe < 0 || pipe >= rdev->num_crtc) { + DRM_ERROR("Invalid crtc %u\n", pipe); return -EINVAL; } @@ -772,29 +772,29 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) * and start of vsync, so vpos >= 0 means to bump the hw frame counter * result by 1 to give the proper appearance to caller. */ - if (rdev->mode_info.crtcs[crtc]) { + if (rdev->mode_info.crtcs[pipe]) { /* Repeat readout if needed to provide stable result if * we cross start of vsync during the queries. */ do { - count = radeon_get_vblank_counter(rdev, crtc); + count = radeon_get_vblank_counter(rdev, pipe); /* Ask radeon_get_crtc_scanoutpos to return vpos as * distance to start of vblank, instead of regular * vertical scanout pos. */ stat = radeon_get_crtc_scanoutpos( - dev, crtc, GET_DISTANCE_TO_VBLANKSTART, + dev, pipe, GET_DISTANCE_TO_VBLANKSTART, &vpos, &hpos, NULL, NULL, - &rdev->mode_info.crtcs[crtc]->base.hwmode); - } while (count != radeon_get_vblank_counter(rdev, crtc)); + &rdev->mode_info.crtcs[pipe]->base.hwmode); + } while (count != radeon_get_vblank_counter(rdev, pipe)); if (((stat & (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE)) != (DRM_SCANOUTPOS_VALID | DRM_SCANOUTPOS_ACCURATE))) { DRM_DEBUG_VBL("Query failed! stat %d\n", stat); } else { - DRM_DEBUG_VBL("crtc %d: dist from vblank start %d\n", - crtc, vpos); + DRM_DEBUG_VBL("crtc %u: dist from vblank start %d\n", + pipe, vpos); /* Bump counter if we are at >= leading edge of vblank, * but before vsync where vpos would turn negative and @@ -806,7 +806,7 @@ u32 radeon_get_vblank_counter_kms(struct drm_device *dev, int crtc) } else { /* Fallback to use value as is. */ - count = radeon_get_vblank_counter(rdev, crtc); + count = radeon_get_vblank_counter(rdev, pipe); DRM_DEBUG_VBL("NULL mode info! Returned count may be wrong.\n"); } diff --git a/drivers/gpu/drm/radeon/radeon_mem.c b/drivers/gpu/drm/radeon/radeon_mem.c deleted file mode 100644 index 146d253f1131..000000000000 --- a/drivers/gpu/drm/radeon/radeon_mem.c +++ /dev/null @@ -1,302 +0,0 @@ -/* radeon_mem.c -- Simple GART/fb memory manager for radeon -*- linux-c -*- */ -/* - * Copyright (C) The Weather Channel, Inc. 2002. All Rights Reserved. - * - * The Weather Channel (TM) funded Tungsten Graphics to develop the - * initial release of the Radeon 8500 driver under the XFree86 license. - * This notice must be preserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: - * Keith Whitwell <keith@tungstengraphics.com> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" - -/* Very simple allocator for GART memory, working on a static range - * already mapped into each client's address space. - */ - -static struct mem_block *split_block(struct mem_block *p, int start, int size, - struct drm_file *file_priv) -{ - /* Maybe cut off the start of an existing block */ - if (start > p->start) { - struct mem_block *newblock = kmalloc(sizeof(*newblock), - GFP_KERNEL); - if (!newblock) - goto out; - newblock->start = start; - newblock->size = p->size - (start - p->start); - newblock->file_priv = NULL; - newblock->next = p->next; - newblock->prev = p; - p->next->prev = newblock; - p->next = newblock; - p->size -= newblock->size; - p = newblock; - } - - /* Maybe cut off the end of an existing block */ - if (size < p->size) { - struct mem_block *newblock = kmalloc(sizeof(*newblock), - GFP_KERNEL); - if (!newblock) - goto out; - newblock->start = start + size; - newblock->size = p->size - size; - newblock->file_priv = NULL; - newblock->next = p->next; - newblock->prev = p; - p->next->prev = newblock; - p->next = newblock; - p->size = size; - } - - out: - /* Our block is in the middle */ - p->file_priv = file_priv; - return p; -} - -static struct mem_block *alloc_block(struct mem_block *heap, int size, - int align2, struct drm_file *file_priv) -{ - struct mem_block *p; - int mask = (1 << align2) - 1; - - list_for_each(p, heap) { - int start = (p->start + mask) & ~mask; - if (p->file_priv == NULL && start + size <= p->start + p->size) - return split_block(p, start, size, file_priv); - } - - return NULL; -} - -static struct mem_block *find_block(struct mem_block *heap, int start) -{ - struct mem_block *p; - - list_for_each(p, heap) - if (p->start == start) - return p; - - return NULL; -} - -static void free_block(struct mem_block *p) -{ - p->file_priv = NULL; - - /* Assumes a single contiguous range. Needs a special file_priv in - * 'heap' to stop it being subsumed. - */ - if (p->next->file_priv == NULL) { - struct mem_block *q = p->next; - p->size += q->size; - p->next = q->next; - p->next->prev = p; - kfree(q); - } - - if (p->prev->file_priv == NULL) { - struct mem_block *q = p->prev; - q->size += p->size; - q->next = p->next; - q->next->prev = q; - kfree(p); - } -} - -/* Initialize. How to check for an uninitialized heap? - */ -static int init_heap(struct mem_block **heap, int start, int size) -{ - struct mem_block *blocks = kmalloc(sizeof(*blocks), GFP_KERNEL); - - if (!blocks) - return -ENOMEM; - - *heap = kzalloc(sizeof(**heap), GFP_KERNEL); - if (!*heap) { - kfree(blocks); - return -ENOMEM; - } - - blocks->start = start; - blocks->size = size; - blocks->file_priv = NULL; - blocks->next = blocks->prev = *heap; - - (*heap)->file_priv = (struct drm_file *) - 1; - (*heap)->next = (*heap)->prev = blocks; - return 0; -} - -/* Free all blocks associated with the releasing file. - */ -void radeon_mem_release(struct drm_file *file_priv, struct mem_block *heap) -{ - struct mem_block *p; - - if (!heap || !heap->next) - return; - - list_for_each(p, heap) { - if (p->file_priv == file_priv) - p->file_priv = NULL; - } - - /* Assumes a single contiguous range. Needs a special file_priv in - * 'heap' to stop it being subsumed. - */ - list_for_each(p, heap) { - while (p->file_priv == NULL && p->next->file_priv == NULL) { - struct mem_block *q = p->next; - p->size += q->size; - p->next = q->next; - p->next->prev = p; - kfree(q); - } - } -} - -/* Shutdown. - */ -void radeon_mem_takedown(struct mem_block **heap) -{ - struct mem_block *p; - - if (!*heap) - return; - - for (p = (*heap)->next; p != *heap;) { - struct mem_block *q = p; - p = p->next; - kfree(q); - } - - kfree(*heap); - *heap = NULL; -} - -/* IOCTL HANDLERS */ - -static struct mem_block **get_heap(drm_radeon_private_t * dev_priv, int region) -{ - switch (region) { - case RADEON_MEM_REGION_GART: - return &dev_priv->gart_heap; - case RADEON_MEM_REGION_FB: - return &dev_priv->fb_heap; - default: - return NULL; - } -} - -int radeon_mem_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_alloc_t *alloc = data; - struct mem_block *block, **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, alloc->region); - if (!heap || !*heap) - return -EFAULT; - - /* Make things easier on ourselves: all allocations at least - * 4k aligned. - */ - if (alloc->alignment < 12) - alloc->alignment = 12; - - block = alloc_block(*heap, alloc->size, alloc->alignment, file_priv); - - if (!block) - return -ENOMEM; - - if (copy_to_user(alloc->region_offset, &block->start, - sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -int radeon_mem_free(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_free_t *memfree = data; - struct mem_block *block, **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, memfree->region); - if (!heap || !*heap) - return -EFAULT; - - block = find_block(*heap, memfree->region_offset); - if (!block) - return -EFAULT; - - if (block->file_priv != file_priv) - return -EPERM; - - free_block(block); - return 0; -} - -int radeon_mem_init_heap(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_mem_init_heap_t *initheap = data; - struct mem_block **heap; - - if (!dev_priv) { - DRM_ERROR("called with no initialization\n"); - return -EINVAL; - } - - heap = get_heap(dev_priv, initheap->region); - if (!heap) - return -EFAULT; - - if (*heap) { - DRM_ERROR("heap already initialized?"); - return -EFAULT; - } - - return init_heap(heap, initheap->start, initheap->size); -} diff --git a/drivers/gpu/drm/radeon/radeon_mode.h b/drivers/gpu/drm/radeon/radeon_mode.h index cddd41b32eda..bb75201a24ba 100644 --- a/drivers/gpu/drm/radeon/radeon_mode.h +++ b/drivers/gpu/drm/radeon/radeon_mode.h @@ -757,8 +757,10 @@ extern u8 radeon_dp_getsinktype(struct radeon_connector *radeon_connector); extern bool radeon_dp_getdpcd(struct radeon_connector *radeon_connector); extern int radeon_dp_get_panel_mode(struct drm_encoder *encoder, struct drm_connector *connector); -int radeon_dp_get_max_link_rate(struct drm_connector *connector, - const u8 *dpcd); +extern int radeon_dp_get_dp_link_config(struct drm_connector *connector, + const u8 *dpcd, + unsigned pix_clock, + unsigned *dp_lanes, unsigned *dp_rate); extern void radeon_dp_set_rx_power_state(struct drm_connector *connector, u8 power_state); extern void radeon_dp_aux_init(struct radeon_connector *radeon_connector); diff --git a/drivers/gpu/drm/radeon/radeon_state.c b/drivers/gpu/drm/radeon/radeon_state.c deleted file mode 100644 index 15aee723db77..000000000000 --- a/drivers/gpu/drm/radeon/radeon_state.c +++ /dev/null @@ -1,3261 +0,0 @@ -/* radeon_state.c -- State support for Radeon -*- linux-c -*- */ -/* - * Copyright 2000 VA Linux Systems, Inc., Fremont, California. - * All Rights Reserved. - * - * 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 (including the next - * paragraph) 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 - * PRECISION INSIGHT AND/OR ITS SUPPLIERS 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: - * Gareth Hughes <gareth@valinux.com> - * Kevin E. Martin <martin@valinux.com> - * - * ------------------------ This file is DEPRECATED! ------------------------- - */ - -#include <drm/drmP.h> -#include <drm/radeon_drm.h> -#include "radeon_drv.h" -#include "drm_buffer.h" - -/* ================================================================ - * Helper functions for client state checking and fixup - */ - -static __inline__ int radeon_check_and_fixup_offset(drm_radeon_private_t * - dev_priv, - struct drm_file * file_priv, - u32 *offset) -{ - u64 off = *offset; - u32 fb_end = dev_priv->fb_location + dev_priv->fb_size - 1; - struct drm_radeon_driver_file_fields *radeon_priv; - - /* Hrm ... the story of the offset ... So this function converts - * the various ideas of what userland clients might have for an - * offset in the card address space into an offset into the card - * address space :) So with a sane client, it should just keep - * the value intact and just do some boundary checking. However, - * not all clients are sane. Some older clients pass us 0 based - * offsets relative to the start of the framebuffer and some may - * assume the AGP aperture it appended to the framebuffer, so we - * try to detect those cases and fix them up. - * - * Note: It might be a good idea here to make sure the offset lands - * in some "allowed" area to protect things like the PCIE GART... - */ - - /* First, the best case, the offset already lands in either the - * framebuffer or the GART mapped space - */ - if (radeon_check_offset(dev_priv, off)) - return 0; - - /* Ok, that didn't happen... now check if we have a zero based - * offset that fits in the framebuffer + gart space, apply the - * magic offset we get from SETPARAM or calculated from fb_location - */ - if (off < (dev_priv->fb_size + dev_priv->gart_size)) { - radeon_priv = file_priv->driver_priv; - off += radeon_priv->radeon_fb_delta; - } - - /* Finally, assume we aimed at a GART offset if beyond the fb */ - if (off > fb_end) - off = off - fb_end - 1 + dev_priv->gart_vm_start; - - /* Now recheck and fail if out of bounds */ - if (radeon_check_offset(dev_priv, off)) { - DRM_DEBUG("offset fixed up to 0x%x\n", (unsigned int)off); - *offset = off; - return 0; - } - return -EINVAL; -} - -static __inline__ int radeon_check_and_fixup_packets(drm_radeon_private_t * - dev_priv, - struct drm_file *file_priv, - int id, struct drm_buffer *buf) -{ - u32 *data; - switch (id) { - - case RADEON_EMIT_PP_MISC: - data = drm_buffer_pointer_to_dword(buf, - (RADEON_RB3D_DEPTHOFFSET - RADEON_PP_MISC) / 4); - - if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { - DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; - } - dev_priv->have_z_offset = 1; - break; - - case RADEON_EMIT_PP_CNTL: - data = drm_buffer_pointer_to_dword(buf, - (RADEON_RB3D_COLOROFFSET - RADEON_PP_CNTL) / 4); - - if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { - DRM_ERROR("Invalid colour buffer offset\n"); - return -EINVAL; - } - break; - - case R200_EMIT_PP_TXOFFSET_0: - case R200_EMIT_PP_TXOFFSET_1: - case R200_EMIT_PP_TXOFFSET_2: - case R200_EMIT_PP_TXOFFSET_3: - case R200_EMIT_PP_TXOFFSET_4: - case R200_EMIT_PP_TXOFFSET_5: - data = drm_buffer_pointer_to_dword(buf, 0); - if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { - DRM_ERROR("Invalid R200 texture offset\n"); - return -EINVAL; - } - break; - - case RADEON_EMIT_PP_TXFILTER_0: - case RADEON_EMIT_PP_TXFILTER_1: - case RADEON_EMIT_PP_TXFILTER_2: - data = drm_buffer_pointer_to_dword(buf, - (RADEON_PP_TXOFFSET_0 - RADEON_PP_TXFILTER_0) / 4); - if (radeon_check_and_fixup_offset(dev_priv, file_priv, data)) { - DRM_ERROR("Invalid R100 texture offset\n"); - return -EINVAL; - } - break; - - case R200_EMIT_PP_CUBIC_OFFSETS_0: - case R200_EMIT_PP_CUBIC_OFFSETS_1: - case R200_EMIT_PP_CUBIC_OFFSETS_2: - case R200_EMIT_PP_CUBIC_OFFSETS_3: - case R200_EMIT_PP_CUBIC_OFFSETS_4: - case R200_EMIT_PP_CUBIC_OFFSETS_5:{ - int i; - for (i = 0; i < 5; i++) { - data = drm_buffer_pointer_to_dword(buf, i); - if (radeon_check_and_fixup_offset(dev_priv, - file_priv, - data)) { - DRM_ERROR - ("Invalid R200 cubic texture offset\n"); - return -EINVAL; - } - } - break; - } - - case RADEON_EMIT_PP_CUBIC_OFFSETS_T0: - case RADEON_EMIT_PP_CUBIC_OFFSETS_T1: - case RADEON_EMIT_PP_CUBIC_OFFSETS_T2:{ - int i; - for (i = 0; i < 5; i++) { - data = drm_buffer_pointer_to_dword(buf, i); - if (radeon_check_and_fixup_offset(dev_priv, - file_priv, - data)) { - DRM_ERROR - ("Invalid R100 cubic texture offset\n"); - return -EINVAL; - } - } - } - break; - - case R200_EMIT_VAP_CTL:{ - RING_LOCALS; - BEGIN_RING(2); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); - ADVANCE_RING(); - } - break; - - case RADEON_EMIT_RB3D_COLORPITCH: - case RADEON_EMIT_RE_LINE_PATTERN: - case RADEON_EMIT_SE_LINE_WIDTH: - case RADEON_EMIT_PP_LUM_MATRIX: - case RADEON_EMIT_PP_ROT_MATRIX_0: - case RADEON_EMIT_RB3D_STENCILREFMASK: - case RADEON_EMIT_SE_VPORT_XSCALE: - case RADEON_EMIT_SE_CNTL: - case RADEON_EMIT_SE_CNTL_STATUS: - case RADEON_EMIT_RE_MISC: - case RADEON_EMIT_PP_BORDER_COLOR_0: - case RADEON_EMIT_PP_BORDER_COLOR_1: - case RADEON_EMIT_PP_BORDER_COLOR_2: - case RADEON_EMIT_SE_ZBIAS_FACTOR: - case RADEON_EMIT_SE_TCL_OUTPUT_VTX_FMT: - case RADEON_EMIT_SE_TCL_MATERIAL_EMMISSIVE_RED: - case R200_EMIT_PP_TXCBLEND_0: - case R200_EMIT_PP_TXCBLEND_1: - case R200_EMIT_PP_TXCBLEND_2: - case R200_EMIT_PP_TXCBLEND_3: - case R200_EMIT_PP_TXCBLEND_4: - case R200_EMIT_PP_TXCBLEND_5: - case R200_EMIT_PP_TXCBLEND_6: - case R200_EMIT_PP_TXCBLEND_7: - case R200_EMIT_TCL_LIGHT_MODEL_CTL_0: - case R200_EMIT_TFACTOR_0: - case R200_EMIT_VTX_FMT_0: - case R200_EMIT_MATRIX_SELECT_0: - case R200_EMIT_TEX_PROC_CTL_2: - case R200_EMIT_TCL_UCP_VERT_BLEND_CTL: - case R200_EMIT_PP_TXFILTER_0: - case R200_EMIT_PP_TXFILTER_1: - case R200_EMIT_PP_TXFILTER_2: - case R200_EMIT_PP_TXFILTER_3: - case R200_EMIT_PP_TXFILTER_4: - case R200_EMIT_PP_TXFILTER_5: - case R200_EMIT_VTE_CNTL: - case R200_EMIT_OUTPUT_VTX_COMP_SEL: - case R200_EMIT_PP_TAM_DEBUG3: - case R200_EMIT_PP_CNTL_X: - case R200_EMIT_RB3D_DEPTHXY_OFFSET: - case R200_EMIT_RE_AUX_SCISSOR_CNTL: - case R200_EMIT_RE_SCISSOR_TL_0: - case R200_EMIT_RE_SCISSOR_TL_1: - case R200_EMIT_RE_SCISSOR_TL_2: - case R200_EMIT_SE_VAP_CNTL_STATUS: - case R200_EMIT_SE_VTX_STATE_CNTL: - case R200_EMIT_RE_POINTSIZE: - case R200_EMIT_TCL_INPUT_VTX_VECTOR_ADDR_0: - case R200_EMIT_PP_CUBIC_FACES_0: - case R200_EMIT_PP_CUBIC_FACES_1: - case R200_EMIT_PP_CUBIC_FACES_2: - case R200_EMIT_PP_CUBIC_FACES_3: - case R200_EMIT_PP_CUBIC_FACES_4: - case R200_EMIT_PP_CUBIC_FACES_5: - case RADEON_EMIT_PP_TEX_SIZE_0: - case RADEON_EMIT_PP_TEX_SIZE_1: - case RADEON_EMIT_PP_TEX_SIZE_2: - case R200_EMIT_RB3D_BLENDCOLOR: - case R200_EMIT_TCL_POINT_SPRITE_CNTL: - case RADEON_EMIT_PP_CUBIC_FACES_0: - case RADEON_EMIT_PP_CUBIC_FACES_1: - case RADEON_EMIT_PP_CUBIC_FACES_2: - case R200_EMIT_PP_TRI_PERF_CNTL: - case R200_EMIT_PP_AFS_0: - case R200_EMIT_PP_AFS_1: - case R200_EMIT_ATF_TFACTOR: - case R200_EMIT_PP_TXCTLALL_0: - case R200_EMIT_PP_TXCTLALL_1: - case R200_EMIT_PP_TXCTLALL_2: - case R200_EMIT_PP_TXCTLALL_3: - case R200_EMIT_PP_TXCTLALL_4: - case R200_EMIT_PP_TXCTLALL_5: - case R200_EMIT_VAP_PVS_CNTL: - /* These packets don't contain memory offsets */ - break; - - default: - DRM_ERROR("Unknown state packet ID %d\n", id); - return -EINVAL; - } - - return 0; -} - -static int radeon_check_and_fixup_packet3(drm_radeon_private_t * - dev_priv, - struct drm_file *file_priv, - drm_radeon_kcmd_buffer_t * - cmdbuf, - unsigned int *cmdsz) -{ - u32 *cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 0); - u32 offset, narrays; - int count, i, k; - - count = ((*cmd & RADEON_CP_PACKET_COUNT_MASK) >> 16); - *cmdsz = 2 + count; - - if ((*cmd & 0xc0000000) != RADEON_CP_PACKET3) { - DRM_ERROR("Not a type 3 packet\n"); - return -EINVAL; - } - - if (4 * *cmdsz > drm_buffer_unprocessed(cmdbuf->buffer)) { - DRM_ERROR("Packet size larger than size of data provided\n"); - return -EINVAL; - } - - switch (*cmd & 0xff00) { - /* XXX Are there old drivers needing other packets? */ - - case RADEON_3D_DRAW_IMMD: - case RADEON_3D_DRAW_VBUF: - case RADEON_3D_DRAW_INDX: - case RADEON_WAIT_FOR_IDLE: - case RADEON_CP_NOP: - case RADEON_3D_CLEAR_ZMASK: -/* case RADEON_CP_NEXT_CHAR: - case RADEON_CP_PLY_NEXTSCAN: - case RADEON_CP_SET_SCISSORS: */ /* probably safe but will never need them? */ - /* these packets are safe */ - break; - - case RADEON_CP_3D_DRAW_IMMD_2: - case RADEON_CP_3D_DRAW_VBUF_2: - case RADEON_CP_3D_DRAW_INDX_2: - case RADEON_3D_CLEAR_HIZ: - /* safe but r200 only */ - if (dev_priv->microcode_version != UCODE_R200) { - DRM_ERROR("Invalid 3d packet for r100-class chip\n"); - return -EINVAL; - } - break; - - case RADEON_3D_LOAD_VBPNTR: - - if (count > 18) { /* 12 arrays max */ - DRM_ERROR("Too large payload in 3D_LOAD_VBPNTR (count=%d)\n", - count); - return -EINVAL; - } - - /* carefully check packet contents */ - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - - narrays = *cmd & ~0xc000; - k = 0; - i = 2; - while ((k < narrays) && (i < (count + 2))) { - i++; /* skip attribute field */ - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - cmd)) { - DRM_ERROR - ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", - k, i); - return -EINVAL; - } - k++; - i++; - if (k == narrays) - break; - /* have one more to process, they come in pairs */ - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, i); - - if (radeon_check_and_fixup_offset(dev_priv, - file_priv, cmd)) - { - DRM_ERROR - ("Invalid offset (k=%d i=%d) in 3D_LOAD_VBPNTR packet.\n", - k, i); - return -EINVAL; - } - k++; - i++; - } - /* do the counts match what we expect ? */ - if ((k != narrays) || (i != (count + 2))) { - DRM_ERROR - ("Malformed 3D_LOAD_VBPNTR packet (k=%d i=%d narrays=%d count+1=%d).\n", - k, i, narrays, count + 1); - return -EINVAL; - } - break; - - case RADEON_3D_RNDR_GEN_INDX_PRIM: - if (dev_priv->microcode_version != UCODE_R100) { - DRM_ERROR("Invalid 3d packet for r200-class chip\n"); - return -EINVAL; - } - - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) { - DRM_ERROR("Invalid rndr_gen_indx offset\n"); - return -EINVAL; - } - break; - - case RADEON_CP_INDX_BUFFER: - if (dev_priv->microcode_version != UCODE_R200) { - DRM_ERROR("Invalid 3d packet for r100-class chip\n"); - return -EINVAL; - } - - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - if ((*cmd & 0x8000ffff) != 0x80000810) { - DRM_ERROR("Invalid indx_buffer reg address %08X\n", *cmd); - return -EINVAL; - } - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); - if (radeon_check_and_fixup_offset(dev_priv, file_priv, cmd)) { - DRM_ERROR("Invalid indx_buffer offset is %08X\n", *cmd); - return -EINVAL; - } - break; - - case RADEON_CNTL_HOSTDATA_BLT: - case RADEON_CNTL_PAINT_MULTI: - case RADEON_CNTL_BITBLT_MULTI: - /* MSB of opcode: next DWORD GUI_CNTL */ - cmd = drm_buffer_pointer_to_dword(cmdbuf->buffer, 1); - if (*cmd & (RADEON_GMC_SRC_PITCH_OFFSET_CNTL - | RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { - u32 *cmd2 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 2); - offset = *cmd2 << 10; - if (radeon_check_and_fixup_offset - (dev_priv, file_priv, &offset)) { - DRM_ERROR("Invalid first packet offset\n"); - return -EINVAL; - } - *cmd2 = (*cmd2 & 0xffc00000) | offset >> 10; - } - - if ((*cmd & RADEON_GMC_SRC_PITCH_OFFSET_CNTL) && - (*cmd & RADEON_GMC_DST_PITCH_OFFSET_CNTL)) { - u32 *cmd3 = drm_buffer_pointer_to_dword(cmdbuf->buffer, 3); - offset = *cmd3 << 10; - if (radeon_check_and_fixup_offset - (dev_priv, file_priv, &offset)) { - DRM_ERROR("Invalid second packet offset\n"); - return -EINVAL; - } - *cmd3 = (*cmd3 & 0xffc00000) | offset >> 10; - } - break; - - default: - DRM_ERROR("Invalid packet type %x\n", *cmd & 0xff00); - return -EINVAL; - } - - return 0; -} - -/* ================================================================ - * CP hardware state programming functions - */ - -static void radeon_emit_clip_rect(drm_radeon_private_t * dev_priv, - struct drm_clip_rect * box) -{ - RING_LOCALS; - - DRM_DEBUG(" box: x1=%d y1=%d x2=%d y2=%d\n", - box->x1, box->y1, box->x2, box->y2); - - BEGIN_RING(4); - OUT_RING(CP_PACKET0(RADEON_RE_TOP_LEFT, 0)); - OUT_RING((box->y1 << 16) | box->x1); - OUT_RING(CP_PACKET0(RADEON_RE_WIDTH_HEIGHT, 0)); - OUT_RING(((box->y2 - 1) << 16) | (box->x2 - 1)); - ADVANCE_RING(); -} - -/* Emit 1.1 state - */ -static int radeon_emit_state(drm_radeon_private_t * dev_priv, - struct drm_file *file_priv, - drm_radeon_context_regs_t * ctx, - drm_radeon_texture_regs_t * tex, - unsigned int dirty) -{ - RING_LOCALS; - DRM_DEBUG("dirty=0x%08x\n", dirty); - - if (dirty & RADEON_UPLOAD_CONTEXT) { - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - &ctx->rb3d_depthoffset)) { - DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; - } - - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - &ctx->rb3d_coloroffset)) { - DRM_ERROR("Invalid depth buffer offset\n"); - return -EINVAL; - } - - BEGIN_RING(14); - OUT_RING(CP_PACKET0(RADEON_PP_MISC, 6)); - OUT_RING(ctx->pp_misc); - OUT_RING(ctx->pp_fog_color); - OUT_RING(ctx->re_solid_color); - OUT_RING(ctx->rb3d_blendcntl); - OUT_RING(ctx->rb3d_depthoffset); - OUT_RING(ctx->rb3d_depthpitch); - OUT_RING(ctx->rb3d_zstencilcntl); - OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 2)); - OUT_RING(ctx->pp_cntl); - OUT_RING(ctx->rb3d_cntl); - OUT_RING(ctx->rb3d_coloroffset); - OUT_RING(CP_PACKET0(RADEON_RB3D_COLORPITCH, 0)); - OUT_RING(ctx->rb3d_colorpitch); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_VERTFMT) { - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_SE_COORD_FMT, 0)); - OUT_RING(ctx->se_coord_fmt); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_LINE) { - BEGIN_RING(5); - OUT_RING(CP_PACKET0(RADEON_RE_LINE_PATTERN, 1)); - OUT_RING(ctx->re_line_pattern); - OUT_RING(ctx->re_line_state); - OUT_RING(CP_PACKET0(RADEON_SE_LINE_WIDTH, 0)); - OUT_RING(ctx->se_line_width); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_BUMPMAP) { - BEGIN_RING(5); - OUT_RING(CP_PACKET0(RADEON_PP_LUM_MATRIX, 0)); - OUT_RING(ctx->pp_lum_matrix); - OUT_RING(CP_PACKET0(RADEON_PP_ROT_MATRIX_0, 1)); - OUT_RING(ctx->pp_rot_matrix_0); - OUT_RING(ctx->pp_rot_matrix_1); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_MASKS) { - BEGIN_RING(4); - OUT_RING(CP_PACKET0(RADEON_RB3D_STENCILREFMASK, 2)); - OUT_RING(ctx->rb3d_stencilrefmask); - OUT_RING(ctx->rb3d_ropcntl); - OUT_RING(ctx->rb3d_planemask); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_VIEWPORT) { - BEGIN_RING(7); - OUT_RING(CP_PACKET0(RADEON_SE_VPORT_XSCALE, 5)); - OUT_RING(ctx->se_vport_xscale); - OUT_RING(ctx->se_vport_xoffset); - OUT_RING(ctx->se_vport_yscale); - OUT_RING(ctx->se_vport_yoffset); - OUT_RING(ctx->se_vport_zscale); - OUT_RING(ctx->se_vport_zoffset); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_SETUP) { - BEGIN_RING(4); - OUT_RING(CP_PACKET0(RADEON_SE_CNTL, 0)); - OUT_RING(ctx->se_cntl); - OUT_RING(CP_PACKET0(RADEON_SE_CNTL_STATUS, 0)); - OUT_RING(ctx->se_cntl_status); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_MISC) { - BEGIN_RING(2); - OUT_RING(CP_PACKET0(RADEON_RE_MISC, 0)); - OUT_RING(ctx->re_misc); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_TEX0) { - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - &tex[0].pp_txoffset)) { - DRM_ERROR("Invalid texture offset for unit 0\n"); - return -EINVAL; - } - - BEGIN_RING(9); - OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_0, 5)); - OUT_RING(tex[0].pp_txfilter); - OUT_RING(tex[0].pp_txformat); - OUT_RING(tex[0].pp_txoffset); - OUT_RING(tex[0].pp_txcblend); - OUT_RING(tex[0].pp_txablend); - OUT_RING(tex[0].pp_tfactor); - OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_0, 0)); - OUT_RING(tex[0].pp_border_color); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_TEX1) { - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - &tex[1].pp_txoffset)) { - DRM_ERROR("Invalid texture offset for unit 1\n"); - return -EINVAL; - } - - BEGIN_RING(9); - OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_1, 5)); - OUT_RING(tex[1].pp_txfilter); - OUT_RING(tex[1].pp_txformat); - OUT_RING(tex[1].pp_txoffset); - OUT_RING(tex[1].pp_txcblend); - OUT_RING(tex[1].pp_txablend); - OUT_RING(tex[1].pp_tfactor); - OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_1, 0)); - OUT_RING(tex[1].pp_border_color); - ADVANCE_RING(); - } - - if (dirty & RADEON_UPLOAD_TEX2) { - if (radeon_check_and_fixup_offset(dev_priv, file_priv, - &tex[2].pp_txoffset)) { - DRM_ERROR("Invalid texture offset for unit 2\n"); - return -EINVAL; - } - - BEGIN_RING(9); - OUT_RING(CP_PACKET0(RADEON_PP_TXFILTER_2, 5)); - OUT_RING(tex[2].pp_txfilter); - OUT_RING(tex[2].pp_txformat); - OUT_RING(tex[2].pp_txoffset); - OUT_RING(tex[2].pp_txcblend); - OUT_RING(tex[2].pp_txablend); - OUT_RING(tex[2].pp_tfactor); - OUT_RING(CP_PACKET0(RADEON_PP_BORDER_COLOR_2, 0)); - OUT_RING(tex[2].pp_border_color); - ADVANCE_RING(); - } - - return 0; -} - -/* Emit 1.2 state - */ -static int radeon_emit_state2(drm_radeon_private_t * dev_priv, - struct drm_file *file_priv, - drm_radeon_state_t * state) -{ - RING_LOCALS; - - if (state->dirty & RADEON_UPLOAD_ZBIAS) { - BEGIN_RING(3); - OUT_RING(CP_PACKET0(RADEON_SE_ZBIAS_FACTOR, 1)); - OUT_RING(state->context2.se_zbias_factor); - OUT_RING(state->context2.se_zbias_constant); - ADVANCE_RING(); - } - - return radeon_emit_state(dev_priv, file_priv, &state->context, - state->tex, state->dirty); -} - -/* New (1.3) state mechanism. 3 commands (packet, scalar, vector) in - * 1.3 cmdbuffers allow all previous state to be updated as well as - * the tcl scalar and vector areas. - */ -static struct { - int start; - int len; - const char *name; -} packet[RADEON_MAX_STATE_PACKETS] = { - {RADEON_PP_MISC, 7, "RADEON_PP_MISC"}, - {RADEON_PP_CNTL, 3, "RADEON_PP_CNTL"}, - {RADEON_RB3D_COLORPITCH, 1, "RADEON_RB3D_COLORPITCH"}, - {RADEON_RE_LINE_PATTERN, 2, "RADEON_RE_LINE_PATTERN"}, - {RADEON_SE_LINE_WIDTH, 1, "RADEON_SE_LINE_WIDTH"}, - {RADEON_PP_LUM_MATRIX, 1, "RADEON_PP_LUM_MATRIX"}, - {RADEON_PP_ROT_MATRIX_0, 2, "RADEON_PP_ROT_MATRIX_0"}, - {RADEON_RB3D_STENCILREFMASK, 3, "RADEON_RB3D_STENCILREFMASK"}, - {RADEON_SE_VPORT_XSCALE, 6, "RADEON_SE_VPORT_XSCALE"}, - {RADEON_SE_CNTL, 2, "RADEON_SE_CNTL"}, - {RADEON_SE_CNTL_STATUS, 1, "RADEON_SE_CNTL_STATUS"}, - {RADEON_RE_MISC, 1, "RADEON_RE_MISC"}, - {RADEON_PP_TXFILTER_0, 6, "RADEON_PP_TXFILTER_0"}, - {RADEON_PP_BORDER_COLOR_0, 1, "RADEON_PP_BORDER_COLOR_0"}, - {RADEON_PP_TXFILTER_1, 6, "RADEON_PP_TXFILTER_1"}, - {RADEON_PP_BORDER_COLOR_1, 1, "RADEON_PP_BORDER_COLOR_1"}, - {RADEON_PP_TXFILTER_2, 6, "RADEON_PP_TXFILTER_2"}, - {RADEON_PP_BORDER_COLOR_2, 1, "RADEON_PP_BORDER_COLOR_2"}, - {RADEON_SE_ZBIAS_FACTOR, 2, "RADEON_SE_ZBIAS_FACTOR"}, - {RADEON_SE_TCL_OUTPUT_VTX_FMT, 11, "RADEON_SE_TCL_OUTPUT_VTX_FMT"}, - {RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED, 17, - "RADEON_SE_TCL_MATERIAL_EMMISSIVE_RED"}, - {R200_PP_TXCBLEND_0, 4, "R200_PP_TXCBLEND_0"}, - {R200_PP_TXCBLEND_1, 4, "R200_PP_TXCBLEND_1"}, - {R200_PP_TXCBLEND_2, 4, "R200_PP_TXCBLEND_2"}, - {R200_PP_TXCBLEND_3, 4, "R200_PP_TXCBLEND_3"}, - {R200_PP_TXCBLEND_4, 4, "R200_PP_TXCBLEND_4"}, - {R200_PP_TXCBLEND_5, 4, "R200_PP_TXCBLEND_5"}, - {R200_PP_TXCBLEND_6, 4, "R200_PP_TXCBLEND_6"}, - {R200_PP_TXCBLEND_7, 4, "R200_PP_TXCBLEND_7"}, - {R200_SE_TCL_LIGHT_MODEL_CTL_0, 6, "R200_SE_TCL_LIGHT_MODEL_CTL_0"}, - {R200_PP_TFACTOR_0, 6, "R200_PP_TFACTOR_0"}, - {R200_SE_VTX_FMT_0, 4, "R200_SE_VTX_FMT_0"}, - {R200_SE_VAP_CNTL, 1, "R200_SE_VAP_CNTL"}, - {R200_SE_TCL_MATRIX_SEL_0, 5, "R200_SE_TCL_MATRIX_SEL_0"}, - {R200_SE_TCL_TEX_PROC_CTL_2, 5, "R200_SE_TCL_TEX_PROC_CTL_2"}, - {R200_SE_TCL_UCP_VERT_BLEND_CTL, 1, "R200_SE_TCL_UCP_VERT_BLEND_CTL"}, - {R200_PP_TXFILTER_0, 6, "R200_PP_TXFILTER_0"}, - {R200_PP_TXFILTER_1, 6, "R200_PP_TXFILTER_1"}, - {R200_PP_TXFILTER_2, 6, "R200_PP_TXFILTER_2"}, - {R200_PP_TXFILTER_3, 6, "R200_PP_TXFILTER_3"}, - {R200_PP_TXFILTER_4, 6, "R200_PP_TXFILTER_4"}, - {R200_PP_TXFILTER_5, 6, "R200_PP_TXFILTER_5"}, - {R200_PP_TXOFFSET_0, 1, "R200_PP_TXOFFSET_0"}, - {R200_PP_TXOFFSET_1, 1, "R200_PP_TXOFFSET_1"}, - {R200_PP_TXOFFSET_2, 1, "R200_PP_TXOFFSET_2"}, - {R200_PP_TXOFFSET_3, 1, "R200_PP_TXOFFSET_3"}, - {R200_PP_TXOFFSET_4, 1, "R200_PP_TXOFFSET_4"}, - {R200_PP_TXOFFSET_5, 1, "R200_PP_TXOFFSET_5"}, - {R200_SE_VTE_CNTL, 1, "R200_SE_VTE_CNTL"}, - {R200_SE_TCL_OUTPUT_VTX_COMP_SEL, 1, - "R200_SE_TCL_OUTPUT_VTX_COMP_SEL"}, - {R200_PP_TAM_DEBUG3, 1, "R200_PP_TAM_DEBUG3"}, - {R200_PP_CNTL_X, 1, "R200_PP_CNTL_X"}, - {R200_RB3D_DEPTHXY_OFFSET, 1, "R200_RB3D_DEPTHXY_OFFSET"}, - {R200_RE_AUX_SCISSOR_CNTL, 1, "R200_RE_AUX_SCISSOR_CNTL"}, - {R200_RE_SCISSOR_TL_0, 2, "R200_RE_SCISSOR_TL_0"}, - {R200_RE_SCISSOR_TL_1, 2, "R200_RE_SCISSOR_TL_1"}, - {R200_RE_SCISSOR_TL_2, 2, "R200_RE_SCISSOR_TL_2"}, - {R200_SE_VAP_CNTL_STATUS, 1, "R200_SE_VAP_CNTL_STATUS"}, - {R200_SE_VTX_STATE_CNTL, 1, "R200_SE_VTX_STATE_CNTL"}, - {R200_RE_POINTSIZE, 1, "R200_RE_POINTSIZE"}, - {R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0, 4, - "R200_SE_TCL_INPUT_VTX_VECTOR_ADDR_0"}, - {R200_PP_CUBIC_FACES_0, 1, "R200_PP_CUBIC_FACES_0"}, /* 61 */ - {R200_PP_CUBIC_OFFSET_F1_0, 5, "R200_PP_CUBIC_OFFSET_F1_0"}, /* 62 */ - {R200_PP_CUBIC_FACES_1, 1, "R200_PP_CUBIC_FACES_1"}, - {R200_PP_CUBIC_OFFSET_F1_1, 5, "R200_PP_CUBIC_OFFSET_F1_1"}, - {R200_PP_CUBIC_FACES_2, 1, "R200_PP_CUBIC_FACES_2"}, - {R200_PP_CUBIC_OFFSET_F1_2, 5, "R200_PP_CUBIC_OFFSET_F1_2"}, - {R200_PP_CUBIC_FACES_3, 1, "R200_PP_CUBIC_FACES_3"}, - {R200_PP_CUBIC_OFFSET_F1_3, 5, "R200_PP_CUBIC_OFFSET_F1_3"}, - {R200_PP_CUBIC_FACES_4, 1, "R200_PP_CUBIC_FACES_4"}, - {R200_PP_CUBIC_OFFSET_F1_4, 5, "R200_PP_CUBIC_OFFSET_F1_4"}, - {R200_PP_CUBIC_FACES_5, 1, "R200_PP_CUBIC_FACES_5"}, - {R200_PP_CUBIC_OFFSET_F1_5, 5, "R200_PP_CUBIC_OFFSET_F1_5"}, - {RADEON_PP_TEX_SIZE_0, 2, "RADEON_PP_TEX_SIZE_0"}, - {RADEON_PP_TEX_SIZE_1, 2, "RADEON_PP_TEX_SIZE_1"}, - {RADEON_PP_TEX_SIZE_2, 2, "RADEON_PP_TEX_SIZE_2"}, - {R200_RB3D_BLENDCOLOR, 3, "R200_RB3D_BLENDCOLOR"}, - {R200_SE_TCL_POINT_SPRITE_CNTL, 1, "R200_SE_TCL_POINT_SPRITE_CNTL"}, - {RADEON_PP_CUBIC_FACES_0, 1, "RADEON_PP_CUBIC_FACES_0"}, - {RADEON_PP_CUBIC_OFFSET_T0_0, 5, "RADEON_PP_CUBIC_OFFSET_T0_0"}, - {RADEON_PP_CUBIC_FACES_1, 1, "RADEON_PP_CUBIC_FACES_1"}, - {RADEON_PP_CUBIC_OFFSET_T1_0, 5, "RADEON_PP_CUBIC_OFFSET_T1_0"}, - {RADEON_PP_CUBIC_FACES_2, 1, "RADEON_PP_CUBIC_FACES_2"}, - {RADEON_PP_CUBIC_OFFSET_T2_0, 5, "RADEON_PP_CUBIC_OFFSET_T2_0"}, - {R200_PP_TRI_PERF, 2, "R200_PP_TRI_PERF"}, - {R200_PP_AFS_0, 32, "R200_PP_AFS_0"}, /* 85 */ - {R200_PP_AFS_1, 32, "R200_PP_AFS_1"}, - {R200_PP_TFACTOR_0, 8, "R200_ATF_TFACTOR"}, - {R200_PP_TXFILTER_0, 8, "R200_PP_TXCTLALL_0"}, - {R200_PP_TXFILTER_1, 8, "R200_PP_TXCTLALL_1"}, - {R200_PP_TXFILTER_2, 8, "R200_PP_TXCTLALL_2"}, - {R200_PP_TXFILTER_3, 8, "R200_PP_TXCTLALL_3"}, - {R200_PP_TXFILTER_4, 8, "R200_PP_TXCTLALL_4"}, - {R200_PP_TXFILTER_5, 8, "R200_PP_TXCTLALL_5"}, - {R200_VAP_PVS_CNTL_1, 2, "R200_VAP_PVS_CNTL"}, -}; - -/* ================================================================ - * Performance monitoring functions - */ - -static void radeon_clear_box(drm_radeon_private_t * dev_priv, - struct drm_radeon_master_private *master_priv, - int x, int y, int w, int h, int r, int g, int b) -{ - u32 color; - RING_LOCALS; - - x += master_priv->sarea_priv->boxes[0].x1; - y += master_priv->sarea_priv->boxes[0].y1; - - switch (dev_priv->color_fmt) { - case RADEON_COLOR_FORMAT_RGB565: - color = (((r & 0xf8) << 8) | - ((g & 0xfc) << 3) | ((b & 0xf8) >> 3)); - break; - case RADEON_COLOR_FORMAT_ARGB8888: - default: - color = (((0xff) << 24) | (r << 16) | (g << 8) | b); - break; - } - - BEGIN_RING(4); - RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); - OUT_RING(0xffffffff); - ADVANCE_RING(); - - BEGIN_RING(6); - - OUT_RING(CP_PACKET3(RADEON_CNTL_PAINT_MULTI, 4)); - OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (dev_priv->color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_P | RADEON_GMC_CLR_CMP_CNTL_DIS); - - if (master_priv->sarea_priv->pfCurrentPage == 1) { - OUT_RING(dev_priv->front_pitch_offset); - } else { - OUT_RING(dev_priv->back_pitch_offset); - } - - OUT_RING(color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); -} - -static void radeon_cp_performance_boxes(drm_radeon_private_t *dev_priv, struct drm_radeon_master_private *master_priv) -{ - /* Collapse various things into a wait flag -- trying to - * guess if userspase slept -- better just to have them tell us. - */ - if (dev_priv->stats.last_frame_reads > 1 || - dev_priv->stats.last_clear_reads > dev_priv->stats.clears) { - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - } - - if (dev_priv->stats.freelist_loops) { - dev_priv->stats.boxes |= RADEON_BOX_WAIT_IDLE; - } - - /* Purple box for page flipping - */ - if (dev_priv->stats.boxes & RADEON_BOX_FLIP) - radeon_clear_box(dev_priv, master_priv, 4, 4, 8, 8, 255, 0, 255); - - /* Red box if we have to wait for idle at any point - */ - if (dev_priv->stats.boxes & RADEON_BOX_WAIT_IDLE) - radeon_clear_box(dev_priv, master_priv, 16, 4, 8, 8, 255, 0, 0); - - /* Blue box: lost context? - */ - - /* Yellow box for texture swaps - */ - if (dev_priv->stats.boxes & RADEON_BOX_TEXTURE_LOAD) - radeon_clear_box(dev_priv, master_priv, 40, 4, 8, 8, 255, 255, 0); - - /* Green box if hardware never idles (as far as we can tell) - */ - if (!(dev_priv->stats.boxes & RADEON_BOX_DMA_IDLE)) - radeon_clear_box(dev_priv, master_priv, 64, 4, 8, 8, 0, 255, 0); - - /* Draw bars indicating number of buffers allocated - * (not a great measure, easily confused) - */ - if (dev_priv->stats.requested_bufs) { - if (dev_priv->stats.requested_bufs > 100) - dev_priv->stats.requested_bufs = 100; - - radeon_clear_box(dev_priv, master_priv, 4, 16, - dev_priv->stats.requested_bufs, 4, - 196, 128, 128); - } - - memset(&dev_priv->stats, 0, sizeof(dev_priv->stats)); - -} - -/* ================================================================ - * CP command dispatch functions - */ - -static void radeon_cp_dispatch_clear(struct drm_device * dev, - struct drm_master *master, - drm_radeon_clear_t * clear, - drm_radeon_clear_rect_t * depth_boxes) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - drm_radeon_depth_clear_t *depth_clear = &dev_priv->depth_clear; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - unsigned int flags = clear->flags; - u32 rb3d_cntl = 0, rb3d_stencilrefmask = 0; - int i; - RING_LOCALS; - DRM_DEBUG("flags = 0x%x\n", flags); - - dev_priv->stats.clears++; - - if (sarea_priv->pfCurrentPage == 1) { - unsigned int tmp = flags; - - flags &= ~(RADEON_FRONT | RADEON_BACK); - if (tmp & RADEON_FRONT) - flags |= RADEON_BACK; - if (tmp & RADEON_BACK) - flags |= RADEON_FRONT; - } - if (flags & (RADEON_DEPTH|RADEON_STENCIL)) { - if (!dev_priv->have_z_offset) { - printk_once(KERN_ERR "radeon: illegal depth clear request. Buggy mesa detected - please update.\n"); - flags &= ~(RADEON_DEPTH | RADEON_STENCIL); - } - } - - if (flags & (RADEON_FRONT | RADEON_BACK)) { - - BEGIN_RING(4); - - /* Ensure the 3D stream is idle before doing a - * 2D fill to clear the front or back buffer. - */ - RADEON_WAIT_UNTIL_3D_IDLE(); - - OUT_RING(CP_PACKET0(RADEON_DP_WRITE_MASK, 0)); - OUT_RING(clear->color_mask); - - ADVANCE_RING(); - - /* Make sure we restore the 3D state next time. - */ - sarea_priv->ctx_owner = 0; - - for (i = 0; i < nbox; i++) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; - - DRM_DEBUG("%d,%d-%d,%d flags 0x%x\n", - x, y, w, h, flags); - - if (flags & RADEON_FRONT) { - BEGIN_RING(6); - - OUT_RING(CP_PACKET3 - (RADEON_CNTL_PAINT_MULTI, 4)); - OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (dev_priv-> - color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_P | - RADEON_GMC_CLR_CMP_CNTL_DIS); - - OUT_RING(dev_priv->front_pitch_offset); - OUT_RING(clear->clear_color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - - if (flags & RADEON_BACK) { - BEGIN_RING(6); - - OUT_RING(CP_PACKET3 - (RADEON_CNTL_PAINT_MULTI, 4)); - OUT_RING(RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_SOLID_COLOR | - (dev_priv-> - color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_P | - RADEON_GMC_CLR_CMP_CNTL_DIS); - - OUT_RING(dev_priv->back_pitch_offset); - OUT_RING(clear->clear_color); - - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - } - } - - /* hyper z clear */ - /* no docs available, based on reverse engineering by Stephane Marchesin */ - if ((flags & (RADEON_DEPTH | RADEON_STENCIL)) - && (flags & RADEON_CLEAR_FASTZ)) { - - int i; - int depthpixperline = - dev_priv->depth_fmt == - RADEON_DEPTH_FORMAT_16BIT_INT_Z ? (dev_priv->depth_pitch / - 2) : (dev_priv-> - depth_pitch / 4); - - u32 clearmask; - - u32 tempRB3D_DEPTHCLEARVALUE = clear->clear_depth | - ((clear->depth_mask & 0xff) << 24); - - /* Make sure we restore the 3D state next time. - * we haven't touched any "normal" state - still need this? - */ - sarea_priv->ctx_owner = 0; - - if ((dev_priv->flags & RADEON_HAS_HIERZ) - && (flags & RADEON_USE_HIERZ)) { - /* FIXME : reverse engineer that for Rx00 cards */ - /* FIXME : the mask supposedly contains low-res z values. So can't set - just to the max (0xff? or actually 0x3fff?), need to take z clear - value into account? */ - /* pattern seems to work for r100, though get slight - rendering errors with glxgears. If hierz is not enabled for r100, - only 4 bits which indicate clear (15,16,31,32, all zero) matter, the - other ones are ignored, and the same clear mask can be used. That's - very different behaviour than R200 which needs different clear mask - and different number of tiles to clear if hierz is enabled or not !?! - */ - clearmask = (0xff << 22) | (0xff << 6) | 0x003f003f; - } else { - /* clear mask : chooses the clearing pattern. - rv250: could be used to clear only parts of macrotiles - (but that would get really complicated...)? - bit 0 and 1 (either or both of them ?!?!) are used to - not clear tile (or maybe one of the bits indicates if the tile is - compressed or not), bit 2 and 3 to not clear tile 1,...,. - Pattern is as follows: - | 0,1 | 4,5 | 8,9 |12,13|16,17|20,21|24,25|28,29| - bits ------------------------------------------------- - | 2,3 | 6,7 |10,11|14,15|18,19|22,23|26,27|30,31| - rv100: clearmask covers 2x8 4x1 tiles, but one clear still - covers 256 pixels ?!? - */ - clearmask = 0x0; - } - - BEGIN_RING(8); - RADEON_WAIT_UNTIL_2D_IDLE(); - OUT_RING_REG(RADEON_RB3D_DEPTHCLEARVALUE, - tempRB3D_DEPTHCLEARVALUE); - /* what offset is this exactly ? */ - OUT_RING_REG(RADEON_RB3D_ZMASKOFFSET, 0); - /* need ctlstat, otherwise get some strange black flickering */ - OUT_RING_REG(RADEON_RB3D_ZCACHE_CTLSTAT, - RADEON_RB3D_ZC_FLUSH_ALL); - ADVANCE_RING(); - - for (i = 0; i < nbox; i++) { - int tileoffset, nrtilesx, nrtilesy, j; - /* it looks like r200 needs rv-style clears, at least if hierz is not enabled? */ - if ((dev_priv->flags & RADEON_HAS_HIERZ) - && !(dev_priv->microcode_version == UCODE_R200)) { - /* FIXME : figure this out for r200 (when hierz is enabled). Or - maybe r200 actually doesn't need to put the low-res z value into - the tile cache like r100, but just needs to clear the hi-level z-buffer? - Works for R100, both with hierz and without. - R100 seems to operate on 2x1 8x8 tiles, but... - odd: offset/nrtiles need to be 64 pix (4 block) aligned? Potentially - problematic with resolutions which are not 64 pix aligned? */ - tileoffset = - ((pbox[i].y1 >> 3) * depthpixperline + - pbox[i].x1) >> 6; - nrtilesx = - ((pbox[i].x2 & ~63) - - (pbox[i].x1 & ~63)) >> 4; - nrtilesy = - (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); - for (j = 0; j <= nrtilesy; j++) { - BEGIN_RING(4); - OUT_RING(CP_PACKET3 - (RADEON_3D_CLEAR_ZMASK, 2)); - /* first tile */ - OUT_RING(tileoffset * 8); - /* the number of tiles to clear */ - OUT_RING(nrtilesx + 4); - /* clear mask : chooses the clearing pattern. */ - OUT_RING(clearmask); - ADVANCE_RING(); - tileoffset += depthpixperline >> 6; - } - } else if (dev_priv->microcode_version == UCODE_R200) { - /* works for rv250. */ - /* find first macro tile (8x2 4x4 z-pixels on rv250) */ - tileoffset = - ((pbox[i].y1 >> 3) * depthpixperline + - pbox[i].x1) >> 5; - nrtilesx = - (pbox[i].x2 >> 5) - (pbox[i].x1 >> 5); - nrtilesy = - (pbox[i].y2 >> 3) - (pbox[i].y1 >> 3); - for (j = 0; j <= nrtilesy; j++) { - BEGIN_RING(4); - OUT_RING(CP_PACKET3 - (RADEON_3D_CLEAR_ZMASK, 2)); - /* first tile */ - /* judging by the first tile offset needed, could possibly - directly address/clear 4x4 tiles instead of 8x2 * 4x4 - macro tiles, though would still need clear mask for - right/bottom if truly 4x4 granularity is desired ? */ - OUT_RING(tileoffset * 16); - /* the number of tiles to clear */ - OUT_RING(nrtilesx + 1); - /* clear mask : chooses the clearing pattern. */ - OUT_RING(clearmask); - ADVANCE_RING(); - tileoffset += depthpixperline >> 5; - } - } else { /* rv 100 */ - /* rv100 might not need 64 pix alignment, who knows */ - /* offsets are, hmm, weird */ - tileoffset = - ((pbox[i].y1 >> 4) * depthpixperline + - pbox[i].x1) >> 6; - nrtilesx = - ((pbox[i].x2 & ~63) - - (pbox[i].x1 & ~63)) >> 4; - nrtilesy = - (pbox[i].y2 >> 4) - (pbox[i].y1 >> 4); - for (j = 0; j <= nrtilesy; j++) { - BEGIN_RING(4); - OUT_RING(CP_PACKET3 - (RADEON_3D_CLEAR_ZMASK, 2)); - OUT_RING(tileoffset * 128); - /* the number of tiles to clear */ - OUT_RING(nrtilesx + 4); - /* clear mask : chooses the clearing pattern. */ - OUT_RING(clearmask); - ADVANCE_RING(); - tileoffset += depthpixperline >> 6; - } - } - } - - /* TODO don't always clear all hi-level z tiles */ - if ((dev_priv->flags & RADEON_HAS_HIERZ) - && (dev_priv->microcode_version == UCODE_R200) - && (flags & RADEON_USE_HIERZ)) - /* r100 and cards without hierarchical z-buffer have no high-level z-buffer */ - /* FIXME : the mask supposedly contains low-res z values. So can't set - just to the max (0xff? or actually 0x3fff?), need to take z clear - value into account? */ - { - BEGIN_RING(4); - OUT_RING(CP_PACKET3(RADEON_3D_CLEAR_HIZ, 2)); - OUT_RING(0x0); /* First tile */ - OUT_RING(0x3cc0); - OUT_RING((0xff << 22) | (0xff << 6) | 0x003f003f); - ADVANCE_RING(); - } - } - - /* We have to clear the depth and/or stencil buffers by - * rendering a quad into just those buffers. Thus, we have to - * make sure the 3D engine is configured correctly. - */ - else if ((dev_priv->microcode_version == UCODE_R200) && - (flags & (RADEON_DEPTH | RADEON_STENCIL))) { - - int tempPP_CNTL; - int tempRE_CNTL; - int tempRB3D_CNTL; - int tempRB3D_ZSTENCILCNTL; - int tempRB3D_STENCILREFMASK; - int tempRB3D_PLANEMASK; - int tempSE_CNTL; - int tempSE_VTE_CNTL; - int tempSE_VTX_FMT_0; - int tempSE_VTX_FMT_1; - int tempSE_VAP_CNTL; - int tempRE_AUX_SCISSOR_CNTL; - - tempPP_CNTL = 0; - tempRE_CNTL = 0; - - tempRB3D_CNTL = depth_clear->rb3d_cntl; - - tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; - tempRB3D_STENCILREFMASK = 0x0; - - tempSE_CNTL = depth_clear->se_cntl; - - /* Disable TCL */ - - tempSE_VAP_CNTL = ( /* SE_VAP_CNTL__FORCE_W_TO_ONE_MASK | */ - (0x9 << - SE_VAP_CNTL__VF_MAX_VTX_NUM__SHIFT)); - - tempRB3D_PLANEMASK = 0x0; - - tempRE_AUX_SCISSOR_CNTL = 0x0; - - tempSE_VTE_CNTL = - SE_VTE_CNTL__VTX_XY_FMT_MASK | SE_VTE_CNTL__VTX_Z_FMT_MASK; - - /* Vertex format (X, Y, Z, W) */ - tempSE_VTX_FMT_0 = - SE_VTX_FMT_0__VTX_Z0_PRESENT_MASK | - SE_VTX_FMT_0__VTX_W0_PRESENT_MASK; - tempSE_VTX_FMT_1 = 0x0; - - /* - * Depth buffer specific enables - */ - if (flags & RADEON_DEPTH) { - /* Enable depth buffer */ - tempRB3D_CNTL |= RADEON_Z_ENABLE; - } else { - /* Disable depth buffer */ - tempRB3D_CNTL &= ~RADEON_Z_ENABLE; - } - - /* - * Stencil buffer specific enables - */ - if (flags & RADEON_STENCIL) { - tempRB3D_CNTL |= RADEON_STENCIL_ENABLE; - tempRB3D_STENCILREFMASK = clear->depth_mask; - } else { - tempRB3D_CNTL &= ~RADEON_STENCIL_ENABLE; - tempRB3D_STENCILREFMASK = 0x00000000; - } - - if (flags & RADEON_USE_COMP_ZBUF) { - tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | - RADEON_Z_DECOMPRESSION_ENABLE; - } - if (flags & RADEON_USE_HIERZ) { - tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; - } - - BEGIN_RING(26); - RADEON_WAIT_UNTIL_2D_IDLE(); - - OUT_RING_REG(RADEON_PP_CNTL, tempPP_CNTL); - OUT_RING_REG(R200_RE_CNTL, tempRE_CNTL); - OUT_RING_REG(RADEON_RB3D_CNTL, tempRB3D_CNTL); - OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); - OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, - tempRB3D_STENCILREFMASK); - OUT_RING_REG(RADEON_RB3D_PLANEMASK, tempRB3D_PLANEMASK); - OUT_RING_REG(RADEON_SE_CNTL, tempSE_CNTL); - OUT_RING_REG(R200_SE_VTE_CNTL, tempSE_VTE_CNTL); - OUT_RING_REG(R200_SE_VTX_FMT_0, tempSE_VTX_FMT_0); - OUT_RING_REG(R200_SE_VTX_FMT_1, tempSE_VTX_FMT_1); - OUT_RING_REG(R200_SE_VAP_CNTL, tempSE_VAP_CNTL); - OUT_RING_REG(R200_RE_AUX_SCISSOR_CNTL, tempRE_AUX_SCISSOR_CNTL); - ADVANCE_RING(); - - /* Make sure we restore the 3D state next time. - */ - sarea_priv->ctx_owner = 0; - - for (i = 0; i < nbox; i++) { - - /* Funny that this should be required -- - * sets top-left? - */ - radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); - - BEGIN_RING(14); - OUT_RING(CP_PACKET3(R200_3D_DRAW_IMMD_2, 12)); - OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | - RADEON_PRIM_WALK_RING | - (3 << RADEON_NUM_VERTICES_SHIFT))); - OUT_RING(depth_boxes[i].ui[CLEAR_X1]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x3f800000); - OUT_RING(depth_boxes[i].ui[CLEAR_X1]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x3f800000); - OUT_RING(depth_boxes[i].ui[CLEAR_X2]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x3f800000); - ADVANCE_RING(); - } - } else if ((flags & (RADEON_DEPTH | RADEON_STENCIL))) { - - int tempRB3D_ZSTENCILCNTL = depth_clear->rb3d_zstencilcntl; - - rb3d_cntl = depth_clear->rb3d_cntl; - - if (flags & RADEON_DEPTH) { - rb3d_cntl |= RADEON_Z_ENABLE; - } else { - rb3d_cntl &= ~RADEON_Z_ENABLE; - } - - if (flags & RADEON_STENCIL) { - rb3d_cntl |= RADEON_STENCIL_ENABLE; - rb3d_stencilrefmask = clear->depth_mask; /* misnamed field */ - } else { - rb3d_cntl &= ~RADEON_STENCIL_ENABLE; - rb3d_stencilrefmask = 0x00000000; - } - - if (flags & RADEON_USE_COMP_ZBUF) { - tempRB3D_ZSTENCILCNTL |= RADEON_Z_COMPRESSION_ENABLE | - RADEON_Z_DECOMPRESSION_ENABLE; - } - if (flags & RADEON_USE_HIERZ) { - tempRB3D_ZSTENCILCNTL |= RADEON_Z_HIERARCHY_ENABLE; - } - - BEGIN_RING(13); - RADEON_WAIT_UNTIL_2D_IDLE(); - - OUT_RING(CP_PACKET0(RADEON_PP_CNTL, 1)); - OUT_RING(0x00000000); - OUT_RING(rb3d_cntl); - - OUT_RING_REG(RADEON_RB3D_ZSTENCILCNTL, tempRB3D_ZSTENCILCNTL); - OUT_RING_REG(RADEON_RB3D_STENCILREFMASK, rb3d_stencilrefmask); - OUT_RING_REG(RADEON_RB3D_PLANEMASK, 0x00000000); - OUT_RING_REG(RADEON_SE_CNTL, depth_clear->se_cntl); - ADVANCE_RING(); - - /* Make sure we restore the 3D state next time. - */ - sarea_priv->ctx_owner = 0; - - for (i = 0; i < nbox; i++) { - - /* Funny that this should be required -- - * sets top-left? - */ - radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); - - BEGIN_RING(15); - - OUT_RING(CP_PACKET3(RADEON_3D_DRAW_IMMD, 13)); - OUT_RING(RADEON_VTX_Z_PRESENT | - RADEON_VTX_PKCOLOR_PRESENT); - OUT_RING((RADEON_PRIM_TYPE_RECT_LIST | - RADEON_PRIM_WALK_RING | - RADEON_MAOS_ENABLE | - RADEON_VTX_FMT_RADEON_MODE | - (3 << RADEON_NUM_VERTICES_SHIFT))); - - OUT_RING(depth_boxes[i].ui[CLEAR_X1]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y1]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x0); - - OUT_RING(depth_boxes[i].ui[CLEAR_X1]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x0); - - OUT_RING(depth_boxes[i].ui[CLEAR_X2]); - OUT_RING(depth_boxes[i].ui[CLEAR_Y2]); - OUT_RING(depth_boxes[i].ui[CLEAR_DEPTH]); - OUT_RING(0x0); - - ADVANCE_RING(); - } - } - - /* Increment the clear counter. The client-side 3D driver must - * wait on this value before performing the clear ioctl. We - * need this because the card's so damned fast... - */ - sarea_priv->last_clear++; - - BEGIN_RING(4); - - RADEON_CLEAR_AGE(sarea_priv->last_clear); - RADEON_WAIT_UNTIL_IDLE(); - - ADVANCE_RING(); -} - -static void radeon_cp_dispatch_swap(struct drm_device *dev, struct drm_master *master) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - int nbox = sarea_priv->nbox; - struct drm_clip_rect *pbox = sarea_priv->boxes; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - /* Do some trivial performance monitoring... - */ - if (dev_priv->do_boxes) - radeon_cp_performance_boxes(dev_priv, master_priv); - - /* Wait for the 3D stream to idle before dispatching the bitblt. - * This will prevent data corruption between the two streams. - */ - BEGIN_RING(2); - - RADEON_WAIT_UNTIL_3D_IDLE(); - - ADVANCE_RING(); - - for (i = 0; i < nbox; i++) { - int x = pbox[i].x1; - int y = pbox[i].y1; - int w = pbox[i].x2 - x; - int h = pbox[i].y2 - y; - - DRM_DEBUG("%d,%d-%d,%d\n", x, y, w, h); - - BEGIN_RING(9); - - OUT_RING(CP_PACKET0(RADEON_DP_GUI_MASTER_CNTL, 0)); - OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (dev_priv->color_fmt << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); - - /* Make this work even if front & back are flipped: - */ - OUT_RING(CP_PACKET0(RADEON_SRC_PITCH_OFFSET, 1)); - if (sarea_priv->pfCurrentPage == 0) { - OUT_RING(dev_priv->back_pitch_offset); - OUT_RING(dev_priv->front_pitch_offset); - } else { - OUT_RING(dev_priv->front_pitch_offset); - OUT_RING(dev_priv->back_pitch_offset); - } - - OUT_RING(CP_PACKET0(RADEON_SRC_X_Y, 2)); - OUT_RING((x << 16) | y); - OUT_RING((x << 16) | y); - OUT_RING((w << 16) | h); - - ADVANCE_RING(); - } - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - sarea_priv->last_frame++; - - BEGIN_RING(4); - - RADEON_FRAME_AGE(sarea_priv->last_frame); - RADEON_WAIT_UNTIL_2D_IDLE(); - - ADVANCE_RING(); -} - -void radeon_cp_dispatch_flip(struct drm_device *dev, struct drm_master *master) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - struct drm_sarea *sarea = (struct drm_sarea *)master_priv->sarea->handle; - int offset = (master_priv->sarea_priv->pfCurrentPage == 1) - ? dev_priv->front_offset : dev_priv->back_offset; - RING_LOCALS; - DRM_DEBUG("pfCurrentPage=%d\n", - master_priv->sarea_priv->pfCurrentPage); - - /* Do some trivial performance monitoring... - */ - if (dev_priv->do_boxes) { - dev_priv->stats.boxes |= RADEON_BOX_FLIP; - radeon_cp_performance_boxes(dev_priv, master_priv); - } - - /* Update the frame offsets for both CRTCs - */ - BEGIN_RING(6); - - RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING_REG(RADEON_CRTC_OFFSET, - ((sarea->frame.y * dev_priv->front_pitch + - sarea->frame.x * (dev_priv->color_fmt - 2)) & ~7) - + offset); - OUT_RING_REG(RADEON_CRTC2_OFFSET, master_priv->sarea_priv->crtc2_base - + offset); - - ADVANCE_RING(); - - /* Increment the frame counter. The client-side 3D driver must - * throttle the framerate by waiting for this value before - * performing the swapbuffer ioctl. - */ - master_priv->sarea_priv->last_frame++; - master_priv->sarea_priv->pfCurrentPage = - 1 - master_priv->sarea_priv->pfCurrentPage; - - BEGIN_RING(2); - - RADEON_FRAME_AGE(master_priv->sarea_priv->last_frame); - - ADVANCE_RING(); -} - -static int bad_prim_vertex_nr(int primitive, int nr) -{ - switch (primitive & RADEON_PRIM_TYPE_MASK) { - case RADEON_PRIM_TYPE_NONE: - case RADEON_PRIM_TYPE_POINT: - return nr < 1; - case RADEON_PRIM_TYPE_LINE: - return (nr & 1) || nr == 0; - case RADEON_PRIM_TYPE_LINE_STRIP: - return nr < 2; - case RADEON_PRIM_TYPE_TRI_LIST: - case RADEON_PRIM_TYPE_3VRT_POINT_LIST: - case RADEON_PRIM_TYPE_3VRT_LINE_LIST: - case RADEON_PRIM_TYPE_RECT_LIST: - return nr % 3 || nr == 0; - case RADEON_PRIM_TYPE_TRI_FAN: - case RADEON_PRIM_TYPE_TRI_STRIP: - return nr < 3; - default: - return 1; - } -} - -typedef struct { - unsigned int start; - unsigned int finish; - unsigned int prim; - unsigned int numverts; - unsigned int offset; - unsigned int vc_format; -} drm_radeon_tcl_prim_t; - -static void radeon_cp_dispatch_vertex(struct drm_device * dev, - struct drm_file *file_priv, - struct drm_buf * buf, - drm_radeon_tcl_prim_t * prim) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - int offset = dev_priv->gart_buffers_offset + buf->offset + prim->start; - int numverts = (int)prim->numverts; - int nbox = sarea_priv->nbox; - int i = 0; - RING_LOCALS; - - DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d %d verts\n", - prim->prim, - prim->vc_format, prim->start, prim->finish, prim->numverts); - - if (bad_prim_vertex_nr(prim->prim, prim->numverts)) { - DRM_ERROR("bad prim %x numverts %d\n", - prim->prim, prim->numverts); - return; - } - - do { - /* Emit the next cliprect */ - if (i < nbox) { - radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); - } - - /* Emit the vertex buffer rendering commands */ - BEGIN_RING(5); - - OUT_RING(CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, 3)); - OUT_RING(offset); - OUT_RING(numverts); - OUT_RING(prim->vc_format); - OUT_RING(prim->prim | RADEON_PRIM_WALK_LIST | - RADEON_COLOR_ORDER_RGBA | - RADEON_VTX_FMT_RADEON_MODE | - (numverts << RADEON_NUM_VERTICES_SHIFT)); - - ADVANCE_RING(); - - i++; - } while (i < nbox); -} - -void radeon_cp_discard_buffer(struct drm_device *dev, struct drm_master *master, struct drm_buf *buf) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - drm_radeon_buf_priv_t *buf_priv = buf->dev_private; - RING_LOCALS; - - buf_priv->age = ++master_priv->sarea_priv->last_dispatch; - - /* Emit the vertex buffer age */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) { - BEGIN_RING(3); - R600_DISPATCH_AGE(buf_priv->age); - ADVANCE_RING(); - } else { - BEGIN_RING(2); - RADEON_DISPATCH_AGE(buf_priv->age); - ADVANCE_RING(); - } - - buf->pending = 1; - buf->used = 0; -} - -static void radeon_cp_dispatch_indirect(struct drm_device * dev, - struct drm_buf * buf, int start, int end) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - DRM_DEBUG("buf=%d s=0x%x e=0x%x\n", buf->idx, start, end); - - if (start != end) { - int offset = (dev_priv->gart_buffers_offset - + buf->offset + start); - int dwords = (end - start + 3) / sizeof(u32); - - /* Indirect buffer data must be an even number of - * dwords, so if we've been given an odd number we must - * pad the data with a Type-2 CP packet. - */ - if (dwords & 1) { - u32 *data = (u32 *) - ((char *)dev->agp_buffer_map->handle - + buf->offset + start); - data[dwords++] = RADEON_CP_PACKET2; - } - - /* Fire off the indirect buffer */ - BEGIN_RING(3); - - OUT_RING(CP_PACKET0(RADEON_CP_IB_BASE, 1)); - OUT_RING(offset); - OUT_RING(dwords); - - ADVANCE_RING(); - } -} - -static void radeon_cp_dispatch_indices(struct drm_device *dev, - struct drm_master *master, - struct drm_buf * elt_buf, - drm_radeon_tcl_prim_t * prim) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - int offset = dev_priv->gart_buffers_offset + prim->offset; - u32 *data; - int dwords; - int i = 0; - int start = prim->start + RADEON_INDEX_PRIM_OFFSET; - int count = (prim->finish - start) / sizeof(u16); - int nbox = sarea_priv->nbox; - - DRM_DEBUG("hwprim 0x%x vfmt 0x%x %d..%d offset: %x nr %d\n", - prim->prim, - prim->vc_format, - prim->start, prim->finish, prim->offset, prim->numverts); - - if (bad_prim_vertex_nr(prim->prim, count)) { - DRM_ERROR("bad prim %x count %d\n", prim->prim, count); - return; - } - - if (start >= prim->finish || (prim->start & 0x7)) { - DRM_ERROR("buffer prim %d\n", prim->prim); - return; - } - - dwords = (prim->finish - prim->start + 3) / sizeof(u32); - - data = (u32 *) ((char *)dev->agp_buffer_map->handle + - elt_buf->offset + prim->start); - - data[0] = CP_PACKET3(RADEON_3D_RNDR_GEN_INDX_PRIM, dwords - 2); - data[1] = offset; - data[2] = prim->numverts; - data[3] = prim->vc_format; - data[4] = (prim->prim | - RADEON_PRIM_WALK_IND | - RADEON_COLOR_ORDER_RGBA | - RADEON_VTX_FMT_RADEON_MODE | - (count << RADEON_NUM_VERTICES_SHIFT)); - - do { - if (i < nbox) - radeon_emit_clip_rect(dev_priv, &sarea_priv->boxes[i]); - - radeon_cp_dispatch_indirect(dev, elt_buf, - prim->start, prim->finish); - - i++; - } while (i < nbox); - -} - -#define RADEON_MAX_TEXTURE_SIZE RADEON_BUFFER_SIZE - -static int radeon_cp_dispatch_texture(struct drm_device * dev, - struct drm_file *file_priv, - drm_radeon_texture_t * tex, - drm_radeon_tex_image_t * image) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_buf *buf; - u32 format; - u32 *buffer; - const u8 __user *data; - unsigned int size, dwords, tex_width, blit_width, spitch; - u32 height; - int i; - u32 texpitch, microtile; - u32 offset, byte_offset; - RING_LOCALS; - - if (radeon_check_and_fixup_offset(dev_priv, file_priv, &tex->offset)) { - DRM_ERROR("Invalid destination offset\n"); - return -EINVAL; - } - - dev_priv->stats.boxes |= RADEON_BOX_TEXTURE_LOAD; - - /* Flush the pixel cache. This ensures no pixel data gets mixed - * up with the texture data from the host data blit, otherwise - * part of the texture image may be corrupted. - */ - BEGIN_RING(4); - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_IDLE(); - ADVANCE_RING(); - - /* The compiler won't optimize away a division by a variable, - * even if the only legal values are powers of two. Thus, we'll - * use a shift instead. - */ - switch (tex->format) { - case RADEON_TXFORMAT_ARGB8888: - case RADEON_TXFORMAT_RGBA8888: - format = RADEON_COLOR_FORMAT_ARGB8888; - tex_width = tex->width * 4; - blit_width = image->width * 4; - break; - case RADEON_TXFORMAT_AI88: - case RADEON_TXFORMAT_ARGB1555: - case RADEON_TXFORMAT_RGB565: - case RADEON_TXFORMAT_ARGB4444: - case RADEON_TXFORMAT_VYUY422: - case RADEON_TXFORMAT_YVYU422: - format = RADEON_COLOR_FORMAT_RGB565; - tex_width = tex->width * 2; - blit_width = image->width * 2; - break; - case RADEON_TXFORMAT_I8: - case RADEON_TXFORMAT_RGB332: - format = RADEON_COLOR_FORMAT_CI8; - tex_width = tex->width * 1; - blit_width = image->width * 1; - break; - default: - DRM_ERROR("invalid texture format %d\n", tex->format); - return -EINVAL; - } - spitch = blit_width >> 6; - if (spitch == 0 && image->height > 1) - return -EINVAL; - - texpitch = tex->pitch; - if ((texpitch << 22) & RADEON_DST_TILE_MICRO) { - microtile = 1; - if (tex_width < 64) { - texpitch &= ~(RADEON_DST_TILE_MICRO >> 22); - /* we got tiled coordinates, untile them */ - image->x *= 2; - } - } else - microtile = 0; - - /* this might fail for zero-sized uploads - are those illegal? */ - if (!radeon_check_offset(dev_priv, tex->offset + image->height * - blit_width - 1)) { - DRM_ERROR("Invalid final destination offset\n"); - return -EINVAL; - } - - DRM_DEBUG("tex=%dx%d blit=%d\n", tex_width, tex->height, blit_width); - - do { - DRM_DEBUG("tex: ofs=0x%x p=%d f=%d x=%hd y=%hd w=%hd h=%hd\n", - tex->offset >> 10, tex->pitch, tex->format, - image->x, image->y, image->width, image->height); - - /* Make a copy of some parameters in case we have to - * update them for a multi-pass texture blit. - */ - height = image->height; - data = (const u8 __user *)image->data; - - size = height * blit_width; - - if (size > RADEON_MAX_TEXTURE_SIZE) { - height = RADEON_MAX_TEXTURE_SIZE / blit_width; - size = height * blit_width; - } else if (size < 4 && size > 0) { - size = 4; - } else if (size == 0) { - return 0; - } - - buf = radeon_freelist_get(dev); - if (0 && !buf) { - radeon_do_cp_idle(dev_priv); - buf = radeon_freelist_get(dev); - } - if (!buf) { - DRM_DEBUG("EAGAIN\n"); - if (copy_to_user(tex->image, image, sizeof(*image))) - return -EFAULT; - return -EAGAIN; - } - - /* Dispatch the indirect buffer. - */ - buffer = - (u32 *) ((char *)dev->agp_buffer_map->handle + buf->offset); - dwords = size / 4; - -#define RADEON_COPY_MT(_buf, _data, _width) \ - do { \ - if (copy_from_user(_buf, _data, (_width))) {\ - DRM_ERROR("EFAULT on pad, %d bytes\n", (_width)); \ - return -EFAULT; \ - } \ - } while(0) - - if (microtile) { - /* texture micro tiling in use, minimum texture width is thus 16 bytes. - however, we cannot use blitter directly for texture width < 64 bytes, - since minimum tex pitch is 64 bytes and we need this to match - the texture width, otherwise the blitter will tile it wrong. - Thus, tiling manually in this case. Additionally, need to special - case tex height = 1, since our actual image will have height 2 - and we need to ensure we don't read beyond the texture size - from user space. */ - if (tex->height == 1) { - if (tex_width >= 64 || tex_width <= 16) { - RADEON_COPY_MT(buffer, data, - (int)(tex_width * sizeof(u32))); - } else if (tex_width == 32) { - RADEON_COPY_MT(buffer, data, 16); - RADEON_COPY_MT(buffer + 8, - data + 16, 16); - } - } else if (tex_width >= 64 || tex_width == 16) { - RADEON_COPY_MT(buffer, data, - (int)(dwords * sizeof(u32))); - } else if (tex_width < 16) { - for (i = 0; i < tex->height; i++) { - RADEON_COPY_MT(buffer, data, tex_width); - buffer += 4; - data += tex_width; - } - } else if (tex_width == 32) { - /* TODO: make sure this works when not fitting in one buffer - (i.e. 32bytes x 2048...) */ - for (i = 0; i < tex->height; i += 2) { - RADEON_COPY_MT(buffer, data, 16); - data += 16; - RADEON_COPY_MT(buffer + 8, data, 16); - data += 16; - RADEON_COPY_MT(buffer + 4, data, 16); - data += 16; - RADEON_COPY_MT(buffer + 12, data, 16); - data += 16; - buffer += 16; - } - } - } else { - if (tex_width >= 32) { - /* Texture image width is larger than the minimum, so we - * can upload it directly. - */ - RADEON_COPY_MT(buffer, data, - (int)(dwords * sizeof(u32))); - } else { - /* Texture image width is less than the minimum, so we - * need to pad out each image scanline to the minimum - * width. - */ - for (i = 0; i < tex->height; i++) { - RADEON_COPY_MT(buffer, data, tex_width); - buffer += 8; - data += tex_width; - } - } - } - -#undef RADEON_COPY_MT - byte_offset = (image->y & ~2047) * blit_width; - buf->file_priv = file_priv; - buf->used = size; - offset = dev_priv->gart_buffers_offset + buf->offset; - BEGIN_RING(9); - OUT_RING(CP_PACKET3(RADEON_CNTL_BITBLT_MULTI, 5)); - OUT_RING(RADEON_GMC_SRC_PITCH_OFFSET_CNTL | - RADEON_GMC_DST_PITCH_OFFSET_CNTL | - RADEON_GMC_BRUSH_NONE | - (format << 8) | - RADEON_GMC_SRC_DATATYPE_COLOR | - RADEON_ROP3_S | - RADEON_DP_SRC_SOURCE_MEMORY | - RADEON_GMC_CLR_CMP_CNTL_DIS | RADEON_GMC_WR_MSK_DIS); - OUT_RING((spitch << 22) | (offset >> 10)); - OUT_RING((texpitch << 22) | ((tex->offset >> 10) + (byte_offset >> 10))); - OUT_RING(0); - OUT_RING((image->x << 16) | (image->y % 2048)); - OUT_RING((image->width << 16) | height); - RADEON_WAIT_UNTIL_2D_IDLE(); - ADVANCE_RING(); - COMMIT_RING(); - - radeon_cp_discard_buffer(dev, file_priv->master, buf); - - /* Update the input parameters for next time */ - image->y += height; - image->height -= height; - image->data = (const u8 __user *)image->data + size; - } while (image->height > 0); - - /* Flush the pixel cache after the blit completes. This ensures - * the texture data is written out to memory before rendering - * continues. - */ - BEGIN_RING(4); - RADEON_FLUSH_CACHE(); - RADEON_WAIT_UNTIL_2D_IDLE(); - ADVANCE_RING(); - COMMIT_RING(); - - return 0; -} - -static void radeon_cp_dispatch_stipple(struct drm_device * dev, u32 * stipple) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - int i; - RING_LOCALS; - DRM_DEBUG("\n"); - - BEGIN_RING(35); - - OUT_RING(CP_PACKET0(RADEON_RE_STIPPLE_ADDR, 0)); - OUT_RING(0x00000000); - - OUT_RING(CP_PACKET0_TABLE(RADEON_RE_STIPPLE_DATA, 31)); - for (i = 0; i < 32; i++) { - OUT_RING(stipple[i]); - } - - ADVANCE_RING(); -} - -static void radeon_apply_surface_regs(int surf_index, - drm_radeon_private_t *dev_priv) -{ - if (!dev_priv->mmio) - return; - - radeon_do_cp_idle(dev_priv); - - RADEON_WRITE(RADEON_SURFACE0_INFO + 16 * surf_index, - dev_priv->surfaces[surf_index].flags); - RADEON_WRITE(RADEON_SURFACE0_LOWER_BOUND + 16 * surf_index, - dev_priv->surfaces[surf_index].lower); - RADEON_WRITE(RADEON_SURFACE0_UPPER_BOUND + 16 * surf_index, - dev_priv->surfaces[surf_index].upper); -} - -/* Allocates a virtual surface - * doesn't always allocate a real surface, will stretch an existing - * surface when possible. - * - * Note that refcount can be at most 2, since during a free refcount=3 - * might mean we have to allocate a new surface which might not always - * be available. - * For example : we allocate three contiguous surfaces ABC. If B is - * freed, we suddenly need two surfaces to store A and C, which might - * not always be available. - */ -static int alloc_surface(drm_radeon_surface_alloc_t *new, - drm_radeon_private_t *dev_priv, - struct drm_file *file_priv) -{ - struct radeon_virt_surface *s; - int i; - int virt_surface_index; - uint32_t new_upper, new_lower; - - new_lower = new->address; - new_upper = new_lower + new->size - 1; - - /* sanity check */ - if ((new_lower >= new_upper) || (new->flags == 0) || (new->size == 0) || - ((new_upper & RADEON_SURF_ADDRESS_FIXED_MASK) != - RADEON_SURF_ADDRESS_FIXED_MASK) - || ((new_lower & RADEON_SURF_ADDRESS_FIXED_MASK) != 0)) - return -1; - - /* make sure there is no overlap with existing surfaces */ - for (i = 0; i < RADEON_MAX_SURFACES; i++) { - if ((dev_priv->surfaces[i].refcount != 0) && - (((new_lower >= dev_priv->surfaces[i].lower) && - (new_lower < dev_priv->surfaces[i].upper)) || - ((new_lower < dev_priv->surfaces[i].lower) && - (new_upper > dev_priv->surfaces[i].lower)))) { - return -1; - } - } - - /* find a virtual surface */ - for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) - if (dev_priv->virt_surfaces[i].file_priv == NULL) - break; - if (i == 2 * RADEON_MAX_SURFACES) { - return -1; - } - virt_surface_index = i; - - /* try to reuse an existing surface */ - for (i = 0; i < RADEON_MAX_SURFACES; i++) { - /* extend before */ - if ((dev_priv->surfaces[i].refcount == 1) && - (new->flags == dev_priv->surfaces[i].flags) && - (new_upper + 1 == dev_priv->surfaces[i].lower)) { - s = &(dev_priv->virt_surfaces[virt_surface_index]); - s->surface_index = i; - s->lower = new_lower; - s->upper = new_upper; - s->flags = new->flags; - s->file_priv = file_priv; - dev_priv->surfaces[i].refcount++; - dev_priv->surfaces[i].lower = s->lower; - radeon_apply_surface_regs(s->surface_index, dev_priv); - return virt_surface_index; - } - - /* extend after */ - if ((dev_priv->surfaces[i].refcount == 1) && - (new->flags == dev_priv->surfaces[i].flags) && - (new_lower == dev_priv->surfaces[i].upper + 1)) { - s = &(dev_priv->virt_surfaces[virt_surface_index]); - s->surface_index = i; - s->lower = new_lower; - s->upper = new_upper; - s->flags = new->flags; - s->file_priv = file_priv; - dev_priv->surfaces[i].refcount++; - dev_priv->surfaces[i].upper = s->upper; - radeon_apply_surface_regs(s->surface_index, dev_priv); - return virt_surface_index; - } - } - - /* okay, we need a new one */ - for (i = 0; i < RADEON_MAX_SURFACES; i++) { - if (dev_priv->surfaces[i].refcount == 0) { - s = &(dev_priv->virt_surfaces[virt_surface_index]); - s->surface_index = i; - s->lower = new_lower; - s->upper = new_upper; - s->flags = new->flags; - s->file_priv = file_priv; - dev_priv->surfaces[i].refcount = 1; - dev_priv->surfaces[i].lower = s->lower; - dev_priv->surfaces[i].upper = s->upper; - dev_priv->surfaces[i].flags = s->flags; - radeon_apply_surface_regs(s->surface_index, dev_priv); - return virt_surface_index; - } - } - - /* we didn't find anything */ - return -1; -} - -static int free_surface(struct drm_file *file_priv, - drm_radeon_private_t * dev_priv, - int lower) -{ - struct radeon_virt_surface *s; - int i; - /* find the virtual surface */ - for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { - s = &(dev_priv->virt_surfaces[i]); - if (s->file_priv) { - if ((lower == s->lower) && (file_priv == s->file_priv)) - { - if (dev_priv->surfaces[s->surface_index]. - lower == s->lower) - dev_priv->surfaces[s->surface_index]. - lower = s->upper; - - if (dev_priv->surfaces[s->surface_index]. - upper == s->upper) - dev_priv->surfaces[s->surface_index]. - upper = s->lower; - - dev_priv->surfaces[s->surface_index].refcount--; - if (dev_priv->surfaces[s->surface_index]. - refcount == 0) - dev_priv->surfaces[s->surface_index]. - flags = 0; - s->file_priv = NULL; - radeon_apply_surface_regs(s->surface_index, - dev_priv); - return 0; - } - } - } - return 1; -} - -static void radeon_surfaces_release(struct drm_file *file_priv, - drm_radeon_private_t * dev_priv) -{ - int i; - for (i = 0; i < 2 * RADEON_MAX_SURFACES; i++) { - if (dev_priv->virt_surfaces[i].file_priv == file_priv) - free_surface(file_priv, dev_priv, - dev_priv->virt_surfaces[i].lower); - } -} - -/* ================================================================ - * IOCTL functions - */ -static int radeon_surface_alloc(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_alloc_t *alloc = data; - - if (alloc_surface(alloc, dev_priv, file_priv) == -1) - return -EINVAL; - else - return 0; -} - -static int radeon_surface_free(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_surface_free_t *memfree = data; - - if (free_surface(file_priv, dev_priv, memfree->address)) - return -EINVAL; - else - return 0; -} - -static int radeon_cp_clear(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - drm_radeon_clear_t *clear = data; - drm_radeon_clear_rect_t depth_boxes[RADEON_NR_SAREA_CLIPRECTS]; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - - if (copy_from_user(&depth_boxes, clear->depth_boxes, - sarea_priv->nbox * sizeof(depth_boxes[0]))) - return -EFAULT; - - radeon_cp_dispatch_clear(dev, file_priv->master, clear, depth_boxes); - - COMMIT_RING(); - return 0; -} - -/* Not sure why this isn't set all the time: - */ -static int radeon_do_init_pageflip(struct drm_device *dev, struct drm_master *master) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = master->driver_priv; - RING_LOCALS; - - DRM_DEBUG("\n"); - - BEGIN_RING(6); - RADEON_WAIT_UNTIL_3D_IDLE(); - OUT_RING(CP_PACKET0(RADEON_CRTC_OFFSET_CNTL, 0)); - OUT_RING(RADEON_READ(RADEON_CRTC_OFFSET_CNTL) | - RADEON_CRTC_OFFSET_FLIP_CNTL); - OUT_RING(CP_PACKET0(RADEON_CRTC2_OFFSET_CNTL, 0)); - OUT_RING(RADEON_READ(RADEON_CRTC2_OFFSET_CNTL) | - RADEON_CRTC_OFFSET_FLIP_CNTL); - ADVANCE_RING(); - - dev_priv->page_flipping = 1; - - if (master_priv->sarea_priv->pfCurrentPage != 1) - master_priv->sarea_priv->pfCurrentPage = 0; - - return 0; -} - -/* Swapping and flipping are different operations, need different ioctls. - * They can & should be intermixed to support multiple 3d windows. - */ -static int radeon_cp_flip(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - if (!dev_priv->page_flipping) - radeon_do_init_pageflip(dev, file_priv->master); - - radeon_cp_dispatch_flip(dev, file_priv->master); - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_swap(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv = master_priv->sarea_priv; - - DRM_DEBUG("\n"); - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) - sarea_priv->nbox = RADEON_NR_SAREA_CLIPRECTS; - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_cp_dispatch_swap(dev, file_priv); - else - radeon_cp_dispatch_swap(dev, file_priv->master); - sarea_priv->ctx_owner = 0; - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_vertex(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_radeon_vertex_t *vertex = data; - drm_radeon_tcl_prim_t prim; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - sarea_priv = master_priv->sarea_priv; - - DRM_DEBUG("pid=%d index=%d count=%d discard=%d\n", - DRM_CURRENTPID, vertex->idx, vertex->count, vertex->discard); - - if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - vertex->idx, dma->buf_count - 1); - return -EINVAL; - } - if (vertex->prim < 0 || vertex->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { - DRM_ERROR("buffer prim %d\n", vertex->prim); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf = dma->buflist[vertex->idx]; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; - } - - /* Build up a prim_t record: - */ - if (vertex->count) { - buf->used = vertex->count; /* not used? */ - - if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { - if (radeon_emit_state(dev_priv, file_priv, - &sarea_priv->context_state, - sarea_priv->tex_state, - sarea_priv->dirty)) { - DRM_ERROR("radeon_emit_state failed\n"); - return -EINVAL; - } - - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES | - RADEON_UPLOAD_TEX2IMAGES | - RADEON_REQUIRE_QUIESCENCE); - } - - prim.start = 0; - prim.finish = vertex->count; /* unused */ - prim.prim = vertex->prim; - prim.numverts = vertex->count; - prim.vc_format = sarea_priv->vc_format; - - radeon_cp_dispatch_vertex(dev, file_priv, buf, &prim); - } - - if (vertex->discard) { - radeon_cp_discard_buffer(dev, file_priv->master, buf); - } - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_indices(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_radeon_indices_t *elts = data; - drm_radeon_tcl_prim_t prim; - int count; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - sarea_priv = master_priv->sarea_priv; - - DRM_DEBUG("pid=%d index=%d start=%d end=%d discard=%d\n", - DRM_CURRENTPID, elts->idx, elts->start, elts->end, - elts->discard); - - if (elts->idx < 0 || elts->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - elts->idx, dma->buf_count - 1); - return -EINVAL; - } - if (elts->prim < 0 || elts->prim > RADEON_PRIM_TYPE_3VRT_LINE_LIST) { - DRM_ERROR("buffer prim %d\n", elts->prim); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf = dma->buflist[elts->idx]; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", elts->idx); - return -EINVAL; - } - - count = (elts->end - elts->start) / sizeof(u16); - elts->start -= RADEON_INDEX_PRIM_OFFSET; - - if (elts->start & 0x7) { - DRM_ERROR("misaligned buffer 0x%x\n", elts->start); - return -EINVAL; - } - if (elts->start < buf->used) { - DRM_ERROR("no header 0x%x - 0x%x\n", elts->start, buf->used); - return -EINVAL; - } - - buf->used = elts->end; - - if (sarea_priv->dirty & ~RADEON_UPLOAD_CLIPRECTS) { - if (radeon_emit_state(dev_priv, file_priv, - &sarea_priv->context_state, - sarea_priv->tex_state, - sarea_priv->dirty)) { - DRM_ERROR("radeon_emit_state failed\n"); - return -EINVAL; - } - - sarea_priv->dirty &= ~(RADEON_UPLOAD_TEX0IMAGES | - RADEON_UPLOAD_TEX1IMAGES | - RADEON_UPLOAD_TEX2IMAGES | - RADEON_REQUIRE_QUIESCENCE); - } - - /* Build up a prim_t record: - */ - prim.start = elts->start; - prim.finish = elts->end; - prim.prim = elts->prim; - prim.offset = 0; /* offset from start of dma buffers */ - prim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - prim.vc_format = sarea_priv->vc_format; - - radeon_cp_dispatch_indices(dev, file_priv->master, buf, &prim); - if (elts->discard) { - radeon_cp_discard_buffer(dev, file_priv->master, buf); - } - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_texture(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_texture_t *tex = data; - drm_radeon_tex_image_t image; - int ret; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (tex->image == NULL) { - DRM_ERROR("null texture image!\n"); - return -EINVAL; - } - - if (copy_from_user(&image, - (drm_radeon_tex_image_t __user *) tex->image, - sizeof(image))) - return -EFAULT; - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - ret = r600_cp_dispatch_texture(dev, file_priv, tex, &image); - else - ret = radeon_cp_dispatch_texture(dev, file_priv, tex, &image); - - return ret; -} - -static int radeon_cp_stipple(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_stipple_t *stipple = data; - u32 mask[32]; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - if (copy_from_user(&mask, stipple->mask, 32 * sizeof(u32))) - return -EFAULT; - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - - radeon_cp_dispatch_stipple(dev, mask); - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_indirect(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_radeon_indirect_t *indirect = data; - RING_LOCALS; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - DRM_DEBUG("idx=%d s=%d e=%d d=%d\n", - indirect->idx, indirect->start, indirect->end, - indirect->discard); - - if (indirect->idx < 0 || indirect->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - indirect->idx, dma->buf_count - 1); - return -EINVAL; - } - - buf = dma->buflist[indirect->idx]; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; - } - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", indirect->idx); - return -EINVAL; - } - - if (indirect->start < buf->used) { - DRM_ERROR("reusing indirect: start=0x%x actual=0x%x\n", - indirect->start, buf->used); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf->used = indirect->end; - - /* Dispatch the indirect buffer full of commands from the - * X server. This is insecure and is thus only available to - * privileged clients. - */ - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - r600_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); - else { - /* Wait for the 3D stream to idle before the indirect buffer - * containing 2D acceleration commands is processed. - */ - BEGIN_RING(2); - RADEON_WAIT_UNTIL_3D_IDLE(); - ADVANCE_RING(); - radeon_cp_dispatch_indirect(dev, buf, indirect->start, indirect->end); - } - - if (indirect->discard) { - radeon_cp_discard_buffer(dev, file_priv->master, buf); - } - - COMMIT_RING(); - return 0; -} - -static int radeon_cp_vertex2(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_sarea_t *sarea_priv; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf; - drm_radeon_vertex2_t *vertex = data; - int i; - unsigned char laststate; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - sarea_priv = master_priv->sarea_priv; - - DRM_DEBUG("pid=%d index=%d discard=%d\n", - DRM_CURRENTPID, vertex->idx, vertex->discard); - - if (vertex->idx < 0 || vertex->idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - vertex->idx, dma->buf_count - 1); - return -EINVAL; - } - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - buf = dma->buflist[vertex->idx]; - - if (buf->file_priv != file_priv) { - DRM_ERROR("process %d using buffer owned by %p\n", - DRM_CURRENTPID, buf->file_priv); - return -EINVAL; - } - - if (buf->pending) { - DRM_ERROR("sending pending buffer %d\n", vertex->idx); - return -EINVAL; - } - - if (sarea_priv->nbox > RADEON_NR_SAREA_CLIPRECTS) - return -EINVAL; - - for (laststate = 0xff, i = 0; i < vertex->nr_prims; i++) { - drm_radeon_prim_t prim; - drm_radeon_tcl_prim_t tclprim; - - if (copy_from_user(&prim, &vertex->prim[i], sizeof(prim))) - return -EFAULT; - - if (prim.stateidx != laststate) { - drm_radeon_state_t state; - - if (copy_from_user(&state, - &vertex->state[prim.stateidx], - sizeof(state))) - return -EFAULT; - - if (radeon_emit_state2(dev_priv, file_priv, &state)) { - DRM_ERROR("radeon_emit_state2 failed\n"); - return -EINVAL; - } - - laststate = prim.stateidx; - } - - tclprim.start = prim.start; - tclprim.finish = prim.finish; - tclprim.prim = prim.prim; - tclprim.vc_format = prim.vc_format; - - if (prim.prim & RADEON_PRIM_WALK_IND) { - tclprim.offset = prim.numverts * 64; - tclprim.numverts = RADEON_MAX_VB_VERTS; /* duh */ - - radeon_cp_dispatch_indices(dev, file_priv->master, buf, &tclprim); - } else { - tclprim.numverts = prim.numverts; - tclprim.offset = 0; /* not used */ - - radeon_cp_dispatch_vertex(dev, file_priv, buf, &tclprim); - } - - if (sarea_priv->nbox == 1) - sarea_priv->nbox = 0; - } - - if (vertex->discard) { - radeon_cp_discard_buffer(dev, file_priv->master, buf); - } - - COMMIT_RING(); - return 0; -} - -static int radeon_emit_packets(drm_radeon_private_t * dev_priv, - struct drm_file *file_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int id = (int)header.packet.packet_id; - int sz, reg; - RING_LOCALS; - - if (id >= RADEON_MAX_STATE_PACKETS) - return -EINVAL; - - sz = packet[id].len; - reg = packet[id].start; - - if (sz * sizeof(u32) > drm_buffer_unprocessed(cmdbuf->buffer)) { - DRM_ERROR("Packet size provided larger than data provided\n"); - return -EINVAL; - } - - if (radeon_check_and_fixup_packets(dev_priv, file_priv, id, - cmdbuf->buffer)) { - DRM_ERROR("Packet verification failed\n"); - return -EINVAL; - } - - BEGIN_RING(sz + 1); - OUT_RING(CP_PACKET0(reg, (sz - 1))); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - - return 0; -} - -static __inline__ int radeon_emit_scalars(drm_radeon_private_t *dev_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int sz = header.scalars.count; - int start = header.scalars.offset; - int stride = header.scalars.stride; - RING_LOCALS; - - BEGIN_RING(3 + sz); - OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); - OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); - OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - return 0; -} - -/* God this is ugly - */ -static __inline__ int radeon_emit_scalars2(drm_radeon_private_t *dev_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int sz = header.scalars.count; - int start = ((unsigned int)header.scalars.offset) + 0x100; - int stride = header.scalars.stride; - RING_LOCALS; - - BEGIN_RING(3 + sz); - OUT_RING(CP_PACKET0(RADEON_SE_TCL_SCALAR_INDX_REG, 0)); - OUT_RING(start | (stride << RADEON_SCAL_INDX_DWORD_STRIDE_SHIFT)); - OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_SCALAR_DATA_REG, sz - 1)); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - return 0; -} - -static __inline__ int radeon_emit_vectors(drm_radeon_private_t *dev_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int sz = header.vectors.count; - int start = header.vectors.offset; - int stride = header.vectors.stride; - RING_LOCALS; - - BEGIN_RING(5 + sz); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); - OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); - OUT_RING(start | (stride << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); - OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - - return 0; -} - -static __inline__ int radeon_emit_veclinear(drm_radeon_private_t *dev_priv, - drm_radeon_cmd_header_t header, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - int sz = header.veclinear.count * 4; - int start = header.veclinear.addr_lo | (header.veclinear.addr_hi << 8); - RING_LOCALS; - - if (!sz) - return 0; - if (sz * 4 > drm_buffer_unprocessed(cmdbuf->buffer)) - return -EINVAL; - - BEGIN_RING(5 + sz); - OUT_RING_REG(RADEON_SE_TCL_STATE_FLUSH, 0); - OUT_RING(CP_PACKET0(RADEON_SE_TCL_VECTOR_INDX_REG, 0)); - OUT_RING(start | (1 << RADEON_VEC_INDX_OCTWORD_STRIDE_SHIFT)); - OUT_RING(CP_PACKET0_TABLE(RADEON_SE_TCL_VECTOR_DATA_REG, (sz - 1))); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, sz); - ADVANCE_RING(); - - return 0; -} - -static int radeon_emit_packet3(struct drm_device * dev, - struct drm_file *file_priv, - drm_radeon_kcmd_buffer_t *cmdbuf) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - unsigned int cmdsz; - int ret; - RING_LOCALS; - - DRM_DEBUG("\n"); - - if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, - cmdbuf, &cmdsz))) { - DRM_ERROR("Packet verification failed\n"); - return ret; - } - - BEGIN_RING(cmdsz); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz); - ADVANCE_RING(); - - return 0; -} - -static int radeon_emit_packet3_cliprect(struct drm_device *dev, - struct drm_file *file_priv, - drm_radeon_kcmd_buffer_t *cmdbuf, - int orig_nbox) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_clip_rect box; - unsigned int cmdsz; - int ret; - struct drm_clip_rect __user *boxes = cmdbuf->boxes; - int i = 0; - RING_LOCALS; - - DRM_DEBUG("\n"); - - if ((ret = radeon_check_and_fixup_packet3(dev_priv, file_priv, - cmdbuf, &cmdsz))) { - DRM_ERROR("Packet verification failed\n"); - return ret; - } - - if (!orig_nbox) - goto out; - - do { - if (i < cmdbuf->nbox) { - if (copy_from_user(&box, &boxes[i], sizeof(box))) - return -EFAULT; - /* FIXME The second and subsequent times round - * this loop, send a WAIT_UNTIL_3D_IDLE before - * calling emit_clip_rect(). This fixes a - * lockup on fast machines when sending - * several cliprects with a cmdbuf, as when - * waving a 2D window over a 3D - * window. Something in the commands from user - * space seems to hang the card when they're - * sent several times in a row. That would be - * the correct place to fix it but this works - * around it until I can figure that out - Tim - * Smith */ - if (i) { - BEGIN_RING(2); - RADEON_WAIT_UNTIL_3D_IDLE(); - ADVANCE_RING(); - } - radeon_emit_clip_rect(dev_priv, &box); - } - - BEGIN_RING(cmdsz); - OUT_RING_DRM_BUFFER(cmdbuf->buffer, cmdsz); - ADVANCE_RING(); - - } while (++i < cmdbuf->nbox); - if (cmdbuf->nbox == 1) - cmdbuf->nbox = 0; - - return 0; - out: - drm_buffer_advance(cmdbuf->buffer, cmdsz * 4); - return 0; -} - -static int radeon_emit_wait(struct drm_device * dev, int flags) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - RING_LOCALS; - - DRM_DEBUG("%x\n", flags); - switch (flags) { - case RADEON_WAIT_2D: - BEGIN_RING(2); - RADEON_WAIT_UNTIL_2D_IDLE(); - ADVANCE_RING(); - break; - case RADEON_WAIT_3D: - BEGIN_RING(2); - RADEON_WAIT_UNTIL_3D_IDLE(); - ADVANCE_RING(); - break; - case RADEON_WAIT_2D | RADEON_WAIT_3D: - BEGIN_RING(2); - RADEON_WAIT_UNTIL_IDLE(); - ADVANCE_RING(); - break; - default: - return -EINVAL; - } - - return 0; -} - -static int radeon_cp_cmdbuf(struct drm_device *dev, void *data, - struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_device_dma *dma = dev->dma; - struct drm_buf *buf = NULL; - drm_radeon_cmd_header_t stack_header; - int idx; - drm_radeon_kcmd_buffer_t *cmdbuf = data; - int orig_nbox; - - LOCK_TEST_WITH_RETURN(dev, file_priv); - - RING_SPACE_TEST_WITH_RETURN(dev_priv); - VB_AGE_TEST_WITH_RETURN(dev_priv); - - if (cmdbuf->bufsz > 64 * 1024 || cmdbuf->bufsz < 0) { - return -EINVAL; - } - - /* Allocate an in-kernel area and copy in the cmdbuf. Do this to avoid - * races between checking values and using those values in other code, - * and simply to avoid a lot of function calls to copy in data. - */ - if (cmdbuf->bufsz != 0) { - int rv; - void __user *buffer = cmdbuf->buffer; - rv = drm_buffer_alloc(&cmdbuf->buffer, cmdbuf->bufsz); - if (rv) - return rv; - rv = drm_buffer_copy_from_user(cmdbuf->buffer, buffer, - cmdbuf->bufsz); - if (rv) { - drm_buffer_free(cmdbuf->buffer); - return rv; - } - } else - goto done; - - orig_nbox = cmdbuf->nbox; - - if (dev_priv->microcode_version == UCODE_R300) { - int temp; - temp = r300_do_cp_cmdbuf(dev, file_priv, cmdbuf); - - drm_buffer_free(cmdbuf->buffer); - - return temp; - } - - /* microcode_version != r300 */ - while (drm_buffer_unprocessed(cmdbuf->buffer) >= sizeof(stack_header)) { - - drm_radeon_cmd_header_t *header; - header = drm_buffer_read_object(cmdbuf->buffer, - sizeof(stack_header), &stack_header); - - switch (header->header.cmd_type) { - case RADEON_CMD_PACKET: - DRM_DEBUG("RADEON_CMD_PACKET\n"); - if (radeon_emit_packets - (dev_priv, file_priv, *header, cmdbuf)) { - DRM_ERROR("radeon_emit_packets failed\n"); - goto err; - } - break; - - case RADEON_CMD_SCALARS: - DRM_DEBUG("RADEON_CMD_SCALARS\n"); - if (radeon_emit_scalars(dev_priv, *header, cmdbuf)) { - DRM_ERROR("radeon_emit_scalars failed\n"); - goto err; - } - break; - - case RADEON_CMD_VECTORS: - DRM_DEBUG("RADEON_CMD_VECTORS\n"); - if (radeon_emit_vectors(dev_priv, *header, cmdbuf)) { - DRM_ERROR("radeon_emit_vectors failed\n"); - goto err; - } - break; - - case RADEON_CMD_DMA_DISCARD: - DRM_DEBUG("RADEON_CMD_DMA_DISCARD\n"); - idx = header->dma.buf_idx; - if (idx < 0 || idx >= dma->buf_count) { - DRM_ERROR("buffer index %d (of %d max)\n", - idx, dma->buf_count - 1); - goto err; - } - - buf = dma->buflist[idx]; - if (buf->file_priv != file_priv || buf->pending) { - DRM_ERROR("bad buffer %p %p %d\n", - buf->file_priv, file_priv, - buf->pending); - goto err; - } - - radeon_cp_discard_buffer(dev, file_priv->master, buf); - break; - - case RADEON_CMD_PACKET3: - DRM_DEBUG("RADEON_CMD_PACKET3\n"); - if (radeon_emit_packet3(dev, file_priv, cmdbuf)) { - DRM_ERROR("radeon_emit_packet3 failed\n"); - goto err; - } - break; - - case RADEON_CMD_PACKET3_CLIP: - DRM_DEBUG("RADEON_CMD_PACKET3_CLIP\n"); - if (radeon_emit_packet3_cliprect - (dev, file_priv, cmdbuf, orig_nbox)) { - DRM_ERROR("radeon_emit_packet3_clip failed\n"); - goto err; - } - break; - - case RADEON_CMD_SCALARS2: - DRM_DEBUG("RADEON_CMD_SCALARS2\n"); - if (radeon_emit_scalars2(dev_priv, *header, cmdbuf)) { - DRM_ERROR("radeon_emit_scalars2 failed\n"); - goto err; - } - break; - - case RADEON_CMD_WAIT: - DRM_DEBUG("RADEON_CMD_WAIT\n"); - if (radeon_emit_wait(dev, header->wait.flags)) { - DRM_ERROR("radeon_emit_wait failed\n"); - goto err; - } - break; - case RADEON_CMD_VECLINEAR: - DRM_DEBUG("RADEON_CMD_VECLINEAR\n"); - if (radeon_emit_veclinear(dev_priv, *header, cmdbuf)) { - DRM_ERROR("radeon_emit_veclinear failed\n"); - goto err; - } - break; - - default: - DRM_ERROR("bad cmd_type %d at byte %d\n", - header->header.cmd_type, - cmdbuf->buffer->iterator); - goto err; - } - } - - drm_buffer_free(cmdbuf->buffer); - - done: - DRM_DEBUG("DONE\n"); - COMMIT_RING(); - return 0; - - err: - drm_buffer_free(cmdbuf->buffer); - return -EINVAL; -} - -static int radeon_cp_getparam(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - drm_radeon_getparam_t *param = data; - int value; - - DRM_DEBUG("pid=%d\n", DRM_CURRENTPID); - - switch (param->param) { - case RADEON_PARAM_GART_BUFFER_OFFSET: - value = dev_priv->gart_buffers_offset; - break; - case RADEON_PARAM_LAST_FRAME: - dev_priv->stats.last_frame_reads++; - value = GET_SCRATCH(dev_priv, 0); - break; - case RADEON_PARAM_LAST_DISPATCH: - value = GET_SCRATCH(dev_priv, 1); - break; - case RADEON_PARAM_LAST_CLEAR: - dev_priv->stats.last_clear_reads++; - value = GET_SCRATCH(dev_priv, 2); - break; - case RADEON_PARAM_IRQ_NR: - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - value = 0; - else - value = dev->pdev->irq; - break; - case RADEON_PARAM_GART_BASE: - value = dev_priv->gart_vm_start; - break; - case RADEON_PARAM_REGISTER_HANDLE: - value = dev_priv->mmio->offset; - break; - case RADEON_PARAM_STATUS_HANDLE: - value = dev_priv->ring_rptr_offset; - break; -#if BITS_PER_LONG == 32 - /* - * This ioctl() doesn't work on 64-bit platforms because hw_lock is a - * pointer which can't fit into an int-sized variable. According to - * Michel Dänzer, the ioctl() is only used on embedded platforms, so - * not supporting it shouldn't be a problem. If the same functionality - * is needed on 64-bit platforms, a new ioctl() would have to be added, - * so backwards-compatibility for the embedded platforms can be - * maintained. --davidm 4-Feb-2004. - */ - case RADEON_PARAM_SAREA_HANDLE: - /* The lock is the first dword in the sarea. */ - /* no users of this parameter */ - break; -#endif - case RADEON_PARAM_GART_TEX_HANDLE: - value = dev_priv->gart_textures_offset; - break; - case RADEON_PARAM_SCRATCH_OFFSET: - if (!dev_priv->writeback_works) - return -EINVAL; - if ((dev_priv->flags & RADEON_FAMILY_MASK) >= CHIP_R600) - value = R600_SCRATCH_REG_OFFSET; - else - value = RADEON_SCRATCH_REG_OFFSET; - break; - case RADEON_PARAM_CARD_TYPE: - if (dev_priv->flags & RADEON_IS_PCIE) - value = RADEON_CARD_PCIE; - else if (dev_priv->flags & RADEON_IS_AGP) - value = RADEON_CARD_AGP; - else - value = RADEON_CARD_PCI; - break; - case RADEON_PARAM_VBLANK_CRTC: - value = radeon_vblank_crtc_get(dev); - break; - case RADEON_PARAM_FB_LOCATION: - value = radeon_read_fb_location(dev_priv); - break; - case RADEON_PARAM_NUM_GB_PIPES: - value = dev_priv->num_gb_pipes; - break; - case RADEON_PARAM_NUM_Z_PIPES: - value = dev_priv->num_z_pipes; - break; - default: - DRM_DEBUG("Invalid parameter %d\n", param->param); - return -EINVAL; - } - - if (copy_to_user(param->value, &value, sizeof(int))) { - DRM_ERROR("copy_to_user\n"); - return -EFAULT; - } - - return 0; -} - -static int radeon_cp_setparam(struct drm_device *dev, void *data, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_master_private *master_priv = file_priv->master->driver_priv; - drm_radeon_setparam_t *sp = data; - struct drm_radeon_driver_file_fields *radeon_priv; - - switch (sp->param) { - case RADEON_SETPARAM_FB_LOCATION: - radeon_priv = file_priv->driver_priv; - radeon_priv->radeon_fb_delta = dev_priv->fb_location - - sp->value; - break; - case RADEON_SETPARAM_SWITCH_TILING: - if (sp->value == 0) { - DRM_DEBUG("color tiling disabled\n"); - dev_priv->front_pitch_offset &= ~RADEON_DST_TILE_MACRO; - dev_priv->back_pitch_offset &= ~RADEON_DST_TILE_MACRO; - if (master_priv->sarea_priv) - master_priv->sarea_priv->tiling_enabled = 0; - } else if (sp->value == 1) { - DRM_DEBUG("color tiling enabled\n"); - dev_priv->front_pitch_offset |= RADEON_DST_TILE_MACRO; - dev_priv->back_pitch_offset |= RADEON_DST_TILE_MACRO; - if (master_priv->sarea_priv) - master_priv->sarea_priv->tiling_enabled = 1; - } - break; - case RADEON_SETPARAM_PCIGART_LOCATION: - dev_priv->pcigart_offset = sp->value; - dev_priv->pcigart_offset_set = 1; - break; - case RADEON_SETPARAM_NEW_MEMMAP: - dev_priv->new_memmap = sp->value; - break; - case RADEON_SETPARAM_PCIGART_TABLE_SIZE: - dev_priv->gart_info.table_size = sp->value; - if (dev_priv->gart_info.table_size < RADEON_PCIGART_TABLE_SIZE) - dev_priv->gart_info.table_size = RADEON_PCIGART_TABLE_SIZE; - break; - case RADEON_SETPARAM_VBLANK_CRTC: - return radeon_vblank_crtc_set(dev, sp->value); - break; - default: - DRM_DEBUG("Invalid parameter %d\n", sp->param); - return -EINVAL; - } - - return 0; -} - -/* When a client dies: - * - Check for and clean up flipped page state - * - Free any alloced GART memory. - * - Free any alloced radeon surfaces. - * - * DRM infrastructure takes care of reclaiming dma buffers. - */ -void radeon_driver_preclose(struct drm_device *dev, struct drm_file *file_priv) -{ - if (dev->dev_private) { - drm_radeon_private_t *dev_priv = dev->dev_private; - dev_priv->page_flipping = 0; - radeon_mem_release(file_priv, dev_priv->gart_heap); - radeon_mem_release(file_priv, dev_priv->fb_heap); - radeon_surfaces_release(file_priv, dev_priv); - } -} - -void radeon_driver_lastclose(struct drm_device *dev) -{ - radeon_surfaces_release(PCIGART_FILE_PRIV, dev->dev_private); - radeon_do_release(dev); -} - -int radeon_driver_open(struct drm_device *dev, struct drm_file *file_priv) -{ - drm_radeon_private_t *dev_priv = dev->dev_private; - struct drm_radeon_driver_file_fields *radeon_priv; - - DRM_DEBUG("\n"); - radeon_priv = kmalloc(sizeof(*radeon_priv), GFP_KERNEL); - - if (!radeon_priv) - return -ENOMEM; - - file_priv->driver_priv = radeon_priv; - - if (dev_priv) - radeon_priv->radeon_fb_delta = dev_priv->fb_location; - else - radeon_priv->radeon_fb_delta = 0; - return 0; -} - -void radeon_driver_postclose(struct drm_device *dev, struct drm_file *file_priv) -{ - struct drm_radeon_driver_file_fields *radeon_priv = - file_priv->driver_priv; - - kfree(radeon_priv); -} - -struct drm_ioctl_desc radeon_ioctls[] = { - DRM_IOCTL_DEF_DRV(RADEON_CP_INIT, radeon_cp_init, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_CP_START, radeon_cp_start, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_CP_STOP, radeon_cp_stop, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_CP_RESET, radeon_cp_reset, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_CP_IDLE, radeon_cp_idle, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_CP_RESUME, radeon_cp_resume, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_RESET, radeon_engine_reset, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_FULLSCREEN, radeon_fullscreen, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_SWAP, radeon_cp_swap, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_CLEAR, radeon_cp_clear, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_VERTEX, radeon_cp_vertex, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_INDICES, radeon_cp_indices, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_TEXTURE, radeon_cp_texture, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_STIPPLE, radeon_cp_stipple, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_INDIRECT, radeon_cp_indirect, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_VERTEX2, radeon_cp_vertex2, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_CMDBUF, radeon_cp_cmdbuf, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_GETPARAM, radeon_cp_getparam, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_FLIP, radeon_cp_flip, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_ALLOC, radeon_mem_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_FREE, radeon_mem_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_INIT_HEAP, radeon_mem_init_heap, DRM_AUTH|DRM_MASTER|DRM_ROOT_ONLY), - DRM_IOCTL_DEF_DRV(RADEON_IRQ_EMIT, radeon_irq_emit, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_IRQ_WAIT, radeon_irq_wait, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_SETPARAM, radeon_cp_setparam, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_SURF_ALLOC, radeon_surface_alloc, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_SURF_FREE, radeon_surface_free, DRM_AUTH), - DRM_IOCTL_DEF_DRV(RADEON_CS, r600_cs_legacy_ioctl, DRM_AUTH) -}; - -int radeon_max_ioctl = ARRAY_SIZE(radeon_ioctls); diff --git a/drivers/gpu/drm/radeon/radeon_vm.c b/drivers/gpu/drm/radeon/radeon_vm.c index 48d97c040f49..3979632b9225 100644 --- a/drivers/gpu/drm/radeon/radeon_vm.c +++ b/drivers/gpu/drm/radeon/radeon_vm.c @@ -455,15 +455,15 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, if (soffset) { /* make sure object fit at this offset */ - eoffset = soffset + size; + eoffset = soffset + size - 1; if (soffset >= eoffset) { r = -EINVAL; goto error_unreserve; } last_pfn = eoffset / RADEON_GPU_PAGE_SIZE; - if (last_pfn > rdev->vm_manager.max_pfn) { - dev_err(rdev->dev, "va above limit (0x%08X > 0x%08X)\n", + if (last_pfn >= rdev->vm_manager.max_pfn) { + dev_err(rdev->dev, "va above limit (0x%08X >= 0x%08X)\n", last_pfn, rdev->vm_manager.max_pfn); r = -EINVAL; goto error_unreserve; @@ -478,7 +478,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, eoffset /= RADEON_GPU_PAGE_SIZE; if (soffset || eoffset) { struct interval_tree_node *it; - it = interval_tree_iter_first(&vm->va, soffset, eoffset - 1); + it = interval_tree_iter_first(&vm->va, soffset, eoffset); if (it && it != &bo_va->it) { struct radeon_bo_va *tmp; tmp = container_of(it, struct radeon_bo_va, it); @@ -518,7 +518,7 @@ int radeon_vm_bo_set_addr(struct radeon_device *rdev, if (soffset || eoffset) { spin_lock(&vm->status_lock); bo_va->it.start = soffset; - bo_va->it.last = eoffset - 1; + bo_va->it.last = eoffset; list_add(&bo_va->vm_status, &vm->cleared); spin_unlock(&vm->status_lock); interval_tree_insert(&bo_va->it, &vm->va); @@ -888,7 +888,7 @@ static void radeon_vm_fence_pts(struct radeon_vm *vm, unsigned i; start >>= radeon_vm_block_size; - end >>= radeon_vm_block_size; + end = (end - 1) >> radeon_vm_block_size; for (i = start; i <= end; ++i) radeon_bo_fence(vm->page_tables[i].bo, fence, true); diff --git a/drivers/gpu/drm/radeon/sid.h b/drivers/gpu/drm/radeon/sid.h index 4c4a7218a3bd..d1a7b58dd291 100644 --- a/drivers/gpu/drm/radeon/sid.h +++ b/drivers/gpu/drm/radeon/sid.h @@ -915,6 +915,11 @@ #define DCCG_AUDIO_DTO1_PHASE 0x05c0 #define DCCG_AUDIO_DTO1_MODULE 0x05c4 +#define DENTIST_DISPCLK_CNTL 0x0490 +# define DENTIST_DPREFCLK_WDIVIDER(x) (((x) & 0x7f) << 24) +# define DENTIST_DPREFCLK_WDIVIDER_MASK (0x7f << 24) +# define DENTIST_DPREFCLK_WDIVIDER_SHIFT 24 + #define AFMT_AUDIO_SRC_CONTROL 0x713c #define AFMT_AUDIO_SRC_SELECT(x) (((x) & 7) << 0) /* AFMT_AUDIO_SRC_SELECT |