drm/amd/dc: Add dc display driver (v2)
Supported DCE versions: 8.0, 10.0, 11.0, 11.2 v2: rebase against 4.11 Signed-off-by: Harry Wentland <harry.wentland@amd.com> Acked-by: Alex Deucher <alexander.deucher@amd.com> Signed-off-by: Alex Deucher <alexander.deucher@amd.com>
This commit is contained in:
parent
9c5b2b0d40
commit
4562236b3b
|
@ -41,3 +41,4 @@ config DRM_AMDGPU_GART_DEBUGFS
|
|||
pages. Uses more memory for housekeeping, enable only for debugging.
|
||||
|
||||
source "drivers/gpu/drm/amd/acp/Kconfig"
|
||||
source "drivers/gpu/drm/amd/display/Kconfig"
|
||||
|
|
|
@ -3,13 +3,19 @@
|
|||
# Direct Rendering Infrastructure (DRI) in XFree86 4.1.0 and higher.
|
||||
|
||||
FULL_AMD_PATH=$(src)/..
|
||||
DISPLAY_FOLDER_NAME=display
|
||||
FULL_AMD_DISPLAY_PATH = $(FULL_AMD_PATH)/$(DISPLAY_FOLDER_NAME)
|
||||
|
||||
ccflags-y := -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 \
|
||||
-I$(FULL_AMD_PATH)/acp/include
|
||||
-I$(FULL_AMD_PATH)/acp/include \
|
||||
-I$(FULL_AMD_DISPLAY_PATH) \
|
||||
-I$(FULL_AMD_DISPLAY_PATH)/include \
|
||||
-I$(FULL_AMD_DISPLAY_PATH)/dc \
|
||||
-I$(FULL_AMD_DISPLAY_PATH)/amdgpu_dm
|
||||
|
||||
amdgpu-y := amdgpu_drv.o
|
||||
|
||||
|
@ -132,4 +138,13 @@ include $(FULL_AMD_PATH)/powerplay/Makefile
|
|||
|
||||
amdgpu-y += $(AMD_POWERPLAY_FILES)
|
||||
|
||||
ifneq ($(CONFIG_DRM_AMD_DC),)
|
||||
|
||||
RELATIVE_AMD_DISPLAY_PATH = ../$(DISPLAY_FOLDER_NAME)
|
||||
include $(FULL_AMD_DISPLAY_PATH)/Makefile
|
||||
|
||||
amdgpu-y += $(AMD_DISPLAY_FILES)
|
||||
|
||||
endif
|
||||
|
||||
obj-$(CONFIG_DRM_AMDGPU)+= amdgpu.o
|
||||
|
|
|
@ -66,6 +66,7 @@
|
|||
#include "amdgpu_vce.h"
|
||||
#include "amdgpu_vcn.h"
|
||||
#include "amdgpu_mn.h"
|
||||
#include "amdgpu_dm.h"
|
||||
|
||||
#include "gpu_scheduler.h"
|
||||
#include "amdgpu_virt.h"
|
||||
|
@ -101,6 +102,7 @@ extern int amdgpu_vm_fragment_size;
|
|||
extern int amdgpu_vm_fault_stop;
|
||||
extern int amdgpu_vm_debug;
|
||||
extern int amdgpu_vm_update_mode;
|
||||
extern int amdgpu_dc;
|
||||
extern int amdgpu_sched_jobs;
|
||||
extern int amdgpu_sched_hw_submission;
|
||||
extern int amdgpu_no_evict;
|
||||
|
@ -1507,6 +1509,7 @@ struct amdgpu_device {
|
|||
/* display */
|
||||
bool enable_virtual_display;
|
||||
struct amdgpu_mode_info mode_info;
|
||||
/* For pre-DCE11. DCE11 and later are in "struct amdgpu_device->dm" */
|
||||
struct work_struct hotplug_work;
|
||||
struct amdgpu_irq_src crtc_irq;
|
||||
struct amdgpu_irq_src pageflip_irq;
|
||||
|
@ -1563,6 +1566,9 @@ struct amdgpu_device {
|
|||
/* GDS */
|
||||
struct amdgpu_gds gds;
|
||||
|
||||
/* display related functionality */
|
||||
struct amdgpu_display_manager dm;
|
||||
|
||||
struct amdgpu_ip_block ip_blocks[AMDGPU_MAX_IP_NUM];
|
||||
int num_ip_blocks;
|
||||
struct mutex mn_lock;
|
||||
|
@ -1624,6 +1630,9 @@ void amdgpu_mm_wdoorbell(struct amdgpu_device *adev, u32 index, u32 v);
|
|||
u64 amdgpu_mm_rdoorbell64(struct amdgpu_device *adev, u32 index);
|
||||
void amdgpu_mm_wdoorbell64(struct amdgpu_device *adev, u32 index, u64 v);
|
||||
|
||||
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type);
|
||||
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev);
|
||||
|
||||
/*
|
||||
* Registers read & write functions.
|
||||
*/
|
||||
|
@ -1884,5 +1893,11 @@ int amdgpu_cs_find_mapping(struct amdgpu_cs_parser *parser,
|
|||
uint64_t addr, struct amdgpu_bo **bo,
|
||||
struct amdgpu_bo_va_mapping **mapping);
|
||||
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
int amdgpu_dm_display_resume(struct amdgpu_device *adev );
|
||||
#else
|
||||
static inline int amdgpu_dm_display_resume(struct amdgpu_device *adev) { return 0; }
|
||||
#endif
|
||||
|
||||
#include "amdgpu_object.h"
|
||||
#endif
|
||||
|
|
|
@ -31,6 +31,7 @@
|
|||
#include <linux/debugfs.h>
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <linux/vgaarb.h>
|
||||
#include <linux/vga_switcheroo.h>
|
||||
|
@ -1973,6 +1974,41 @@ static void amdgpu_device_detect_sriov_bios(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
bool amdgpu_device_asic_has_dc_support(enum amd_asic_type asic_type)
|
||||
{
|
||||
switch (asic_type) {
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
case CHIP_BONAIRE:
|
||||
case CHIP_HAWAII:
|
||||
case CHIP_CARRIZO:
|
||||
case CHIP_STONEY:
|
||||
case CHIP_POLARIS11:
|
||||
case CHIP_POLARIS10:
|
||||
case CHIP_TONGA:
|
||||
case CHIP_FIJI:
|
||||
#if defined(CONFIG_DRM_AMD_DC_PRE_VEGA)
|
||||
return amdgpu_dc != 0;
|
||||
#else
|
||||
return amdgpu_dc > 0;
|
||||
#endif
|
||||
#endif
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_has_dc_support - check if dc is supported
|
||||
*
|
||||
* @adev: amdgpu_device_pointer
|
||||
*
|
||||
* Returns true for supported, false for not supported
|
||||
*/
|
||||
bool amdgpu_device_has_dc_support(struct amdgpu_device *adev)
|
||||
{
|
||||
return amdgpu_device_asic_has_dc_support(adev->asic_type);
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_device_init - initialize the driver
|
||||
*
|
||||
|
@ -2168,7 +2204,8 @@ int amdgpu_device_init(struct amdgpu_device *adev,
|
|||
goto failed;
|
||||
}
|
||||
/* init i2c buses */
|
||||
amdgpu_atombios_i2c_init(adev);
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_atombios_i2c_init(adev);
|
||||
}
|
||||
|
||||
/* Fence driver */
|
||||
|
@ -2296,7 +2333,8 @@ void amdgpu_device_fini(struct amdgpu_device *adev)
|
|||
adev->accel_working = false;
|
||||
cancel_delayed_work_sync(&adev->late_init_work);
|
||||
/* free i2c buses */
|
||||
amdgpu_i2c_fini(adev);
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_i2c_fini(adev);
|
||||
amdgpu_atombios_fini(adev);
|
||||
kfree(adev->bios);
|
||||
adev->bios = NULL;
|
||||
|
@ -2346,12 +2384,14 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
|
|||
|
||||
drm_kms_helper_poll_disable(dev);
|
||||
|
||||
/* turn off display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
/* turn off display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_OFF);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
amdgpu_amdkfd_suspend(adev);
|
||||
|
||||
|
@ -2494,13 +2534,25 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
|||
|
||||
/* blat the mode back in */
|
||||
if (fbcon) {
|
||||
drm_helper_resume_force_mode(dev);
|
||||
/* turn on display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
/* pre DCE11 */
|
||||
drm_helper_resume_force_mode(dev);
|
||||
|
||||
/* turn on display hw */
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
drm_helper_connector_dpms(connector, DRM_MODE_DPMS_ON);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
} else {
|
||||
/*
|
||||
* There is no equivalent atomic helper to turn on
|
||||
* display, so we defined our own function for this,
|
||||
* once suspend resume is supported by the atomic
|
||||
* framework this will be reworked
|
||||
*/
|
||||
amdgpu_dm_display_resume(adev);
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
}
|
||||
|
||||
drm_kms_helper_poll_enable(dev);
|
||||
|
@ -2517,7 +2569,10 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
|
|||
#ifdef CONFIG_PM
|
||||
dev->dev->power.disable_depth++;
|
||||
#endif
|
||||
drm_helper_hpd_irq_event(dev);
|
||||
if (!amdgpu_device_has_dc_support(adev))
|
||||
drm_helper_hpd_irq_event(dev);
|
||||
else
|
||||
drm_kms_helper_hotplug_event(dev);
|
||||
#ifdef CONFIG_PM
|
||||
dev->dev->power.disable_depth--;
|
||||
#endif
|
||||
|
@ -2814,6 +2869,7 @@ give_up_reset:
|
|||
*/
|
||||
int amdgpu_gpu_reset(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_atomic_state *state = NULL;
|
||||
int i, r;
|
||||
int resched;
|
||||
bool need_full_reset, vram_lost = false;
|
||||
|
@ -2827,6 +2883,9 @@ int amdgpu_gpu_reset(struct amdgpu_device *adev)
|
|||
|
||||
/* block TTM */
|
||||
resched = ttm_bo_lock_delayed_workqueue(&adev->mman.bdev);
|
||||
/* store modesetting */
|
||||
if (amdgpu_device_has_dc_support(adev))
|
||||
state = drm_atomic_helper_suspend(adev->ddev);
|
||||
|
||||
/* block scheduler */
|
||||
for (i = 0; i < AMDGPU_MAX_RINGS; ++i) {
|
||||
|
@ -2944,7 +3003,11 @@ out:
|
|||
}
|
||||
}
|
||||
|
||||
drm_helper_resume_force_mode(adev->ddev);
|
||||
if (amdgpu_device_has_dc_support(adev)) {
|
||||
r = drm_atomic_helper_resume(adev->ddev, state);
|
||||
amdgpu_dm_display_resume(adev);
|
||||
} else
|
||||
drm_helper_resume_force_mode(adev->ddev);
|
||||
|
||||
ttm_bo_unlock_delayed_workqueue(&adev->mman.bdev, resched);
|
||||
if (r) {
|
||||
|
|
|
@ -429,7 +429,7 @@ struct amdgpu_pm {
|
|||
uint32_t fw_version;
|
||||
uint32_t pcie_gen_mask;
|
||||
uint32_t pcie_mlw_mask;
|
||||
struct amd_pp_display_configuration pm_display_cfg;/* set by DAL */
|
||||
struct amd_pp_display_configuration pm_display_cfg;/* set by dc */
|
||||
};
|
||||
|
||||
#define R600_SSTU_DFLT 0
|
||||
|
|
|
@ -103,6 +103,7 @@ int amdgpu_vm_debug = 0;
|
|||
int amdgpu_vram_page_split = 512;
|
||||
int amdgpu_vm_update_mode = -1;
|
||||
int amdgpu_exp_hw_support = 0;
|
||||
int amdgpu_dc = -1;
|
||||
int amdgpu_sched_jobs = 32;
|
||||
int amdgpu_sched_hw_submission = 2;
|
||||
int amdgpu_no_evict = 0;
|
||||
|
@ -207,6 +208,9 @@ module_param_named(vram_page_split, amdgpu_vram_page_split, int, 0444);
|
|||
MODULE_PARM_DESC(exp_hw_support, "experimental hw support (1 = enable, 0 = disable (default))");
|
||||
module_param_named(exp_hw_support, amdgpu_exp_hw_support, int, 0444);
|
||||
|
||||
MODULE_PARM_DESC(dc, "Display Core driver (1 = enable, 0 = disable, -1 = auto (default))");
|
||||
module_param_named(dc, amdgpu_dc, int, 0444);
|
||||
|
||||
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);
|
||||
|
||||
|
|
|
@ -42,11 +42,6 @@
|
|||
this contains a helper + a amdgpu fb
|
||||
the helper contains a pointer to amdgpu framebuffer baseclass.
|
||||
*/
|
||||
struct amdgpu_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct amdgpu_framebuffer rfb;
|
||||
struct amdgpu_device *adev;
|
||||
};
|
||||
|
||||
static int
|
||||
amdgpufb_open(struct fb_info *info, int user)
|
||||
|
|
|
@ -37,6 +37,10 @@
|
|||
|
||||
#include <linux/pm_runtime.h>
|
||||
|
||||
#ifdef CONFIG_DRM_AMD_DC
|
||||
#include "amdgpu_dm_irq.h"
|
||||
#endif
|
||||
|
||||
#define AMDGPU_WAIT_IDLE_TIMEOUT 200
|
||||
|
||||
/*
|
||||
|
@ -221,15 +225,6 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
|
||||
spin_lock_init(&adev->irq.lock);
|
||||
|
||||
if (!adev->enable_virtual_display)
|
||||
/* Disable vblank irqs aggressively for power-saving */
|
||||
adev->ddev->vblank_disable_immediate = true;
|
||||
|
||||
r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
|
||||
if (r) {
|
||||
return r;
|
||||
}
|
||||
|
||||
/* enable msi */
|
||||
adev->irq.msi_enabled = false;
|
||||
|
||||
|
@ -241,7 +236,21 @@ int amdgpu_irq_init(struct amdgpu_device *adev)
|
|||
}
|
||||
}
|
||||
|
||||
INIT_WORK(&adev->hotplug_work, amdgpu_hotplug_work_func);
|
||||
if (!amdgpu_device_has_dc_support(adev)) {
|
||||
if (!adev->enable_virtual_display)
|
||||
/* Disable vblank irqs aggressively for power-saving */
|
||||
/* XXX: can this be enabled for DC? */
|
||||
adev->ddev->vblank_disable_immediate = true;
|
||||
|
||||
r = drm_vblank_init(adev->ddev, adev->mode_info.num_crtc);
|
||||
if (r)
|
||||
return r;
|
||||
|
||||
/* pre DCE11 */
|
||||
INIT_WORK(&adev->hotplug_work,
|
||||
amdgpu_hotplug_work_func);
|
||||
}
|
||||
|
||||
INIT_WORK(&adev->reset_work, amdgpu_irq_reset_work_func);
|
||||
|
||||
adev->irq.installed = true;
|
||||
|
|
|
@ -1034,7 +1034,7 @@ const struct drm_ioctl_desc amdgpu_ioctls_kms[] = {
|
|||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_METADATA, amdgpu_gem_metadata_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_VA, amdgpu_gem_va_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_OP, amdgpu_gem_op_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW),
|
||||
DRM_IOCTL_DEF_DRV(AMDGPU_GEM_USERPTR, amdgpu_gem_userptr_ioctl, DRM_AUTH|DRM_RENDER_ALLOW)
|
||||
};
|
||||
const int amdgpu_max_kms_ioctl = ARRAY_SIZE(amdgpu_ioctls_kms);
|
||||
|
||||
|
|
|
@ -38,11 +38,15 @@
|
|||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <drm/drm_plane_helper.h>
|
||||
#include <drm/drm_fb_helper.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-algo-bit.h>
|
||||
#include <linux/hrtimer.h>
|
||||
#include "amdgpu_irq.h"
|
||||
|
||||
#include <drm/drm_dp_mst_helper.h>
|
||||
#include "modules/inc/mod_freesync.h"
|
||||
|
||||
struct amdgpu_bo;
|
||||
struct amdgpu_device;
|
||||
struct amdgpu_encoder;
|
||||
|
@ -292,6 +296,27 @@ struct amdgpu_display_funcs {
|
|||
uint16_t connector_object_id,
|
||||
struct amdgpu_hpd *hpd,
|
||||
struct amdgpu_router *router);
|
||||
/* it is used to enter or exit into free sync mode */
|
||||
int (*notify_freesync)(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp);
|
||||
/* it is used to allow enablement of freesync mode */
|
||||
int (*set_freesync_property)(struct drm_connector *connector,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
|
||||
};
|
||||
|
||||
struct amdgpu_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
struct drm_gem_object *obj;
|
||||
};
|
||||
|
||||
struct amdgpu_fbdev {
|
||||
struct drm_fb_helper helper;
|
||||
struct amdgpu_framebuffer rfb;
|
||||
struct list_head fbdev_list;
|
||||
struct amdgpu_device *adev;
|
||||
};
|
||||
|
||||
struct amdgpu_mode_info {
|
||||
|
@ -400,6 +425,11 @@ struct amdgpu_crtc {
|
|||
/* for virtual dce */
|
||||
struct hrtimer vblank_timer;
|
||||
enum amdgpu_interrupt_state vsync_timer_enabled;
|
||||
|
||||
int otg_inst;
|
||||
uint32_t flip_flags;
|
||||
/* After Set Mode target will be non-NULL */
|
||||
struct dc_target *target;
|
||||
};
|
||||
|
||||
struct amdgpu_encoder_atom_dig {
|
||||
|
@ -489,6 +519,19 @@ enum amdgpu_connector_dither {
|
|||
AMDGPU_FMT_DITHER_ENABLE = 1,
|
||||
};
|
||||
|
||||
struct amdgpu_dm_dp_aux {
|
||||
struct drm_dp_aux aux;
|
||||
uint32_t link_index;
|
||||
};
|
||||
|
||||
struct amdgpu_i2c_adapter {
|
||||
struct i2c_adapter base;
|
||||
struct amdgpu_display_manager *dm;
|
||||
uint32_t link_index;
|
||||
};
|
||||
|
||||
#define TO_DM_AUX(x) container_of((x), struct amdgpu_dm_dp_aux, aux)
|
||||
|
||||
struct amdgpu_connector {
|
||||
struct drm_connector base;
|
||||
uint32_t connector_id;
|
||||
|
@ -500,6 +543,14 @@ struct amdgpu_connector {
|
|||
/* we need to mind the EDID between detect
|
||||
and get modes due to analog/digital/tvencoder */
|
||||
struct edid *edid;
|
||||
/* number of modes generated from EDID at 'dc_sink' */
|
||||
int num_modes;
|
||||
/* The 'old' sink - before an HPD.
|
||||
* The 'current' sink is in dc_link->sink. */
|
||||
const struct dc_sink *dc_sink;
|
||||
const struct dc_link *dc_link;
|
||||
const struct dc_sink *dc_em_sink;
|
||||
const struct dc_target *target;
|
||||
void *con_priv;
|
||||
bool dac_load_detect;
|
||||
bool detected_by_load; /* if the connection status was determined by load */
|
||||
|
@ -510,11 +561,39 @@ struct amdgpu_connector {
|
|||
enum amdgpu_connector_audio audio;
|
||||
enum amdgpu_connector_dither dither;
|
||||
unsigned pixelclock_for_modeset;
|
||||
|
||||
struct drm_dp_mst_topology_mgr mst_mgr;
|
||||
struct amdgpu_dm_dp_aux dm_dp_aux;
|
||||
struct drm_dp_mst_port *port;
|
||||
struct amdgpu_connector *mst_port;
|
||||
struct amdgpu_encoder *mst_encoder;
|
||||
struct semaphore mst_sem;
|
||||
|
||||
/* TODO see if we can merge with ddc_bus or make a dm_connector */
|
||||
struct amdgpu_i2c_adapter *i2c;
|
||||
|
||||
/* Monitor range limits */
|
||||
int min_vfreq ;
|
||||
int max_vfreq ;
|
||||
int pixel_clock_mhz;
|
||||
|
||||
/*freesync caps*/
|
||||
struct mod_freesync_caps caps;
|
||||
|
||||
struct mutex hpd_lock;
|
||||
|
||||
};
|
||||
|
||||
struct amdgpu_framebuffer {
|
||||
struct drm_framebuffer base;
|
||||
struct drm_gem_object *obj;
|
||||
/* TODO: start to use this struct and remove same field from base one */
|
||||
struct amdgpu_mst_connector {
|
||||
struct amdgpu_connector base;
|
||||
|
||||
struct drm_dp_mst_topology_mgr mst_mgr;
|
||||
struct amdgpu_dm_dp_aux dm_dp_aux;
|
||||
struct drm_dp_mst_port *port;
|
||||
struct amdgpu_connector *mst_port;
|
||||
bool is_mst_connector;
|
||||
struct amdgpu_encoder *mst_encoder;
|
||||
};
|
||||
|
||||
#define ENCODER_MODE_IS_DP(em) (((em) == ATOM_ENCODER_MODE_DP) || \
|
||||
|
|
|
@ -1467,7 +1467,7 @@ void amdgpu_pm_compute_clocks(struct amdgpu_device *adev)
|
|||
list_for_each_entry(crtc,
|
||||
&ddev->mode_config.crtc_list, head) {
|
||||
amdgpu_crtc = to_amdgpu_crtc(crtc);
|
||||
if (crtc->enabled) {
|
||||
if (amdgpu_crtc->enabled) {
|
||||
adev->pm.dpm.new_active_crtcs |= (1 << amdgpu_crtc->crtc_id);
|
||||
adev->pm.dpm.new_active_crtc_count++;
|
||||
}
|
||||
|
|
|
@ -65,6 +65,7 @@
|
|||
#include "oss/oss_2_0_d.h"
|
||||
#include "oss/oss_2_0_sh_mask.h"
|
||||
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_amdkfd.h"
|
||||
#include "amdgpu_powerplay.h"
|
||||
#include "dce_virtual.h"
|
||||
|
@ -1900,6 +1901,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v8_2_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v7_2_ip_block);
|
||||
|
@ -1914,6 +1919,10 @@ int cik_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v8_5_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v7_3_ip_block);
|
||||
|
|
|
@ -77,6 +77,7 @@
|
|||
#endif
|
||||
#include "dce_virtual.h"
|
||||
#include "mxgpu_vi.h"
|
||||
#include "amdgpu_dm.h"
|
||||
|
||||
/*
|
||||
* Indirect registers accessor
|
||||
|
@ -1496,6 +1497,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v10_1_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
|
||||
|
@ -1512,6 +1517,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display || amdgpu_sriov_vf(adev))
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v10_0_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
|
||||
|
@ -1530,6 +1539,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v11_2_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
|
||||
|
@ -1544,6 +1557,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v8_0_ip_block);
|
||||
|
@ -1561,6 +1578,10 @@ int vi_set_ip_blocks(struct amdgpu_device *adev)
|
|||
amdgpu_ip_block_add(adev, &amdgpu_pp_ip_block);
|
||||
if (adev->enable_virtual_display)
|
||||
amdgpu_ip_block_add(adev, &dce_virtual_ip_block);
|
||||
#if defined(CONFIG_DRM_AMD_DC)
|
||||
else if (amdgpu_device_has_dc_support(adev))
|
||||
amdgpu_ip_block_add(adev, &dm_ip_block);
|
||||
#endif
|
||||
else
|
||||
amdgpu_ip_block_add(adev, &dce_v11_0_ip_block);
|
||||
amdgpu_ip_block_add(adev, &gfx_v8_1_ip_block);
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
menu "Display Engine Configuration"
|
||||
depends on DRM && DRM_AMDGPU
|
||||
|
||||
config DRM_AMD_DC
|
||||
bool "AMD DC - Enable new display engine"
|
||||
default y
|
||||
help
|
||||
Choose this option if you want to use the new display engine
|
||||
support for AMDGPU. This adds required support for Vega and
|
||||
Raven ASICs.
|
||||
|
||||
config DRM_AMD_DC_PRE_VEGA
|
||||
bool "DC support for Polaris and older ASICs"
|
||||
default n
|
||||
help
|
||||
Choose this option to enable the new DC support for older asics
|
||||
by default. This includes Polaris, Carrizo, Tonga, Bonaire,
|
||||
and Hawaii.
|
||||
|
||||
config DEBUG_KERNEL_DC
|
||||
bool "Enable kgdb break in DC"
|
||||
depends on DRM_AMD_DC
|
||||
help
|
||||
Choose this option
|
||||
if you want to hit
|
||||
kdgb_break in assert.
|
||||
|
||||
endmenu
|
|
@ -0,0 +1,22 @@
|
|||
#
|
||||
# Makefile for the DAL (Display Abstract Layer), which is a sub-component
|
||||
# of the AMDGPU drm driver.
|
||||
# It provides the HW control for display related functionalities.
|
||||
|
||||
AMDDALPATH = $(RELATIVE_AMD_DISPLAY_PATH)
|
||||
|
||||
subdir-ccflags-y += -I$(AMDDALPATH)/ -I$(AMDDALPATH)/include
|
||||
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc/inc/hw
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/inc
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/modules/freesync
|
||||
|
||||
#TODO: remove when Timing Sync feature is complete
|
||||
subdir-ccflags-y += -DBUILD_FEATURE_TIMING_SYNC=0
|
||||
|
||||
DAL_LIBS = amdgpu_dm dc modules/freesync
|
||||
|
||||
AMD_DAL = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/,$(DAL_LIBS)))
|
||||
|
||||
include $(AMD_DAL)
|
|
@ -0,0 +1,17 @@
|
|||
#
|
||||
# Makefile for the 'dm' sub-component of DAL.
|
||||
# It provides the control and status of dm blocks.
|
||||
|
||||
|
||||
|
||||
AMDGPUDM = amdgpu_dm_types.o amdgpu_dm.o amdgpu_dm_irq.o amdgpu_dm_mst_types.o
|
||||
|
||||
ifneq ($(CONFIG_DRM_AMD_DC),)
|
||||
AMDGPUDM += amdgpu_dm_services.o amdgpu_dm_helpers.o
|
||||
endif
|
||||
|
||||
subdir-ccflags-y += -I$(FULL_AMD_DISPLAY_PATH)/dc
|
||||
|
||||
AMDGPU_DM = $(addprefix $(AMDDALPATH)/amdgpu_dm/,$(AMDGPUDM))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMDGPU_DM)
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,171 @@
|
|||
/*
|
||||
* 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_DM_H__
|
||||
#define __AMDGPU_DM_H__
|
||||
|
||||
/*
|
||||
#include "linux/switch.h"
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file contains the definition for amdgpu_display_manager
|
||||
* and its API for amdgpu driver's use.
|
||||
* This component provides all the display related functionality
|
||||
* and this is the only component that calls DAL API.
|
||||
* The API contained here intended for amdgpu driver use.
|
||||
* The API that is called directly from KMS framework is located
|
||||
* in amdgpu_dm_kms.h file
|
||||
*/
|
||||
|
||||
#define AMDGPU_DM_MAX_DISPLAY_INDEX 31
|
||||
/*
|
||||
#include "include/amdgpu_dal_power_if.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
*/
|
||||
|
||||
#include "irq_types.h"
|
||||
#include "signal_types.h"
|
||||
|
||||
/* Forward declarations */
|
||||
struct amdgpu_device;
|
||||
struct drm_device;
|
||||
struct amdgpu_dm_irq_handler_data;
|
||||
|
||||
struct amdgpu_dm_prev_state {
|
||||
struct drm_framebuffer *fb;
|
||||
int32_t x;
|
||||
int32_t y;
|
||||
struct drm_display_mode mode;
|
||||
};
|
||||
|
||||
struct common_irq_params {
|
||||
struct amdgpu_device *adev;
|
||||
enum dc_irq_source irq_src;
|
||||
};
|
||||
|
||||
struct irq_list_head {
|
||||
struct list_head head;
|
||||
/* In case this interrupt needs post-processing, 'work' will be queued*/
|
||||
struct work_struct work;
|
||||
};
|
||||
|
||||
struct amdgpu_display_manager {
|
||||
struct dal *dal;
|
||||
struct dc *dc;
|
||||
struct cgs_device *cgs_device;
|
||||
/* lock to be used when DAL is called from SYNC IRQ context */
|
||||
spinlock_t dal_lock;
|
||||
|
||||
struct amdgpu_device *adev; /*AMD base driver*/
|
||||
struct drm_device *ddev; /*DRM base driver*/
|
||||
u16 display_indexes_num;
|
||||
|
||||
struct amdgpu_dm_prev_state prev_state;
|
||||
|
||||
/*
|
||||
* 'irq_source_handler_table' holds a list of handlers
|
||||
* per (DAL) IRQ source.
|
||||
*
|
||||
* Each IRQ source may need to be handled at different contexts.
|
||||
* By 'context' we mean, for example:
|
||||
* - The ISR context, which is the direct interrupt handler.
|
||||
* - The 'deferred' context - this is the post-processing of the
|
||||
* interrupt, but at a lower priority.
|
||||
*
|
||||
* Note that handlers are called in the same order as they were
|
||||
* registered (FIFO).
|
||||
*/
|
||||
struct irq_list_head irq_handler_list_low_tab[DAL_IRQ_SOURCES_NUMBER];
|
||||
struct list_head irq_handler_list_high_tab[DAL_IRQ_SOURCES_NUMBER];
|
||||
|
||||
struct common_irq_params
|
||||
pflip_params[DC_IRQ_SOURCE_PFLIP_LAST - DC_IRQ_SOURCE_PFLIP_FIRST + 1];
|
||||
|
||||
struct common_irq_params
|
||||
vupdate_params[DC_IRQ_SOURCE_VUPDATE6 - DC_IRQ_SOURCE_VUPDATE1 + 1];
|
||||
|
||||
/* this spin lock synchronizes access to 'irq_handler_list_table' */
|
||||
spinlock_t irq_handler_list_table_lock;
|
||||
|
||||
/* Timer-related data. */
|
||||
struct list_head timer_handler_list;
|
||||
struct workqueue_struct *timer_workqueue;
|
||||
|
||||
/* Use dal_mutex for any activity which is NOT syncronized by
|
||||
* DRM mode setting locks.
|
||||
* For example: amdgpu_dm_hpd_low_irq() calls into DAL *without*
|
||||
* DRM mode setting locks being acquired. This is where dal_mutex
|
||||
* is acquired before calling into DAL. */
|
||||
struct mutex dal_mutex;
|
||||
|
||||
struct backlight_device *backlight_dev;
|
||||
|
||||
const struct dc_link *backlight_link;
|
||||
|
||||
struct work_struct mst_hotplug_work;
|
||||
|
||||
struct mod_freesync *freesync_module;
|
||||
};
|
||||
|
||||
/* basic init/fini API */
|
||||
int amdgpu_dm_init(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_dm_fini(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_dm_destroy(void);
|
||||
|
||||
/* initializes drm_device display related structures, based on the information
|
||||
* provided by DAL. The drm strcutures are: drm_crtc, drm_connector,
|
||||
* drm_encoder, drm_mode_config
|
||||
*
|
||||
* Returns 0 on success
|
||||
*/
|
||||
int amdgpu_dm_initialize_drm_device(
|
||||
struct amdgpu_device *adev);
|
||||
|
||||
/* removes and deallocates the drm structures, created by the above function */
|
||||
void amdgpu_dm_destroy_drm_device(
|
||||
struct amdgpu_display_manager *dm);
|
||||
|
||||
/* Locking/Mutex */
|
||||
bool amdgpu_dm_acquire_dal_lock(struct amdgpu_display_manager *dm);
|
||||
|
||||
bool amdgpu_dm_release_dal_lock(struct amdgpu_display_manager *dm);
|
||||
|
||||
/* Register "Backlight device" accessible by user-mode. */
|
||||
void amdgpu_dm_register_backlight_device(struct amdgpu_display_manager *dm);
|
||||
|
||||
extern const struct amdgpu_ip_block_version dm_ip_block;
|
||||
|
||||
void amdgpu_dm_update_connector_after_detect(
|
||||
struct amdgpu_connector *aconnector);
|
||||
|
||||
struct amdgpu_connector *amdgpu_dm_find_first_crct_matching_connector(
|
||||
struct drm_atomic_state *state,
|
||||
struct drm_crtc *crtc,
|
||||
bool from_state_var);
|
||||
|
||||
#endif /* __AMDGPU_DM_H__ */
|
|
@ -0,0 +1,484 @@
|
|||
/*
|
||||
* 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 <linux/string.h>
|
||||
#include <linux/acpi.h>
|
||||
#include <linux/version.h>
|
||||
#include <linux/i2c.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include <drm/drm_edid.h>
|
||||
|
||||
#include "dm_services.h"
|
||||
#include "amdgpu.h"
|
||||
#include "dc.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
#include "amdgpu_dm_types.h"
|
||||
|
||||
#include "dm_helpers.h"
|
||||
|
||||
/* dm_helpers_parse_edid_caps
|
||||
*
|
||||
* Parse edid caps
|
||||
*
|
||||
* @edid: [in] pointer to edid
|
||||
* edid_caps: [in] pointer to edid caps
|
||||
* @return
|
||||
* void
|
||||
* */
|
||||
enum dc_edid_status dm_helpers_parse_edid_caps(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_edid *edid,
|
||||
struct dc_edid_caps *edid_caps)
|
||||
{
|
||||
struct edid *edid_buf = (struct edid *) edid->raw_edid;
|
||||
struct cea_sad *sads;
|
||||
int sad_count = -1;
|
||||
int sadb_count = -1;
|
||||
int i = 0;
|
||||
int j = 0;
|
||||
uint8_t *sadb = NULL;
|
||||
|
||||
enum dc_edid_status result = EDID_OK;
|
||||
|
||||
if (!edid_caps || !edid)
|
||||
return EDID_BAD_INPUT;
|
||||
|
||||
if (!drm_edid_is_valid(edid_buf))
|
||||
result = EDID_BAD_CHECKSUM;
|
||||
|
||||
edid_caps->manufacturer_id = (uint16_t) edid_buf->mfg_id[0] |
|
||||
((uint16_t) edid_buf->mfg_id[1])<<8;
|
||||
edid_caps->product_id = (uint16_t) edid_buf->prod_code[0] |
|
||||
((uint16_t) edid_buf->prod_code[1])<<8;
|
||||
edid_caps->serial_number = edid_buf->serial;
|
||||
edid_caps->manufacture_week = edid_buf->mfg_week;
|
||||
edid_caps->manufacture_year = edid_buf->mfg_year;
|
||||
|
||||
/* One of the four detailed_timings stores the monitor name. It's
|
||||
* stored in an array of length 13. */
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (edid_buf->detailed_timings[i].data.other_data.type == 0xfc) {
|
||||
while (j < 13 && edid_buf->detailed_timings[i].data.other_data.data.str.str[j]) {
|
||||
if (edid_buf->detailed_timings[i].data.other_data.data.str.str[j] == '\n')
|
||||
break;
|
||||
|
||||
edid_caps->display_name[j] =
|
||||
edid_buf->detailed_timings[i].data.other_data.data.str.str[j];
|
||||
j++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
edid_caps->edid_hdmi = drm_detect_hdmi_monitor(
|
||||
(struct edid *) edid->raw_edid);
|
||||
|
||||
sad_count = drm_edid_to_sad((struct edid *) edid->raw_edid, &sads);
|
||||
if (sad_count <= 0) {
|
||||
DRM_INFO("SADs count is: %d, don't need to read it\n",
|
||||
sad_count);
|
||||
return result;
|
||||
}
|
||||
|
||||
edid_caps->audio_mode_count = sad_count < DC_MAX_AUDIO_DESC_COUNT ? sad_count : DC_MAX_AUDIO_DESC_COUNT;
|
||||
for (i = 0; i < edid_caps->audio_mode_count; ++i) {
|
||||
struct cea_sad *sad = &sads[i];
|
||||
|
||||
edid_caps->audio_modes[i].format_code = sad->format;
|
||||
edid_caps->audio_modes[i].channel_count = sad->channels;
|
||||
edid_caps->audio_modes[i].sample_rate = sad->freq;
|
||||
edid_caps->audio_modes[i].sample_size = sad->byte2;
|
||||
}
|
||||
|
||||
sadb_count = drm_edid_to_speaker_allocation((struct edid *) edid->raw_edid, &sadb);
|
||||
|
||||
if (sadb_count < 0) {
|
||||
DRM_ERROR("Couldn't read Speaker Allocation Data Block: %d\n", sadb_count);
|
||||
sadb_count = 0;
|
||||
}
|
||||
|
||||
if (sadb_count)
|
||||
edid_caps->speaker_flags = sadb[0];
|
||||
else
|
||||
edid_caps->speaker_flags = DEFAULT_SPEAKER_LOCATION;
|
||||
|
||||
kfree(sads);
|
||||
kfree(sadb);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static struct amdgpu_connector *get_connector_for_sink(
|
||||
struct drm_device *dev,
|
||||
const struct dc_sink *sink)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
|
||||
if (aconnector->dc_sink == sink)
|
||||
return aconnector;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct amdgpu_connector *get_connector_for_link(
|
||||
struct drm_device *dev,
|
||||
const struct dc_link *link)
|
||||
{
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
|
||||
if (aconnector->dc_link == link)
|
||||
return aconnector;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void get_payload_table(
|
||||
struct amdgpu_connector *aconnector,
|
||||
struct dp_mst_stream_allocation_table *proposed_table)
|
||||
{
|
||||
int i;
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr =
|
||||
&aconnector->mst_port->mst_mgr;
|
||||
|
||||
mutex_lock(&mst_mgr->payload_lock);
|
||||
|
||||
proposed_table->stream_count = 0;
|
||||
|
||||
/* number of active streams */
|
||||
for (i = 0; i < mst_mgr->max_payloads; i++) {
|
||||
if (mst_mgr->payloads[i].num_slots == 0)
|
||||
break; /* end of vcp_id table */
|
||||
|
||||
ASSERT(mst_mgr->payloads[i].payload_state !=
|
||||
DP_PAYLOAD_DELETE_LOCAL);
|
||||
|
||||
if (mst_mgr->payloads[i].payload_state == DP_PAYLOAD_LOCAL ||
|
||||
mst_mgr->payloads[i].payload_state ==
|
||||
DP_PAYLOAD_REMOTE) {
|
||||
|
||||
struct dp_mst_stream_allocation *sa =
|
||||
&proposed_table->stream_allocations[
|
||||
proposed_table->stream_count];
|
||||
|
||||
sa->slot_count = mst_mgr->payloads[i].num_slots;
|
||||
sa->vcp_id = mst_mgr->proposed_vcpis[i]->vcpi;
|
||||
proposed_table->stream_count++;
|
||||
}
|
||||
}
|
||||
|
||||
mutex_unlock(&mst_mgr->payload_lock);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes payload allocation table in immediate downstream device.
|
||||
*/
|
||||
bool dm_helpers_dp_mst_write_payload_allocation_table(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_stream *stream,
|
||||
struct dp_mst_stream_allocation_table *proposed_table,
|
||||
bool enable)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector;
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
struct drm_dp_mst_port *mst_port;
|
||||
int slots = 0;
|
||||
bool ret;
|
||||
int clock;
|
||||
int bpp = 0;
|
||||
int pbn = 0;
|
||||
|
||||
aconnector = get_connector_for_sink(dev, stream->sink);
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
||||
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||
|
||||
if (!mst_mgr->mst_state)
|
||||
return false;
|
||||
|
||||
mst_port = aconnector->port;
|
||||
|
||||
if (enable) {
|
||||
clock = stream->timing.pix_clk_khz;
|
||||
|
||||
switch (stream->timing.display_color_depth) {
|
||||
|
||||
case COLOR_DEPTH_666:
|
||||
bpp = 6;
|
||||
break;
|
||||
case COLOR_DEPTH_888:
|
||||
bpp = 8;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
bpp = 10;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
bpp = 12;
|
||||
break;
|
||||
case COLOR_DEPTH_141414:
|
||||
bpp = 14;
|
||||
break;
|
||||
case COLOR_DEPTH_161616:
|
||||
bpp = 16;
|
||||
break;
|
||||
default:
|
||||
ASSERT(bpp != 0);
|
||||
break;
|
||||
}
|
||||
|
||||
bpp = bpp * 3;
|
||||
|
||||
/* TODO need to know link rate */
|
||||
|
||||
pbn = drm_dp_calc_pbn_mode(clock, bpp);
|
||||
|
||||
slots = drm_dp_find_vcpi_slots(mst_mgr, pbn);
|
||||
ret = drm_dp_mst_allocate_vcpi(mst_mgr, mst_port, pbn, slots);
|
||||
|
||||
if (!ret)
|
||||
return false;
|
||||
|
||||
} else {
|
||||
drm_dp_mst_reset_vcpi_slots(mst_mgr, mst_port);
|
||||
}
|
||||
|
||||
ret = drm_dp_update_payload_part1(mst_mgr);
|
||||
|
||||
/* mst_mgr->->payloads are VC payload notify MST branch using DPCD or
|
||||
* AUX message. The sequence is slot 1-63 allocated sequence for each
|
||||
* stream. AMD ASIC stream slot allocation should follow the same
|
||||
* sequence. copy DRM MST allocation to dc */
|
||||
|
||||
get_payload_table(aconnector, proposed_table);
|
||||
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*
|
||||
* Polls for ACT (allocation change trigger) handled and sends
|
||||
* ALLOCATE_PAYLOAD message.
|
||||
*/
|
||||
bool dm_helpers_dp_mst_poll_for_allocation_change_trigger(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_stream *stream)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector;
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
int ret;
|
||||
|
||||
aconnector = get_connector_for_sink(dev, stream->sink);
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
||||
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||
|
||||
if (!mst_mgr->mst_state)
|
||||
return false;
|
||||
|
||||
ret = drm_dp_check_act_status(mst_mgr);
|
||||
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dm_helpers_dp_mst_send_payload_allocation(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_stream *stream,
|
||||
bool enable)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector;
|
||||
struct drm_dp_mst_topology_mgr *mst_mgr;
|
||||
struct drm_dp_mst_port *mst_port;
|
||||
int ret;
|
||||
|
||||
aconnector = get_connector_for_sink(dev, stream->sink);
|
||||
|
||||
if (!aconnector || !aconnector->mst_port)
|
||||
return false;
|
||||
|
||||
mst_port = aconnector->port;
|
||||
|
||||
mst_mgr = &aconnector->mst_port->mst_mgr;
|
||||
|
||||
if (!mst_mgr->mst_state)
|
||||
return false;
|
||||
|
||||
ret = drm_dp_update_payload_part2(mst_mgr);
|
||||
|
||||
if (ret)
|
||||
return false;
|
||||
|
||||
if (!enable)
|
||||
drm_dp_mst_deallocate_vcpi(mst_mgr, mst_port);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dm_helpers_dp_mst_start_top_mgr(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
bool boot)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
|
||||
|
||||
if (!aconnector) {
|
||||
DRM_ERROR("Failed to found connector for link!");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (boot) {
|
||||
DRM_INFO("DM_MST: Differing MST start on aconnector: %p [id: %d]\n",
|
||||
aconnector, aconnector->base.base.id);
|
||||
return true;
|
||||
}
|
||||
|
||||
DRM_INFO("DM_MST: starting TM on aconnector: %p [id: %d]\n",
|
||||
aconnector, aconnector->base.base.id);
|
||||
|
||||
return (drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, true) == 0);
|
||||
}
|
||||
|
||||
void dm_helpers_dp_mst_stop_top_mgr(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
|
||||
|
||||
if (!aconnector) {
|
||||
DRM_ERROR("Failed to found connector for link!");
|
||||
return;
|
||||
}
|
||||
|
||||
DRM_INFO("DM_MST: stopping TM on aconnector: %p [id: %d]\n",
|
||||
aconnector, aconnector->base.base.id);
|
||||
|
||||
if (aconnector->mst_mgr.mst_state == true)
|
||||
drm_dp_mst_topology_mgr_set_mst(&aconnector->mst_mgr, false);
|
||||
}
|
||||
|
||||
bool dm_helpers_dp_read_dpcd(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
uint32_t address,
|
||||
uint8_t *data,
|
||||
uint32_t size)
|
||||
{
|
||||
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
|
||||
|
||||
if (!aconnector) {
|
||||
DRM_ERROR("Failed to found connector for link!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return drm_dp_dpcd_read(&aconnector->dm_dp_aux.aux, address,
|
||||
data, size) > 0;
|
||||
}
|
||||
|
||||
bool dm_helpers_dp_write_dpcd(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
uint32_t address,
|
||||
const uint8_t *data,
|
||||
uint32_t size)
|
||||
{
|
||||
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
|
||||
|
||||
if (!aconnector) {
|
||||
DRM_ERROR("Failed to found connector for link!");
|
||||
return false;
|
||||
}
|
||||
|
||||
return drm_dp_dpcd_write(&aconnector->dm_dp_aux.aux,
|
||||
address, (uint8_t *)data, size) > 0;
|
||||
}
|
||||
|
||||
bool dm_helpers_submit_i2c(
|
||||
struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
struct i2c_command *cmd)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct amdgpu_connector *aconnector = get_connector_for_link(dev, link);
|
||||
struct i2c_msg *msgs;
|
||||
int i = 0;
|
||||
int num = cmd->number_of_payloads;
|
||||
bool result;
|
||||
|
||||
if (!aconnector) {
|
||||
DRM_ERROR("Failed to found connector for link!");
|
||||
return false;
|
||||
}
|
||||
|
||||
msgs = kzalloc(num * sizeof(struct i2c_msg), GFP_KERNEL);
|
||||
|
||||
if (!msgs)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < num; i++) {
|
||||
msgs[i].flags = cmd->payloads[i].write ? I2C_M_RD : 0;
|
||||
msgs[i].addr = cmd->payloads[i].address;
|
||||
msgs[i].len = cmd->payloads[i].length;
|
||||
msgs[i].buf = cmd->payloads[i].data;
|
||||
}
|
||||
|
||||
result = i2c_transfer(&aconnector->i2c->base, msgs, num) == num;
|
||||
|
||||
kfree(msgs);
|
||||
|
||||
return result;
|
||||
}
|
|
@ -0,0 +1,829 @@
|
|||
/*
|
||||
* 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 <drm/drmP.h>
|
||||
|
||||
#include "dm_services_types.h"
|
||||
#include "dc.h"
|
||||
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Private declarations.
|
||||
*****************************************************************************/
|
||||
|
||||
struct handler_common_data {
|
||||
struct list_head list;
|
||||
interrupt_handler handler;
|
||||
void *handler_arg;
|
||||
|
||||
/* DM which this handler belongs to */
|
||||
struct amdgpu_display_manager *dm;
|
||||
};
|
||||
|
||||
struct amdgpu_dm_irq_handler_data {
|
||||
struct handler_common_data hcd;
|
||||
/* DAL irq source which registered for this interrupt. */
|
||||
enum dc_irq_source irq_source;
|
||||
};
|
||||
|
||||
struct amdgpu_dm_timer_handler_data {
|
||||
struct handler_common_data hcd;
|
||||
struct delayed_work d_work;
|
||||
};
|
||||
|
||||
#define DM_IRQ_TABLE_LOCK(adev, flags) \
|
||||
spin_lock_irqsave(&adev->dm.irq_handler_list_table_lock, flags)
|
||||
|
||||
#define DM_IRQ_TABLE_UNLOCK(adev, flags) \
|
||||
spin_unlock_irqrestore(&adev->dm.irq_handler_list_table_lock, flags)
|
||||
|
||||
/******************************************************************************
|
||||
* Private functions.
|
||||
*****************************************************************************/
|
||||
|
||||
static void init_handler_common_data(
|
||||
struct handler_common_data *hcd,
|
||||
void (*ih)(void *),
|
||||
void *args,
|
||||
struct amdgpu_display_manager *dm)
|
||||
{
|
||||
hcd->handler = ih;
|
||||
hcd->handler_arg = args;
|
||||
hcd->dm = dm;
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_irq_work_func - Handle an IRQ outside of the interrupt handler proper.
|
||||
*
|
||||
* @work: work struct
|
||||
*/
|
||||
static void dm_irq_work_func(struct work_struct *work)
|
||||
{
|
||||
struct list_head *entry;
|
||||
struct irq_list_head *irq_list_head =
|
||||
container_of(work, struct irq_list_head, work);
|
||||
struct list_head *handler_list = &irq_list_head->head;
|
||||
struct amdgpu_dm_irq_handler_data *handler_data;
|
||||
|
||||
list_for_each(entry, handler_list) {
|
||||
handler_data =
|
||||
list_entry(
|
||||
entry,
|
||||
struct amdgpu_dm_irq_handler_data,
|
||||
hcd.list);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: work_func: for dal_src=%d\n",
|
||||
handler_data->irq_source);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: schedule_work: for dal_src=%d\n",
|
||||
handler_data->irq_source);
|
||||
|
||||
handler_data->hcd.handler(handler_data->hcd.handler_arg);
|
||||
}
|
||||
|
||||
/* Call a DAL subcomponent which registered for interrupt notification
|
||||
* at INTERRUPT_LOW_IRQ_CONTEXT.
|
||||
* (The most common use is HPD interrupt) */
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a handler and return a pointer to hander list from which the
|
||||
* handler was removed.
|
||||
*/
|
||||
static struct list_head *remove_irq_handler(
|
||||
struct amdgpu_device *adev,
|
||||
void *ih,
|
||||
const struct dc_interrupt_params *int_params)
|
||||
{
|
||||
struct list_head *hnd_list;
|
||||
struct list_head *entry, *tmp;
|
||||
struct amdgpu_dm_irq_handler_data *handler;
|
||||
unsigned long irq_table_flags;
|
||||
bool handler_removed = false;
|
||||
enum dc_irq_source irq_source;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
irq_source = int_params->irq_source;
|
||||
|
||||
switch (int_params->int_context) {
|
||||
case INTERRUPT_HIGH_IRQ_CONTEXT:
|
||||
hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
|
||||
break;
|
||||
case INTERRUPT_LOW_IRQ_CONTEXT:
|
||||
default:
|
||||
hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
|
||||
break;
|
||||
}
|
||||
|
||||
list_for_each_safe(entry, tmp, hnd_list) {
|
||||
|
||||
handler = list_entry(entry, struct amdgpu_dm_irq_handler_data,
|
||||
hcd.list);
|
||||
|
||||
if (ih == handler) {
|
||||
/* Found our handler. Remove it from the list. */
|
||||
list_del(&handler->hcd.list);
|
||||
handler_removed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
if (handler_removed == false) {
|
||||
/* Not necessarily an error - caller may not
|
||||
* know the context. */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
kfree(handler);
|
||||
|
||||
DRM_DEBUG_KMS(
|
||||
"DM_IRQ: removed irq handler: %p for: dal_src=%d, irq context=%d\n",
|
||||
ih, int_params->irq_source, int_params->int_context);
|
||||
|
||||
return hnd_list;
|
||||
}
|
||||
|
||||
/* If 'handler_in == NULL' then remove ALL handlers. */
|
||||
static void remove_timer_handler(
|
||||
struct amdgpu_device *adev,
|
||||
struct amdgpu_dm_timer_handler_data *handler_in)
|
||||
{
|
||||
struct amdgpu_dm_timer_handler_data *handler_temp;
|
||||
struct list_head *handler_list;
|
||||
struct list_head *entry, *tmp;
|
||||
unsigned long irq_table_flags;
|
||||
bool handler_removed = false;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
handler_list = &adev->dm.timer_handler_list;
|
||||
|
||||
list_for_each_safe(entry, tmp, handler_list) {
|
||||
/* Note that list_for_each_safe() guarantees that
|
||||
* handler_temp is NOT null. */
|
||||
handler_temp = list_entry(entry,
|
||||
struct amdgpu_dm_timer_handler_data, hcd.list);
|
||||
|
||||
if (handler_in == NULL || handler_in == handler_temp) {
|
||||
list_del(&handler_temp->hcd.list);
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: removing timer handler: %p\n",
|
||||
handler_temp);
|
||||
|
||||
if (handler_in == NULL) {
|
||||
/* Since it is still in the queue, it must
|
||||
* be cancelled. */
|
||||
cancel_delayed_work_sync(&handler_temp->d_work);
|
||||
}
|
||||
|
||||
kfree(handler_temp);
|
||||
handler_removed = true;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
}
|
||||
|
||||
if (handler_in == NULL) {
|
||||
/* Remove ALL handlers. */
|
||||
continue;
|
||||
}
|
||||
|
||||
if (handler_in == handler_temp) {
|
||||
/* Remove a SPECIFIC handler.
|
||||
* Found our handler - we can stop here. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
if (handler_in != NULL && handler_removed == false) {
|
||||
DRM_ERROR("DM_IRQ: handler: %p is not in the list!\n",
|
||||
handler_in);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* dm_timer_work_func - Handle a timer.
|
||||
*
|
||||
* @work: work struct
|
||||
*/
|
||||
static void dm_timer_work_func(
|
||||
struct work_struct *work)
|
||||
{
|
||||
struct amdgpu_dm_timer_handler_data *handler_data =
|
||||
container_of(work, struct amdgpu_dm_timer_handler_data,
|
||||
d_work.work);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: work_func: handler_data=%p\n", handler_data);
|
||||
|
||||
/* Call a DAL subcomponent which registered for timer notification. */
|
||||
handler_data->hcd.handler(handler_data->hcd.handler_arg);
|
||||
|
||||
/* We support only "single shot" timers. That means we must delete
|
||||
* the handler after it was called. */
|
||||
remove_timer_handler(handler_data->hcd.dm->adev, handler_data);
|
||||
}
|
||||
|
||||
static bool validate_irq_registration_params(
|
||||
struct dc_interrupt_params *int_params,
|
||||
void (*ih)(void *))
|
||||
{
|
||||
if (NULL == int_params || NULL == ih) {
|
||||
DRM_ERROR("DM_IRQ: invalid input!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (int_params->int_context >= INTERRUPT_CONTEXT_NUMBER) {
|
||||
DRM_ERROR("DM_IRQ: invalid context: %d!\n",
|
||||
int_params->int_context);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DAL_VALID_IRQ_SRC_NUM(int_params->irq_source)) {
|
||||
DRM_ERROR("DM_IRQ: invalid irq_source: %d!\n",
|
||||
int_params->irq_source);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool validate_irq_unregistration_params(
|
||||
enum dc_irq_source irq_source,
|
||||
irq_handler_idx handler_idx)
|
||||
{
|
||||
if (DAL_INVALID_IRQ_HANDLER_IDX == handler_idx) {
|
||||
DRM_ERROR("DM_IRQ: invalid handler_idx==NULL!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!DAL_VALID_IRQ_SRC_NUM(irq_source)) {
|
||||
DRM_ERROR("DM_IRQ: invalid irq_source:%d!\n", irq_source);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
/******************************************************************************
|
||||
* Public functions.
|
||||
*
|
||||
* Note: caller is responsible for input validation.
|
||||
*****************************************************************************/
|
||||
|
||||
void *amdgpu_dm_irq_register_interrupt(
|
||||
struct amdgpu_device *adev,
|
||||
struct dc_interrupt_params *int_params,
|
||||
void (*ih)(void *),
|
||||
void *handler_args)
|
||||
{
|
||||
struct list_head *hnd_list;
|
||||
struct amdgpu_dm_irq_handler_data *handler_data;
|
||||
unsigned long irq_table_flags;
|
||||
enum dc_irq_source irq_source;
|
||||
|
||||
if (false == validate_irq_registration_params(int_params, ih))
|
||||
return DAL_INVALID_IRQ_HANDLER_IDX;
|
||||
|
||||
handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
|
||||
if (!handler_data) {
|
||||
DRM_ERROR("DM_IRQ: failed to allocate irq handler!\n");
|
||||
return DAL_INVALID_IRQ_HANDLER_IDX;
|
||||
}
|
||||
|
||||
memset(handler_data, 0, sizeof(*handler_data));
|
||||
|
||||
init_handler_common_data(&handler_data->hcd, ih, handler_args,
|
||||
&adev->dm);
|
||||
|
||||
irq_source = int_params->irq_source;
|
||||
|
||||
handler_data->irq_source = irq_source;
|
||||
|
||||
/* Lock the list, add the handler. */
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
switch (int_params->int_context) {
|
||||
case INTERRUPT_HIGH_IRQ_CONTEXT:
|
||||
hnd_list = &adev->dm.irq_handler_list_high_tab[irq_source];
|
||||
break;
|
||||
case INTERRUPT_LOW_IRQ_CONTEXT:
|
||||
default:
|
||||
hnd_list = &adev->dm.irq_handler_list_low_tab[irq_source].head;
|
||||
break;
|
||||
}
|
||||
|
||||
list_add_tail(&handler_data->hcd.list, hnd_list);
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
/* This pointer will be stored by code which requested interrupt
|
||||
* registration.
|
||||
* The same pointer will be needed in order to unregister the
|
||||
* interrupt. */
|
||||
|
||||
DRM_DEBUG_KMS(
|
||||
"DM_IRQ: added irq handler: %p for: dal_src=%d, irq context=%d\n",
|
||||
handler_data,
|
||||
irq_source,
|
||||
int_params->int_context);
|
||||
|
||||
return handler_data;
|
||||
}
|
||||
|
||||
void amdgpu_dm_irq_unregister_interrupt(
|
||||
struct amdgpu_device *adev,
|
||||
enum dc_irq_source irq_source,
|
||||
void *ih)
|
||||
{
|
||||
struct list_head *handler_list;
|
||||
struct dc_interrupt_params int_params;
|
||||
int i;
|
||||
|
||||
if (false == validate_irq_unregistration_params(irq_source, ih))
|
||||
return;
|
||||
|
||||
memset(&int_params, 0, sizeof(int_params));
|
||||
|
||||
int_params.irq_source = irq_source;
|
||||
|
||||
for (i = 0; i < INTERRUPT_CONTEXT_NUMBER; i++) {
|
||||
|
||||
int_params.int_context = i;
|
||||
|
||||
handler_list = remove_irq_handler(adev, ih, &int_params);
|
||||
|
||||
if (handler_list != NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
if (handler_list == NULL) {
|
||||
/* If we got here, it means we searched all irq contexts
|
||||
* for this irq source, but the handler was not found. */
|
||||
DRM_ERROR(
|
||||
"DM_IRQ: failed to find irq handler:%p for irq_source:%d!\n",
|
||||
ih, irq_source);
|
||||
}
|
||||
}
|
||||
|
||||
int amdgpu_dm_irq_init(
|
||||
struct amdgpu_device *adev)
|
||||
{
|
||||
int src;
|
||||
struct irq_list_head *lh;
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ\n");
|
||||
|
||||
spin_lock_init(&adev->dm.irq_handler_list_table_lock);
|
||||
|
||||
for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
|
||||
/* low context handler list init */
|
||||
lh = &adev->dm.irq_handler_list_low_tab[src];
|
||||
INIT_LIST_HEAD(&lh->head);
|
||||
INIT_WORK(&lh->work, dm_irq_work_func);
|
||||
|
||||
/* high context handler init */
|
||||
INIT_LIST_HEAD(&adev->dm.irq_handler_list_high_tab[src]);
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&adev->dm.timer_handler_list);
|
||||
|
||||
/* allocate and initialize the workqueue for DM timer */
|
||||
adev->dm.timer_workqueue = create_singlethread_workqueue(
|
||||
"dm_timer_queue");
|
||||
if (adev->dm.timer_workqueue == NULL) {
|
||||
DRM_ERROR("DM_IRQ: unable to create timer queue!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void amdgpu_dm_irq_register_timer(
|
||||
struct amdgpu_device *adev,
|
||||
struct dc_timer_interrupt_params *int_params,
|
||||
interrupt_handler ih,
|
||||
void *args)
|
||||
{
|
||||
unsigned long jf_delay;
|
||||
struct list_head *handler_list;
|
||||
struct amdgpu_dm_timer_handler_data *handler_data;
|
||||
unsigned long irq_table_flags;
|
||||
|
||||
handler_data = kzalloc(sizeof(*handler_data), GFP_KERNEL);
|
||||
if (!handler_data) {
|
||||
DRM_ERROR("DM_IRQ: failed to allocate timer handler!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
memset(handler_data, 0, sizeof(*handler_data));
|
||||
|
||||
init_handler_common_data(&handler_data->hcd, ih, args, &adev->dm);
|
||||
|
||||
INIT_DELAYED_WORK(&handler_data->d_work, dm_timer_work_func);
|
||||
|
||||
/* Lock the list, add the handler. */
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
handler_list = &adev->dm.timer_handler_list;
|
||||
|
||||
list_add_tail(&handler_data->hcd.list, handler_list);
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
jf_delay = usecs_to_jiffies(int_params->micro_sec_interval);
|
||||
|
||||
queue_delayed_work(adev->dm.timer_workqueue, &handler_data->d_work,
|
||||
jf_delay);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: added handler:%p with micro_sec_interval=%u\n",
|
||||
handler_data, int_params->micro_sec_interval);
|
||||
return;
|
||||
}
|
||||
|
||||
/* DM IRQ and timer resource release */
|
||||
void amdgpu_dm_irq_fini(
|
||||
struct amdgpu_device *adev)
|
||||
{
|
||||
int src;
|
||||
struct irq_list_head *lh;
|
||||
DRM_DEBUG_KMS("DM_IRQ: releasing resources.\n");
|
||||
|
||||
for (src = 0; src < DAL_IRQ_SOURCES_NUMBER; src++) {
|
||||
|
||||
/* The handler was removed from the table,
|
||||
* it means it is safe to flush all the 'work'
|
||||
* (because no code can schedule a new one). */
|
||||
lh = &adev->dm.irq_handler_list_low_tab[src];
|
||||
flush_work(&lh->work);
|
||||
}
|
||||
|
||||
/* Cancel ALL timers and release handlers (if any). */
|
||||
remove_timer_handler(adev, NULL);
|
||||
/* Release the queue itself. */
|
||||
destroy_workqueue(adev->dm.timer_workqueue);
|
||||
}
|
||||
|
||||
int amdgpu_dm_irq_suspend(
|
||||
struct amdgpu_device *adev)
|
||||
{
|
||||
int src;
|
||||
struct list_head *hnd_list_h;
|
||||
struct list_head *hnd_list_l;
|
||||
unsigned long irq_table_flags;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: suspend\n");
|
||||
|
||||
/* disable HW interrupt */
|
||||
for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
|
||||
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
|
||||
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
|
||||
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
|
||||
dc_interrupt_set(adev->dm.dc, src, false);
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
flush_work(&adev->dm.irq_handler_list_low_tab[src].work);
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev)
|
||||
{
|
||||
int src;
|
||||
struct list_head *hnd_list_h, *hnd_list_l;
|
||||
unsigned long irq_table_flags;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: early resume\n");
|
||||
|
||||
/* re-enable short pulse interrupts HW interrupt */
|
||||
for (src = DC_IRQ_SOURCE_HPD1RX; src < DC_IRQ_SOURCE_HPD6RX + 1; src++) {
|
||||
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
|
||||
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
|
||||
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
|
||||
dc_interrupt_set(adev->dm.dc, src, true);
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int amdgpu_dm_irq_resume(struct amdgpu_device *adev)
|
||||
{
|
||||
int src;
|
||||
struct list_head *hnd_list_h, *hnd_list_l;
|
||||
unsigned long irq_table_flags;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
DRM_DEBUG_KMS("DM_IRQ: resume\n");
|
||||
|
||||
/* re-enable HW interrupt */
|
||||
for (src = DC_IRQ_SOURCE_HPD1; src < DAL_IRQ_SOURCES_NUMBER; src++) {
|
||||
hnd_list_l = &adev->dm.irq_handler_list_low_tab[src].head;
|
||||
hnd_list_h = &adev->dm.irq_handler_list_high_tab[src];
|
||||
if (!list_empty(hnd_list_l) || !list_empty(hnd_list_h))
|
||||
dc_interrupt_set(adev->dm.dc, src, true);
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_schedule_work - schedule all work items registered for the
|
||||
* "irq_source".
|
||||
*/
|
||||
static void amdgpu_dm_irq_schedule_work(
|
||||
struct amdgpu_device *adev,
|
||||
enum dc_irq_source irq_source)
|
||||
{
|
||||
unsigned long irq_table_flags;
|
||||
struct work_struct *work = NULL;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
if (!list_empty(&adev->dm.irq_handler_list_low_tab[irq_source].head))
|
||||
work = &adev->dm.irq_handler_list_low_tab[irq_source].work;
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
|
||||
if (work) {
|
||||
if (!schedule_work(work))
|
||||
DRM_INFO("amdgpu_dm_irq_schedule_work FAILED src %d\n",
|
||||
irq_source);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** amdgpu_dm_irq_immediate_work
|
||||
* Callback high irq work immediately, don't send to work queue
|
||||
*/
|
||||
static void amdgpu_dm_irq_immediate_work(
|
||||
struct amdgpu_device *adev,
|
||||
enum dc_irq_source irq_source)
|
||||
{
|
||||
struct amdgpu_dm_irq_handler_data *handler_data;
|
||||
struct list_head *entry;
|
||||
unsigned long irq_table_flags;
|
||||
|
||||
DM_IRQ_TABLE_LOCK(adev, irq_table_flags);
|
||||
|
||||
list_for_each(
|
||||
entry,
|
||||
&adev->dm.irq_handler_list_high_tab[irq_source]) {
|
||||
|
||||
handler_data =
|
||||
list_entry(
|
||||
entry,
|
||||
struct amdgpu_dm_irq_handler_data,
|
||||
hcd.list);
|
||||
|
||||
/* Call a subcomponent which registered for immediate
|
||||
* interrupt notification */
|
||||
handler_data->hcd.handler(handler_data->hcd.handler_arg);
|
||||
}
|
||||
|
||||
DM_IRQ_TABLE_UNLOCK(adev, irq_table_flags);
|
||||
}
|
||||
|
||||
/*
|
||||
* amdgpu_dm_irq_handler
|
||||
*
|
||||
* Generic IRQ handler, calls all registered high irq work immediately, and
|
||||
* schedules work for low irq
|
||||
*/
|
||||
int amdgpu_dm_irq_handler(
|
||||
struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry)
|
||||
{
|
||||
|
||||
enum dc_irq_source src =
|
||||
dc_interrupt_to_irq_source(
|
||||
adev->dm.dc,
|
||||
entry->src_id,
|
||||
entry->src_data[0]);
|
||||
|
||||
dc_interrupt_ack(adev->dm.dc, src);
|
||||
|
||||
/* Call high irq work immediately */
|
||||
amdgpu_dm_irq_immediate_work(adev, src);
|
||||
/*Schedule low_irq work */
|
||||
amdgpu_dm_irq_schedule_work(adev, src);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static enum dc_irq_source amdgpu_dm_hpd_to_dal_irq_source(unsigned type)
|
||||
{
|
||||
switch (type) {
|
||||
case AMDGPU_HPD_1:
|
||||
return DC_IRQ_SOURCE_HPD1;
|
||||
case AMDGPU_HPD_2:
|
||||
return DC_IRQ_SOURCE_HPD2;
|
||||
case AMDGPU_HPD_3:
|
||||
return DC_IRQ_SOURCE_HPD3;
|
||||
case AMDGPU_HPD_4:
|
||||
return DC_IRQ_SOURCE_HPD4;
|
||||
case AMDGPU_HPD_5:
|
||||
return DC_IRQ_SOURCE_HPD5;
|
||||
case AMDGPU_HPD_6:
|
||||
return DC_IRQ_SOURCE_HPD6;
|
||||
default:
|
||||
return DC_IRQ_SOURCE_INVALID;
|
||||
}
|
||||
}
|
||||
|
||||
static int amdgpu_dm_set_hpd_irq_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned type,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
enum dc_irq_source src = amdgpu_dm_hpd_to_dal_irq_source(type);
|
||||
bool st = (state == AMDGPU_IRQ_STATE_ENABLE);
|
||||
|
||||
dc_interrupt_set(adev->dm.dc, src, st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int dm_irq_state(
|
||||
struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned crtc_id,
|
||||
enum amdgpu_interrupt_state state,
|
||||
const enum irq_type dal_irq_type,
|
||||
const char *func)
|
||||
{
|
||||
bool st;
|
||||
enum dc_irq_source irq_source;
|
||||
|
||||
struct amdgpu_crtc *acrtc = adev->mode_info.crtcs[crtc_id];
|
||||
|
||||
if (!acrtc) {
|
||||
DRM_ERROR(
|
||||
"%s: crtc is NULL at id :%d\n",
|
||||
func,
|
||||
crtc_id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
irq_source = dal_irq_type + acrtc->otg_inst;
|
||||
|
||||
st = (state == AMDGPU_IRQ_STATE_ENABLE);
|
||||
|
||||
dc_interrupt_set(adev->dm.dc, irq_source, st);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int amdgpu_dm_set_pflip_irq_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned crtc_id,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
return dm_irq_state(
|
||||
adev,
|
||||
source,
|
||||
crtc_id,
|
||||
state,
|
||||
IRQ_TYPE_PFLIP,
|
||||
__func__);
|
||||
}
|
||||
|
||||
static int amdgpu_dm_set_crtc_irq_state(struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
unsigned crtc_id,
|
||||
enum amdgpu_interrupt_state state)
|
||||
{
|
||||
return dm_irq_state(
|
||||
adev,
|
||||
source,
|
||||
crtc_id,
|
||||
state,
|
||||
IRQ_TYPE_VUPDATE,
|
||||
__func__);
|
||||
}
|
||||
|
||||
static const struct amdgpu_irq_src_funcs dm_crtc_irq_funcs = {
|
||||
.set = amdgpu_dm_set_crtc_irq_state,
|
||||
.process = amdgpu_dm_irq_handler,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs dm_pageflip_irq_funcs = {
|
||||
.set = amdgpu_dm_set_pflip_irq_state,
|
||||
.process = amdgpu_dm_irq_handler,
|
||||
};
|
||||
|
||||
static const struct amdgpu_irq_src_funcs dm_hpd_irq_funcs = {
|
||||
.set = amdgpu_dm_set_hpd_irq_state,
|
||||
.process = amdgpu_dm_irq_handler,
|
||||
};
|
||||
|
||||
void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev)
|
||||
{
|
||||
adev->crtc_irq.num_types = AMDGPU_CRTC_IRQ_LAST;
|
||||
adev->crtc_irq.funcs = &dm_crtc_irq_funcs;
|
||||
|
||||
adev->pageflip_irq.num_types = AMDGPU_PAGEFLIP_IRQ_LAST;
|
||||
adev->pageflip_irq.funcs = &dm_pageflip_irq_funcs;
|
||||
|
||||
adev->hpd_irq.num_types = AMDGPU_HPD_LAST;
|
||||
adev->hpd_irq.funcs = &dm_hpd_irq_funcs;
|
||||
}
|
||||
|
||||
/*
|
||||
* amdgpu_dm_hpd_init - hpd setup callback.
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Setup the hpd pins used by the card (evergreen+).
|
||||
* Enable the pin, set the polarity, and enable the hpd interrupts.
|
||||
*/
|
||||
void amdgpu_dm_hpd_init(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct amdgpu_connector *amdgpu_connector =
|
||||
to_amdgpu_connector(connector);
|
||||
|
||||
const struct dc_link *dc_link = amdgpu_connector->dc_link;
|
||||
|
||||
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd) {
|
||||
dc_interrupt_set(adev->dm.dc,
|
||||
dc_link->irq_source_hpd,
|
||||
true);
|
||||
}
|
||||
|
||||
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
|
||||
dc_interrupt_set(adev->dm.dc,
|
||||
dc_link->irq_source_hpd_rx,
|
||||
true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* amdgpu_dm_hpd_fini - hpd tear down callback.
|
||||
*
|
||||
* @adev: amdgpu_device pointer
|
||||
*
|
||||
* Tear down the hpd pins used by the card (evergreen+).
|
||||
* Disable the hpd interrupts.
|
||||
*/
|
||||
void amdgpu_dm_hpd_fini(struct amdgpu_device *adev)
|
||||
{
|
||||
struct drm_device *dev = adev->ddev;
|
||||
struct drm_connector *connector;
|
||||
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
struct amdgpu_connector *amdgpu_connector =
|
||||
to_amdgpu_connector(connector);
|
||||
const struct dc_link *dc_link = amdgpu_connector->dc_link;
|
||||
|
||||
dc_interrupt_set(adev->dm.dc, dc_link->irq_source_hpd, false);
|
||||
|
||||
if (DC_IRQ_SOURCE_INVALID != dc_link->irq_source_hpd_rx) {
|
||||
dc_interrupt_set(adev->dm.dc,
|
||||
dc_link->irq_source_hpd_rx,
|
||||
false);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,122 @@
|
|||
/*
|
||||
* 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 __AMDGPU_DM_IRQ_H__
|
||||
#define __AMDGPU_DM_IRQ_H__
|
||||
|
||||
#include "irq_types.h" /* DAL irq definitions */
|
||||
|
||||
/*
|
||||
* Display Manager IRQ-related interfaces (for use by DAL).
|
||||
*/
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_init - Initialize internal structures of 'amdgpu_dm_irq'.
|
||||
*
|
||||
* This function should be called exactly once - during DM initialization.
|
||||
*
|
||||
* Returns:
|
||||
* 0 - success
|
||||
* non-zero - error
|
||||
*/
|
||||
int amdgpu_dm_irq_init(
|
||||
struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_fini - deallocate internal structures of 'amdgpu_dm_irq'.
|
||||
*
|
||||
* This function should be called exactly once - during DM destruction.
|
||||
*
|
||||
*/
|
||||
void amdgpu_dm_irq_fini(
|
||||
struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_register_interrupt - register irq handler for Display block.
|
||||
*
|
||||
* @adev: AMD DRM device
|
||||
* @int_params: parameters for the irq
|
||||
* @ih: pointer to the irq hander function
|
||||
* @handler_args: arguments which will be passed to ih
|
||||
*
|
||||
* Returns:
|
||||
* IRQ Handler Index on success.
|
||||
* NULL on failure.
|
||||
*
|
||||
* Cannot be called from an interrupt handler.
|
||||
*/
|
||||
void *amdgpu_dm_irq_register_interrupt(
|
||||
struct amdgpu_device *adev,
|
||||
struct dc_interrupt_params *int_params,
|
||||
void (*ih)(void *),
|
||||
void *handler_args);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_unregister_interrupt - unregister handler which was registered
|
||||
* by amdgpu_dm_irq_register_interrupt().
|
||||
*
|
||||
* @adev: AMD DRM device.
|
||||
* @ih_index: irq handler index which was returned by
|
||||
* amdgpu_dm_irq_register_interrupt
|
||||
*/
|
||||
void amdgpu_dm_irq_unregister_interrupt(
|
||||
struct amdgpu_device *adev,
|
||||
enum dc_irq_source irq_source,
|
||||
void *ih_index);
|
||||
|
||||
void amdgpu_dm_irq_register_timer(
|
||||
struct amdgpu_device *adev,
|
||||
struct dc_timer_interrupt_params *int_params,
|
||||
interrupt_handler ih,
|
||||
void *args);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_handler
|
||||
* Generic IRQ handler, calls all registered high irq work immediately, and
|
||||
* schedules work for low irq
|
||||
*/
|
||||
int amdgpu_dm_irq_handler(
|
||||
struct amdgpu_device *adev,
|
||||
struct amdgpu_irq_src *source,
|
||||
struct amdgpu_iv_entry *entry);
|
||||
|
||||
void amdgpu_dm_set_irq_funcs(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_dm_hpd_init(struct amdgpu_device *adev);
|
||||
void amdgpu_dm_hpd_fini(struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_suspend - disable ASIC interrupt during suspend.
|
||||
*
|
||||
*/
|
||||
int amdgpu_dm_irq_suspend(struct amdgpu_device *adev);
|
||||
|
||||
/**
|
||||
* amdgpu_dm_irq_resume_early - enable HPDRX ASIC interrupts during resume.
|
||||
* amdgpu_dm_irq_resume - enable ASIC interrupt during resume.
|
||||
*
|
||||
*/
|
||||
int amdgpu_dm_irq_resume_early(struct amdgpu_device *adev);
|
||||
int amdgpu_dm_irq_resume(struct amdgpu_device *adev);
|
||||
|
||||
#endif /* __AMDGPU_DM_IRQ_H__ */
|
|
@ -0,0 +1,443 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 <linux/version.h>
|
||||
#include <drm/drm_atomic_helper.h>
|
||||
#include "dm_services.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm_types.h"
|
||||
#include "amdgpu_dm_mst_types.h"
|
||||
|
||||
#include "dc.h"
|
||||
#include "dm_helpers.h"
|
||||
|
||||
/* #define TRACE_DPCD */
|
||||
|
||||
#ifdef TRACE_DPCD
|
||||
#define SIDE_BAND_MSG(address) (address >= DP_SIDEBAND_MSG_DOWN_REQ_BASE && address < DP_SINK_COUNT_ESI)
|
||||
|
||||
static inline char *side_band_msg_type_to_str(uint32_t address)
|
||||
{
|
||||
static char str[10] = {0};
|
||||
|
||||
if (address < DP_SIDEBAND_MSG_UP_REP_BASE)
|
||||
strcpy(str, "DOWN_REQ");
|
||||
else if (address < DP_SIDEBAND_MSG_DOWN_REP_BASE)
|
||||
strcpy(str, "UP_REP");
|
||||
else if (address < DP_SIDEBAND_MSG_UP_REQ_BASE)
|
||||
strcpy(str, "DOWN_REP");
|
||||
else
|
||||
strcpy(str, "UP_REQ");
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
void log_dpcd(uint8_t type,
|
||||
uint32_t address,
|
||||
uint8_t *data,
|
||||
uint32_t size,
|
||||
bool res)
|
||||
{
|
||||
DRM_DEBUG_KMS("Op: %s, addr: %04x, SideBand Msg: %s, Op res: %s\n",
|
||||
(type == DP_AUX_NATIVE_READ) ||
|
||||
(type == DP_AUX_I2C_READ) ?
|
||||
"Read" : "Write",
|
||||
address,
|
||||
SIDE_BAND_MSG(address) ?
|
||||
side_band_msg_type_to_str(address) : "Nop",
|
||||
res ? "OK" : "Fail");
|
||||
|
||||
if (res) {
|
||||
print_hex_dump(KERN_INFO, "Body: ", DUMP_PREFIX_NONE, 16, 1, data, size, false);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
static ssize_t dm_dp_aux_transfer(struct drm_dp_aux *aux, struct drm_dp_aux_msg *msg)
|
||||
{
|
||||
struct pci_dev *pdev = to_pci_dev(aux->dev);
|
||||
struct drm_device *drm_dev = pci_get_drvdata(pdev);
|
||||
struct amdgpu_device *adev = drm_dev->dev_private;
|
||||
struct dc *dc = adev->dm.dc;
|
||||
bool res;
|
||||
|
||||
switch (msg->request) {
|
||||
case DP_AUX_NATIVE_READ:
|
||||
res = dc_read_dpcd(
|
||||
dc,
|
||||
TO_DM_AUX(aux)->link_index,
|
||||
msg->address,
|
||||
msg->buffer,
|
||||
msg->size);
|
||||
break;
|
||||
case DP_AUX_NATIVE_WRITE:
|
||||
res = dc_write_dpcd(
|
||||
dc,
|
||||
TO_DM_AUX(aux)->link_index,
|
||||
msg->address,
|
||||
msg->buffer,
|
||||
msg->size);
|
||||
break;
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
|
||||
#ifdef TRACE_DPCD
|
||||
log_dpcd(msg->request,
|
||||
msg->address,
|
||||
msg->buffer,
|
||||
msg->size,
|
||||
res);
|
||||
#endif
|
||||
|
||||
return msg->size;
|
||||
}
|
||||
|
||||
static enum drm_connector_status
|
||||
dm_dp_mst_detect(struct drm_connector *connector, bool force)
|
||||
{
|
||||
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
|
||||
struct amdgpu_connector *master = aconnector->mst_port;
|
||||
|
||||
enum drm_connector_status status =
|
||||
drm_dp_mst_detect_port(
|
||||
connector,
|
||||
&master->mst_mgr,
|
||||
aconnector->port);
|
||||
|
||||
/*
|
||||
* we do not want to make this connector connected until we have edid on
|
||||
* it
|
||||
*/
|
||||
if (status == connector_status_connected &&
|
||||
!aconnector->port->cached_edid)
|
||||
status = connector_status_disconnected;
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
static void
|
||||
dm_dp_mst_connector_destroy(struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
struct amdgpu_encoder *amdgpu_encoder = amdgpu_connector->mst_encoder;
|
||||
|
||||
drm_encoder_cleanup(&amdgpu_encoder->base);
|
||||
kfree(amdgpu_encoder);
|
||||
drm_connector_cleanup(connector);
|
||||
kfree(amdgpu_connector);
|
||||
}
|
||||
|
||||
static const struct drm_connector_funcs dm_dp_mst_connector_funcs = {
|
||||
.detect = dm_dp_mst_detect,
|
||||
.fill_modes = drm_helper_probe_single_connector_modes,
|
||||
.destroy = dm_dp_mst_connector_destroy,
|
||||
.reset = amdgpu_dm_connector_funcs_reset,
|
||||
.atomic_duplicate_state = amdgpu_dm_connector_atomic_duplicate_state,
|
||||
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
|
||||
.atomic_set_property = amdgpu_dm_connector_atomic_set_property
|
||||
};
|
||||
|
||||
static int dm_dp_mst_get_modes(struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
|
||||
int ret = 0;
|
||||
|
||||
ret = drm_add_edid_modes(&aconnector->base, aconnector->edid);
|
||||
|
||||
drm_edid_to_eld(&aconnector->base, aconnector->edid);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static struct drm_encoder *dm_mst_best_encoder(struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *amdgpu_connector = to_amdgpu_connector(connector);
|
||||
|
||||
return &amdgpu_connector->mst_encoder->base;
|
||||
}
|
||||
|
||||
static const struct drm_connector_helper_funcs dm_dp_mst_connector_helper_funcs = {
|
||||
.get_modes = dm_dp_mst_get_modes,
|
||||
.mode_valid = amdgpu_dm_connector_mode_valid,
|
||||
.best_encoder = dm_mst_best_encoder,
|
||||
};
|
||||
|
||||
static struct amdgpu_encoder *
|
||||
dm_dp_create_fake_mst_encoder(struct amdgpu_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->base.dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_encoder *amdgpu_encoder;
|
||||
struct drm_encoder *encoder;
|
||||
const struct drm_connector_helper_funcs *connector_funcs =
|
||||
connector->base.helper_private;
|
||||
struct drm_encoder *enc_master =
|
||||
connector_funcs->best_encoder(&connector->base);
|
||||
|
||||
DRM_DEBUG_KMS("enc master is %p\n", enc_master);
|
||||
amdgpu_encoder = kzalloc(sizeof(*amdgpu_encoder), GFP_KERNEL);
|
||||
if (!amdgpu_encoder)
|
||||
return NULL;
|
||||
|
||||
encoder = &amdgpu_encoder->base;
|
||||
encoder->possible_crtcs = amdgpu_dm_get_encoder_crtc_mask(adev);
|
||||
|
||||
drm_encoder_init(
|
||||
dev,
|
||||
&amdgpu_encoder->base,
|
||||
NULL,
|
||||
DRM_MODE_ENCODER_DPMST,
|
||||
NULL);
|
||||
|
||||
drm_encoder_helper_add(encoder, &amdgpu_dm_encoder_helper_funcs);
|
||||
|
||||
return amdgpu_encoder;
|
||||
}
|
||||
|
||||
static struct drm_connector *dm_dp_add_mst_connector(struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_dp_mst_port *port,
|
||||
const char *pathprop)
|
||||
{
|
||||
struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct amdgpu_connector *aconnector;
|
||||
struct drm_connector *connector;
|
||||
|
||||
drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
aconnector = to_amdgpu_connector(connector);
|
||||
if (aconnector->mst_port == master
|
||||
&& !aconnector->port) {
|
||||
DRM_INFO("DM_MST: reusing connector: %p [id: %d] [master: %p]\n",
|
||||
aconnector, connector->base.id, aconnector->mst_port);
|
||||
|
||||
aconnector->port = port;
|
||||
drm_mode_connector_set_path_property(connector, pathprop);
|
||||
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
return &aconnector->base;
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock(&dev->mode_config.connection_mutex);
|
||||
|
||||
aconnector = kzalloc(sizeof(*aconnector), GFP_KERNEL);
|
||||
if (!aconnector)
|
||||
return NULL;
|
||||
|
||||
connector = &aconnector->base;
|
||||
aconnector->port = port;
|
||||
aconnector->mst_port = master;
|
||||
|
||||
if (drm_connector_init(
|
||||
dev,
|
||||
connector,
|
||||
&dm_dp_mst_connector_funcs,
|
||||
DRM_MODE_CONNECTOR_DisplayPort)) {
|
||||
kfree(aconnector);
|
||||
return NULL;
|
||||
}
|
||||
drm_connector_helper_add(connector, &dm_dp_mst_connector_helper_funcs);
|
||||
|
||||
amdgpu_dm_connector_init_helper(
|
||||
&adev->dm,
|
||||
aconnector,
|
||||
DRM_MODE_CONNECTOR_DisplayPort,
|
||||
master->dc_link,
|
||||
master->connector_id);
|
||||
|
||||
aconnector->mst_encoder = dm_dp_create_fake_mst_encoder(master);
|
||||
|
||||
/*
|
||||
* TODO: understand why this one is needed
|
||||
*/
|
||||
drm_object_attach_property(
|
||||
&connector->base,
|
||||
dev->mode_config.path_property,
|
||||
0);
|
||||
drm_object_attach_property(
|
||||
&connector->base,
|
||||
dev->mode_config.tile_property,
|
||||
0);
|
||||
|
||||
drm_mode_connector_set_path_property(connector, pathprop);
|
||||
|
||||
/*
|
||||
* Initialize connector state before adding the connectror to drm and
|
||||
* framebuffer lists
|
||||
*/
|
||||
amdgpu_dm_connector_funcs_reset(connector);
|
||||
|
||||
DRM_INFO("DM_MST: added connector: %p [id: %d] [master: %p]\n",
|
||||
aconnector, connector->base.id, aconnector->mst_port);
|
||||
|
||||
DRM_DEBUG_KMS(":%d\n", connector->base.id);
|
||||
|
||||
return connector;
|
||||
}
|
||||
|
||||
static void dm_dp_destroy_mst_connector(
|
||||
struct drm_dp_mst_topology_mgr *mgr,
|
||||
struct drm_connector *connector)
|
||||
{
|
||||
struct amdgpu_connector *aconnector = to_amdgpu_connector(connector);
|
||||
|
||||
DRM_INFO("DM_MST: Disabling connector: %p [id: %d] [master: %p]\n",
|
||||
aconnector, connector->base.id, aconnector->mst_port);
|
||||
|
||||
aconnector->port = NULL;
|
||||
if (aconnector->dc_sink) {
|
||||
amdgpu_dm_remove_sink_from_freesync_module(connector);
|
||||
dc_link_remove_remote_sink(aconnector->dc_link, aconnector->dc_sink);
|
||||
dc_sink_release(aconnector->dc_sink);
|
||||
aconnector->dc_sink = NULL;
|
||||
}
|
||||
if (aconnector->edid) {
|
||||
kfree(aconnector->edid);
|
||||
aconnector->edid = NULL;
|
||||
}
|
||||
|
||||
drm_mode_connector_update_edid_property(
|
||||
&aconnector->base,
|
||||
NULL);
|
||||
}
|
||||
|
||||
static void dm_dp_mst_hotplug(struct drm_dp_mst_topology_mgr *mgr)
|
||||
{
|
||||
struct amdgpu_connector *master = container_of(mgr, struct amdgpu_connector, mst_mgr);
|
||||
struct drm_device *dev = master->base.dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
struct drm_connector *connector;
|
||||
struct amdgpu_connector *aconnector;
|
||||
struct edid *edid;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
|
||||
aconnector = to_amdgpu_connector(connector);
|
||||
if (aconnector->port &&
|
||||
aconnector->port->pdt != DP_PEER_DEVICE_NONE &&
|
||||
aconnector->port->pdt != DP_PEER_DEVICE_MST_BRANCHING &&
|
||||
!aconnector->dc_sink) {
|
||||
/*
|
||||
* This is plug in case, where port has been created but
|
||||
* sink hasn't been created yet
|
||||
*/
|
||||
if (!aconnector->edid) {
|
||||
struct dc_sink_init_data init_params = {
|
||||
.link = aconnector->dc_link,
|
||||
.sink_signal = SIGNAL_TYPE_DISPLAY_PORT_MST};
|
||||
edid = drm_dp_mst_get_edid(connector, &aconnector->mst_port->mst_mgr, aconnector->port);
|
||||
|
||||
if (!edid) {
|
||||
drm_mode_connector_update_edid_property(
|
||||
&aconnector->base,
|
||||
NULL);
|
||||
continue;
|
||||
}
|
||||
|
||||
aconnector->edid = edid;
|
||||
|
||||
aconnector->dc_sink = dc_link_add_remote_sink(
|
||||
aconnector->dc_link,
|
||||
(uint8_t *)edid,
|
||||
(edid->extensions + 1) * EDID_LENGTH,
|
||||
&init_params);
|
||||
if (aconnector->dc_sink)
|
||||
amdgpu_dm_add_sink_to_freesync_module(
|
||||
connector,
|
||||
edid);
|
||||
|
||||
dm_restore_drm_connector_state(connector->dev, connector);
|
||||
} else
|
||||
edid = aconnector->edid;
|
||||
|
||||
DRM_DEBUG_KMS("edid retrieved %p\n", edid);
|
||||
|
||||
drm_mode_connector_update_edid_property(
|
||||
&aconnector->base,
|
||||
aconnector->edid);
|
||||
}
|
||||
}
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
schedule_work(&adev->dm.mst_hotplug_work);
|
||||
}
|
||||
|
||||
static void dm_dp_mst_register_connector(struct drm_connector *connector)
|
||||
{
|
||||
struct drm_device *dev = connector->dev;
|
||||
struct amdgpu_device *adev = dev->dev_private;
|
||||
int i;
|
||||
|
||||
drm_modeset_lock_all(dev);
|
||||
if (adev->mode_info.rfbdev) {
|
||||
/*Do not add if already registered in past*/
|
||||
for (i = 0; i < adev->mode_info.rfbdev->helper.connector_count; i++) {
|
||||
if (adev->mode_info.rfbdev->helper.connector_info[i]->connector
|
||||
== connector) {
|
||||
drm_modeset_unlock_all(dev);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
drm_fb_helper_add_one_connector(&adev->mode_info.rfbdev->helper, connector);
|
||||
}
|
||||
else
|
||||
DRM_ERROR("adev->mode_info.rfbdev is NULL\n");
|
||||
|
||||
drm_modeset_unlock_all(dev);
|
||||
|
||||
drm_connector_register(connector);
|
||||
|
||||
}
|
||||
|
||||
static const struct drm_dp_mst_topology_cbs dm_mst_cbs = {
|
||||
.add_connector = dm_dp_add_mst_connector,
|
||||
.destroy_connector = dm_dp_destroy_mst_connector,
|
||||
.hotplug = dm_dp_mst_hotplug,
|
||||
.register_connector = dm_dp_mst_register_connector
|
||||
};
|
||||
|
||||
void amdgpu_dm_initialize_mst_connector(
|
||||
struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_connector *aconnector)
|
||||
{
|
||||
aconnector->dm_dp_aux.aux.name = "dmdc";
|
||||
aconnector->dm_dp_aux.aux.dev = dm->adev->dev;
|
||||
aconnector->dm_dp_aux.aux.transfer = dm_dp_aux_transfer;
|
||||
aconnector->dm_dp_aux.link_index = aconnector->connector_id;
|
||||
|
||||
drm_dp_aux_register(&aconnector->dm_dp_aux.aux);
|
||||
aconnector->mst_mgr.cbs = &dm_mst_cbs;
|
||||
drm_dp_mst_topology_mgr_init(
|
||||
&aconnector->mst_mgr,
|
||||
dm->adev->ddev,
|
||||
&aconnector->dm_dp_aux.aux,
|
||||
16,
|
||||
4,
|
||||
aconnector->connector_id);
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_AMDGPU_DM_MST_TYPES_H__
|
||||
#define __DAL_AMDGPU_DM_MST_TYPES_H__
|
||||
|
||||
struct amdgpu_display_manager;
|
||||
struct amdgpu_connector;
|
||||
|
||||
void amdgpu_dm_initialize_mst_connector(
|
||||
struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_connector *aconnector);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,463 @@
|
|||
/*
|
||||
* 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 <linux/string.h>
|
||||
#include <linux/acpi.h>
|
||||
|
||||
#include <drm/drmP.h>
|
||||
#include <drm/drm_crtc_helper.h>
|
||||
#include <drm/amdgpu_drm.h>
|
||||
#include "dm_services.h"
|
||||
#include "amdgpu.h"
|
||||
#include "amdgpu_dm.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
#include "amdgpu_dm_types.h"
|
||||
#include "amdgpu_pm.h"
|
||||
|
||||
#define dm_alloc(size) kzalloc(size, GFP_KERNEL)
|
||||
#define dm_realloc(ptr, size) krealloc(ptr, size, GFP_KERNEL)
|
||||
#define dm_free(ptr) kfree(ptr)
|
||||
|
||||
/******************************************************************************
|
||||
* IRQ Interfaces.
|
||||
*****************************************************************************/
|
||||
|
||||
void dal_register_timer_interrupt(
|
||||
struct dc_context *ctx,
|
||||
struct dc_timer_interrupt_params *int_params,
|
||||
interrupt_handler ih,
|
||||
void *args)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
|
||||
if (!adev || !int_params) {
|
||||
DRM_ERROR("DM_IRQ: invalid input!\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (int_params->int_context != INTERRUPT_LOW_IRQ_CONTEXT) {
|
||||
/* only low irq ctx is supported. */
|
||||
DRM_ERROR("DM_IRQ: invalid context: %d!\n",
|
||||
int_params->int_context);
|
||||
return;
|
||||
}
|
||||
|
||||
amdgpu_dm_irq_register_timer(adev, int_params, ih, args);
|
||||
}
|
||||
|
||||
void dal_isr_acquire_lock(struct dc_context *ctx)
|
||||
{
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
void dal_isr_release_lock(struct dc_context *ctx)
|
||||
{
|
||||
/*TODO*/
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* End-of-IRQ Interfaces.
|
||||
*****************************************************************************/
|
||||
|
||||
bool dm_get_platform_info(struct dc_context *ctx,
|
||||
struct platform_info_params *params)
|
||||
{
|
||||
/*TODO*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_write_persistent_data(struct dc_context *ctx,
|
||||
const struct dc_sink *sink,
|
||||
const char *module_name,
|
||||
const char *key_name,
|
||||
void *params,
|
||||
unsigned int size,
|
||||
struct persistent_data_flag *flag)
|
||||
{
|
||||
/*TODO implement*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_read_persistent_data(struct dc_context *ctx,
|
||||
const struct dc_sink *sink,
|
||||
const char *module_name,
|
||||
const char *key_name,
|
||||
void *params,
|
||||
unsigned int size,
|
||||
struct persistent_data_flag *flag)
|
||||
{
|
||||
/*TODO implement*/
|
||||
return false;
|
||||
}
|
||||
|
||||
void dm_delay_in_microseconds(struct dc_context *ctx,
|
||||
unsigned int microSeconds)
|
||||
{
|
||||
/*TODO implement*/
|
||||
return;
|
||||
}
|
||||
|
||||
/**** power component interfaces ****/
|
||||
|
||||
bool dm_pp_pre_dce_clock_change(
|
||||
struct dc_context *ctx,
|
||||
struct dm_pp_gpu_clock_range *requested_state,
|
||||
struct dm_pp_gpu_clock_range *actual_state)
|
||||
{
|
||||
/*TODO*/
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_apply_safe_state(
|
||||
const struct dc_context *ctx)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
/* TODO: Does this require PreModeChange event to PPLIB? */
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dm_pp_apply_display_requirements(
|
||||
const struct dc_context *ctx,
|
||||
const struct dm_pp_display_configuration *pp_display_cfg)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
|
||||
memset(&adev->pm.pm_display_cfg, 0,
|
||||
sizeof(adev->pm.pm_display_cfg));
|
||||
|
||||
adev->pm.pm_display_cfg.cpu_cc6_disable =
|
||||
pp_display_cfg->cpu_cc6_disable;
|
||||
|
||||
adev->pm.pm_display_cfg.cpu_pstate_disable =
|
||||
pp_display_cfg->cpu_pstate_disable;
|
||||
|
||||
adev->pm.pm_display_cfg.cpu_pstate_separation_time =
|
||||
pp_display_cfg->cpu_pstate_separation_time;
|
||||
|
||||
adev->pm.pm_display_cfg.nb_pstate_switch_disable =
|
||||
pp_display_cfg->nb_pstate_switch_disable;
|
||||
|
||||
adev->pm.pm_display_cfg.num_display =
|
||||
pp_display_cfg->display_count;
|
||||
adev->pm.pm_display_cfg.num_path_including_non_display =
|
||||
pp_display_cfg->display_count;
|
||||
|
||||
adev->pm.pm_display_cfg.min_core_set_clock =
|
||||
pp_display_cfg->min_engine_clock_khz/10;
|
||||
adev->pm.pm_display_cfg.min_core_set_clock_in_sr =
|
||||
pp_display_cfg->min_engine_clock_deep_sleep_khz/10;
|
||||
adev->pm.pm_display_cfg.min_mem_set_clock =
|
||||
pp_display_cfg->min_memory_clock_khz/10;
|
||||
|
||||
adev->pm.pm_display_cfg.multi_monitor_in_sync =
|
||||
pp_display_cfg->all_displays_in_sync;
|
||||
adev->pm.pm_display_cfg.min_vblank_time =
|
||||
pp_display_cfg->avail_mclk_switch_time_us;
|
||||
|
||||
adev->pm.pm_display_cfg.display_clk =
|
||||
pp_display_cfg->disp_clk_khz/10;
|
||||
|
||||
adev->pm.pm_display_cfg.dce_tolerable_mclk_in_active_latency =
|
||||
pp_display_cfg->avail_mclk_switch_time_in_disp_active_us;
|
||||
|
||||
adev->pm.pm_display_cfg.crtc_index = pp_display_cfg->crtc_index;
|
||||
adev->pm.pm_display_cfg.line_time_in_us =
|
||||
pp_display_cfg->line_time_in_us;
|
||||
|
||||
adev->pm.pm_display_cfg.vrefresh = pp_display_cfg->disp_configs[0].v_refresh;
|
||||
adev->pm.pm_display_cfg.crossfire_display_index = -1;
|
||||
adev->pm.pm_display_cfg.min_bus_bandwidth = 0;
|
||||
|
||||
/* TODO: complete implementation of
|
||||
* amd_powerplay_display_configuration_change().
|
||||
* Follow example of:
|
||||
* PHM_StoreDALConfigurationData - powerplay\hwmgr\hardwaremanager.c
|
||||
* PP_IRI_DisplayConfigurationChange - powerplay\eventmgr\iri.c */
|
||||
amd_powerplay_display_configuration_change(
|
||||
adev->powerplay.pp_handle,
|
||||
&adev->pm.pm_display_cfg);
|
||||
|
||||
/* TODO: replace by a separate call to 'apply display cfg'? */
|
||||
amdgpu_pm_compute_clocks(adev);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dc_service_get_system_clocks_range(
|
||||
const struct dc_context *ctx,
|
||||
struct dm_pp_gpu_clock_range *sys_clks)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
|
||||
/* Default values, in case PPLib is not compiled-in. */
|
||||
sys_clks->mclk.max_khz = 800000;
|
||||
sys_clks->mclk.min_khz = 800000;
|
||||
|
||||
sys_clks->sclk.max_khz = 600000;
|
||||
sys_clks->sclk.min_khz = 300000;
|
||||
|
||||
if (adev->pm.dpm_enabled) {
|
||||
sys_clks->mclk.max_khz = amdgpu_dpm_get_mclk(adev, false);
|
||||
sys_clks->mclk.min_khz = amdgpu_dpm_get_mclk(adev, true);
|
||||
|
||||
sys_clks->sclk.max_khz = amdgpu_dpm_get_sclk(adev, false);
|
||||
sys_clks->sclk.min_khz = amdgpu_dpm_get_sclk(adev, true);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void get_default_clock_levels(
|
||||
enum dm_pp_clock_type clk_type,
|
||||
struct dm_pp_clock_levels *clks)
|
||||
{
|
||||
uint32_t disp_clks_in_khz[6] = {
|
||||
300000, 400000, 496560, 626090, 685720, 757900 };
|
||||
uint32_t sclks_in_khz[6] = {
|
||||
300000, 360000, 423530, 514290, 626090, 720000 };
|
||||
uint32_t mclks_in_khz[2] = { 333000, 800000 };
|
||||
|
||||
switch (clk_type) {
|
||||
case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
|
||||
clks->num_levels = 6;
|
||||
memmove(clks->clocks_in_khz, disp_clks_in_khz,
|
||||
sizeof(disp_clks_in_khz));
|
||||
break;
|
||||
case DM_PP_CLOCK_TYPE_ENGINE_CLK:
|
||||
clks->num_levels = 6;
|
||||
memmove(clks->clocks_in_khz, sclks_in_khz,
|
||||
sizeof(sclks_in_khz));
|
||||
break;
|
||||
case DM_PP_CLOCK_TYPE_MEMORY_CLK:
|
||||
clks->num_levels = 2;
|
||||
memmove(clks->clocks_in_khz, mclks_in_khz,
|
||||
sizeof(mclks_in_khz));
|
||||
break;
|
||||
default:
|
||||
clks->num_levels = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
static enum amd_pp_clock_type dc_to_pp_clock_type(
|
||||
enum dm_pp_clock_type dm_pp_clk_type)
|
||||
{
|
||||
enum amd_pp_clock_type amd_pp_clk_type = 0;
|
||||
|
||||
switch (dm_pp_clk_type) {
|
||||
case DM_PP_CLOCK_TYPE_DISPLAY_CLK:
|
||||
amd_pp_clk_type = amd_pp_disp_clock;
|
||||
break;
|
||||
case DM_PP_CLOCK_TYPE_ENGINE_CLK:
|
||||
amd_pp_clk_type = amd_pp_sys_clock;
|
||||
break;
|
||||
case DM_PP_CLOCK_TYPE_MEMORY_CLK:
|
||||
amd_pp_clk_type = amd_pp_mem_clock;
|
||||
break;
|
||||
default:
|
||||
DRM_ERROR("DM_PPLIB: invalid clock type: %d!\n",
|
||||
dm_pp_clk_type);
|
||||
break;
|
||||
}
|
||||
|
||||
return amd_pp_clk_type;
|
||||
}
|
||||
|
||||
static void pp_to_dc_clock_levels(
|
||||
const struct amd_pp_clocks *pp_clks,
|
||||
struct dm_pp_clock_levels *dc_clks,
|
||||
enum dm_pp_clock_type dc_clk_type)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
if (pp_clks->count > DM_PP_MAX_CLOCK_LEVELS) {
|
||||
DRM_INFO("DM_PPLIB: Warning: %s clock: number of levels %d exceeds maximum of %d!\n",
|
||||
DC_DECODE_PP_CLOCK_TYPE(dc_clk_type),
|
||||
pp_clks->count,
|
||||
DM_PP_MAX_CLOCK_LEVELS);
|
||||
|
||||
dc_clks->num_levels = DM_PP_MAX_CLOCK_LEVELS;
|
||||
} else
|
||||
dc_clks->num_levels = pp_clks->count;
|
||||
|
||||
DRM_INFO("DM_PPLIB: values for %s clock\n",
|
||||
DC_DECODE_PP_CLOCK_TYPE(dc_clk_type));
|
||||
|
||||
for (i = 0; i < dc_clks->num_levels; i++) {
|
||||
DRM_INFO("DM_PPLIB:\t %d\n", pp_clks->clock[i]);
|
||||
/* translate 10kHz to kHz */
|
||||
dc_clks->clocks_in_khz[i] = pp_clks->clock[i] * 10;
|
||||
}
|
||||
}
|
||||
|
||||
bool dm_pp_get_clock_levels_by_type(
|
||||
const struct dc_context *ctx,
|
||||
enum dm_pp_clock_type clk_type,
|
||||
struct dm_pp_clock_levels *dc_clks)
|
||||
{
|
||||
struct amdgpu_device *adev = ctx->driver_context;
|
||||
void *pp_handle = adev->powerplay.pp_handle;
|
||||
struct amd_pp_clocks pp_clks = { 0 };
|
||||
struct amd_pp_simple_clock_info validation_clks = { 0 };
|
||||
uint32_t i;
|
||||
|
||||
if (amd_powerplay_get_clock_by_type(pp_handle,
|
||||
dc_to_pp_clock_type(clk_type), &pp_clks)) {
|
||||
/* Error in pplib. Provide default values. */
|
||||
get_default_clock_levels(clk_type, dc_clks);
|
||||
return true;
|
||||
}
|
||||
|
||||
pp_to_dc_clock_levels(&pp_clks, dc_clks, clk_type);
|
||||
|
||||
if (amd_powerplay_get_display_mode_validation_clocks(pp_handle,
|
||||
&validation_clks)) {
|
||||
/* Error in pplib. Provide default values. */
|
||||
DRM_INFO("DM_PPLIB: Warning: using default validation clocks!\n");
|
||||
validation_clks.engine_max_clock = 72000;
|
||||
validation_clks.memory_max_clock = 80000;
|
||||
validation_clks.level = 0;
|
||||
}
|
||||
|
||||
DRM_INFO("DM_PPLIB: Validation clocks:\n");
|
||||
DRM_INFO("DM_PPLIB: engine_max_clock: %d\n",
|
||||
validation_clks.engine_max_clock);
|
||||
DRM_INFO("DM_PPLIB: memory_max_clock: %d\n",
|
||||
validation_clks.memory_max_clock);
|
||||
DRM_INFO("DM_PPLIB: level : %d\n",
|
||||
validation_clks.level);
|
||||
|
||||
/* Translate 10 kHz to kHz. */
|
||||
validation_clks.engine_max_clock *= 10;
|
||||
validation_clks.memory_max_clock *= 10;
|
||||
|
||||
/* Determine the highest non-boosted level from the Validation Clocks */
|
||||
if (clk_type == DM_PP_CLOCK_TYPE_ENGINE_CLK) {
|
||||
for (i = 0; i < dc_clks->num_levels; i++) {
|
||||
if (dc_clks->clocks_in_khz[i] > validation_clks.engine_max_clock) {
|
||||
/* This clock is higher the validation clock.
|
||||
* Than means the previous one is the highest
|
||||
* non-boosted one. */
|
||||
DRM_INFO("DM_PPLIB: reducing engine clock level from %d to %d\n",
|
||||
dc_clks->num_levels, i + 1);
|
||||
dc_clks->num_levels = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (clk_type == DM_PP_CLOCK_TYPE_MEMORY_CLK) {
|
||||
for (i = 0; i < dc_clks->num_levels; i++) {
|
||||
if (dc_clks->clocks_in_khz[i] > validation_clks.memory_max_clock) {
|
||||
DRM_INFO("DM_PPLIB: reducing memory clock level from %d to %d\n",
|
||||
dc_clks->num_levels, i + 1);
|
||||
dc_clks->num_levels = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dm_pp_get_clock_levels_by_type_with_latency(
|
||||
const struct dc_context *ctx,
|
||||
enum dm_pp_clock_type clk_type,
|
||||
struct dm_pp_clock_levels_with_latency *clk_level_info)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_get_clock_levels_by_type_with_voltage(
|
||||
const struct dc_context *ctx,
|
||||
enum dm_pp_clock_type clk_type,
|
||||
struct dm_pp_clock_levels_with_voltage *clk_level_info)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_notify_wm_clock_changes(
|
||||
const struct dc_context *ctx,
|
||||
struct dm_pp_wm_sets_with_clock_ranges *wm_with_clock_ranges)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_apply_power_level_change_request(
|
||||
const struct dc_context *ctx,
|
||||
struct dm_pp_power_level_change_request *level_change_req)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_apply_clock_for_voltage_request(
|
||||
const struct dc_context *ctx,
|
||||
struct dm_pp_clock_for_voltage_req *clock_for_voltage_req)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dm_pp_get_static_clocks(
|
||||
const struct dc_context *ctx,
|
||||
struct dm_pp_static_clock_info *static_clk_info)
|
||||
{
|
||||
/* TODO: to be implemented */
|
||||
return false;
|
||||
}
|
||||
|
||||
/**** end of power component interfaces ****/
|
||||
|
||||
/* Calls to notification */
|
||||
|
||||
void dal_notify_setmode_complete(struct dc_context *ctx,
|
||||
uint32_t h_total,
|
||||
uint32_t v_total,
|
||||
uint32_t h_active,
|
||||
uint32_t v_active,
|
||||
uint32_t pix_clk_in_khz)
|
||||
{
|
||||
/*TODO*/
|
||||
}
|
||||
/* End of calls to notification */
|
||||
|
||||
long dm_get_pid(void)
|
||||
{
|
||||
return current->pid;
|
||||
}
|
||||
|
||||
long dm_get_tgid(void)
|
||||
{
|
||||
return current->tgid;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,101 @@
|
|||
/*
|
||||
* Copyright 2012-13 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_DM_TYPES_H__
|
||||
#define __AMDGPU_DM_TYPES_H__
|
||||
|
||||
#include <drm/drmP.h>
|
||||
|
||||
struct amdgpu_framebuffer;
|
||||
struct amdgpu_display_manager;
|
||||
struct dc_validation_set;
|
||||
struct dc_surface;
|
||||
|
||||
/*TODO Jodan Hersen use the one in amdgpu_dm*/
|
||||
int amdgpu_dm_crtc_init(struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_crtc *amdgpu_crtc,
|
||||
uint32_t link_index);
|
||||
int amdgpu_dm_connector_init(struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_connector *amdgpu_connector,
|
||||
uint32_t link_index,
|
||||
struct amdgpu_encoder *amdgpu_encoder);
|
||||
int amdgpu_dm_encoder_init(
|
||||
struct drm_device *dev,
|
||||
struct amdgpu_encoder *aencoder,
|
||||
uint32_t link_index);
|
||||
|
||||
void amdgpu_dm_crtc_destroy(struct drm_crtc *crtc);
|
||||
void amdgpu_dm_connector_destroy(struct drm_connector *connector);
|
||||
void amdgpu_dm_encoder_destroy(struct drm_encoder *encoder);
|
||||
|
||||
int amdgpu_dm_connector_get_modes(struct drm_connector *connector);
|
||||
|
||||
int amdgpu_dm_atomic_commit(
|
||||
struct drm_device *dev,
|
||||
struct drm_atomic_state *state,
|
||||
bool async);
|
||||
int amdgpu_dm_atomic_check(struct drm_device *dev,
|
||||
struct drm_atomic_state *state);
|
||||
|
||||
int dm_create_validation_set_for_target(
|
||||
struct drm_connector *connector,
|
||||
struct drm_display_mode *mode,
|
||||
struct dc_validation_set *val_set);
|
||||
|
||||
void amdgpu_dm_connector_funcs_reset(struct drm_connector *connector);
|
||||
struct drm_connector_state *amdgpu_dm_connector_atomic_duplicate_state(
|
||||
struct drm_connector *connector);
|
||||
|
||||
int amdgpu_dm_connector_atomic_set_property(
|
||||
struct drm_connector *connector,
|
||||
struct drm_connector_state *state,
|
||||
struct drm_property *property,
|
||||
uint64_t val);
|
||||
|
||||
int amdgpu_dm_get_encoder_crtc_mask(struct amdgpu_device *adev);
|
||||
|
||||
void amdgpu_dm_connector_init_helper(
|
||||
struct amdgpu_display_manager *dm,
|
||||
struct amdgpu_connector *aconnector,
|
||||
int connector_type,
|
||||
const struct dc_link *link,
|
||||
int link_index);
|
||||
|
||||
int amdgpu_dm_connector_mode_valid(
|
||||
struct drm_connector *connector,
|
||||
struct drm_display_mode *mode);
|
||||
|
||||
void dm_restore_drm_connector_state(struct drm_device *dev, struct drm_connector *connector);
|
||||
|
||||
void amdgpu_dm_add_sink_to_freesync_module(
|
||||
struct drm_connector *connector,
|
||||
struct edid *edid);
|
||||
|
||||
void amdgpu_dm_remove_sink_from_freesync_module(
|
||||
struct drm_connector *connector);
|
||||
|
||||
extern const struct drm_encoder_helper_funcs amdgpu_dm_encoder_helper_funcs;
|
||||
|
||||
#endif /* __AMDGPU_DM_TYPES_H__ */
|
|
@ -0,0 +1,28 @@
|
|||
#
|
||||
# Makefile for Display Core (dc) component.
|
||||
#
|
||||
|
||||
DC_LIBS = basics bios calcs dce \
|
||||
gpio gpu i2caux irq virtual
|
||||
|
||||
DC_LIBS += dce112
|
||||
DC_LIBS += dce110
|
||||
DC_LIBS += dce100
|
||||
DC_LIBS += dce80
|
||||
|
||||
AMD_DC = $(addsuffix /Makefile, $(addprefix $(FULL_AMD_DISPLAY_PATH)/dc/,$(DC_LIBS)))
|
||||
|
||||
include $(AMD_DC)
|
||||
|
||||
DISPLAY_CORE = dc.o dc_link.o dc_resource.o dc_hw_sequencer.o dc_target.o dc_sink.o dc_stream.o \
|
||||
dc_surface.o dc_link_hwss.o dc_link_dp.o dc_link_ddc.o dc_debug.o
|
||||
|
||||
AMD_DISPLAY_CORE = $(addprefix $(AMDDALPATH)/dc/core/,$(DISPLAY_CORE))
|
||||
|
||||
AMD_DM_REG_UPDATE = $(addprefix $(AMDDALPATH)/dc/,dc_helper.o)
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DISPLAY_CORE)
|
||||
AMD_DISPLAY_FILES += $(AMD_DM_REG_UPDATE)
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,11 @@
|
|||
#
|
||||
# Makefile for the 'utils' sub-component of DAL.
|
||||
# It provides the general basic services required by other DAL
|
||||
# subcomponents.
|
||||
|
||||
BASICS = conversion.o fixpt31_32.o fixpt32_32.o grph_object_id.o \
|
||||
logger.o log_helpers.o register_logger.o signal_types.o vector.o
|
||||
|
||||
AMD_DAL_BASICS = $(addprefix $(AMDDALPATH)/dc/basics/,$(BASICS))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_BASICS)
|
|
@ -0,0 +1,223 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#define DIVIDER 10000
|
||||
|
||||
/* S2D13 value in [-3.00...0.9999] */
|
||||
#define S2D13_MIN (-3 * DIVIDER)
|
||||
#define S2D13_MAX (3 * DIVIDER)
|
||||
|
||||
uint16_t fixed_point_to_int_frac(
|
||||
struct fixed31_32 arg,
|
||||
uint8_t integer_bits,
|
||||
uint8_t fractional_bits)
|
||||
{
|
||||
int32_t numerator;
|
||||
int32_t divisor = 1 << fractional_bits;
|
||||
|
||||
uint16_t result;
|
||||
|
||||
uint16_t d = (uint16_t)dal_fixed31_32_floor(
|
||||
dal_fixed31_32_abs(
|
||||
arg));
|
||||
|
||||
if (d <= (uint16_t)(1 << integer_bits) - (1 / (uint16_t)divisor))
|
||||
numerator = (uint16_t)dal_fixed31_32_floor(
|
||||
dal_fixed31_32_mul_int(
|
||||
arg,
|
||||
divisor));
|
||||
else {
|
||||
numerator = dal_fixed31_32_floor(
|
||||
dal_fixed31_32_sub(
|
||||
dal_fixed31_32_from_int(
|
||||
1LL << integer_bits),
|
||||
dal_fixed31_32_recip(
|
||||
dal_fixed31_32_from_int(
|
||||
divisor))));
|
||||
}
|
||||
|
||||
if (numerator >= 0)
|
||||
result = (uint16_t)numerator;
|
||||
else
|
||||
result = (uint16_t)(
|
||||
(1 << (integer_bits + fractional_bits + 1)) + numerator);
|
||||
|
||||
if ((result != 0) && dal_fixed31_32_lt(
|
||||
arg, dal_fixed31_32_zero))
|
||||
result |= 1 << (integer_bits + fractional_bits);
|
||||
|
||||
return result;
|
||||
}
|
||||
/**
|
||||
* convert_float_matrix
|
||||
* This converts a double into HW register spec defined format S2D13.
|
||||
* @param :
|
||||
* @return None
|
||||
*/
|
||||
void convert_float_matrix(
|
||||
uint16_t *matrix,
|
||||
struct fixed31_32 *flt,
|
||||
uint32_t buffer_size)
|
||||
{
|
||||
const struct fixed31_32 min_2_13 =
|
||||
dal_fixed31_32_from_fraction(S2D13_MIN, DIVIDER);
|
||||
const struct fixed31_32 max_2_13 =
|
||||
dal_fixed31_32_from_fraction(S2D13_MAX, DIVIDER);
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < buffer_size; ++i) {
|
||||
uint32_t reg_value =
|
||||
fixed_point_to_int_frac(
|
||||
dal_fixed31_32_clamp(
|
||||
flt[i],
|
||||
min_2_13,
|
||||
max_2_13),
|
||||
2,
|
||||
13);
|
||||
|
||||
matrix[i] = (uint16_t)reg_value;
|
||||
}
|
||||
}
|
||||
|
||||
static void calculate_adjustments_common(
|
||||
const struct fixed31_32 *ideal_matrix,
|
||||
const struct dc_csc_adjustments *adjustments,
|
||||
struct fixed31_32 *matrix)
|
||||
{
|
||||
const struct fixed31_32 sin_hue =
|
||||
dal_fixed31_32_sin(adjustments->hue);
|
||||
const struct fixed31_32 cos_hue =
|
||||
dal_fixed31_32_cos(adjustments->hue);
|
||||
|
||||
const struct fixed31_32 multiplier =
|
||||
dal_fixed31_32_mul(
|
||||
adjustments->contrast,
|
||||
adjustments->saturation);
|
||||
|
||||
matrix[0] = dal_fixed31_32_mul(
|
||||
ideal_matrix[0],
|
||||
adjustments->contrast);
|
||||
|
||||
matrix[1] = dal_fixed31_32_mul(
|
||||
ideal_matrix[1],
|
||||
adjustments->contrast);
|
||||
|
||||
matrix[2] = dal_fixed31_32_mul(
|
||||
ideal_matrix[2],
|
||||
adjustments->contrast);
|
||||
|
||||
matrix[4] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_add(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[8],
|
||||
sin_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[4],
|
||||
cos_hue)));
|
||||
|
||||
matrix[5] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_add(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[9],
|
||||
sin_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[5],
|
||||
cos_hue)));
|
||||
|
||||
matrix[6] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_add(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[10],
|
||||
sin_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[6],
|
||||
cos_hue)));
|
||||
|
||||
matrix[7] = ideal_matrix[7];
|
||||
|
||||
matrix[8] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_sub(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[8],
|
||||
cos_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[4],
|
||||
sin_hue)));
|
||||
|
||||
matrix[9] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_sub(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[9],
|
||||
cos_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[5],
|
||||
sin_hue)));
|
||||
|
||||
matrix[10] = dal_fixed31_32_mul(
|
||||
multiplier,
|
||||
dal_fixed31_32_sub(
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[10],
|
||||
cos_hue),
|
||||
dal_fixed31_32_mul(
|
||||
ideal_matrix[6],
|
||||
sin_hue)));
|
||||
|
||||
matrix[11] = ideal_matrix[11];
|
||||
}
|
||||
|
||||
void calculate_adjustments(
|
||||
const struct fixed31_32 *ideal_matrix,
|
||||
const struct dc_csc_adjustments *adjustments,
|
||||
struct fixed31_32 *matrix)
|
||||
{
|
||||
calculate_adjustments_common(ideal_matrix, adjustments, matrix);
|
||||
|
||||
matrix[3] = dal_fixed31_32_add(
|
||||
ideal_matrix[3],
|
||||
dal_fixed31_32_mul(
|
||||
adjustments->brightness,
|
||||
dal_fixed31_32_from_fraction(86, 100)));
|
||||
}
|
||||
|
||||
void calculate_adjustments_y_only(
|
||||
const struct fixed31_32 *ideal_matrix,
|
||||
const struct dc_csc_adjustments *adjustments,
|
||||
struct fixed31_32 *matrix)
|
||||
{
|
||||
calculate_adjustments_common(ideal_matrix, adjustments, matrix);
|
||||
|
||||
matrix[3] = dal_fixed31_32_add(
|
||||
ideal_matrix[3],
|
||||
adjustments->brightness);
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_CONVERSION_H__
|
||||
#define __DAL_CONVERSION_H__
|
||||
|
||||
#include "include/fixed31_32.h"
|
||||
|
||||
uint16_t fixed_point_to_int_frac(
|
||||
struct fixed31_32 arg,
|
||||
uint8_t integer_bits,
|
||||
uint8_t fractional_bits);
|
||||
|
||||
void convert_float_matrix(
|
||||
uint16_t *matrix,
|
||||
struct fixed31_32 *flt,
|
||||
uint32_t buffer_size);
|
||||
|
||||
void calculate_adjustments(
|
||||
const struct fixed31_32 *ideal_matrix,
|
||||
const struct dc_csc_adjustments *adjustments,
|
||||
struct fixed31_32 *matrix);
|
||||
|
||||
void calculate_adjustments_y_only(
|
||||
const struct fixed31_32 *ideal_matrix,
|
||||
const struct dc_csc_adjustments *adjustments,
|
||||
struct fixed31_32 *matrix);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,691 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/fixed31_32.h"
|
||||
|
||||
static inline uint64_t abs_i64(
|
||||
int64_t arg)
|
||||
{
|
||||
if (arg > 0)
|
||||
return (uint64_t)arg;
|
||||
else
|
||||
return (uint64_t)(-arg);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* result = dividend / divisor
|
||||
* *remainder = dividend % divisor
|
||||
*/
|
||||
static inline uint64_t complete_integer_division_u64(
|
||||
uint64_t dividend,
|
||||
uint64_t divisor,
|
||||
uint64_t *remainder)
|
||||
{
|
||||
uint64_t result;
|
||||
|
||||
ASSERT(divisor);
|
||||
|
||||
result = div64_u64_rem(dividend, divisor, remainder);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#define BITS_PER_FRACTIONAL_PART \
|
||||
32
|
||||
|
||||
#define FRACTIONAL_PART_MASK \
|
||||
((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
|
||||
|
||||
#define GET_INTEGER_PART(x) \
|
||||
((x) >> BITS_PER_FRACTIONAL_PART)
|
||||
|
||||
#define GET_FRACTIONAL_PART(x) \
|
||||
(FRACTIONAL_PART_MASK & (x))
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_from_fraction(
|
||||
int64_t numerator,
|
||||
int64_t denominator)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
bool arg1_negative = numerator < 0;
|
||||
bool arg2_negative = denominator < 0;
|
||||
|
||||
uint64_t arg1_value = arg1_negative ? -numerator : numerator;
|
||||
uint64_t arg2_value = arg2_negative ? -denominator : denominator;
|
||||
|
||||
uint64_t remainder;
|
||||
|
||||
/* determine integer part */
|
||||
|
||||
uint64_t res_value = complete_integer_division_u64(
|
||||
arg1_value, arg2_value, &remainder);
|
||||
|
||||
ASSERT(res_value <= LONG_MAX);
|
||||
|
||||
/* determine fractional part */
|
||||
{
|
||||
uint32_t i = BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
do {
|
||||
remainder <<= 1;
|
||||
|
||||
res_value <<= 1;
|
||||
|
||||
if (remainder >= arg2_value) {
|
||||
res_value |= 1;
|
||||
remainder -= arg2_value;
|
||||
}
|
||||
} while (--i != 0);
|
||||
}
|
||||
|
||||
/* round up LSB */
|
||||
{
|
||||
uint64_t summand = (remainder << 1) >= arg2_value;
|
||||
|
||||
ASSERT(res_value <= LLONG_MAX - summand);
|
||||
|
||||
res_value += summand;
|
||||
}
|
||||
|
||||
res.value = (int64_t)res_value;
|
||||
|
||||
if (arg1_negative ^ arg2_negative)
|
||||
res.value = -res.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_from_int(
|
||||
int64_t arg)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
ASSERT((LONG_MIN <= arg) && (arg <= LONG_MAX));
|
||||
|
||||
res.value = arg << BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_neg(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
res.value = -arg.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_abs(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
if (arg.value < 0)
|
||||
return dal_fixed31_32_neg(arg);
|
||||
else
|
||||
return arg;
|
||||
}
|
||||
|
||||
bool dal_fixed31_32_lt(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
return arg1.value < arg2.value;
|
||||
}
|
||||
|
||||
bool dal_fixed31_32_le(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
return arg1.value <= arg2.value;
|
||||
}
|
||||
|
||||
bool dal_fixed31_32_eq(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
return arg1.value == arg2.value;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_min(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
if (arg1.value <= arg2.value)
|
||||
return arg1;
|
||||
else
|
||||
return arg2;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_max(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
if (arg1.value <= arg2.value)
|
||||
return arg2;
|
||||
else
|
||||
return arg1;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_clamp(
|
||||
struct fixed31_32 arg,
|
||||
struct fixed31_32 min_value,
|
||||
struct fixed31_32 max_value)
|
||||
{
|
||||
if (dal_fixed31_32_le(arg, min_value))
|
||||
return min_value;
|
||||
else if (dal_fixed31_32_le(max_value, arg))
|
||||
return max_value;
|
||||
else
|
||||
return arg;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_shl(
|
||||
struct fixed31_32 arg,
|
||||
uint8_t shift)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
ASSERT(((arg.value >= 0) && (arg.value <= LLONG_MAX >> shift)) ||
|
||||
((arg.value < 0) && (arg.value >= LLONG_MIN >> shift)));
|
||||
|
||||
res.value = arg.value << shift;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_shr(
|
||||
struct fixed31_32 arg,
|
||||
uint8_t shift)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
ASSERT(shift < 64);
|
||||
|
||||
res.value = arg.value >> shift;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_add(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
ASSERT(((arg1.value >= 0) && (LLONG_MAX - arg1.value >= arg2.value)) ||
|
||||
((arg1.value < 0) && (LLONG_MIN - arg1.value <= arg2.value)));
|
||||
|
||||
res.value = arg1.value + arg2.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_sub_int(
|
||||
struct fixed31_32 arg1,
|
||||
int32_t arg2)
|
||||
{
|
||||
return dal_fixed31_32_sub(
|
||||
arg1,
|
||||
dal_fixed31_32_from_int(arg2));
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_sub(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
ASSERT(((arg2.value >= 0) && (LLONG_MIN + arg2.value <= arg1.value)) ||
|
||||
((arg2.value < 0) && (LLONG_MAX + arg2.value >= arg1.value)));
|
||||
|
||||
res.value = arg1.value - arg2.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_mul_int(
|
||||
struct fixed31_32 arg1,
|
||||
int32_t arg2)
|
||||
{
|
||||
return dal_fixed31_32_mul(
|
||||
arg1,
|
||||
dal_fixed31_32_from_int(arg2));
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_mul(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
bool arg1_negative = arg1.value < 0;
|
||||
bool arg2_negative = arg2.value < 0;
|
||||
|
||||
uint64_t arg1_value = arg1_negative ? -arg1.value : arg1.value;
|
||||
uint64_t arg2_value = arg2_negative ? -arg2.value : arg2.value;
|
||||
|
||||
uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
|
||||
uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
|
||||
|
||||
uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
|
||||
uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
|
||||
|
||||
uint64_t tmp;
|
||||
|
||||
res.value = arg1_int * arg2_int;
|
||||
|
||||
ASSERT(res.value <= LONG_MAX);
|
||||
|
||||
res.value <<= BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
tmp = arg1_int * arg2_fra;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
tmp = arg2_int * arg1_fra;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
tmp = arg1_fra * arg2_fra;
|
||||
|
||||
tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
|
||||
(tmp >= (uint64_t)dal_fixed31_32_half.value);
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
if (arg1_negative ^ arg2_negative)
|
||||
res.value = -res.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_sqr(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
struct fixed31_32 res;
|
||||
|
||||
uint64_t arg_value = abs_i64(arg.value);
|
||||
|
||||
uint64_t arg_int = GET_INTEGER_PART(arg_value);
|
||||
|
||||
uint64_t arg_fra = GET_FRACTIONAL_PART(arg_value);
|
||||
|
||||
uint64_t tmp;
|
||||
|
||||
res.value = arg_int * arg_int;
|
||||
|
||||
ASSERT(res.value <= LONG_MAX);
|
||||
|
||||
res.value <<= BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
tmp = arg_int * arg_fra;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
tmp = arg_fra * arg_fra;
|
||||
|
||||
tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
|
||||
(tmp >= (uint64_t)dal_fixed31_32_half.value);
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(LLONG_MAX - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_div_int(
|
||||
struct fixed31_32 arg1,
|
||||
int64_t arg2)
|
||||
{
|
||||
return dal_fixed31_32_from_fraction(
|
||||
arg1.value,
|
||||
dal_fixed31_32_from_int(arg2).value);
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_div(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
return dal_fixed31_32_from_fraction(
|
||||
arg1.value,
|
||||
arg2.value);
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_recip(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
/*
|
||||
* @note
|
||||
* Good idea to use Newton's method
|
||||
*/
|
||||
|
||||
ASSERT(arg.value);
|
||||
|
||||
return dal_fixed31_32_from_fraction(
|
||||
dal_fixed31_32_one.value,
|
||||
arg.value);
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_sinc(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
struct fixed31_32 square;
|
||||
|
||||
struct fixed31_32 res = dal_fixed31_32_one;
|
||||
|
||||
int32_t n = 27;
|
||||
|
||||
struct fixed31_32 arg_norm = arg;
|
||||
|
||||
if (dal_fixed31_32_le(
|
||||
dal_fixed31_32_two_pi,
|
||||
dal_fixed31_32_abs(arg))) {
|
||||
arg_norm = dal_fixed31_32_sub(
|
||||
arg_norm,
|
||||
dal_fixed31_32_mul_int(
|
||||
dal_fixed31_32_two_pi,
|
||||
(int32_t)div64_s64(
|
||||
arg_norm.value,
|
||||
dal_fixed31_32_two_pi.value)));
|
||||
}
|
||||
|
||||
square = dal_fixed31_32_sqr(arg_norm);
|
||||
|
||||
do {
|
||||
res = dal_fixed31_32_sub(
|
||||
dal_fixed31_32_one,
|
||||
dal_fixed31_32_div_int(
|
||||
dal_fixed31_32_mul(
|
||||
square,
|
||||
res),
|
||||
n * (n - 1)));
|
||||
|
||||
n -= 2;
|
||||
} while (n > 2);
|
||||
|
||||
if (arg.value != arg_norm.value)
|
||||
res = dal_fixed31_32_div(
|
||||
dal_fixed31_32_mul(res, arg_norm),
|
||||
arg);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_sin(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
return dal_fixed31_32_mul(
|
||||
arg,
|
||||
dal_fixed31_32_sinc(arg));
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_cos(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
/* TODO implement argument normalization */
|
||||
|
||||
const struct fixed31_32 square = dal_fixed31_32_sqr(arg);
|
||||
|
||||
struct fixed31_32 res = dal_fixed31_32_one;
|
||||
|
||||
int32_t n = 26;
|
||||
|
||||
do {
|
||||
res = dal_fixed31_32_sub(
|
||||
dal_fixed31_32_one,
|
||||
dal_fixed31_32_div_int(
|
||||
dal_fixed31_32_mul(
|
||||
square,
|
||||
res),
|
||||
n * (n - 1)));
|
||||
|
||||
n -= 2;
|
||||
} while (n != 0);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* result = exp(arg),
|
||||
* where abs(arg) < 1
|
||||
*
|
||||
* Calculated as Taylor series.
|
||||
*/
|
||||
static struct fixed31_32 fixed31_32_exp_from_taylor_series(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
uint32_t n = 9;
|
||||
|
||||
struct fixed31_32 res = dal_fixed31_32_from_fraction(
|
||||
n + 2,
|
||||
n + 1);
|
||||
/* TODO find correct res */
|
||||
|
||||
ASSERT(dal_fixed31_32_lt(arg, dal_fixed31_32_one));
|
||||
|
||||
do
|
||||
res = dal_fixed31_32_add(
|
||||
dal_fixed31_32_one,
|
||||
dal_fixed31_32_div_int(
|
||||
dal_fixed31_32_mul(
|
||||
arg,
|
||||
res),
|
||||
n));
|
||||
while (--n != 1);
|
||||
|
||||
return dal_fixed31_32_add(
|
||||
dal_fixed31_32_one,
|
||||
dal_fixed31_32_mul(
|
||||
arg,
|
||||
res));
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_exp(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
/*
|
||||
* @brief
|
||||
* Main equation is:
|
||||
* exp(x) = exp(r + m * ln(2)) = (1 << m) * exp(r),
|
||||
* where m = round(x / ln(2)), r = x - m * ln(2)
|
||||
*/
|
||||
|
||||
if (dal_fixed31_32_le(
|
||||
dal_fixed31_32_ln2_div_2,
|
||||
dal_fixed31_32_abs(arg))) {
|
||||
int32_t m = dal_fixed31_32_round(
|
||||
dal_fixed31_32_div(
|
||||
arg,
|
||||
dal_fixed31_32_ln2));
|
||||
|
||||
struct fixed31_32 r = dal_fixed31_32_sub(
|
||||
arg,
|
||||
dal_fixed31_32_mul_int(
|
||||
dal_fixed31_32_ln2,
|
||||
m));
|
||||
|
||||
ASSERT(m != 0);
|
||||
|
||||
ASSERT(dal_fixed31_32_lt(
|
||||
dal_fixed31_32_abs(r),
|
||||
dal_fixed31_32_one));
|
||||
|
||||
if (m > 0)
|
||||
return dal_fixed31_32_shl(
|
||||
fixed31_32_exp_from_taylor_series(r),
|
||||
(uint8_t)m);
|
||||
else
|
||||
return dal_fixed31_32_div_int(
|
||||
fixed31_32_exp_from_taylor_series(r),
|
||||
1LL << -m);
|
||||
} else if (arg.value != 0)
|
||||
return fixed31_32_exp_from_taylor_series(arg);
|
||||
else
|
||||
return dal_fixed31_32_one;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_log(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
struct fixed31_32 res = dal_fixed31_32_neg(dal_fixed31_32_one);
|
||||
/* TODO improve 1st estimation */
|
||||
|
||||
struct fixed31_32 error;
|
||||
|
||||
ASSERT(arg.value > 0);
|
||||
/* TODO if arg is negative, return NaN */
|
||||
/* TODO if arg is zero, return -INF */
|
||||
|
||||
do {
|
||||
struct fixed31_32 res1 = dal_fixed31_32_add(
|
||||
dal_fixed31_32_sub(
|
||||
res,
|
||||
dal_fixed31_32_one),
|
||||
dal_fixed31_32_div(
|
||||
arg,
|
||||
dal_fixed31_32_exp(res)));
|
||||
|
||||
error = dal_fixed31_32_sub(
|
||||
res,
|
||||
res1);
|
||||
|
||||
res = res1;
|
||||
/* TODO determine max_allowed_error based on quality of exp() */
|
||||
} while (abs_i64(error.value) > 100ULL);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct fixed31_32 dal_fixed31_32_pow(
|
||||
struct fixed31_32 arg1,
|
||||
struct fixed31_32 arg2)
|
||||
{
|
||||
return dal_fixed31_32_exp(
|
||||
dal_fixed31_32_mul(
|
||||
dal_fixed31_32_log(arg1),
|
||||
arg2));
|
||||
}
|
||||
|
||||
int32_t dal_fixed31_32_floor(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
uint64_t arg_value = abs_i64(arg.value);
|
||||
|
||||
if (arg.value >= 0)
|
||||
return (int32_t)GET_INTEGER_PART(arg_value);
|
||||
else
|
||||
return -(int32_t)GET_INTEGER_PART(arg_value);
|
||||
}
|
||||
|
||||
int32_t dal_fixed31_32_round(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
uint64_t arg_value = abs_i64(arg.value);
|
||||
|
||||
const int64_t summand = dal_fixed31_32_half.value;
|
||||
|
||||
ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
|
||||
|
||||
arg_value += summand;
|
||||
|
||||
if (arg.value >= 0)
|
||||
return (int32_t)GET_INTEGER_PART(arg_value);
|
||||
else
|
||||
return -(int32_t)GET_INTEGER_PART(arg_value);
|
||||
}
|
||||
|
||||
int32_t dal_fixed31_32_ceil(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
uint64_t arg_value = abs_i64(arg.value);
|
||||
|
||||
const int64_t summand = dal_fixed31_32_one.value -
|
||||
dal_fixed31_32_epsilon.value;
|
||||
|
||||
ASSERT(LLONG_MAX - (int64_t)arg_value >= summand);
|
||||
|
||||
arg_value += summand;
|
||||
|
||||
if (arg.value >= 0)
|
||||
return (int32_t)GET_INTEGER_PART(arg_value);
|
||||
else
|
||||
return -(int32_t)GET_INTEGER_PART(arg_value);
|
||||
}
|
||||
|
||||
/* this function is a generic helper to translate fixed point value to
|
||||
* specified integer format that will consist of integer_bits integer part and
|
||||
* fractional_bits fractional part. For example it is used in
|
||||
* dal_fixed31_32_u2d19 to receive 2 bits integer part and 19 bits fractional
|
||||
* part in 32 bits. It is used in hw programming (scaler)
|
||||
*/
|
||||
|
||||
static inline uint32_t ux_dy(
|
||||
int64_t value,
|
||||
uint32_t integer_bits,
|
||||
uint32_t fractional_bits)
|
||||
{
|
||||
/* 1. create mask of integer part */
|
||||
uint32_t result = (1 << integer_bits) - 1;
|
||||
/* 2. mask out fractional part */
|
||||
uint32_t fractional_part = FRACTIONAL_PART_MASK & value;
|
||||
/* 3. shrink fixed point integer part to be of integer_bits width*/
|
||||
result &= GET_INTEGER_PART(value);
|
||||
/* 4. make space for fractional part to be filled in after integer */
|
||||
result <<= fractional_bits;
|
||||
/* 5. shrink fixed point fractional part to of fractional_bits width*/
|
||||
fractional_part >>= BITS_PER_FRACTIONAL_PART - fractional_bits;
|
||||
/* 6. merge the result */
|
||||
return result | fractional_part;
|
||||
}
|
||||
|
||||
uint32_t dal_fixed31_32_u2d19(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
return ux_dy(arg.value, 2, 19);
|
||||
}
|
||||
|
||||
uint32_t dal_fixed31_32_u0d19(
|
||||
struct fixed31_32 arg)
|
||||
{
|
||||
return ux_dy(arg.value, 0, 19);
|
||||
}
|
|
@ -0,0 +1,221 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/fixed32_32.h"
|
||||
|
||||
static uint64_t u64_div(uint64_t n, uint64_t d)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
uint64_t r;
|
||||
uint64_t q = div64_u64_rem(n, d, &r);
|
||||
|
||||
for (i = 0; i < 32; ++i) {
|
||||
uint64_t sbit = q & (1ULL<<63);
|
||||
|
||||
r <<= 1;
|
||||
r |= sbit ? 1 : 0;
|
||||
q <<= 1;
|
||||
if (r >= d) {
|
||||
r -= d;
|
||||
q |= 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (2*r >= d)
|
||||
q += 1;
|
||||
return q;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_from_fraction(uint32_t n, uint32_t d)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
fx.value = u64_div((uint64_t)n << 32, (uint64_t)d << 32);
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_from_int(uint32_t value)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
fx.value = (uint64_t)value<<32;
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_add(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
struct fixed32_32 fx = {lhs.value + rhs.value};
|
||||
|
||||
ASSERT(fx.value >= rhs.value);
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_add_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
struct fixed32_32 fx = {lhs.value + ((uint64_t)rhs << 32)};
|
||||
|
||||
ASSERT(fx.value >= (uint64_t)rhs << 32);
|
||||
return fx;
|
||||
|
||||
}
|
||||
struct fixed32_32 dal_fixed32_32_sub(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
ASSERT(lhs.value >= rhs.value);
|
||||
fx.value = lhs.value - rhs.value;
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_sub_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
ASSERT(lhs.value >= ((uint64_t)rhs<<32));
|
||||
fx.value = lhs.value - ((uint64_t)rhs<<32);
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_mul(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
uint64_t lhs_int = lhs.value>>32;
|
||||
uint64_t lhs_frac = (uint32_t)lhs.value;
|
||||
uint64_t rhs_int = rhs.value>>32;
|
||||
uint64_t rhs_frac = (uint32_t)rhs.value;
|
||||
uint64_t ahbh = lhs_int * rhs_int;
|
||||
uint64_t ahbl = lhs_int * rhs_frac;
|
||||
uint64_t albh = lhs_frac * rhs_int;
|
||||
uint64_t albl = lhs_frac * rhs_frac;
|
||||
|
||||
ASSERT((ahbh>>32) == 0);
|
||||
|
||||
fx.value = (ahbh<<32) + ahbl + albh + (albl>>32);
|
||||
return fx;
|
||||
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_mul_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
uint64_t lhsi = (lhs.value>>32) * (uint64_t)rhs;
|
||||
uint64_t lhsf;
|
||||
|
||||
ASSERT((lhsi>>32) == 0);
|
||||
lhsf = ((uint32_t)lhs.value) * (uint64_t)rhs;
|
||||
ASSERT((lhsi<<32) + lhsf >= lhsf);
|
||||
fx.value = (lhsi<<32) + lhsf;
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_div(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
fx.value = u64_div(lhs.value, rhs.value);
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_div_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
struct fixed32_32 fx;
|
||||
|
||||
fx.value = u64_div(lhs.value, (uint64_t)rhs << 32);
|
||||
return fx;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_min(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
return (lhs.value < rhs.value) ? lhs : rhs;
|
||||
}
|
||||
|
||||
struct fixed32_32 dal_fixed32_32_max(
|
||||
struct fixed32_32 lhs,
|
||||
struct fixed32_32 rhs)
|
||||
{
|
||||
return (lhs.value > rhs.value) ? lhs : rhs;
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_gt(struct fixed32_32 lhs, struct fixed32_32 rhs)
|
||||
{
|
||||
return lhs.value > rhs.value;
|
||||
}
|
||||
bool dal_fixed32_32_gt_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
return lhs.value > ((uint64_t)rhs<<32);
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_lt(struct fixed32_32 lhs, struct fixed32_32 rhs)
|
||||
{
|
||||
return lhs.value < rhs.value;
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_le(struct fixed32_32 lhs, struct fixed32_32 rhs)
|
||||
{
|
||||
return lhs.value <= rhs.value;
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_lt_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
return lhs.value < ((uint64_t)rhs<<32);
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_le_int(struct fixed32_32 lhs, uint32_t rhs)
|
||||
{
|
||||
return lhs.value <= ((uint64_t)rhs<<32);
|
||||
}
|
||||
|
||||
uint32_t dal_fixed32_32_ceil(struct fixed32_32 v)
|
||||
{
|
||||
ASSERT((uint32_t)v.value ? (v.value >> 32) + 1 >= 1 : true);
|
||||
return (v.value>>32) + ((uint32_t)v.value ? 1 : 0);
|
||||
}
|
||||
|
||||
uint32_t dal_fixed32_32_floor(struct fixed32_32 v)
|
||||
{
|
||||
return v.value>>32;
|
||||
}
|
||||
|
||||
uint32_t dal_fixed32_32_round(struct fixed32_32 v)
|
||||
{
|
||||
ASSERT(v.value + (1ULL<<31) >= (1ULL<<31));
|
||||
return (v.value + (1ULL<<31))>>32;
|
||||
}
|
||||
|
||||
bool dal_fixed32_32_eq(struct fixed32_32 lhs, struct fixed32_32 rhs)
|
||||
{
|
||||
return lhs.value == rhs.value;
|
||||
}
|
|
@ -0,0 +1,134 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/grph_object_id.h"
|
||||
|
||||
bool dal_graphics_object_id_is_valid(struct graphics_object_id id)
|
||||
{
|
||||
bool rc = true;
|
||||
|
||||
switch (id.type) {
|
||||
case OBJECT_TYPE_UNKNOWN:
|
||||
rc = false;
|
||||
break;
|
||||
case OBJECT_TYPE_GPU:
|
||||
case OBJECT_TYPE_ENGINE:
|
||||
/* do NOT check for id.id == 0 */
|
||||
if (id.enum_id == ENUM_ID_UNKNOWN)
|
||||
rc = false;
|
||||
break;
|
||||
default:
|
||||
if (id.id == 0 || id.enum_id == ENUM_ID_UNKNOWN)
|
||||
rc = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
bool dal_graphics_object_id_is_equal(
|
||||
struct graphics_object_id id1,
|
||||
struct graphics_object_id id2)
|
||||
{
|
||||
if (false == dal_graphics_object_id_is_valid(id1)) {
|
||||
dm_output_to_console(
|
||||
"%s: Warning: comparing invalid object 'id1'!\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (false == dal_graphics_object_id_is_valid(id2)) {
|
||||
dm_output_to_console(
|
||||
"%s: Warning: comparing invalid object 'id2'!\n", __func__);
|
||||
return false;
|
||||
}
|
||||
|
||||
if (id1.id == id2.id && id1.enum_id == id2.enum_id
|
||||
&& id1.type == id2.type)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Based on internal data members memory layout */
|
||||
uint32_t dal_graphics_object_id_to_uint(struct graphics_object_id id)
|
||||
{
|
||||
uint32_t object_id = 0;
|
||||
|
||||
object_id = id.id + (id.enum_id << 0x8) + (id.type << 0xc);
|
||||
return object_id;
|
||||
}
|
||||
|
||||
/*
|
||||
* ******* get specific ID - internal safe cast into specific type *******
|
||||
*/
|
||||
|
||||
enum controller_id dal_graphics_object_id_get_controller_id(
|
||||
struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_CONTROLLER)
|
||||
return id.id;
|
||||
return CONTROLLER_ID_UNDEFINED;
|
||||
}
|
||||
|
||||
enum clock_source_id dal_graphics_object_id_get_clock_source_id(
|
||||
struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_CLOCK_SOURCE)
|
||||
return id.id;
|
||||
return CLOCK_SOURCE_ID_UNDEFINED;
|
||||
}
|
||||
|
||||
enum encoder_id dal_graphics_object_id_get_encoder_id(
|
||||
struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_ENCODER)
|
||||
return id.id;
|
||||
return ENCODER_ID_UNKNOWN;
|
||||
}
|
||||
|
||||
enum connector_id dal_graphics_object_id_get_connector_id(
|
||||
struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_CONNECTOR)
|
||||
return id.id;
|
||||
return CONNECTOR_ID_UNKNOWN;
|
||||
}
|
||||
|
||||
enum audio_id dal_graphics_object_id_get_audio_id(struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_AUDIO)
|
||||
return id.id;
|
||||
return AUDIO_ID_UNKNOWN;
|
||||
}
|
||||
|
||||
enum engine_id dal_graphics_object_id_get_engine_id(
|
||||
struct graphics_object_id id)
|
||||
{
|
||||
if (id.type == OBJECT_TYPE_ENGINE)
|
||||
return id.id;
|
||||
return ENGINE_ID_UNKNOWN;
|
||||
}
|
||||
|
|
@ -0,0 +1,100 @@
|
|||
/*
|
||||
* Copyright 2012-16 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 "core_types.h"
|
||||
#include "logger.h"
|
||||
#include "include/logger_interface.h"
|
||||
|
||||
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
struct dc_signal_type_info {
|
||||
enum signal_type type;
|
||||
char name[MAX_NAME_LEN];
|
||||
};
|
||||
|
||||
static const struct dc_signal_type_info signal_type_info_tbl[] = {
|
||||
{SIGNAL_TYPE_NONE, "NC"},
|
||||
{SIGNAL_TYPE_DVI_SINGLE_LINK, "DVI"},
|
||||
{SIGNAL_TYPE_DVI_DUAL_LINK, "DDVI"},
|
||||
{SIGNAL_TYPE_HDMI_TYPE_A, "HDMIA"},
|
||||
{SIGNAL_TYPE_LVDS, "LVDS"},
|
||||
{SIGNAL_TYPE_RGB, "VGA"},
|
||||
{SIGNAL_TYPE_DISPLAY_PORT, "DP"},
|
||||
{SIGNAL_TYPE_DISPLAY_PORT_MST, "MST"},
|
||||
{SIGNAL_TYPE_EDP, "eDP"},
|
||||
{SIGNAL_TYPE_WIRELESS, "Wireless"},
|
||||
{SIGNAL_TYPE_VIRTUAL, "Virtual"}
|
||||
};
|
||||
|
||||
void dc_conn_log(struct dc_context *ctx,
|
||||
const struct dc_link *link,
|
||||
uint8_t *hex_data,
|
||||
int hex_data_count,
|
||||
enum dc_log_type event,
|
||||
const char *msg,
|
||||
...)
|
||||
{
|
||||
int i;
|
||||
va_list args;
|
||||
struct log_entry entry = { 0 };
|
||||
enum signal_type signal;
|
||||
|
||||
if (link->local_sink)
|
||||
signal = link->local_sink->sink_signal;
|
||||
else
|
||||
signal = link->connector_signal;
|
||||
|
||||
if (link->type == dc_connection_mst_branch)
|
||||
signal = SIGNAL_TYPE_DISPLAY_PORT_MST;
|
||||
|
||||
dm_logger_open(ctx->logger, &entry, event);
|
||||
|
||||
for (i = 0; i < NUM_ELEMENTS(signal_type_info_tbl); i++)
|
||||
if (signal == signal_type_info_tbl[i].type)
|
||||
break;
|
||||
|
||||
dm_logger_append(&entry, "[%s][ConnIdx:%d] ",
|
||||
signal_type_info_tbl[i].name,
|
||||
link->link_index);
|
||||
|
||||
va_start(args, msg);
|
||||
entry.buf_offset += dm_log_to_buffer(
|
||||
&entry.buf[entry.buf_offset],
|
||||
LOG_MAX_LINE_SIZE - entry.buf_offset,
|
||||
msg, args);
|
||||
|
||||
if (entry.buf[strlen(entry.buf) - 1] == '\n') {
|
||||
entry.buf[strlen(entry.buf) - 1] = '\0';
|
||||
entry.buf_offset--;
|
||||
}
|
||||
|
||||
if (hex_data)
|
||||
for (i = 0; i < hex_data_count; i++)
|
||||
dm_logger_append(&entry, "%2.2X ", hex_data[i]);
|
||||
|
||||
dm_logger_append(&entry, "^\n");
|
||||
dm_logger_close(&entry);
|
||||
va_end(args);
|
||||
}
|
|
@ -0,0 +1,457 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/logger_interface.h"
|
||||
#include "logger.h"
|
||||
|
||||
|
||||
#define NUM_ELEMENTS(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
static const struct dc_log_type_info log_type_info_tbl[] = {
|
||||
{LOG_ERROR, "Error"},
|
||||
{LOG_WARNING, "Warning"},
|
||||
{LOG_DC, "DC_Interface"},
|
||||
{LOG_SURFACE, "Surface"},
|
||||
{LOG_HW_HOTPLUG, "HW_Hotplug"},
|
||||
{LOG_HW_LINK_TRAINING, "HW_LKTN"},
|
||||
{LOG_HW_SET_MODE, "HW_Mode"},
|
||||
{LOG_HW_RESUME_S3, "HW_Resume"},
|
||||
{LOG_HW_AUDIO, "HW_Audio"},
|
||||
{LOG_HW_HPD_IRQ, "HW_HPDIRQ"},
|
||||
{LOG_MST, "MST"},
|
||||
{LOG_SCALER, "Scaler"},
|
||||
{LOG_BIOS, "BIOS"},
|
||||
{LOG_BANDWIDTH_CALCS, "BWCalcs"},
|
||||
{LOG_BANDWIDTH_VALIDATION, "BWValidation"},
|
||||
{LOG_I2C_AUX, "I2C_AUX"},
|
||||
{LOG_SYNC, "Sync"},
|
||||
{LOG_BACKLIGHT, "Backlight"},
|
||||
{LOG_FEATURE_OVERRIDE, "Override"},
|
||||
{LOG_DETECTION_EDID_PARSER, "Edid"},
|
||||
{LOG_DETECTION_DP_CAPS, "DP_Caps"},
|
||||
{LOG_RESOURCE, "Resource"},
|
||||
{LOG_DML, "DML"},
|
||||
{LOG_EVENT_MODE_SET, "Mode"},
|
||||
{LOG_EVENT_DETECTION, "Detect"},
|
||||
{LOG_EVENT_LINK_TRAINING, "LKTN"},
|
||||
{LOG_EVENT_LINK_LOSS, "LinkLoss"},
|
||||
{LOG_EVENT_UNDERFLOW, "Underflow"},
|
||||
{LOG_IF_TRACE, "InterfaceTrace"}
|
||||
};
|
||||
|
||||
|
||||
#define DC_DEFAULT_LOG_MASK ((1 << LOG_ERROR) | \
|
||||
(1 << LOG_WARNING) | \
|
||||
(1 << LOG_EVENT_MODE_SET) | \
|
||||
(1 << LOG_EVENT_DETECTION) | \
|
||||
(1 << LOG_EVENT_LINK_TRAINING) | \
|
||||
(1 << LOG_EVENT_LINK_LOSS) | \
|
||||
(1 << LOG_EVENT_UNDERFLOW) | \
|
||||
(1 << LOG_RESOURCE) | \
|
||||
(1 << LOG_FEATURE_OVERRIDE) | \
|
||||
(1 << LOG_DETECTION_EDID_PARSER) | \
|
||||
(1 << LOG_DC) | \
|
||||
(1 << LOG_HW_HOTPLUG) | \
|
||||
(1 << LOG_HW_SET_MODE) | \
|
||||
(1 << LOG_HW_RESUME_S3) | \
|
||||
(1 << LOG_HW_HPD_IRQ) | \
|
||||
(1 << LOG_SYNC) | \
|
||||
(1 << LOG_BANDWIDTH_VALIDATION) | \
|
||||
(1 << LOG_MST) | \
|
||||
(1 << LOG_BIOS) | \
|
||||
(1 << LOG_DETECTION_EDID_PARSER) | \
|
||||
(1 << LOG_DETECTION_DP_CAPS) | \
|
||||
(1 << LOG_BACKLIGHT)) | \
|
||||
(1 << LOG_I2C_AUX) | \
|
||||
(1 << LOG_IF_TRACE) /* | \
|
||||
(1 << LOG_SURFACE) | \
|
||||
(1 << LOG_SCALER) | \
|
||||
(1 << LOG_DML) | \
|
||||
(1 << LOG_HW_LINK_TRAINING) | \
|
||||
(1 << LOG_HW_AUDIO)| \
|
||||
(1 << LOG_BANDWIDTH_CALCS)*/
|
||||
|
||||
/* ----------- Object init and destruction ----------- */
|
||||
static bool construct(struct dc_context *ctx, struct dal_logger *logger)
|
||||
{
|
||||
/* malloc buffer and init offsets */
|
||||
logger->log_buffer_size = DAL_LOGGER_BUFFER_MAX_SIZE;
|
||||
logger->log_buffer = (char *)dm_alloc(logger->log_buffer_size *
|
||||
sizeof(char));
|
||||
|
||||
if (!logger->log_buffer)
|
||||
return false;
|
||||
|
||||
/* Initialize both offsets to start of buffer (empty) */
|
||||
logger->buffer_read_offset = 0;
|
||||
logger->buffer_write_offset = 0;
|
||||
|
||||
logger->write_wrap_count = 0;
|
||||
logger->read_wrap_count = 0;
|
||||
logger->open_count = 0;
|
||||
|
||||
logger->flags.bits.ENABLE_CONSOLE = 1;
|
||||
logger->flags.bits.ENABLE_BUFFER = 0;
|
||||
|
||||
logger->ctx = ctx;
|
||||
|
||||
logger->mask = DC_DEFAULT_LOG_MASK;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void destruct(struct dal_logger *logger)
|
||||
{
|
||||
if (logger->log_buffer) {
|
||||
dm_free(logger->log_buffer);
|
||||
logger->log_buffer = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
struct dal_logger *dal_logger_create(struct dc_context *ctx)
|
||||
{
|
||||
/* malloc struct */
|
||||
struct dal_logger *logger = dm_alloc(sizeof(struct dal_logger));
|
||||
|
||||
if (!logger)
|
||||
return NULL;
|
||||
if (!construct(ctx, logger)) {
|
||||
dm_free(logger);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return logger;
|
||||
}
|
||||
|
||||
uint32_t dal_logger_destroy(struct dal_logger **logger)
|
||||
{
|
||||
if (logger == NULL || *logger == NULL)
|
||||
return 1;
|
||||
destruct(*logger);
|
||||
dm_free(*logger);
|
||||
*logger = NULL;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
static bool dal_logger_should_log(
|
||||
struct dal_logger *logger,
|
||||
enum dc_log_type log_type)
|
||||
{
|
||||
if (logger->mask & (1 << log_type))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void log_to_debug_console(struct log_entry *entry)
|
||||
{
|
||||
struct dal_logger *logger = entry->logger;
|
||||
|
||||
if (logger->flags.bits.ENABLE_CONSOLE == 0)
|
||||
return;
|
||||
|
||||
if (entry->buf_offset) {
|
||||
switch (entry->type) {
|
||||
case LOG_ERROR:
|
||||
dm_error("%s", entry->buf);
|
||||
break;
|
||||
default:
|
||||
dm_output_to_console("%s", entry->buf);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Print everything unread existing in log_buffer to debug console*/
|
||||
static void flush_to_debug_console(struct dal_logger *logger)
|
||||
{
|
||||
int i = logger->buffer_read_offset;
|
||||
char *string_start = &logger->log_buffer[i];
|
||||
|
||||
dm_output_to_console(
|
||||
"---------------- FLUSHING LOG BUFFER ----------------\n");
|
||||
while (i < logger->buffer_write_offset) {
|
||||
|
||||
if (logger->log_buffer[i] == '\0') {
|
||||
dm_output_to_console("%s", string_start);
|
||||
string_start = (char *)logger->log_buffer + i + 1;
|
||||
}
|
||||
i++;
|
||||
}
|
||||
dm_output_to_console(
|
||||
"-------------- END FLUSHING LOG BUFFER --------------\n\n");
|
||||
}
|
||||
|
||||
static void log_to_internal_buffer(struct log_entry *entry)
|
||||
{
|
||||
|
||||
uint32_t size = entry->buf_offset;
|
||||
struct dal_logger *logger = entry->logger;
|
||||
|
||||
if (logger->flags.bits.ENABLE_BUFFER == 0)
|
||||
return;
|
||||
|
||||
if (logger->log_buffer == NULL)
|
||||
return;
|
||||
|
||||
if (size > 0 && size < logger->log_buffer_size) {
|
||||
|
||||
int total_free_space = 0;
|
||||
int space_before_wrap = 0;
|
||||
|
||||
if (logger->buffer_write_offset > logger->buffer_read_offset) {
|
||||
total_free_space = logger->log_buffer_size -
|
||||
logger->buffer_write_offset +
|
||||
logger->buffer_read_offset;
|
||||
space_before_wrap = logger->log_buffer_size -
|
||||
logger->buffer_write_offset;
|
||||
} else if (logger->buffer_write_offset <
|
||||
logger->buffer_read_offset) {
|
||||
total_free_space = logger->log_buffer_size -
|
||||
logger->buffer_read_offset +
|
||||
logger->buffer_write_offset;
|
||||
space_before_wrap = total_free_space;
|
||||
} else if (logger->write_wrap_count !=
|
||||
logger->read_wrap_count) {
|
||||
/* Buffer is completely full already */
|
||||
total_free_space = 0;
|
||||
space_before_wrap = 0;
|
||||
} else {
|
||||
/* Buffer is empty, start writing at beginning */
|
||||
total_free_space = logger->log_buffer_size;
|
||||
space_before_wrap = logger->log_buffer_size;
|
||||
logger->buffer_write_offset = 0;
|
||||
logger->buffer_read_offset = 0;
|
||||
}
|
||||
|
||||
if (space_before_wrap > size) {
|
||||
/* No wrap around, copy 'size' bytes
|
||||
* from 'entry->buf' to 'log_buffer'
|
||||
*/
|
||||
memmove(logger->log_buffer +
|
||||
logger->buffer_write_offset,
|
||||
entry->buf, size);
|
||||
logger->buffer_write_offset += size;
|
||||
|
||||
} else if (total_free_space > size) {
|
||||
/* We have enough room without flushing,
|
||||
* but need to wrap around */
|
||||
|
||||
int space_after_wrap = total_free_space -
|
||||
space_before_wrap;
|
||||
|
||||
memmove(logger->log_buffer +
|
||||
logger->buffer_write_offset,
|
||||
entry->buf, space_before_wrap);
|
||||
memmove(logger->log_buffer, entry->buf +
|
||||
space_before_wrap, space_after_wrap);
|
||||
|
||||
logger->buffer_write_offset = space_after_wrap;
|
||||
logger->write_wrap_count++;
|
||||
|
||||
} else {
|
||||
/* Not enough room remaining, we should flush
|
||||
* existing logs */
|
||||
|
||||
/* Flush existing unread logs to console */
|
||||
flush_to_debug_console(logger);
|
||||
|
||||
/* Start writing to beginning of buffer */
|
||||
memmove(logger->log_buffer, entry->buf, size);
|
||||
logger->buffer_write_offset = size;
|
||||
logger->buffer_read_offset = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
static void log_heading(struct log_entry *entry)
|
||||
{
|
||||
int j;
|
||||
|
||||
for (j = 0; j < NUM_ELEMENTS(log_type_info_tbl); j++) {
|
||||
|
||||
const struct dc_log_type_info *info = &log_type_info_tbl[j];
|
||||
|
||||
if (info->type == entry->type)
|
||||
dm_logger_append(entry, "[%s]\t", info->name);
|
||||
}
|
||||
}
|
||||
|
||||
static void append_entry(
|
||||
struct log_entry *entry,
|
||||
char *buffer,
|
||||
uint32_t buf_size)
|
||||
{
|
||||
if (!entry->buf ||
|
||||
entry->buf_offset + buf_size > entry->max_buf_bytes
|
||||
) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
/* Todo: check if off by 1 byte due to \0 anywhere */
|
||||
memmove(entry->buf + entry->buf_offset, buffer, buf_size);
|
||||
entry->buf_offset += buf_size;
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
/* Warning: Be careful that 'msg' is null terminated and the total size is
|
||||
* less than DAL_LOGGER_BUFFER_MAX_LOG_LINE_SIZE (256) including '\0'
|
||||
*/
|
||||
void dm_logger_write(
|
||||
struct dal_logger *logger,
|
||||
enum dc_log_type log_type,
|
||||
const char *msg,
|
||||
...)
|
||||
{
|
||||
if (logger && dal_logger_should_log(logger, log_type)) {
|
||||
uint32_t size;
|
||||
va_list args;
|
||||
char buffer[LOG_MAX_LINE_SIZE];
|
||||
struct log_entry entry;
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
entry.logger = logger;
|
||||
|
||||
entry.buf = buffer;
|
||||
|
||||
entry.buf_offset = 0;
|
||||
entry.max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
|
||||
|
||||
entry.type = log_type;
|
||||
|
||||
log_heading(&entry);
|
||||
|
||||
size = dm_log_to_buffer(
|
||||
buffer, LOG_MAX_LINE_SIZE, msg, args);
|
||||
|
||||
entry.buf_offset += size;
|
||||
|
||||
/* --Flush log_entry buffer-- */
|
||||
/* print to kernel console */
|
||||
log_to_debug_console(&entry);
|
||||
/* log internally for dsat */
|
||||
log_to_internal_buffer(&entry);
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
/* Same as dm_logger_write, except without open() and close(), which must
|
||||
* be done separately.
|
||||
*/
|
||||
void dm_logger_append(
|
||||
struct log_entry *entry,
|
||||
const char *msg,
|
||||
...)
|
||||
{
|
||||
struct dal_logger *logger;
|
||||
|
||||
if (!entry) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
logger = entry->logger;
|
||||
|
||||
if (logger && logger->open_count > 0 &&
|
||||
dal_logger_should_log(logger, entry->type)) {
|
||||
|
||||
uint32_t size;
|
||||
va_list args;
|
||||
char buffer[LOG_MAX_LINE_SIZE];
|
||||
|
||||
va_start(args, msg);
|
||||
|
||||
size = dm_log_to_buffer(
|
||||
buffer, LOG_MAX_LINE_SIZE, msg, args);
|
||||
|
||||
if (size < LOG_MAX_LINE_SIZE - 1) {
|
||||
append_entry(entry, buffer, size);
|
||||
} else {
|
||||
append_entry(entry, "LOG_ERROR, line too long\n", 27);
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
}
|
||||
|
||||
void dm_logger_open(
|
||||
struct dal_logger *logger,
|
||||
struct log_entry *entry, /* out */
|
||||
enum dc_log_type log_type)
|
||||
{
|
||||
if (!entry) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
|
||||
entry->type = log_type;
|
||||
entry->logger = logger;
|
||||
|
||||
entry->buf = dm_alloc(DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char));
|
||||
|
||||
entry->buf_offset = 0;
|
||||
entry->max_buf_bytes = DAL_LOGGER_BUFFER_MAX_SIZE * sizeof(char);
|
||||
|
||||
logger->open_count++;
|
||||
|
||||
log_heading(entry);
|
||||
}
|
||||
|
||||
void dm_logger_close(struct log_entry *entry)
|
||||
{
|
||||
struct dal_logger *logger = entry->logger;
|
||||
|
||||
if (logger && logger->open_count > 0) {
|
||||
logger->open_count--;
|
||||
} else {
|
||||
BREAK_TO_DEBUGGER();
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
/* --Flush log_entry buffer-- */
|
||||
/* print to kernel console */
|
||||
log_to_debug_console(entry);
|
||||
/* log internally for dsat */
|
||||
log_to_internal_buffer(entry);
|
||||
|
||||
/* TODO: Write end heading */
|
||||
|
||||
cleanup:
|
||||
if (entry->buf) {
|
||||
dm_free(entry->buf);
|
||||
entry->buf = NULL;
|
||||
entry->buf_offset = 0;
|
||||
entry->max_buf_bytes = 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,67 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_LOGGER_H__
|
||||
#define __DAL_LOGGER_H__
|
||||
|
||||
/* Structure for keeping track of offsets, buffer, etc */
|
||||
|
||||
#define DAL_LOGGER_BUFFER_MAX_SIZE 2048
|
||||
|
||||
/*Connectivity log needs to output EDID, which needs at lease 256x3 bytes,
|
||||
* change log line size to 896 to meet the request.
|
||||
*/
|
||||
#define LOG_MAX_LINE_SIZE 896
|
||||
|
||||
#include "include/logger_types.h"
|
||||
|
||||
struct dal_logger {
|
||||
|
||||
/* How far into the circular buffer has been read by dsat
|
||||
* Read offset should never cross write offset. Write \0's to
|
||||
* read data just to be sure?
|
||||
*/
|
||||
uint32_t buffer_read_offset;
|
||||
|
||||
/* How far into the circular buffer we have written
|
||||
* Write offset should never cross read offset
|
||||
*/
|
||||
uint32_t buffer_write_offset;
|
||||
|
||||
uint32_t write_wrap_count;
|
||||
uint32_t read_wrap_count;
|
||||
|
||||
uint32_t open_count;
|
||||
|
||||
char *log_buffer; /* Pointer to malloc'ed buffer */
|
||||
uint32_t log_buffer_size; /* Size of circular buffer */
|
||||
|
||||
uint32_t mask; /*array of masks for major elements*/
|
||||
|
||||
union logger_flags flags;
|
||||
struct dc_context *ctx;
|
||||
};
|
||||
|
||||
#endif /* __DAL_LOGGER_H__ */
|
|
@ -0,0 +1,197 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/dal_types.h"
|
||||
#include "include/logger_interface.h"
|
||||
#include "logger.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Register Logger.
|
||||
* A facility to create register R/W logs.
|
||||
* Currently used for DAL Test.
|
||||
*****************************************************************************/
|
||||
|
||||
/******************************************************************************
|
||||
* Private structures
|
||||
*****************************************************************************/
|
||||
struct dal_reg_dump_stack_location {
|
||||
const char *current_caller_func;
|
||||
long current_pid;
|
||||
long current_tgid;
|
||||
uint32_t rw_count;/* register access counter for current function. */
|
||||
};
|
||||
|
||||
/* This the maximum number of nested calls to the 'reg_dump' facility. */
|
||||
#define DAL_REG_DUMP_STACK_MAX_SIZE 32
|
||||
|
||||
struct dal_reg_dump_stack {
|
||||
int32_t stack_pointer;
|
||||
struct dal_reg_dump_stack_location
|
||||
stack_locations[DAL_REG_DUMP_STACK_MAX_SIZE];
|
||||
uint32_t total_rw_count; /* Total count for *all* functions. */
|
||||
};
|
||||
|
||||
static struct dal_reg_dump_stack reg_dump_stack = {0};
|
||||
|
||||
/******************************************************************************
|
||||
* Private functions
|
||||
*****************************************************************************/
|
||||
|
||||
/* Check if current process is the one which requested register dump.
|
||||
* The reason for the check:
|
||||
* mmCRTC_STATUS_FRAME_COUNT is accessed by dal_controller_get_vblank_counter().
|
||||
* Which runs all the time when at least one display is connected.
|
||||
* (Triggered by drm_mode_page_flip_ioctl()). */
|
||||
static bool is_reg_dump_process(void)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
/* walk the list of our processes */
|
||||
for (i = 0; i < reg_dump_stack.stack_pointer; i++) {
|
||||
struct dal_reg_dump_stack_location *stack_location
|
||||
= ®_dump_stack.stack_locations[i];
|
||||
|
||||
if (stack_location->current_pid == dm_get_pid()
|
||||
&& stack_location->current_tgid == dm_get_tgid())
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool dal_reg_dump_stack_is_empty(void)
|
||||
{
|
||||
if (reg_dump_stack.stack_pointer <= 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static struct dal_reg_dump_stack_location *dal_reg_dump_stack_push(void)
|
||||
{
|
||||
struct dal_reg_dump_stack_location *current_location = NULL;
|
||||
|
||||
if (reg_dump_stack.stack_pointer >= DAL_REG_DUMP_STACK_MAX_SIZE) {
|
||||
/* stack is full */
|
||||
dm_output_to_console("[REG_DUMP]: %s: stack is full!\n",
|
||||
__func__);
|
||||
} else {
|
||||
current_location =
|
||||
®_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
|
||||
++reg_dump_stack.stack_pointer;
|
||||
}
|
||||
|
||||
return current_location;
|
||||
}
|
||||
|
||||
static struct dal_reg_dump_stack_location *dal_reg_dump_stack_pop(void)
|
||||
{
|
||||
struct dal_reg_dump_stack_location *current_location = NULL;
|
||||
|
||||
if (dal_reg_dump_stack_is_empty()) {
|
||||
/* stack is empty */
|
||||
dm_output_to_console("[REG_DUMP]: %s: stack is empty!\n",
|
||||
__func__);
|
||||
} else {
|
||||
--reg_dump_stack.stack_pointer;
|
||||
current_location =
|
||||
®_dump_stack.stack_locations[reg_dump_stack.stack_pointer];
|
||||
}
|
||||
|
||||
return current_location;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* Public functions
|
||||
*****************************************************************************/
|
||||
|
||||
void dal_reg_logger_push(const char *caller_func)
|
||||
{
|
||||
struct dal_reg_dump_stack_location *free_stack_location;
|
||||
|
||||
free_stack_location = dal_reg_dump_stack_push();
|
||||
|
||||
if (NULL == free_stack_location)
|
||||
return;
|
||||
|
||||
memset(free_stack_location, 0, sizeof(*free_stack_location));
|
||||
|
||||
free_stack_location->current_caller_func = caller_func;
|
||||
free_stack_location->current_pid = dm_get_pid();
|
||||
free_stack_location->current_tgid = dm_get_tgid();
|
||||
|
||||
dm_output_to_console("[REG_DUMP]:%s - start (pid:%ld, tgid:%ld)\n",
|
||||
caller_func,
|
||||
free_stack_location->current_pid,
|
||||
free_stack_location->current_tgid);
|
||||
}
|
||||
|
||||
void dal_reg_logger_pop(void)
|
||||
{
|
||||
struct dal_reg_dump_stack_location *top_stack_location;
|
||||
|
||||
top_stack_location = dal_reg_dump_stack_pop();
|
||||
|
||||
if (NULL == top_stack_location) {
|
||||
dm_output_to_console("[REG_DUMP]:%s - Stack is Empty!\n",
|
||||
__func__);
|
||||
return;
|
||||
}
|
||||
|
||||
dm_output_to_console(
|
||||
"[REG_DUMP]:%s - end."\
|
||||
" Reg R/W Count: Total=%d Function=%d. (pid:%ld, tgid:%ld)\n",
|
||||
top_stack_location->current_caller_func,
|
||||
reg_dump_stack.total_rw_count,
|
||||
top_stack_location->rw_count,
|
||||
dm_get_pid(),
|
||||
dm_get_tgid());
|
||||
|
||||
memset(top_stack_location, 0, sizeof(*top_stack_location));
|
||||
}
|
||||
|
||||
void dal_reg_logger_rw_count_increment(void)
|
||||
{
|
||||
++reg_dump_stack.total_rw_count;
|
||||
|
||||
++reg_dump_stack.stack_locations
|
||||
[reg_dump_stack.stack_pointer - 1].rw_count;
|
||||
}
|
||||
|
||||
bool dal_reg_logger_should_dump_register(void)
|
||||
{
|
||||
if (true == dal_reg_dump_stack_is_empty())
|
||||
return false;
|
||||
|
||||
if (false == is_reg_dump_process())
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* End of File.
|
||||
*****************************************************************************/
|
|
@ -0,0 +1,116 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/signal_types.h"
|
||||
|
||||
bool dc_is_hdmi_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_HDMI_TYPE_A);
|
||||
}
|
||||
|
||||
bool dc_is_dp_sst_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
signal == SIGNAL_TYPE_EDP);
|
||||
}
|
||||
|
||||
bool dc_is_dp_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
signal == SIGNAL_TYPE_EDP ||
|
||||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
|
||||
}
|
||||
|
||||
bool dc_is_dp_external_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST);
|
||||
}
|
||||
|
||||
bool dc_is_analog_signal(enum signal_type signal)
|
||||
{
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_RGB:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool dc_is_embedded_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_EDP || signal == SIGNAL_TYPE_LVDS);
|
||||
}
|
||||
|
||||
bool dc_is_dvi_signal(enum signal_type signal)
|
||||
{
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
bool dc_is_dvi_single_link_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DVI_SINGLE_LINK);
|
||||
}
|
||||
|
||||
bool dc_is_dual_link_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DVI_DUAL_LINK);
|
||||
}
|
||||
|
||||
bool dc_is_audio_capable_signal(enum signal_type signal)
|
||||
{
|
||||
return (signal == SIGNAL_TYPE_DISPLAY_PORT ||
|
||||
signal == SIGNAL_TYPE_DISPLAY_PORT_MST ||
|
||||
dc_is_hdmi_signal(signal) ||
|
||||
signal == SIGNAL_TYPE_WIRELESS);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief
|
||||
* Returns whether the signal is compatible
|
||||
* with other digital encoder signal types.
|
||||
* This is true for DVI, LVDS, and HDMI signal types.
|
||||
*/
|
||||
bool dc_is_digital_encoder_compatible_signal(enum signal_type signal)
|
||||
{
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
case SIGNAL_TYPE_LVDS:
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/vector.h"
|
||||
|
||||
bool dal_vector_construct(
|
||||
struct vector *vector,
|
||||
struct dc_context *ctx,
|
||||
uint32_t capacity,
|
||||
uint32_t struct_size)
|
||||
{
|
||||
vector->container = NULL;
|
||||
|
||||
if (!struct_size || !capacity) {
|
||||
/* Container must be non-zero size*/
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
|
||||
vector->container = dm_alloc(struct_size * capacity);
|
||||
if (vector->container == NULL)
|
||||
return false;
|
||||
vector->capacity = capacity;
|
||||
vector->struct_size = struct_size;
|
||||
vector->count = 0;
|
||||
vector->ctx = ctx;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dal_vector_presized_costruct(
|
||||
struct vector *vector,
|
||||
struct dc_context *ctx,
|
||||
uint32_t count,
|
||||
void *initial_value,
|
||||
uint32_t struct_size)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
vector->container = NULL;
|
||||
|
||||
if (!struct_size || !count) {
|
||||
/* Container must be non-zero size*/
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
|
||||
vector->container = dm_alloc(struct_size * count);
|
||||
|
||||
if (vector->container == NULL)
|
||||
return false;
|
||||
|
||||
/* If caller didn't supply initial value then the default
|
||||
* of all zeros is expected, which is exactly what dal_alloc()
|
||||
* initialises the memory to. */
|
||||
if (NULL != initial_value) {
|
||||
for (i = 0; i < count; ++i)
|
||||
memmove(
|
||||
vector->container + i * struct_size,
|
||||
initial_value,
|
||||
struct_size);
|
||||
}
|
||||
|
||||
vector->capacity = count;
|
||||
vector->struct_size = struct_size;
|
||||
vector->count = count;
|
||||
return true;
|
||||
}
|
||||
|
||||
struct vector *dal_vector_presized_create(
|
||||
struct dc_context *ctx,
|
||||
uint32_t size,
|
||||
void *initial_value,
|
||||
uint32_t struct_size)
|
||||
{
|
||||
struct vector *vector = dm_alloc(sizeof(struct vector));
|
||||
|
||||
if (vector == NULL)
|
||||
return NULL;
|
||||
|
||||
if (dal_vector_presized_costruct(
|
||||
vector, ctx, size, initial_value, struct_size))
|
||||
return vector;
|
||||
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_free(vector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct vector *dal_vector_create(
|
||||
struct dc_context *ctx,
|
||||
uint32_t capacity,
|
||||
uint32_t struct_size)
|
||||
{
|
||||
struct vector *vector = dm_alloc(sizeof(struct vector));
|
||||
|
||||
if (vector == NULL)
|
||||
return NULL;
|
||||
|
||||
if (dal_vector_construct(vector, ctx, capacity, struct_size))
|
||||
return vector;
|
||||
|
||||
BREAK_TO_DEBUGGER();
|
||||
dm_free(vector);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void dal_vector_destruct(
|
||||
struct vector *vector)
|
||||
{
|
||||
if (vector->container != NULL)
|
||||
dm_free(vector->container);
|
||||
vector->count = 0;
|
||||
vector->capacity = 0;
|
||||
}
|
||||
|
||||
void dal_vector_destroy(
|
||||
struct vector **vector)
|
||||
{
|
||||
if (vector == NULL || *vector == NULL)
|
||||
return;
|
||||
dal_vector_destruct(*vector);
|
||||
dm_free(*vector);
|
||||
*vector = NULL;
|
||||
}
|
||||
|
||||
uint32_t dal_vector_get_count(
|
||||
const struct vector *vector)
|
||||
{
|
||||
return vector->count;
|
||||
}
|
||||
|
||||
void *dal_vector_at_index(
|
||||
const struct vector *vector,
|
||||
uint32_t index)
|
||||
{
|
||||
if (vector->container == NULL || index >= vector->count)
|
||||
return NULL;
|
||||
return vector->container + (index * vector->struct_size);
|
||||
}
|
||||
|
||||
bool dal_vector_remove_at_index(
|
||||
struct vector *vector,
|
||||
uint32_t index)
|
||||
{
|
||||
if (index >= vector->count)
|
||||
return false;
|
||||
|
||||
if (index != vector->count - 1)
|
||||
memmove(
|
||||
vector->container + (index * vector->struct_size),
|
||||
vector->container + ((index + 1) * vector->struct_size),
|
||||
(vector->count - index - 1) * vector->struct_size);
|
||||
vector->count -= 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dal_vector_set_at_index(
|
||||
const struct vector *vector,
|
||||
const void *what,
|
||||
uint32_t index)
|
||||
{
|
||||
void *where = dal_vector_at_index(vector, index);
|
||||
|
||||
if (!where) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return;
|
||||
}
|
||||
memmove(
|
||||
where,
|
||||
what,
|
||||
vector->struct_size);
|
||||
}
|
||||
|
||||
static inline uint32_t calc_increased_capacity(
|
||||
uint32_t old_capacity)
|
||||
{
|
||||
return old_capacity * 2;
|
||||
}
|
||||
|
||||
bool dal_vector_insert_at(
|
||||
struct vector *vector,
|
||||
const void *what,
|
||||
uint32_t position)
|
||||
{
|
||||
uint8_t *insert_address;
|
||||
|
||||
if (vector->count == vector->capacity) {
|
||||
if (!dal_vector_reserve(
|
||||
vector,
|
||||
calc_increased_capacity(vector->capacity)))
|
||||
return false;
|
||||
}
|
||||
|
||||
insert_address = vector->container + (vector->struct_size * position);
|
||||
|
||||
if (vector->count && position < vector->count)
|
||||
memmove(
|
||||
insert_address + vector->struct_size,
|
||||
insert_address,
|
||||
vector->struct_size * (vector->count - position));
|
||||
|
||||
memmove(
|
||||
insert_address,
|
||||
what,
|
||||
vector->struct_size);
|
||||
|
||||
vector->count++;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool dal_vector_append(
|
||||
struct vector *vector,
|
||||
const void *item)
|
||||
{
|
||||
return dal_vector_insert_at(vector, item, vector->count);
|
||||
}
|
||||
|
||||
struct vector *dal_vector_clone(
|
||||
const struct vector *vector)
|
||||
{
|
||||
struct vector *vec_cloned;
|
||||
uint32_t count;
|
||||
|
||||
/* create new vector */
|
||||
count = dal_vector_get_count(vector);
|
||||
|
||||
if (count == 0)
|
||||
/* when count is 0 we still want to create clone of the vector
|
||||
*/
|
||||
vec_cloned = dal_vector_create(
|
||||
vector->ctx,
|
||||
vector->capacity,
|
||||
vector->struct_size);
|
||||
else
|
||||
/* Call "presized create" version, independently of how the
|
||||
* original vector was created.
|
||||
* The owner of original vector must know how to treat the new
|
||||
* vector - as "presized" or as "regular".
|
||||
* But from vector point of view it doesn't matter. */
|
||||
vec_cloned = dal_vector_presized_create(vector->ctx, count,
|
||||
NULL,/* no initial value */
|
||||
vector->struct_size);
|
||||
|
||||
if (NULL == vec_cloned) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* copy vector's data */
|
||||
memmove(vec_cloned->container, vector->container,
|
||||
vec_cloned->struct_size * vec_cloned->capacity);
|
||||
|
||||
return vec_cloned;
|
||||
}
|
||||
|
||||
uint32_t dal_vector_capacity(const struct vector *vector)
|
||||
{
|
||||
return vector->capacity;
|
||||
}
|
||||
|
||||
bool dal_vector_reserve(struct vector *vector, uint32_t capacity)
|
||||
{
|
||||
void *new_container;
|
||||
|
||||
if (capacity <= vector->capacity)
|
||||
return true;
|
||||
|
||||
new_container = dm_realloc(vector->container, capacity * vector->struct_size);
|
||||
|
||||
if (new_container) {
|
||||
vector->container = new_container;
|
||||
vector->capacity = capacity;
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void dal_vector_clear(struct vector *vector)
|
||||
{
|
||||
vector->count = 0;
|
||||
}
|
|
@ -0,0 +1,24 @@
|
|||
#
|
||||
# Makefile for the 'bios' sub-component of DAL.
|
||||
# It provides the parsing and executing controls for atom bios image.
|
||||
|
||||
BIOS = bios_parser.o bios_parser_interface.o bios_parser_helper.o command_table.o command_table_helper.o
|
||||
|
||||
AMD_DAL_BIOS = $(addprefix $(AMDDALPATH)/dc/bios/,$(BIOS))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_BIOS)
|
||||
|
||||
###############################################################################
|
||||
# DCE 8x
|
||||
###############################################################################
|
||||
# All DCE8.x are derived from DCE8.0, so 8.0 MUST be defined if ANY of
|
||||
# DCE8.x is compiled.
|
||||
AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce80/command_table_helper_dce80.o
|
||||
|
||||
###############################################################################
|
||||
# DCE 11x
|
||||
###############################################################################
|
||||
AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce110/command_table_helper_dce110.o
|
||||
|
||||
ccflags-y += -DLATEST_ATOM_BIOS_SUPPORT
|
||||
AMD_DISPLAY_FILES += $(AMDDALPATH)/dc/bios/dce112/command_table_helper_dce112.o
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_BIOS_PARSER_H__
|
||||
#define __DAL_BIOS_PARSER_H__
|
||||
|
||||
struct dc_bios *bios_parser_create(
|
||||
struct bp_init_data *init,
|
||||
enum dce_version dce_version);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,82 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
#include "include/bios_parser_types.h"
|
||||
#include "bios_parser_helper.h"
|
||||
#include "command_table_helper.h"
|
||||
#include "command_table.h"
|
||||
#include "bios_parser_types_internal.h"
|
||||
|
||||
uint8_t *get_image(struct dc_bios *bp,
|
||||
uint32_t offset,
|
||||
uint32_t size)
|
||||
{
|
||||
if (bp->bios && offset + size < bp->bios_size)
|
||||
return bp->bios + offset;
|
||||
else
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#include "reg_helper.h"
|
||||
|
||||
#define CTX \
|
||||
bios->ctx
|
||||
#define REG(reg)\
|
||||
(bios->regs->reg)
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
ATOM_ ## field_name ## _SHIFT, ATOM_ ## field_name
|
||||
|
||||
bool bios_is_accelerated_mode(
|
||||
struct dc_bios *bios)
|
||||
{
|
||||
uint32_t acc_mode;
|
||||
REG_GET(BIOS_SCRATCH_6, S6_ACC_MODE, &acc_mode);
|
||||
return (acc_mode == 1);
|
||||
}
|
||||
|
||||
|
||||
void bios_set_scratch_acc_mode_change(
|
||||
struct dc_bios *bios)
|
||||
{
|
||||
REG_UPDATE(BIOS_SCRATCH_6, S6_ACC_MODE, 1);
|
||||
}
|
||||
|
||||
|
||||
void bios_set_scratch_critical_state(
|
||||
struct dc_bios *bios,
|
||||
bool state)
|
||||
{
|
||||
uint32_t critial_state = state ? 1 : 0;
|
||||
REG_UPDATE(BIOS_SCRATCH_6, S6_CRITICAL_STATE, critial_state);
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,40 @@
|
|||
/*
|
||||
* Copyright 2012-16 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 __DAL_BIOS_PARSER_HELPER_H__
|
||||
#define __DAL_BIOS_PARSER_HELPER_H__
|
||||
|
||||
struct bios_parser;
|
||||
|
||||
uint8_t *get_image(struct dc_bios *bp, uint32_t offset,
|
||||
uint32_t size);
|
||||
|
||||
bool bios_is_accelerated_mode(struct dc_bios *bios);
|
||||
void bios_set_scratch_acc_mode_change(struct dc_bios *bios);
|
||||
void bios_set_scratch_critical_state(struct dc_bios *bios, bool state);
|
||||
|
||||
#define GET_IMAGE(type, offset) ((type *) get_image(&bp->base, offset, sizeof(type)))
|
||||
|
||||
#endif
|
|
@ -0,0 +1,50 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "include/logger_interface.h"
|
||||
|
||||
#include "bios_parser_interface.h"
|
||||
#include "bios_parser.h"
|
||||
|
||||
|
||||
struct dc_bios *dal_bios_parser_create(
|
||||
struct bp_init_data *init,
|
||||
enum dce_version dce_version)
|
||||
{
|
||||
struct dc_bios *bios = NULL;
|
||||
|
||||
bios = bios_parser_create(init, dce_version);
|
||||
|
||||
return bios;
|
||||
}
|
||||
|
||||
void dal_bios_parser_destroy(struct dc_bios **dcb)
|
||||
{
|
||||
struct dc_bios *bios = *dcb;
|
||||
|
||||
bios->funcs->bios_parser_destroy(dcb);
|
||||
}
|
||||
|
|
@ -0,0 +1,72 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_BIOS_PARSER_TYPES_BIOS_H__
|
||||
#define __DAL_BIOS_PARSER_TYPES_BIOS_H__
|
||||
|
||||
#include "dc_bios_types.h"
|
||||
#include "bios_parser_helper.h"
|
||||
|
||||
struct atom_data_revision {
|
||||
uint32_t major;
|
||||
uint32_t minor;
|
||||
};
|
||||
|
||||
struct object_info_table {
|
||||
struct atom_data_revision revision;
|
||||
union {
|
||||
ATOM_OBJECT_HEADER *v1_1;
|
||||
ATOM_OBJECT_HEADER_V3 *v1_3;
|
||||
};
|
||||
};
|
||||
|
||||
enum spread_spectrum_id {
|
||||
SS_ID_UNKNOWN = 0,
|
||||
SS_ID_DP1 = 0xf1,
|
||||
SS_ID_DP2 = 0xf2,
|
||||
SS_ID_LVLINK_2700MHZ = 0xf3,
|
||||
SS_ID_LVLINK_1620MHZ = 0xf4
|
||||
};
|
||||
|
||||
struct bios_parser {
|
||||
struct dc_bios base;
|
||||
|
||||
struct object_info_table object_info_tbl;
|
||||
uint32_t object_info_tbl_offset;
|
||||
ATOM_MASTER_DATA_TABLE *master_data_tbl;
|
||||
|
||||
const struct bios_parser_helper *bios_helper;
|
||||
|
||||
const struct command_table_helper *cmd_helper;
|
||||
struct cmd_tbl cmd_tbl;
|
||||
|
||||
bool remap_device_tags;
|
||||
};
|
||||
|
||||
/* Bios Parser from DC Bios */
|
||||
#define BP_FROM_DCB(dc_bios) \
|
||||
container_of(dc_bios, struct bios_parser, base)
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,112 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_COMMAND_TABLE_H__
|
||||
#define __DAL_COMMAND_TABLE_H__
|
||||
|
||||
struct bios_parser;
|
||||
struct bp_encoder_control;
|
||||
|
||||
struct cmd_tbl {
|
||||
enum bp_result (*dig_encoder_control)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_encoder_control *control);
|
||||
enum bp_result (*encoder_control_dig1)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_encoder_control *control);
|
||||
enum bp_result (*encoder_control_dig2)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_encoder_control *control);
|
||||
enum bp_result (*transmitter_control)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_transmitter_control *control);
|
||||
enum bp_result (*set_pixel_clock)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_pixel_clock_parameters *bp_params);
|
||||
enum bp_result (*enable_spread_spectrum_on_ppll)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_spread_spectrum_parameters *bp_params,
|
||||
bool enable);
|
||||
enum bp_result (*adjust_display_pll)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_adjust_pixel_clock_parameters *bp_params);
|
||||
enum bp_result (*dac1_encoder_control)(
|
||||
struct bios_parser *bp,
|
||||
bool enable,
|
||||
uint32_t pixel_clock,
|
||||
uint8_t dac_standard);
|
||||
enum bp_result (*dac2_encoder_control)(
|
||||
struct bios_parser *bp,
|
||||
bool enable,
|
||||
uint32_t pixel_clock,
|
||||
uint8_t dac_standard);
|
||||
enum bp_result (*dac1_output_control)(
|
||||
struct bios_parser *bp,
|
||||
bool enable);
|
||||
enum bp_result (*dac2_output_control)(
|
||||
struct bios_parser *bp,
|
||||
bool enable);
|
||||
enum bp_result (*blank_crtc)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_blank_crtc_parameters *bp_params,
|
||||
bool blank);
|
||||
enum bp_result (*set_crtc_timing)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_hw_crtc_timing_parameters *bp_params);
|
||||
enum bp_result (*set_crtc_overscan)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_hw_crtc_overscan_parameters *bp_params);
|
||||
enum bp_result (*select_crtc_source)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
enum bp_result (*enable_crtc)(
|
||||
struct bios_parser *bp,
|
||||
enum controller_id controller_id,
|
||||
bool enable);
|
||||
enum bp_result (*enable_crtc_mem_req)(
|
||||
struct bios_parser *bp,
|
||||
enum controller_id controller_id,
|
||||
bool enable);
|
||||
enum bp_result (*program_clock)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_pixel_clock_parameters *bp_params);
|
||||
enum bp_result (*compute_memore_engine_pll)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_display_clock_parameters *bp_params);
|
||||
enum bp_result (*external_encoder_control)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_external_encoder_control *cntl);
|
||||
enum bp_result (*enable_disp_power_gating)(
|
||||
struct bios_parser *bp,
|
||||
enum controller_id crtc_id,
|
||||
enum bp_pipe_control_action action);
|
||||
enum bp_result (*set_dce_clock)(
|
||||
struct bios_parser *bp,
|
||||
struct bp_set_dce_clock_parameters *bp_params);
|
||||
};
|
||||
|
||||
void dal_bios_parser_init_cmd_tbl(struct bios_parser *bp);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,288 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
#include "include/bios_parser_types.h"
|
||||
|
||||
#include "command_table_helper.h"
|
||||
|
||||
bool dal_bios_parser_init_cmd_tbl_helper(
|
||||
const struct command_table_helper **h,
|
||||
enum dce_version dce)
|
||||
{
|
||||
switch (dce) {
|
||||
case DCE_VERSION_8_0:
|
||||
*h = dal_cmd_tbl_helper_dce80_get_table();
|
||||
return true;
|
||||
|
||||
case DCE_VERSION_10_0:
|
||||
*h = dal_cmd_tbl_helper_dce110_get_table();
|
||||
return true;
|
||||
|
||||
case DCE_VERSION_11_0:
|
||||
*h = dal_cmd_tbl_helper_dce110_get_table();
|
||||
return true;
|
||||
|
||||
case DCE_VERSION_11_2:
|
||||
*h = dal_cmd_tbl_helper_dce112_get_table();
|
||||
return true;
|
||||
|
||||
default:
|
||||
/* Unsupported DCE */
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/* real implementations */
|
||||
|
||||
bool dal_cmd_table_helper_controller_id_to_atom(
|
||||
enum controller_id id,
|
||||
uint8_t *atom_id)
|
||||
{
|
||||
if (atom_id == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case CONTROLLER_ID_D0:
|
||||
*atom_id = ATOM_CRTC1;
|
||||
return true;
|
||||
case CONTROLLER_ID_D1:
|
||||
*atom_id = ATOM_CRTC2;
|
||||
return true;
|
||||
case CONTROLLER_ID_D2:
|
||||
*atom_id = ATOM_CRTC3;
|
||||
return true;
|
||||
case CONTROLLER_ID_D3:
|
||||
*atom_id = ATOM_CRTC4;
|
||||
return true;
|
||||
case CONTROLLER_ID_D4:
|
||||
*atom_id = ATOM_CRTC5;
|
||||
return true;
|
||||
case CONTROLLER_ID_D5:
|
||||
*atom_id = ATOM_CRTC6;
|
||||
return true;
|
||||
case CONTROLLER_ID_UNDERLAY0:
|
||||
*atom_id = ATOM_UNDERLAY_PIPE0;
|
||||
return true;
|
||||
case CONTROLLER_ID_UNDEFINED:
|
||||
*atom_id = ATOM_CRTC_INVALID;
|
||||
return true;
|
||||
default:
|
||||
/* Wrong controller id */
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* translate_transmitter_bp_to_atom
|
||||
*
|
||||
* @brief
|
||||
* Translate the Transmitter to the corresponding ATOM BIOS value
|
||||
*
|
||||
* @param
|
||||
* input transmitter
|
||||
* output digitalTransmitter
|
||||
* // =00: Digital Transmitter1 ( UNIPHY linkAB )
|
||||
* // =01: Digital Transmitter2 ( UNIPHY linkCD )
|
||||
* // =02: Digital Transmitter3 ( UNIPHY linkEF )
|
||||
*/
|
||||
uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
|
||||
enum transmitter t)
|
||||
{
|
||||
switch (t) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
case TRANSMITTER_TRAVIS_LCD:
|
||||
return 0;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
return 1;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
case TRANSMITTER_UNIPHY_F:
|
||||
return 2;
|
||||
default:
|
||||
/* Invalid Transmitter Type! */
|
||||
BREAK_TO_DEBUGGER();
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
|
||||
enum signal_type s,
|
||||
bool enable_dp_audio)
|
||||
{
|
||||
switch (s) {
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
return ATOM_ENCODER_MODE_DVI;
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
return ATOM_ENCODER_MODE_HDMI;
|
||||
case SIGNAL_TYPE_LVDS:
|
||||
return ATOM_ENCODER_MODE_LVDS;
|
||||
case SIGNAL_TYPE_EDP:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_VIRTUAL:
|
||||
if (enable_dp_audio)
|
||||
return ATOM_ENCODER_MODE_DP_AUDIO;
|
||||
else
|
||||
return ATOM_ENCODER_MODE_DP;
|
||||
case SIGNAL_TYPE_RGB:
|
||||
return ATOM_ENCODER_MODE_CRT;
|
||||
default:
|
||||
return ATOM_ENCODER_MODE_CRT;
|
||||
}
|
||||
}
|
||||
|
||||
void dal_cmd_table_helper_assign_control_parameter(
|
||||
const struct command_table_helper *h,
|
||||
struct bp_encoder_control *control,
|
||||
DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param)
|
||||
{
|
||||
/* there are three transmitter blocks, each one has two links 4-lanes
|
||||
* each, A+B, C+D, E+F, Uniphy A, C and E are enumerated as link 0 in
|
||||
* each transmitter block B, D and F as link 1, third transmitter block
|
||||
* has non splitable links (UniphyE and UniphyF can not be configured
|
||||
* separately to drive two different streams)
|
||||
*/
|
||||
if ((control->transmitter == TRANSMITTER_UNIPHY_B) ||
|
||||
(control->transmitter == TRANSMITTER_UNIPHY_D) ||
|
||||
(control->transmitter == TRANSMITTER_UNIPHY_F)) {
|
||||
/* Bit2: Link Select
|
||||
* =0: PHY linkA/C/E
|
||||
* =1: PHY linkB/D/F
|
||||
*/
|
||||
ctrl_param->acConfig.ucLinkSel = 1;
|
||||
}
|
||||
|
||||
/* Bit[4:3]: Transmitter Selection
|
||||
* =00: Digital Transmitter1 ( UNIPHY linkAB )
|
||||
* =01: Digital Transmitter2 ( UNIPHY linkCD )
|
||||
* =02: Digital Transmitter3 ( UNIPHY linkEF )
|
||||
* =03: Reserved
|
||||
*/
|
||||
ctrl_param->acConfig.ucTransmitterSel =
|
||||
(uint8_t)(h->transmitter_bp_to_atom(control->transmitter));
|
||||
|
||||
/* We need to convert from KHz units into 10KHz units */
|
||||
ctrl_param->ucAction = h->encoder_action_to_atom(control->action);
|
||||
ctrl_param->usPixelClock = cpu_to_le16((uint16_t)(control->pixel_clock / 10));
|
||||
ctrl_param->ucEncoderMode =
|
||||
(uint8_t)(h->encoder_mode_bp_to_atom(
|
||||
control->signal, control->enable_dp_audio));
|
||||
ctrl_param->ucLaneNum = (uint8_t)(control->lanes_number);
|
||||
}
|
||||
|
||||
bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
|
||||
enum clock_source_id id,
|
||||
uint32_t *ref_clk_src_id)
|
||||
{
|
||||
if (ref_clk_src_id == NULL) {
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
*ref_clk_src_id = ENCODER_REFCLK_SRC_P1PLL;
|
||||
return true;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
*ref_clk_src_id = ENCODER_REFCLK_SRC_P2PLL;
|
||||
return true;
|
||||
case CLOCK_SOURCE_ID_DCPLL:
|
||||
*ref_clk_src_id = ENCODER_REFCLK_SRC_DCPLL;
|
||||
return true;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
*ref_clk_src_id = ENCODER_REFCLK_SRC_EXTCLK;
|
||||
return true;
|
||||
case CLOCK_SOURCE_ID_UNDEFINED:
|
||||
*ref_clk_src_id = ENCODER_REFCLK_SRC_INVALID;
|
||||
return true;
|
||||
default:
|
||||
/* Unsupported clock source id */
|
||||
BREAK_TO_DEBUGGER();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
uint8_t dal_cmd_table_helper_encoder_id_to_atom(
|
||||
enum encoder_id id)
|
||||
{
|
||||
switch (id) {
|
||||
case ENCODER_ID_INTERNAL_LVDS:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_LVDS;
|
||||
case ENCODER_ID_INTERNAL_TMDS1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_TMDS1;
|
||||
case ENCODER_ID_INTERNAL_TMDS2:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_TMDS2;
|
||||
case ENCODER_ID_INTERNAL_DAC1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_DAC1;
|
||||
case ENCODER_ID_INTERNAL_DAC2:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_DAC2;
|
||||
case ENCODER_ID_INTERNAL_LVTM1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_LVTM1;
|
||||
case ENCODER_ID_INTERNAL_HDMI:
|
||||
return ENCODER_OBJECT_ID_HDMI_INTERNAL;
|
||||
case ENCODER_ID_EXTERNAL_TRAVIS:
|
||||
return ENCODER_OBJECT_ID_TRAVIS;
|
||||
case ENCODER_ID_EXTERNAL_NUTMEG:
|
||||
return ENCODER_OBJECT_ID_NUTMEG;
|
||||
case ENCODER_ID_INTERNAL_KLDSCP_TMDS1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_TMDS1;
|
||||
case ENCODER_ID_INTERNAL_KLDSCP_DAC1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC1;
|
||||
case ENCODER_ID_INTERNAL_KLDSCP_DAC2:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_DAC2;
|
||||
case ENCODER_ID_EXTERNAL_MVPU_FPGA:
|
||||
return ENCODER_OBJECT_ID_MVPU_FPGA;
|
||||
case ENCODER_ID_INTERNAL_DDI:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_DDI;
|
||||
case ENCODER_ID_INTERNAL_UNIPHY:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_UNIPHY;
|
||||
case ENCODER_ID_INTERNAL_KLDSCP_LVTMA:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_KLDSCP_LVTMA;
|
||||
case ENCODER_ID_INTERNAL_UNIPHY1:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_UNIPHY1;
|
||||
case ENCODER_ID_INTERNAL_UNIPHY2:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_UNIPHY2;
|
||||
case ENCODER_ID_INTERNAL_UNIPHY3:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_UNIPHY3;
|
||||
case ENCODER_ID_INTERNAL_WIRELESS:
|
||||
return ENCODER_OBJECT_ID_INTERNAL_VCE;
|
||||
case ENCODER_ID_UNKNOWN:
|
||||
return ENCODER_OBJECT_ID_NONE;
|
||||
default:
|
||||
/* Invalid encoder id */
|
||||
BREAK_TO_DEBUGGER();
|
||||
return ENCODER_OBJECT_ID_NONE;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_COMMAND_TABLE_HELPER_H__
|
||||
#define __DAL_COMMAND_TABLE_HELPER_H__
|
||||
|
||||
#include "dce80/command_table_helper_dce80.h"
|
||||
#include "dce110/command_table_helper_dce110.h"
|
||||
#include "dce112/command_table_helper_dce112.h"
|
||||
|
||||
struct command_table_helper {
|
||||
bool (*controller_id_to_atom)(enum controller_id id, uint8_t *atom_id);
|
||||
uint8_t (*encoder_action_to_atom)(
|
||||
enum bp_encoder_control_action action);
|
||||
uint32_t (*encoder_mode_bp_to_atom)(enum signal_type s,
|
||||
bool enable_dp_audio);
|
||||
bool (*engine_bp_to_atom)(enum engine_id engine_id,
|
||||
uint32_t *atom_engine_id);
|
||||
void (*assign_control_parameter)(
|
||||
const struct command_table_helper *h,
|
||||
struct bp_encoder_control *control,
|
||||
DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
|
||||
bool (*clock_source_id_to_atom)(enum clock_source_id id,
|
||||
uint32_t *atom_pll_id);
|
||||
bool (*clock_source_id_to_ref_clk_src)(
|
||||
enum clock_source_id id,
|
||||
uint32_t *ref_clk_src_id);
|
||||
uint8_t (*transmitter_bp_to_atom)(enum transmitter t);
|
||||
uint8_t (*encoder_id_to_atom)(enum encoder_id id);
|
||||
uint8_t (*clock_source_id_to_atom_phy_clk_src_id)(
|
||||
enum clock_source_id id);
|
||||
uint8_t (*signal_type_to_atom_dig_mode)(enum signal_type s);
|
||||
uint8_t (*hpd_sel_to_atom)(enum hpd_source_id id);
|
||||
uint8_t (*dig_encoder_sel_to_atom)(enum engine_id engine_id);
|
||||
uint8_t (*phy_id_to_atom)(enum transmitter t);
|
||||
uint8_t (*disp_power_gating_action_to_atom)(
|
||||
enum bp_pipe_control_action action);
|
||||
bool (*dc_clock_type_to_atom)(enum bp_dce_clock_type id,
|
||||
uint32_t *atom_clock_type);
|
||||
uint8_t (*transmitter_color_depth_to_atom)(enum transmitter_color_depth id);
|
||||
};
|
||||
|
||||
bool dal_bios_parser_init_cmd_tbl_helper(const struct command_table_helper **h,
|
||||
enum dce_version dce);
|
||||
|
||||
bool dal_cmd_table_helper_controller_id_to_atom(
|
||||
enum controller_id id,
|
||||
uint8_t *atom_id);
|
||||
|
||||
uint32_t dal_cmd_table_helper_encoder_mode_bp_to_atom(
|
||||
enum signal_type s,
|
||||
bool enable_dp_audio);
|
||||
|
||||
void dal_cmd_table_helper_assign_control_parameter(
|
||||
const struct command_table_helper *h,
|
||||
struct bp_encoder_control *control,
|
||||
DIG_ENCODER_CONTROL_PARAMETERS_V2 *ctrl_param);
|
||||
|
||||
bool dal_cmd_table_helper_clock_source_id_to_ref_clk_src(
|
||||
enum clock_source_id id,
|
||||
uint32_t *ref_clk_src_id);
|
||||
|
||||
uint8_t dal_cmd_table_helper_transmitter_bp_to_atom(
|
||||
enum transmitter t);
|
||||
|
||||
uint8_t dal_cmd_table_helper_encoder_id_to_atom(
|
||||
enum encoder_id id);
|
||||
#endif
|
|
@ -0,0 +1,364 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
#include "include/bios_parser_types.h"
|
||||
|
||||
#include "../command_table_helper.h"
|
||||
|
||||
static uint8_t phy_id_to_atom(enum transmitter t)
|
||||
{
|
||||
uint8_t atom_phy_id;
|
||||
|
||||
switch (t) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYB;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYC;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYD;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYE;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_F:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYF;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_G:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYG;
|
||||
break;
|
||||
default:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
}
|
||||
return atom_phy_id;
|
||||
}
|
||||
|
||||
static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
|
||||
{
|
||||
uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
|
||||
|
||||
switch (s) {
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_EDP:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
|
||||
break;
|
||||
case SIGNAL_TYPE_LVDS:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS;
|
||||
break;
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
|
||||
break;
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI;
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST;
|
||||
break;
|
||||
default:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_mode;
|
||||
}
|
||||
|
||||
static uint8_t clock_source_id_to_atom_phy_clk_src_id(
|
||||
enum clock_source_id id)
|
||||
{
|
||||
uint8_t atom_phy_clk_src_id = 0;
|
||||
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL0:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
|
||||
break;
|
||||
default:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_phy_clk_src_id >> 2;
|
||||
}
|
||||
|
||||
static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
||||
{
|
||||
uint8_t atom_hpd_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case HPD_SOURCEID1:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID2:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID3:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID4:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID5:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID6:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID_UNKNOWN:
|
||||
default:
|
||||
atom_hpd_sel = 0;
|
||||
break;
|
||||
}
|
||||
return atom_hpd_sel >> 4;
|
||||
}
|
||||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
uint8_t atom_dig_encoder_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL;
|
||||
break;
|
||||
case ENGINE_ID_UNKNOWN:
|
||||
/* No DIG_FRONT is associated to DIG_BACKEND */
|
||||
atom_dig_encoder_sel = 0;
|
||||
break;
|
||||
default:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_encoder_sel;
|
||||
}
|
||||
|
||||
static bool clock_source_id_to_atom(
|
||||
enum clock_source_id id,
|
||||
uint32_t *atom_pll_id)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (atom_pll_id != NULL)
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL0:
|
||||
*atom_pll_id = ATOM_PPLL0;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
*atom_pll_id = ATOM_PPLL1;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
*atom_pll_id = ATOM_PPLL2;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DFS:
|
||||
*atom_pll_id = ATOM_EXT_PLL1;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_VCE:
|
||||
/* for VCE encoding,
|
||||
* we need to pass in ATOM_PPLL_INVALID
|
||||
*/
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DP_DTO:
|
||||
/* When programming DP DTO PLL ID should be invalid */
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_UNDEFINED:
|
||||
/* Should not happen */
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (atom_engine_id != NULL)
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DACA:
|
||||
*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
|
||||
{
|
||||
uint8_t atom_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ENCODER_CONTROL_ENABLE:
|
||||
atom_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_DISABLE:
|
||||
atom_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_SETUP:
|
||||
atom_action = ATOM_ENCODER_CMD_SETUP;
|
||||
break;
|
||||
case ENCODER_CONTROL_INIT:
|
||||
atom_action = ATOM_ENCODER_INIT;
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_action;
|
||||
}
|
||||
|
||||
static uint8_t disp_power_gating_action_to_atom(
|
||||
enum bp_pipe_control_action action)
|
||||
{
|
||||
uint8_t atom_pipe_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ASIC_PIPE_DISABLE:
|
||||
atom_pipe_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ASIC_PIPE_ENABLE:
|
||||
atom_pipe_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ASIC_PIPE_INIT:
|
||||
atom_pipe_action = ATOM_INIT;
|
||||
break;
|
||||
default:
|
||||
ASSERT_CRITICAL(false); /* Unhandle action in driver! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_pipe_action;
|
||||
}
|
||||
|
||||
/* function table */
|
||||
static const struct command_table_helper command_table_helper_funcs = {
|
||||
.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
|
||||
.encoder_action_to_atom = encoder_action_to_atom,
|
||||
.engine_bp_to_atom = engine_bp_to_atom,
|
||||
.clock_source_id_to_atom = clock_source_id_to_atom,
|
||||
.clock_source_id_to_atom_phy_clk_src_id =
|
||||
clock_source_id_to_atom_phy_clk_src_id,
|
||||
.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
|
||||
.hpd_sel_to_atom = hpd_sel_to_atom,
|
||||
.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
|
||||
.phy_id_to_atom = phy_id_to_atom,
|
||||
.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
|
||||
.assign_control_parameter = NULL,
|
||||
.clock_source_id_to_ref_clk_src = NULL,
|
||||
.transmitter_bp_to_atom = NULL,
|
||||
.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
|
||||
.encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom,
|
||||
};
|
||||
|
||||
/*
|
||||
* dal_cmd_tbl_helper_dce110_get_table
|
||||
*
|
||||
* @brief
|
||||
* Initialize command table helper functions
|
||||
*
|
||||
* @param
|
||||
* const struct command_table_helper **h - [out] struct of functions
|
||||
*
|
||||
*/
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table()
|
||||
{
|
||||
return &command_table_helper_funcs;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_COMMAND_TABLE_HELPER_DCE110_H__
|
||||
#define __DAL_COMMAND_TABLE_HELPER_DCE110_H__
|
||||
|
||||
struct command_table_helper;
|
||||
|
||||
/* Initialize command table helper functions */
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce110_get_table(void);
|
||||
|
||||
#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
|
|
@ -0,0 +1,418 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
#include "include/bios_parser_types.h"
|
||||
|
||||
#include "../command_table_helper.h"
|
||||
|
||||
static uint8_t phy_id_to_atom(enum transmitter t)
|
||||
{
|
||||
uint8_t atom_phy_id;
|
||||
|
||||
switch (t) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYB;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYC;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYD;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYE;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_F:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYF;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_G:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYG;
|
||||
break;
|
||||
default:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
}
|
||||
return atom_phy_id;
|
||||
}
|
||||
|
||||
static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
|
||||
{
|
||||
uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP;
|
||||
|
||||
switch (s) {
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_EDP:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP;
|
||||
break;
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI;
|
||||
break;
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_HDMI;
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DP_MST;
|
||||
break;
|
||||
default:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V6_DVI;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_mode;
|
||||
}
|
||||
|
||||
static uint8_t clock_source_id_to_atom_phy_clk_src_id(
|
||||
enum clock_source_id id)
|
||||
{
|
||||
uint8_t atom_phy_clk_src_id = 0;
|
||||
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL0:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
|
||||
break;
|
||||
default:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_phy_clk_src_id >> 2;
|
||||
}
|
||||
|
||||
static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
||||
{
|
||||
uint8_t atom_hpd_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case HPD_SOURCEID1:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD1_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID2:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD2_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID3:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD3_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID4:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD4_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID5:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD5_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID6:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_V6_HPD6_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID_UNKNOWN:
|
||||
default:
|
||||
atom_hpd_sel = 0;
|
||||
break;
|
||||
}
|
||||
return atom_hpd_sel;
|
||||
}
|
||||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
uint8_t atom_dig_encoder_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGB_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGC_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGD_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGE_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGF_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGG_SEL;
|
||||
break;
|
||||
case ENGINE_ID_UNKNOWN:
|
||||
/* No DIG_FRONT is associated to DIG_BACKEND */
|
||||
atom_dig_encoder_sel = 0;
|
||||
break;
|
||||
default:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V6__DIGA_SEL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_encoder_sel;
|
||||
}
|
||||
|
||||
static bool clock_source_id_to_atom(
|
||||
enum clock_source_id id,
|
||||
uint32_t *atom_pll_id)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (atom_pll_id != NULL)
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL0:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL0;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL1:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL1;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL2:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL2;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL3:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL3;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL4:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL4;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_PHY_PLL5:
|
||||
*atom_pll_id = ATOM_COMBOPHY_PLL5;
|
||||
break;
|
||||
case CLOCK_SOURCE_COMBO_DISPLAY_PLL0:
|
||||
*atom_pll_id = ATOM_PPLL0;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DFS:
|
||||
*atom_pll_id = ATOM_GCK_DFS;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_VCE:
|
||||
*atom_pll_id = ATOM_DP_DTO;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DP_DTO:
|
||||
*atom_pll_id = ATOM_DP_DTO;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_UNDEFINED:
|
||||
/* Should not happen */
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (atom_engine_id != NULL)
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DACA:
|
||||
*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
|
||||
{
|
||||
uint8_t atom_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ENCODER_CONTROL_ENABLE:
|
||||
atom_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_DISABLE:
|
||||
atom_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_SETUP:
|
||||
atom_action = ATOM_ENCODER_CMD_STREAM_SETUP;
|
||||
break;
|
||||
case ENCODER_CONTROL_INIT:
|
||||
atom_action = ATOM_ENCODER_INIT;
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_action;
|
||||
}
|
||||
|
||||
static uint8_t disp_power_gating_action_to_atom(
|
||||
enum bp_pipe_control_action action)
|
||||
{
|
||||
uint8_t atom_pipe_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ASIC_PIPE_DISABLE:
|
||||
atom_pipe_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ASIC_PIPE_ENABLE:
|
||||
atom_pipe_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ASIC_PIPE_INIT:
|
||||
atom_pipe_action = ATOM_INIT;
|
||||
break;
|
||||
default:
|
||||
ASSERT_CRITICAL(false); /* Unhandle action in driver! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_pipe_action;
|
||||
}
|
||||
|
||||
static bool dc_clock_type_to_atom(
|
||||
enum bp_dce_clock_type id,
|
||||
uint32_t *atom_clock_type)
|
||||
{
|
||||
bool retCode = true;
|
||||
|
||||
if (atom_clock_type != NULL) {
|
||||
switch (id) {
|
||||
case DCECLOCK_TYPE_DISPLAY_CLOCK:
|
||||
*atom_clock_type = DCE_CLOCK_TYPE_DISPCLK;
|
||||
break;
|
||||
|
||||
case DCECLOCK_TYPE_DPREFCLK:
|
||||
*atom_clock_type = DCE_CLOCK_TYPE_DPREFCLK;
|
||||
break;
|
||||
|
||||
default:
|
||||
ASSERT_CRITICAL(false); /* Unhandle action in driver! */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return retCode;
|
||||
}
|
||||
|
||||
static uint8_t transmitter_color_depth_to_atom(enum transmitter_color_depth id)
|
||||
{
|
||||
uint8_t atomColorDepth = 0;
|
||||
|
||||
switch (id) {
|
||||
case TRANSMITTER_COLOR_DEPTH_24:
|
||||
atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_DIS;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_30:
|
||||
atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_5_4;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_36:
|
||||
atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_3_2;
|
||||
break;
|
||||
case TRANSMITTER_COLOR_DEPTH_48:
|
||||
atomColorDepth = PIXEL_CLOCK_V7_DEEPCOLOR_RATIO_2_1;
|
||||
break;
|
||||
default:
|
||||
ASSERT_CRITICAL(false); /* Unhandle action in driver! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atomColorDepth;
|
||||
}
|
||||
|
||||
/* function table */
|
||||
static const struct command_table_helper command_table_helper_funcs = {
|
||||
.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
|
||||
.encoder_action_to_atom = encoder_action_to_atom,
|
||||
.engine_bp_to_atom = engine_bp_to_atom,
|
||||
.clock_source_id_to_atom = clock_source_id_to_atom,
|
||||
.clock_source_id_to_atom_phy_clk_src_id =
|
||||
clock_source_id_to_atom_phy_clk_src_id,
|
||||
.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
|
||||
.hpd_sel_to_atom = hpd_sel_to_atom,
|
||||
.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
|
||||
.phy_id_to_atom = phy_id_to_atom,
|
||||
.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
|
||||
.assign_control_parameter = NULL,
|
||||
.clock_source_id_to_ref_clk_src = NULL,
|
||||
.transmitter_bp_to_atom = NULL,
|
||||
.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
|
||||
.encoder_mode_bp_to_atom = dal_cmd_table_helper_encoder_mode_bp_to_atom,
|
||||
.dc_clock_type_to_atom = dc_clock_type_to_atom,
|
||||
.transmitter_color_depth_to_atom = transmitter_color_depth_to_atom,
|
||||
};
|
||||
|
||||
/*
|
||||
* dal_cmd_tbl_helper_dce110_get_table
|
||||
*
|
||||
* @brief
|
||||
* Initialize command table helper functions
|
||||
*
|
||||
* @param
|
||||
* const struct command_table_helper **h - [out] struct of functions
|
||||
*
|
||||
*/
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table()
|
||||
{
|
||||
return &command_table_helper_funcs;
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_COMMAND_TABLE_HELPER_DCE112_H__
|
||||
#define __DAL_COMMAND_TABLE_HELPER_DCE112_H__
|
||||
|
||||
struct command_table_helper;
|
||||
|
||||
/* Initialize command table helper functions */
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce112_get_table(void);
|
||||
|
||||
#endif /* __DAL_COMMAND_TABLE_HELPER_DCE110_H__ */
|
|
@ -0,0 +1,354 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
|
||||
#include "atom.h"
|
||||
|
||||
#include "include/grph_object_id.h"
|
||||
#include "include/grph_object_defs.h"
|
||||
#include "include/bios_parser_types.h"
|
||||
|
||||
#include "../command_table_helper.h"
|
||||
|
||||
static uint8_t encoder_action_to_atom(enum bp_encoder_control_action action)
|
||||
{
|
||||
uint8_t atom_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ENCODER_CONTROL_ENABLE:
|
||||
atom_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_DISABLE:
|
||||
atom_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ENCODER_CONTROL_SETUP:
|
||||
atom_action = ATOM_ENCODER_CMD_SETUP;
|
||||
break;
|
||||
case ENCODER_CONTROL_INIT:
|
||||
atom_action = ATOM_ENCODER_INIT;
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER(); /* Unhandle action in driver.!! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_action;
|
||||
}
|
||||
|
||||
static bool engine_bp_to_atom(enum engine_id id, uint32_t *atom_engine_id)
|
||||
{
|
||||
bool result = false;
|
||||
|
||||
if (atom_engine_id != NULL)
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
*atom_engine_id = ASIC_INT_DIG1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
*atom_engine_id = ASIC_INT_DIG2_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
*atom_engine_id = ASIC_INT_DIG3_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
*atom_engine_id = ASIC_INT_DIG4_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
*atom_engine_id = ASIC_INT_DIG5_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
*atom_engine_id = ASIC_INT_DIG6_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
*atom_engine_id = ASIC_INT_DIG7_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
case ENGINE_ID_DACA:
|
||||
*atom_engine_id = ASIC_INT_DAC1_ENCODER_ID;
|
||||
result = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static bool clock_source_id_to_atom(
|
||||
enum clock_source_id id,
|
||||
uint32_t *atom_pll_id)
|
||||
{
|
||||
bool result = true;
|
||||
|
||||
if (atom_pll_id != NULL)
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL0:
|
||||
*atom_pll_id = ATOM_PPLL0;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
*atom_pll_id = ATOM_PPLL1;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
*atom_pll_id = ATOM_PPLL2;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DFS:
|
||||
*atom_pll_id = ATOM_EXT_PLL1;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_VCE:
|
||||
/* for VCE encoding,
|
||||
* we need to pass in ATOM_PPLL_INVALID
|
||||
*/
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_DP_DTO:
|
||||
/* When programming DP DTO PLL ID should be invalid */
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_UNDEFINED:
|
||||
BREAK_TO_DEBUGGER(); /* check when this will happen! */
|
||||
*atom_pll_id = ATOM_PPLL_INVALID;
|
||||
result = false;
|
||||
break;
|
||||
default:
|
||||
result = false;
|
||||
break;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t clock_source_id_to_atom_phy_clk_src_id(
|
||||
enum clock_source_id id)
|
||||
{
|
||||
uint8_t atom_phy_clk_src_id = 0;
|
||||
|
||||
switch (id) {
|
||||
case CLOCK_SOURCE_ID_PLL0:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P0PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL1:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_PLL2:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P2PLL;
|
||||
break;
|
||||
case CLOCK_SOURCE_ID_EXTERNAL:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_REFCLK_SRC_EXT;
|
||||
break;
|
||||
default:
|
||||
atom_phy_clk_src_id = ATOM_TRANSMITTER_CONFIG_V5_P1PLL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_phy_clk_src_id >> 2;
|
||||
}
|
||||
|
||||
static uint8_t signal_type_to_atom_dig_mode(enum signal_type s)
|
||||
{
|
||||
uint8_t atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
|
||||
|
||||
switch (s) {
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_EDP:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP;
|
||||
break;
|
||||
case SIGNAL_TYPE_LVDS:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_LVDS;
|
||||
break;
|
||||
case SIGNAL_TYPE_DVI_SINGLE_LINK:
|
||||
case SIGNAL_TYPE_DVI_DUAL_LINK:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
|
||||
break;
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_HDMI;
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DP_MST;
|
||||
break;
|
||||
default:
|
||||
atom_dig_mode = ATOM_TRANSMITTER_DIGMODE_V5_DVI;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_mode;
|
||||
}
|
||||
|
||||
static uint8_t hpd_sel_to_atom(enum hpd_source_id id)
|
||||
{
|
||||
uint8_t atom_hpd_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case HPD_SOURCEID1:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD1_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID2:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD2_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID3:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD3_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID4:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD4_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID5:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD5_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID6:
|
||||
atom_hpd_sel = ATOM_TRANSMITTER_CONFIG_V5_HPD6_SEL;
|
||||
break;
|
||||
case HPD_SOURCEID_UNKNOWN:
|
||||
default:
|
||||
atom_hpd_sel = 0;
|
||||
break;
|
||||
}
|
||||
return atom_hpd_sel >> 4;
|
||||
}
|
||||
|
||||
static uint8_t dig_encoder_sel_to_atom(enum engine_id id)
|
||||
{
|
||||
uint8_t atom_dig_encoder_sel = 0;
|
||||
|
||||
switch (id) {
|
||||
case ENGINE_ID_DIGA:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGB:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGB_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGC:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGC_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGD:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGD_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGE:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGE_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGF:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGF_SEL;
|
||||
break;
|
||||
case ENGINE_ID_DIGG:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGG_SEL;
|
||||
break;
|
||||
default:
|
||||
atom_dig_encoder_sel = ATOM_TRANMSITTER_V5__DIGA_SEL;
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_dig_encoder_sel;
|
||||
}
|
||||
|
||||
static uint8_t phy_id_to_atom(enum transmitter t)
|
||||
{
|
||||
uint8_t atom_phy_id;
|
||||
|
||||
switch (t) {
|
||||
case TRANSMITTER_UNIPHY_A:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_B:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYB;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_C:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYC;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_D:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYD;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_E:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYE;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_F:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYF;
|
||||
break;
|
||||
case TRANSMITTER_UNIPHY_G:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYG;
|
||||
break;
|
||||
default:
|
||||
atom_phy_id = ATOM_PHY_ID_UNIPHYA;
|
||||
break;
|
||||
}
|
||||
return atom_phy_id;
|
||||
}
|
||||
|
||||
static uint8_t disp_power_gating_action_to_atom(
|
||||
enum bp_pipe_control_action action)
|
||||
{
|
||||
uint8_t atom_pipe_action = 0;
|
||||
|
||||
switch (action) {
|
||||
case ASIC_PIPE_DISABLE:
|
||||
atom_pipe_action = ATOM_DISABLE;
|
||||
break;
|
||||
case ASIC_PIPE_ENABLE:
|
||||
atom_pipe_action = ATOM_ENABLE;
|
||||
break;
|
||||
case ASIC_PIPE_INIT:
|
||||
atom_pipe_action = ATOM_INIT;
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER(); /* Unhandle action in driver! */
|
||||
break;
|
||||
}
|
||||
|
||||
return atom_pipe_action;
|
||||
}
|
||||
|
||||
static const struct command_table_helper command_table_helper_funcs = {
|
||||
.controller_id_to_atom = dal_cmd_table_helper_controller_id_to_atom,
|
||||
.encoder_action_to_atom = encoder_action_to_atom,
|
||||
.engine_bp_to_atom = engine_bp_to_atom,
|
||||
.clock_source_id_to_atom = clock_source_id_to_atom,
|
||||
.clock_source_id_to_atom_phy_clk_src_id =
|
||||
clock_source_id_to_atom_phy_clk_src_id,
|
||||
.signal_type_to_atom_dig_mode = signal_type_to_atom_dig_mode,
|
||||
.hpd_sel_to_atom = hpd_sel_to_atom,
|
||||
.dig_encoder_sel_to_atom = dig_encoder_sel_to_atom,
|
||||
.phy_id_to_atom = phy_id_to_atom,
|
||||
.disp_power_gating_action_to_atom = disp_power_gating_action_to_atom,
|
||||
.assign_control_parameter =
|
||||
dal_cmd_table_helper_assign_control_parameter,
|
||||
.clock_source_id_to_ref_clk_src =
|
||||
dal_cmd_table_helper_clock_source_id_to_ref_clk_src,
|
||||
.transmitter_bp_to_atom = dal_cmd_table_helper_transmitter_bp_to_atom,
|
||||
.encoder_id_to_atom = dal_cmd_table_helper_encoder_id_to_atom,
|
||||
.encoder_mode_bp_to_atom =
|
||||
dal_cmd_table_helper_encoder_mode_bp_to_atom,
|
||||
};
|
||||
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table()
|
||||
{
|
||||
return &command_table_helper_funcs;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_COMMAND_TABLE_HELPER_DCE80_H__
|
||||
#define __DAL_COMMAND_TABLE_HELPER_DCE80_H__
|
||||
|
||||
struct command_table_helper;
|
||||
|
||||
const struct command_table_helper *dal_cmd_tbl_helper_dce80_get_table(void);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,10 @@
|
|||
#
|
||||
# Makefile for the 'calcs' sub-component of DAL.
|
||||
# It calculates Bandwidth and Watermarks values for HW programming
|
||||
#
|
||||
|
||||
BW_CALCS = bandwidth_calcs.o bw_fixed.o gamma_calcs.o
|
||||
|
||||
AMD_DAL_BW_CALCS = $(addprefix $(AMDDALPATH)/dc/calcs/,$(BW_CALCS))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_BW_CALCS)
|
File diff suppressed because it is too large
Load Diff
|
@ -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.
|
||||
*
|
||||
* Authors: AMD
|
||||
*
|
||||
*/
|
||||
#include "dm_services.h"
|
||||
#include "bw_fixed.h"
|
||||
|
||||
#define BITS_PER_FRACTIONAL_PART 24
|
||||
|
||||
#define MIN_I32 \
|
||||
(int64_t)(-(1LL << (63 - BITS_PER_FRACTIONAL_PART)))
|
||||
|
||||
#define MAX_I32 \
|
||||
(int64_t)((1ULL << (63 - BITS_PER_FRACTIONAL_PART)) - 1)
|
||||
|
||||
#define MIN_I64 \
|
||||
(int64_t)(-(1LL << 63))
|
||||
|
||||
#define MAX_I64 \
|
||||
(int64_t)((1ULL << 63) - 1)
|
||||
|
||||
#define FRACTIONAL_PART_MASK \
|
||||
((1ULL << BITS_PER_FRACTIONAL_PART) - 1)
|
||||
|
||||
#define GET_INTEGER_PART(x) \
|
||||
((x) >> BITS_PER_FRACTIONAL_PART)
|
||||
|
||||
#define GET_FRACTIONAL_PART(x) \
|
||||
(FRACTIONAL_PART_MASK & (x))
|
||||
|
||||
static uint64_t abs_i64(int64_t arg)
|
||||
{
|
||||
if (arg >= 0)
|
||||
return (uint64_t)(arg);
|
||||
else
|
||||
return (uint64_t)(-arg);
|
||||
}
|
||||
|
||||
struct bw_fixed bw_min3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
|
||||
{
|
||||
return bw_min2(bw_min2(v1, v2), v3);
|
||||
}
|
||||
|
||||
struct bw_fixed bw_max3(struct bw_fixed v1, struct bw_fixed v2, struct bw_fixed v3)
|
||||
{
|
||||
return bw_max2(bw_max2(v1, v2), v3);
|
||||
}
|
||||
|
||||
struct bw_fixed bw_int_to_fixed(int64_t value)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
ASSERT(value < MAX_I32 && value > MIN_I32);
|
||||
res.value = value << BITS_PER_FRACTIONAL_PART;
|
||||
return res;
|
||||
}
|
||||
|
||||
int32_t bw_fixed_to_int(struct bw_fixed value)
|
||||
{
|
||||
return GET_INTEGER_PART(value.value);
|
||||
}
|
||||
|
||||
struct bw_fixed bw_frc_to_fixed(int64_t numerator, int64_t denominator)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
bool arg1_negative = numerator < 0;
|
||||
bool arg2_negative = denominator < 0;
|
||||
uint64_t arg1_value;
|
||||
uint64_t arg2_value;
|
||||
uint64_t remainder;
|
||||
|
||||
/* determine integer part */
|
||||
uint64_t res_value;
|
||||
|
||||
ASSERT(denominator != 0);
|
||||
|
||||
arg1_value = abs_i64(numerator);
|
||||
arg2_value = abs_i64(denominator);
|
||||
res_value = div64_u64_rem(arg1_value, arg2_value, &remainder);
|
||||
|
||||
ASSERT(res_value <= MAX_I32);
|
||||
|
||||
/* determine fractional part */
|
||||
{
|
||||
uint32_t i = BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
do
|
||||
{
|
||||
remainder <<= 1;
|
||||
|
||||
res_value <<= 1;
|
||||
|
||||
if (remainder >= arg2_value)
|
||||
{
|
||||
res_value |= 1;
|
||||
remainder -= arg2_value;
|
||||
}
|
||||
} while (--i != 0);
|
||||
}
|
||||
|
||||
/* round up LSB */
|
||||
{
|
||||
uint64_t summand = (remainder << 1) >= arg2_value;
|
||||
|
||||
ASSERT(res_value <= MAX_I64 - summand);
|
||||
|
||||
res_value += summand;
|
||||
}
|
||||
|
||||
res.value = (int64_t)(res_value);
|
||||
|
||||
if (arg1_negative ^ arg2_negative)
|
||||
res.value = -res.value;
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_min2(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return (arg1.value <= arg2.value) ? arg1 : arg2;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_max2(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return (arg2.value <= arg1.value) ? arg1 : arg2;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_floor2(
|
||||
const struct bw_fixed arg,
|
||||
const struct bw_fixed significance)
|
||||
{
|
||||
struct bw_fixed result;
|
||||
int64_t multiplicand;
|
||||
|
||||
multiplicand = div64_s64(arg.value, abs_i64(significance.value));
|
||||
result.value = abs_i64(significance.value) * multiplicand;
|
||||
ASSERT(abs_i64(result.value) <= abs_i64(arg.value));
|
||||
return result;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_ceil2(
|
||||
const struct bw_fixed arg,
|
||||
const struct bw_fixed significance)
|
||||
{
|
||||
struct bw_fixed result;
|
||||
int64_t multiplicand;
|
||||
|
||||
multiplicand = div64_s64(arg.value, abs_i64(significance.value));
|
||||
result.value = abs_i64(significance.value) * multiplicand;
|
||||
if (abs_i64(result.value) < abs_i64(arg.value)) {
|
||||
if (arg.value < 0)
|
||||
result.value -= abs_i64(significance.value);
|
||||
else
|
||||
result.value += abs_i64(significance.value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_add(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
|
||||
res.value = arg1.value + arg2.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_sub(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
|
||||
res.value = arg1.value - arg2.value;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_mul(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
|
||||
bool arg1_negative = arg1.value < 0;
|
||||
bool arg2_negative = arg2.value < 0;
|
||||
|
||||
uint64_t arg1_value = abs_i64(arg1.value);
|
||||
uint64_t arg2_value = abs_i64(arg2.value);
|
||||
|
||||
uint64_t arg1_int = GET_INTEGER_PART(arg1_value);
|
||||
uint64_t arg2_int = GET_INTEGER_PART(arg2_value);
|
||||
|
||||
uint64_t arg1_fra = GET_FRACTIONAL_PART(arg1_value);
|
||||
uint64_t arg2_fra = GET_FRACTIONAL_PART(arg2_value);
|
||||
|
||||
uint64_t tmp;
|
||||
|
||||
res.value = arg1_int * arg2_int;
|
||||
|
||||
ASSERT(res.value <= MAX_I32);
|
||||
|
||||
res.value <<= BITS_PER_FRACTIONAL_PART;
|
||||
|
||||
tmp = arg1_int * arg2_fra;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
tmp = arg2_int * arg1_fra;
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
tmp = arg1_fra * arg2_fra;
|
||||
|
||||
tmp = (tmp >> BITS_PER_FRACTIONAL_PART) +
|
||||
(tmp >= (uint64_t)(bw_frc_to_fixed(1, 2).value));
|
||||
|
||||
ASSERT(tmp <= (uint64_t)(MAX_I64 - res.value));
|
||||
|
||||
res.value += tmp;
|
||||
|
||||
if (arg1_negative ^ arg2_negative)
|
||||
res.value = -res.value;
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_div(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
struct bw_fixed res = bw_frc_to_fixed(arg1.value, arg2.value);
|
||||
return res;
|
||||
}
|
||||
|
||||
struct bw_fixed bw_mod(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
struct bw_fixed res;
|
||||
div64_u64_rem(arg1.value, arg2.value, &res.value);
|
||||
return res;
|
||||
}
|
||||
struct bw_fixed fixed31_32_to_bw_fixed(int64_t raw)
|
||||
{
|
||||
struct bw_fixed result = { 0 };
|
||||
|
||||
if (raw < 0) {
|
||||
raw = -raw;
|
||||
result.value = -(raw >> (32 - BITS_PER_FRACTIONAL_PART));
|
||||
} else {
|
||||
result.value = raw >> (32 - BITS_PER_FRACTIONAL_PART);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool bw_equ(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value == arg2.value;
|
||||
}
|
||||
|
||||
bool bw_neq(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value != arg2.value;
|
||||
}
|
||||
|
||||
bool bw_leq(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value <= arg2.value;
|
||||
}
|
||||
|
||||
bool bw_meq(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value >= arg2.value;
|
||||
}
|
||||
|
||||
bool bw_ltn(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value < arg2.value;
|
||||
}
|
||||
|
||||
bool bw_mtn(const struct bw_fixed arg1, const struct bw_fixed arg2)
|
||||
{
|
||||
return arg1.value > arg2.value;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,270 @@
|
|||
/*
|
||||
* dc_debug.c
|
||||
*
|
||||
* Created on: Nov 3, 2016
|
||||
* Author: yonsun
|
||||
*/
|
||||
|
||||
#include "dm_services.h"
|
||||
|
||||
#include "dc.h"
|
||||
|
||||
#include "core_status.h"
|
||||
#include "core_types.h"
|
||||
#include "hw_sequencer.h"
|
||||
|
||||
#include "resource.h"
|
||||
|
||||
#define SURFACE_TRACE(...) do {\
|
||||
if (dc->debug.surface_trace) \
|
||||
dm_logger_write(logger, \
|
||||
LOG_IF_TRACE, \
|
||||
##__VA_ARGS__); \
|
||||
} while (0)
|
||||
|
||||
void pre_surface_trace(
|
||||
const struct dc *dc,
|
||||
const struct dc_surface *const *surfaces,
|
||||
int surface_count)
|
||||
{
|
||||
int i;
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
struct dal_logger *logger = core_dc->ctx->logger;
|
||||
|
||||
for (i = 0; i < surface_count; i++) {
|
||||
const struct dc_surface *surface = surfaces[i];
|
||||
|
||||
SURFACE_TRACE("Surface %d:\n", i);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"surface->visible = %d;\n"
|
||||
"surface->flip_immediate = %d;\n"
|
||||
"surface->address.type = %d;\n"
|
||||
"surface->address.grph.addr.quad_part = 0x%X;\n"
|
||||
"surface->address.grph.meta_addr.quad_part = 0x%X;\n"
|
||||
"surface->scaling_quality.h_taps = %d;\n"
|
||||
"surface->scaling_quality.v_taps = %d;\n"
|
||||
"surface->scaling_quality.h_taps_c = %d;\n"
|
||||
"surface->scaling_quality.v_taps_c = %d;\n",
|
||||
surface->visible,
|
||||
surface->flip_immediate,
|
||||
surface->address.type,
|
||||
surface->address.grph.addr.quad_part,
|
||||
surface->address.grph.meta_addr.quad_part,
|
||||
surface->scaling_quality.h_taps,
|
||||
surface->scaling_quality.v_taps,
|
||||
surface->scaling_quality.h_taps_c,
|
||||
surface->scaling_quality.v_taps_c);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"surface->src_rect.x = %d;\n"
|
||||
"surface->src_rect.y = %d;\n"
|
||||
"surface->src_rect.width = %d;\n"
|
||||
"surface->src_rect.height = %d;\n"
|
||||
"surface->dst_rect.x = %d;\n"
|
||||
"surface->dst_rect.y = %d;\n"
|
||||
"surface->dst_rect.width = %d;\n"
|
||||
"surface->dst_rect.height = %d;\n"
|
||||
"surface->clip_rect.x = %d;\n"
|
||||
"surface->clip_rect.y = %d;\n"
|
||||
"surface->clip_rect.width = %d;\n"
|
||||
"surface->clip_rect.height = %d;\n",
|
||||
surface->src_rect.x,
|
||||
surface->src_rect.y,
|
||||
surface->src_rect.width,
|
||||
surface->src_rect.height,
|
||||
surface->dst_rect.x,
|
||||
surface->dst_rect.y,
|
||||
surface->dst_rect.width,
|
||||
surface->dst_rect.height,
|
||||
surface->clip_rect.x,
|
||||
surface->clip_rect.y,
|
||||
surface->clip_rect.width,
|
||||
surface->clip_rect.height);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"surface->plane_size.grph.surface_size.x = %d;\n"
|
||||
"surface->plane_size.grph.surface_size.y = %d;\n"
|
||||
"surface->plane_size.grph.surface_size.width = %d;\n"
|
||||
"surface->plane_size.grph.surface_size.height = %d;\n"
|
||||
"surface->plane_size.grph.surface_pitch = %d;\n"
|
||||
"surface->plane_size.grph.meta_pitch = %d;\n",
|
||||
surface->plane_size.grph.surface_size.x,
|
||||
surface->plane_size.grph.surface_size.y,
|
||||
surface->plane_size.grph.surface_size.width,
|
||||
surface->plane_size.grph.surface_size.height,
|
||||
surface->plane_size.grph.surface_pitch,
|
||||
surface->plane_size.grph.meta_pitch);
|
||||
|
||||
|
||||
SURFACE_TRACE(
|
||||
"surface->tiling_info.gfx8.num_banks = %d;\n"
|
||||
"surface->tiling_info.gfx8.bank_width = %d;\n"
|
||||
"surface->tiling_info.gfx8.bank_width_c = %d;\n"
|
||||
"surface->tiling_info.gfx8.bank_height = %d;\n"
|
||||
"surface->tiling_info.gfx8.bank_height_c = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_aspect = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_aspect_c = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_split = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_split_c = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_mode = %d;\n"
|
||||
"surface->tiling_info.gfx8.tile_mode_c = %d;\n",
|
||||
surface->tiling_info.gfx8.num_banks,
|
||||
surface->tiling_info.gfx8.bank_width,
|
||||
surface->tiling_info.gfx8.bank_width_c,
|
||||
surface->tiling_info.gfx8.bank_height,
|
||||
surface->tiling_info.gfx8.bank_height_c,
|
||||
surface->tiling_info.gfx8.tile_aspect,
|
||||
surface->tiling_info.gfx8.tile_aspect_c,
|
||||
surface->tiling_info.gfx8.tile_split,
|
||||
surface->tiling_info.gfx8.tile_split_c,
|
||||
surface->tiling_info.gfx8.tile_mode,
|
||||
surface->tiling_info.gfx8.tile_mode_c);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"surface->tiling_info.gfx8.pipe_config = %d;\n"
|
||||
"surface->tiling_info.gfx8.array_mode = %d;\n"
|
||||
"surface->color_space = %d;\n"
|
||||
"surface->dcc.enable = %d;\n"
|
||||
"surface->format = %d;\n"
|
||||
"surface->rotation = %d;\n"
|
||||
"surface->stereo_format = %d;\n",
|
||||
surface->tiling_info.gfx8.pipe_config,
|
||||
surface->tiling_info.gfx8.array_mode,
|
||||
surface->color_space,
|
||||
surface->dcc.enable,
|
||||
surface->format,
|
||||
surface->rotation,
|
||||
surface->stereo_format);
|
||||
SURFACE_TRACE("\n");
|
||||
}
|
||||
SURFACE_TRACE("\n");
|
||||
}
|
||||
|
||||
void update_surface_trace(
|
||||
const struct dc *dc,
|
||||
const struct dc_surface_update *updates,
|
||||
int surface_count)
|
||||
{
|
||||
int i;
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
struct dal_logger *logger = core_dc->ctx->logger;
|
||||
|
||||
for (i = 0; i < surface_count; i++) {
|
||||
const struct dc_surface_update *update = &updates[i];
|
||||
|
||||
SURFACE_TRACE("Update %d\n", i);
|
||||
if (update->flip_addr) {
|
||||
SURFACE_TRACE("flip_addr->address.type = %d;\n"
|
||||
"flip_addr->address.grph.addr.quad_part = 0x%X;\n"
|
||||
"flip_addr->address.grph.meta_addr.quad_part = 0x%X;\n"
|
||||
"flip_addr->flip_immediate = %d;\n",
|
||||
update->flip_addr->address.type,
|
||||
update->flip_addr->address.grph.addr.quad_part,
|
||||
update->flip_addr->address.grph.meta_addr.quad_part,
|
||||
update->flip_addr->flip_immediate);
|
||||
}
|
||||
|
||||
if (update->plane_info) {
|
||||
SURFACE_TRACE(
|
||||
"plane_info->color_space = %d;\n"
|
||||
"plane_info->format = %d;\n"
|
||||
"plane_info->plane_size.grph.meta_pitch = %d;\n"
|
||||
"plane_info->plane_size.grph.surface_pitch = %d;\n"
|
||||
"plane_info->plane_size.grph.surface_size.height = %d;\n"
|
||||
"plane_info->plane_size.grph.surface_size.width = %d;\n"
|
||||
"plane_info->plane_size.grph.surface_size.x = %d;\n"
|
||||
"plane_info->plane_size.grph.surface_size.y = %d;\n"
|
||||
"plane_info->rotation = %d;\n",
|
||||
update->plane_info->color_space,
|
||||
update->plane_info->format,
|
||||
update->plane_info->plane_size.grph.meta_pitch,
|
||||
update->plane_info->plane_size.grph.surface_pitch,
|
||||
update->plane_info->plane_size.grph.surface_size.height,
|
||||
update->plane_info->plane_size.grph.surface_size.width,
|
||||
update->plane_info->plane_size.grph.surface_size.x,
|
||||
update->plane_info->plane_size.grph.surface_size.y,
|
||||
update->plane_info->rotation,
|
||||
update->plane_info->stereo_format);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"plane_info->tiling_info.gfx8.num_banks = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.bank_width = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.bank_width_c = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.bank_height = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.bank_height_c = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_aspect = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_aspect_c = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_split = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_split_c = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_mode = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.tile_mode_c = %d;\n",
|
||||
update->plane_info->tiling_info.gfx8.num_banks,
|
||||
update->plane_info->tiling_info.gfx8.bank_width,
|
||||
update->plane_info->tiling_info.gfx8.bank_width_c,
|
||||
update->plane_info->tiling_info.gfx8.bank_height,
|
||||
update->plane_info->tiling_info.gfx8.bank_height_c,
|
||||
update->plane_info->tiling_info.gfx8.tile_aspect,
|
||||
update->plane_info->tiling_info.gfx8.tile_aspect_c,
|
||||
update->plane_info->tiling_info.gfx8.tile_split,
|
||||
update->plane_info->tiling_info.gfx8.tile_split_c,
|
||||
update->plane_info->tiling_info.gfx8.tile_mode,
|
||||
update->plane_info->tiling_info.gfx8.tile_mode_c);
|
||||
|
||||
SURFACE_TRACE(
|
||||
"plane_info->tiling_info.gfx8.pipe_config = %d;\n"
|
||||
"plane_info->tiling_info.gfx8.array_mode = %d;\n"
|
||||
"plane_info->visible = %d;\n",
|
||||
update->plane_info->tiling_info.gfx8.pipe_config,
|
||||
update->plane_info->tiling_info.gfx8.array_mode,
|
||||
update->plane_info->visible);
|
||||
}
|
||||
|
||||
if (update->scaling_info) {
|
||||
SURFACE_TRACE(
|
||||
"scaling_info->src_rect.x = %d;\n"
|
||||
"scaling_info->src_rect.y = %d;\n"
|
||||
"scaling_info->src_rect.width = %d;\n"
|
||||
"scaling_info->src_rect.height = %d;\n"
|
||||
"scaling_info->dst_rect.x = %d;\n"
|
||||
"scaling_info->dst_rect.y = %d;\n"
|
||||
"scaling_info->dst_rect.width = %d;\n"
|
||||
"scaling_info->dst_rect.height = %d;\n"
|
||||
"scaling_info->clip_rect.x = %d;\n"
|
||||
"scaling_info->clip_rect.y = %d;\n"
|
||||
"scaling_info->clip_rect.width = %d;\n"
|
||||
"scaling_info->clip_rect.height = %d;\n"
|
||||
"scaling_info->scaling_quality.h_taps = %d;\n"
|
||||
"scaling_info->scaling_quality.v_taps = %d;\n"
|
||||
"scaling_info->scaling_quality.h_taps_c = %d;\n"
|
||||
"scaling_info->scaling_quality.v_taps_c = %d;\n",
|
||||
update->scaling_info->src_rect.x,
|
||||
update->scaling_info->src_rect.y,
|
||||
update->scaling_info->src_rect.width,
|
||||
update->scaling_info->src_rect.height,
|
||||
update->scaling_info->dst_rect.x,
|
||||
update->scaling_info->dst_rect.y,
|
||||
update->scaling_info->dst_rect.width,
|
||||
update->scaling_info->dst_rect.height,
|
||||
update->scaling_info->clip_rect.x,
|
||||
update->scaling_info->clip_rect.y,
|
||||
update->scaling_info->clip_rect.width,
|
||||
update->scaling_info->clip_rect.height,
|
||||
update->scaling_info->scaling_quality.h_taps,
|
||||
update->scaling_info->scaling_quality.v_taps,
|
||||
update->scaling_info->scaling_quality.h_taps_c,
|
||||
update->scaling_info->scaling_quality.v_taps_c);
|
||||
}
|
||||
SURFACE_TRACE("\n");
|
||||
}
|
||||
SURFACE_TRACE("\n");
|
||||
}
|
||||
|
||||
void post_surface_trace(const struct dc *dc)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
struct dal_logger *logger = core_dc->ctx->logger;
|
||||
|
||||
SURFACE_TRACE("post surface process.\n");
|
||||
|
||||
}
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* 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 "dm_services.h"
|
||||
#include "core_types.h"
|
||||
#include "core_dc.h"
|
||||
#include "timing_generator.h"
|
||||
#include "hw_sequencer.h"
|
||||
|
||||
/* used as index in array of black_color_format */
|
||||
enum black_color_format {
|
||||
BLACK_COLOR_FORMAT_RGB_FULLRANGE = 0,
|
||||
BLACK_COLOR_FORMAT_RGB_LIMITED,
|
||||
BLACK_COLOR_FORMAT_YUV_TV,
|
||||
BLACK_COLOR_FORMAT_YUV_CV,
|
||||
BLACK_COLOR_FORMAT_YUV_SUPER_AA,
|
||||
BLACK_COLOR_FORMAT_DEBUG,
|
||||
};
|
||||
|
||||
static const struct tg_color black_color_format[] = {
|
||||
/* BlackColorFormat_RGB_FullRange */
|
||||
{0, 0, 0},
|
||||
/* BlackColorFormat_RGB_Limited */
|
||||
{0x40, 0x40, 0x40},
|
||||
/* BlackColorFormat_YUV_TV */
|
||||
{0x200, 0x40, 0x200},
|
||||
/* BlackColorFormat_YUV_CV */
|
||||
{0x1f4, 0x40, 0x1f4},
|
||||
/* BlackColorFormat_YUV_SuperAA */
|
||||
{0x1a2, 0x20, 0x1a2},
|
||||
/* visual confirm debug */
|
||||
{0xff, 0xff, 0},
|
||||
};
|
||||
|
||||
void color_space_to_black_color(
|
||||
const struct core_dc *dc,
|
||||
enum dc_color_space colorspace,
|
||||
struct tg_color *black_color)
|
||||
{
|
||||
if (dc->public.debug.surface_visual_confirm) {
|
||||
*black_color =
|
||||
black_color_format[BLACK_COLOR_FORMAT_DEBUG];
|
||||
return;
|
||||
}
|
||||
|
||||
switch (colorspace) {
|
||||
case COLOR_SPACE_YPBPR601:
|
||||
*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_TV];
|
||||
break;
|
||||
|
||||
case COLOR_SPACE_YPBPR709:
|
||||
case COLOR_SPACE_YCBCR601:
|
||||
case COLOR_SPACE_YCBCR709:
|
||||
case COLOR_SPACE_YCBCR601_LIMITED:
|
||||
case COLOR_SPACE_YCBCR709_LIMITED:
|
||||
*black_color = black_color_format[BLACK_COLOR_FORMAT_YUV_CV];
|
||||
break;
|
||||
|
||||
case COLOR_SPACE_SRGB_LIMITED:
|
||||
*black_color =
|
||||
black_color_format[BLACK_COLOR_FORMAT_RGB_LIMITED];
|
||||
break;
|
||||
|
||||
default:
|
||||
/* fefault is sRGB black (full range). */
|
||||
*black_color =
|
||||
black_color_format[BLACK_COLOR_FORMAT_RGB_FULLRANGE];
|
||||
/* default is sRGB black 0. */
|
||||
break;
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,222 @@
|
|||
/* Copyright 2015 Advanced Micro Devices, Inc. */
|
||||
|
||||
|
||||
#include "dm_services.h"
|
||||
#include "dc.h"
|
||||
#include "inc/core_dc.h"
|
||||
#include "include/ddc_service_types.h"
|
||||
#include "include/i2caux_interface.h"
|
||||
#include "link_hwss.h"
|
||||
#include "hw_sequencer.h"
|
||||
#include "dc_link_dp.h"
|
||||
#include "dc_link_ddc.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "dce/dce_link_encoder.h"
|
||||
#include "dce/dce_stream_encoder.h"
|
||||
|
||||
enum dc_status core_link_read_dpcd(
|
||||
struct core_link* link,
|
||||
uint32_t address,
|
||||
uint8_t *data,
|
||||
uint32_t size)
|
||||
{
|
||||
if (!dm_helpers_dp_read_dpcd(link->ctx,
|
||||
&link->public,
|
||||
address, data, size))
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
enum dc_status core_link_write_dpcd(
|
||||
struct core_link* link,
|
||||
uint32_t address,
|
||||
const uint8_t *data,
|
||||
uint32_t size)
|
||||
{
|
||||
if (!dm_helpers_dp_write_dpcd(link->ctx,
|
||||
&link->public,
|
||||
address, data, size))
|
||||
return DC_ERROR_UNEXPECTED;
|
||||
|
||||
return DC_OK;
|
||||
}
|
||||
|
||||
void dp_receiver_power_ctrl(struct core_link *link, bool on)
|
||||
{
|
||||
uint8_t state;
|
||||
|
||||
state = on ? DP_POWER_STATE_D0 : DP_POWER_STATE_D3;
|
||||
|
||||
core_link_write_dpcd(link, DPCD_ADDRESS_POWER_STATE, &state,
|
||||
sizeof(state));
|
||||
}
|
||||
|
||||
void dp_enable_link_phy(
|
||||
struct core_link *link,
|
||||
enum signal_type signal,
|
||||
enum clock_source_id clock_source,
|
||||
const struct dc_link_settings *link_settings)
|
||||
{
|
||||
struct link_encoder *link_enc = link->link_enc;
|
||||
|
||||
if (dc_is_dp_sst_signal(signal)) {
|
||||
if (signal == SIGNAL_TYPE_EDP) {
|
||||
link_enc->funcs->power_control(link_enc, true);
|
||||
link_enc->funcs->backlight_control(link_enc, true);
|
||||
}
|
||||
|
||||
link_enc->funcs->enable_dp_output(
|
||||
link_enc,
|
||||
link_settings,
|
||||
clock_source);
|
||||
} else {
|
||||
link_enc->funcs->enable_dp_mst_output(
|
||||
link_enc,
|
||||
link_settings,
|
||||
clock_source);
|
||||
}
|
||||
|
||||
dp_receiver_power_ctrl(link, true);
|
||||
}
|
||||
|
||||
void dp_disable_link_phy(struct core_link *link, enum signal_type signal)
|
||||
{
|
||||
if (!link->wa_flags.dp_keep_receiver_powered)
|
||||
dp_receiver_power_ctrl(link, false);
|
||||
|
||||
if (signal == SIGNAL_TYPE_EDP)
|
||||
link->link_enc->funcs->backlight_control(link->link_enc, false);
|
||||
|
||||
link->link_enc->funcs->disable_output(link->link_enc, signal);
|
||||
|
||||
/* Clear current link setting.*/
|
||||
memset(&link->public.cur_link_settings, 0,
|
||||
sizeof(link->public.cur_link_settings));
|
||||
}
|
||||
|
||||
void dp_disable_link_phy_mst(struct core_link *link, enum signal_type signal)
|
||||
{
|
||||
/* MST disable link only when no stream use the link */
|
||||
if (link->mst_stream_alloc_table.stream_count > 0)
|
||||
return;
|
||||
|
||||
dp_disable_link_phy(link, signal);
|
||||
}
|
||||
|
||||
bool dp_set_hw_training_pattern(
|
||||
struct core_link *link,
|
||||
enum hw_dp_training_pattern pattern)
|
||||
{
|
||||
enum dp_test_pattern test_pattern = DP_TEST_PATTERN_UNSUPPORTED;
|
||||
|
||||
switch (pattern) {
|
||||
case HW_DP_TRAINING_PATTERN_1:
|
||||
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN1;
|
||||
break;
|
||||
case HW_DP_TRAINING_PATTERN_2:
|
||||
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN2;
|
||||
break;
|
||||
case HW_DP_TRAINING_PATTERN_3:
|
||||
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN3;
|
||||
break;
|
||||
case HW_DP_TRAINING_PATTERN_4:
|
||||
test_pattern = DP_TEST_PATTERN_TRAINING_PATTERN4;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
dp_set_hw_test_pattern(link, test_pattern, NULL, 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dp_set_hw_lane_settings(
|
||||
struct core_link *link,
|
||||
const struct link_training_settings *link_settings)
|
||||
{
|
||||
struct link_encoder *encoder = link->link_enc;
|
||||
|
||||
/* call Encoder to set lane settings */
|
||||
encoder->funcs->dp_set_lane_settings(encoder, link_settings);
|
||||
}
|
||||
|
||||
enum dp_panel_mode dp_get_panel_mode(struct core_link *link)
|
||||
{
|
||||
/* We need to explicitly check that connector
|
||||
* is not DP. Some Travis_VGA get reported
|
||||
* by video bios as DP.
|
||||
*/
|
||||
if (link->public.connector_signal != SIGNAL_TYPE_DISPLAY_PORT) {
|
||||
|
||||
switch (link->dpcd_caps.branch_dev_id) {
|
||||
case DP_BRANCH_DEVICE_ID_2:
|
||||
if (strncmp(
|
||||
link->dpcd_caps.branch_dev_name,
|
||||
DP_VGA_LVDS_CONVERTER_ID_2,
|
||||
sizeof(
|
||||
link->dpcd_caps.
|
||||
branch_dev_name)) == 0) {
|
||||
return DP_PANEL_MODE_SPECIAL;
|
||||
}
|
||||
break;
|
||||
case DP_BRANCH_DEVICE_ID_3:
|
||||
if (strncmp(link->dpcd_caps.branch_dev_name,
|
||||
DP_VGA_LVDS_CONVERTER_ID_3,
|
||||
sizeof(
|
||||
link->dpcd_caps.
|
||||
branch_dev_name)) == 0) {
|
||||
return DP_PANEL_MODE_SPECIAL;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (link->dpcd_caps.panel_mode_edp) {
|
||||
return DP_PANEL_MODE_EDP;
|
||||
}
|
||||
}
|
||||
|
||||
return DP_PANEL_MODE_DEFAULT;
|
||||
}
|
||||
|
||||
void dp_set_hw_test_pattern(
|
||||
struct core_link *link,
|
||||
enum dp_test_pattern test_pattern,
|
||||
uint8_t *custom_pattern,
|
||||
uint32_t custom_pattern_size)
|
||||
{
|
||||
struct encoder_set_dp_phy_pattern_param pattern_param = {0};
|
||||
struct link_encoder *encoder = link->link_enc;
|
||||
|
||||
pattern_param.dp_phy_pattern = test_pattern;
|
||||
pattern_param.custom_pattern = custom_pattern;
|
||||
pattern_param.custom_pattern_size = custom_pattern_size;
|
||||
pattern_param.dp_panel_mode = dp_get_panel_mode(link);
|
||||
|
||||
encoder->funcs->dp_set_phy_pattern(encoder, &pattern_param);
|
||||
}
|
||||
|
||||
|
||||
void dp_retrain_link(struct core_link *link)
|
||||
{
|
||||
struct pipe_ctx *pipes = link->dc->current_context->res_ctx.pipe_ctx;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < MAX_PIPES; i++) {
|
||||
if (pipes[i].stream_enc != NULL) {
|
||||
dm_delay_in_microseconds(link->ctx, 100);
|
||||
pipes->stream_enc->funcs->dp_blank(pipes[i].stream_enc);
|
||||
link->dc->hwss.disable_stream(&pipes[i]);
|
||||
dc_link_dp_perform_link_training(
|
||||
&link->public,
|
||||
&link->public.verified_link_cap,
|
||||
true);
|
||||
link->dc->hwss.enable_stream(&pipes[i]);
|
||||
link->dc->hwss.unblank_stream(&pipes[i],
|
||||
&link->public.verified_link_cap);
|
||||
}
|
||||
}
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,113 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "dm_helpers.h"
|
||||
#include "core_types.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Private definitions
|
||||
******************************************************************************/
|
||||
|
||||
struct sink {
|
||||
struct core_sink protected;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
#define DC_SINK_TO_SINK(dc_sink) \
|
||||
container_of(dc_sink, struct sink, protected.public)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private functions
|
||||
******************************************************************************/
|
||||
|
||||
static void destruct(struct sink *sink)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
static bool construct(struct sink *sink, const struct dc_sink_init_data *init_params)
|
||||
{
|
||||
|
||||
struct core_link *core_link = DC_LINK_TO_LINK(init_params->link);
|
||||
|
||||
sink->protected.public.sink_signal = init_params->sink_signal;
|
||||
sink->protected.link = core_link;
|
||||
sink->protected.ctx = core_link->ctx;
|
||||
sink->protected.dongle_max_pix_clk = init_params->dongle_max_pix_clk;
|
||||
sink->protected.converter_disable_audio =
|
||||
init_params->converter_disable_audio;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Public functions
|
||||
******************************************************************************/
|
||||
|
||||
void dc_sink_retain(const struct dc_sink *dc_sink)
|
||||
{
|
||||
struct sink *sink = DC_SINK_TO_SINK(dc_sink);
|
||||
|
||||
++sink->ref_count;
|
||||
}
|
||||
|
||||
void dc_sink_release(const struct dc_sink *dc_sink)
|
||||
{
|
||||
struct sink *sink = DC_SINK_TO_SINK(dc_sink);
|
||||
|
||||
--sink->ref_count;
|
||||
|
||||
if (sink->ref_count == 0) {
|
||||
destruct(sink);
|
||||
dm_free(sink);
|
||||
}
|
||||
}
|
||||
|
||||
struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params)
|
||||
{
|
||||
struct sink *sink = dm_alloc(sizeof(*sink));
|
||||
|
||||
if (NULL == sink)
|
||||
goto alloc_fail;
|
||||
|
||||
if (false == construct(sink, init_params))
|
||||
goto construct_fail;
|
||||
|
||||
/* TODO should we move this outside to where the assignment actually happens? */
|
||||
dc_sink_retain(&sink->protected.public);
|
||||
|
||||
return &sink->protected.public;
|
||||
|
||||
construct_fail:
|
||||
dm_free(sink);
|
||||
|
||||
alloc_fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Protected functions - visible only inside of DC (not visible in DM)
|
||||
******************************************************************************/
|
|
@ -0,0 +1,141 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "dc.h"
|
||||
#include "core_types.h"
|
||||
#include "resource.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Private definitions
|
||||
******************************************************************************/
|
||||
|
||||
struct stream {
|
||||
struct core_stream protected;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
#define DC_STREAM_TO_STREAM(dc_stream) container_of(dc_stream, struct stream, protected.public)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private functions
|
||||
******************************************************************************/
|
||||
|
||||
static bool construct(struct core_stream *stream,
|
||||
const struct dc_sink *dc_sink_data)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
stream->sink = DC_SINK_TO_CORE(dc_sink_data);
|
||||
stream->ctx = stream->sink->ctx;
|
||||
stream->public.sink = dc_sink_data;
|
||||
|
||||
dc_sink_retain(dc_sink_data);
|
||||
|
||||
/* Copy audio modes */
|
||||
/* TODO - Remove this translation */
|
||||
for (i = 0; i < (dc_sink_data->edid_caps.audio_mode_count); i++)
|
||||
{
|
||||
stream->public.audio_info.modes[i].channel_count = dc_sink_data->edid_caps.audio_modes[i].channel_count;
|
||||
stream->public.audio_info.modes[i].format_code = dc_sink_data->edid_caps.audio_modes[i].format_code;
|
||||
stream->public.audio_info.modes[i].sample_rates.all = dc_sink_data->edid_caps.audio_modes[i].sample_rate;
|
||||
stream->public.audio_info.modes[i].sample_size = dc_sink_data->edid_caps.audio_modes[i].sample_size;
|
||||
}
|
||||
stream->public.audio_info.mode_count = dc_sink_data->edid_caps.audio_mode_count;
|
||||
stream->public.audio_info.audio_latency = dc_sink_data->edid_caps.audio_latency;
|
||||
stream->public.audio_info.video_latency = dc_sink_data->edid_caps.video_latency;
|
||||
memmove(
|
||||
stream->public.audio_info.display_name,
|
||||
dc_sink_data->edid_caps.display_name,
|
||||
AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS);
|
||||
stream->public.audio_info.manufacture_id = dc_sink_data->edid_caps.manufacturer_id;
|
||||
stream->public.audio_info.product_id = dc_sink_data->edid_caps.product_id;
|
||||
stream->public.audio_info.flags.all = dc_sink_data->edid_caps.speaker_flags;
|
||||
|
||||
/* TODO - Unhardcode port_id */
|
||||
stream->public.audio_info.port_id[0] = 0x5558859e;
|
||||
stream->public.audio_info.port_id[1] = 0xd989449;
|
||||
|
||||
/* EDID CAP translation for HDMI 2.0 */
|
||||
stream->public.timing.flags.LTE_340MCSC_SCRAMBLE = dc_sink_data->edid_caps.lte_340mcsc_scramble;
|
||||
|
||||
stream->status.link = &stream->sink->link->public;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void destruct(struct core_stream *stream)
|
||||
{
|
||||
dc_sink_release(&stream->sink->public);
|
||||
}
|
||||
|
||||
void dc_stream_retain(const struct dc_stream *dc_stream)
|
||||
{
|
||||
struct stream *stream = DC_STREAM_TO_STREAM(dc_stream);
|
||||
stream->ref_count++;
|
||||
}
|
||||
|
||||
void dc_stream_release(const struct dc_stream *public)
|
||||
{
|
||||
struct stream *stream = DC_STREAM_TO_STREAM(public);
|
||||
struct core_stream *protected = DC_STREAM_TO_CORE(public);
|
||||
|
||||
if (public != NULL) {
|
||||
stream->ref_count--;
|
||||
|
||||
if (stream->ref_count == 0) {
|
||||
destruct(protected);
|
||||
dm_free(stream);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct dc_stream *dc_create_stream_for_sink(
|
||||
const struct dc_sink *dc_sink)
|
||||
{
|
||||
struct core_sink *sink = DC_SINK_TO_CORE(dc_sink);
|
||||
struct stream *stream;
|
||||
|
||||
if (sink == NULL)
|
||||
goto alloc_fail;
|
||||
|
||||
stream = dm_alloc(sizeof(struct stream));
|
||||
|
||||
if (NULL == stream)
|
||||
goto alloc_fail;
|
||||
|
||||
if (false == construct(&stream->protected, dc_sink))
|
||||
goto construct_fail;
|
||||
|
||||
dc_stream_retain(&stream->protected.public);
|
||||
|
||||
return &stream->protected.public;
|
||||
|
||||
construct_fail:
|
||||
dm_free(stream);
|
||||
|
||||
alloc_fail:
|
||||
return NULL;
|
||||
}
|
|
@ -0,0 +1,213 @@
|
|||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
/* DC interface (public) */
|
||||
#include "dm_services.h"
|
||||
#include "dc.h"
|
||||
|
||||
/* DC core (private) */
|
||||
#include "core_dc.h"
|
||||
#include "transform.h"
|
||||
|
||||
/*******************************************************************************
|
||||
* Private structures
|
||||
******************************************************************************/
|
||||
struct surface {
|
||||
struct core_surface protected;
|
||||
enum dc_irq_source irq_source;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
struct gamma {
|
||||
struct core_gamma protected;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
#define DC_SURFACE_TO_SURFACE(dc_surface) container_of(dc_surface, struct surface, protected.public)
|
||||
#define CORE_SURFACE_TO_SURFACE(core_surface) container_of(core_surface, struct surface, protected)
|
||||
|
||||
#define DC_GAMMA_TO_GAMMA(dc_gamma) \
|
||||
container_of(dc_gamma, struct gamma, protected.public)
|
||||
#define CORE_GAMMA_TO_GAMMA(core_gamma) \
|
||||
container_of(core_gamma, struct gamma, protected)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private functions
|
||||
******************************************************************************/
|
||||
static bool construct(struct dc_context *ctx, struct surface *surface)
|
||||
{
|
||||
surface->protected.ctx = ctx;
|
||||
return true;
|
||||
}
|
||||
|
||||
static void destruct(struct surface *surface)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
* Public functions
|
||||
******************************************************************************/
|
||||
void enable_surface_flip_reporting(struct dc_surface *dc_surface,
|
||||
uint32_t controller_id)
|
||||
{
|
||||
struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
|
||||
surface->irq_source = controller_id + DC_IRQ_SOURCE_PFLIP1 - 1;
|
||||
/*register_flip_interrupt(surface);*/
|
||||
}
|
||||
|
||||
struct dc_surface *dc_create_surface(const struct dc *dc)
|
||||
{
|
||||
struct core_dc *core_dc = DC_TO_CORE(dc);
|
||||
|
||||
struct surface *surface = dm_alloc(sizeof(*surface));
|
||||
|
||||
if (NULL == surface)
|
||||
goto alloc_fail;
|
||||
|
||||
if (false == construct(core_dc->ctx, surface))
|
||||
goto construct_fail;
|
||||
|
||||
dc_surface_retain(&surface->protected.public);
|
||||
|
||||
return &surface->protected.public;
|
||||
|
||||
construct_fail:
|
||||
dm_free(surface);
|
||||
|
||||
alloc_fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct dc_surface_status *dc_surface_get_status(
|
||||
const struct dc_surface *dc_surface)
|
||||
{
|
||||
struct dc_surface_status *surface_status;
|
||||
struct core_surface *core_surface;
|
||||
struct core_dc *core_dc;
|
||||
int i;
|
||||
|
||||
if (dc_surface == NULL)
|
||||
return NULL;
|
||||
|
||||
core_surface = DC_SURFACE_TO_CORE(dc_surface);
|
||||
|
||||
if (core_surface == NULL || core_surface->ctx == NULL)
|
||||
return NULL;
|
||||
|
||||
surface_status = &core_surface->status;
|
||||
|
||||
if (core_surface->ctx == NULL || core_surface->ctx->dc == NULL)
|
||||
return NULL;
|
||||
|
||||
core_dc = DC_TO_CORE(core_surface->ctx->dc);
|
||||
|
||||
|
||||
if (core_dc->current_context == NULL)
|
||||
return NULL;
|
||||
|
||||
for (i = 0; i < core_dc->current_context->res_ctx.pool->pipe_count;
|
||||
i++) {
|
||||
struct pipe_ctx *pipe_ctx =
|
||||
&core_dc->current_context->res_ctx.pipe_ctx[i];
|
||||
|
||||
if (pipe_ctx->surface !=
|
||||
DC_SURFACE_TO_CORE(dc_surface))
|
||||
continue;
|
||||
|
||||
core_dc->hwss.update_pending_status(pipe_ctx);
|
||||
}
|
||||
|
||||
return surface_status;
|
||||
}
|
||||
|
||||
void dc_surface_retain(const struct dc_surface *dc_surface)
|
||||
{
|
||||
struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
|
||||
|
||||
++surface->ref_count;
|
||||
}
|
||||
|
||||
void dc_surface_release(const struct dc_surface *dc_surface)
|
||||
{
|
||||
struct surface *surface = DC_SURFACE_TO_SURFACE(dc_surface);
|
||||
|
||||
--surface->ref_count;
|
||||
|
||||
if (surface->ref_count == 0) {
|
||||
destruct(surface);
|
||||
dm_free(surface);
|
||||
}
|
||||
}
|
||||
|
||||
static bool construct_gamma(struct gamma *gamma)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
static void destruct_gamma(struct gamma *gamma)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
void dc_gamma_retain(const struct dc_gamma *dc_gamma)
|
||||
{
|
||||
struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
|
||||
|
||||
++gamma->ref_count;
|
||||
}
|
||||
|
||||
void dc_gamma_release(const struct dc_gamma *dc_gamma)
|
||||
{
|
||||
struct gamma *gamma = DC_GAMMA_TO_GAMMA(dc_gamma);
|
||||
--gamma->ref_count;
|
||||
|
||||
if (gamma->ref_count == 0) {
|
||||
destruct_gamma(gamma);
|
||||
dm_free(gamma);
|
||||
}
|
||||
}
|
||||
|
||||
struct dc_gamma *dc_create_gamma()
|
||||
{
|
||||
struct gamma *gamma = dm_alloc(sizeof(*gamma));
|
||||
|
||||
if (gamma == NULL)
|
||||
goto alloc_fail;
|
||||
|
||||
if (false == construct_gamma(gamma))
|
||||
goto construct_fail;
|
||||
|
||||
dc_gamma_retain(&gamma->protected.public);
|
||||
|
||||
return &gamma->protected.public;
|
||||
|
||||
construct_fail:
|
||||
dm_free(gamma);
|
||||
|
||||
alloc_fail:
|
||||
return NULL;
|
||||
}
|
||||
|
|
@ -0,0 +1,334 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "dm_services.h"
|
||||
#include "core_types.h"
|
||||
#include "hw_sequencer.h"
|
||||
#include "resource.h"
|
||||
#include "ipp.h"
|
||||
#include "timing_generator.h"
|
||||
|
||||
struct target {
|
||||
struct core_target protected;
|
||||
int ref_count;
|
||||
};
|
||||
|
||||
#define DC_TARGET_TO_TARGET(dc_target) \
|
||||
container_of(dc_target, struct target, protected.public)
|
||||
#define CORE_TARGET_TO_TARGET(core_target) \
|
||||
container_of(core_target, struct target, protected)
|
||||
|
||||
static void construct(
|
||||
struct core_target *target,
|
||||
struct dc_context *ctx,
|
||||
struct dc_stream *dc_streams[],
|
||||
uint8_t stream_count)
|
||||
{
|
||||
uint8_t i;
|
||||
for (i = 0; i < stream_count; i++) {
|
||||
target->public.streams[i] = dc_streams[i];
|
||||
dc_stream_retain(dc_streams[i]);
|
||||
}
|
||||
|
||||
target->ctx = ctx;
|
||||
target->public.stream_count = stream_count;
|
||||
}
|
||||
|
||||
static void destruct(struct core_target *core_target)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < core_target->public.stream_count; i++) {
|
||||
dc_stream_release(
|
||||
(struct dc_stream *)core_target->public.streams[i]);
|
||||
core_target->public.streams[i] = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
void dc_target_retain(const struct dc_target *dc_target)
|
||||
{
|
||||
struct target *target = DC_TARGET_TO_TARGET(dc_target);
|
||||
|
||||
target->ref_count++;
|
||||
}
|
||||
|
||||
void dc_target_release(const struct dc_target *dc_target)
|
||||
{
|
||||
struct target *target = DC_TARGET_TO_TARGET(dc_target);
|
||||
struct core_target *protected = DC_TARGET_TO_CORE(dc_target);
|
||||
|
||||
ASSERT(target->ref_count > 0);
|
||||
target->ref_count--;
|
||||
if (target->ref_count == 0) {
|
||||
destruct(protected);
|
||||
dm_free(target);
|
||||
}
|
||||
}
|
||||
|
||||
const struct dc_target_status *dc_target_get_status(
|
||||
const struct dc_target* dc_target)
|
||||
{
|
||||
uint8_t i;
|
||||
struct core_target* target = DC_TARGET_TO_CORE(dc_target);
|
||||
struct core_dc *dc = DC_TO_CORE(target->ctx->dc);
|
||||
|
||||
for (i = 0; i < dc->current_context->target_count; i++)
|
||||
if (target == dc->current_context->targets[i])
|
||||
return &dc->current_context->target_status[i];
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct dc_target *dc_create_target_for_streams(
|
||||
struct dc_stream *dc_streams[],
|
||||
uint8_t stream_count)
|
||||
{
|
||||
struct core_stream *stream;
|
||||
struct target *target;
|
||||
|
||||
if (0 == stream_count)
|
||||
goto target_alloc_fail;
|
||||
|
||||
stream = DC_STREAM_TO_CORE(dc_streams[0]);
|
||||
|
||||
target = dm_alloc(sizeof(struct target));
|
||||
|
||||
if (NULL == target)
|
||||
goto target_alloc_fail;
|
||||
|
||||
construct(&target->protected, stream->ctx, dc_streams, stream_count);
|
||||
|
||||
dc_target_retain(&target->protected.public);
|
||||
|
||||
return &target->protected.public;
|
||||
|
||||
target_alloc_fail:
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool dc_target_is_connected_to_sink(
|
||||
const struct dc_target * dc_target,
|
||||
const struct dc_sink *dc_sink)
|
||||
{
|
||||
struct core_target *target = DC_TARGET_TO_CORE(dc_target);
|
||||
uint8_t i;
|
||||
for (i = 0; i < target->public.stream_count; i++) {
|
||||
if (target->public.streams[i]->sink == dc_sink)
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the cursor attributes and set cursor surface address
|
||||
*/
|
||||
bool dc_target_set_cursor_attributes(
|
||||
struct dc_target *dc_target,
|
||||
const struct dc_cursor_attributes *attributes)
|
||||
{
|
||||
uint8_t i, j;
|
||||
struct core_target *target;
|
||||
struct core_dc *core_dc;
|
||||
struct resource_context *res_ctx;
|
||||
|
||||
if (NULL == dc_target) {
|
||||
dm_error("DC: dc_target is NULL!\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
if (NULL == attributes) {
|
||||
dm_error("DC: attributes is NULL!\n");
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
target = DC_TARGET_TO_CORE(dc_target);
|
||||
core_dc = DC_TO_CORE(target->ctx->dc);
|
||||
res_ctx = &core_dc->current_context->res_ctx;
|
||||
|
||||
for (i = 0; i < target->public.stream_count; i++) {
|
||||
for (j = 0; j < MAX_PIPES; j++) {
|
||||
struct input_pixel_processor *ipp =
|
||||
res_ctx->pipe_ctx[j].ipp;
|
||||
|
||||
if (res_ctx->pipe_ctx[j].stream !=
|
||||
DC_STREAM_TO_CORE(target->public.streams[i]))
|
||||
continue;
|
||||
|
||||
/* As of writing of this code cursor is on the top
|
||||
* plane so we only need to set it on first pipe we
|
||||
* find. May need to make this code dce specific later.
|
||||
*/
|
||||
if (ipp->funcs->ipp_cursor_set_attributes(
|
||||
ipp, attributes))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dc_target_set_cursor_position(
|
||||
struct dc_target *dc_target,
|
||||
const struct dc_cursor_position *position)
|
||||
{
|
||||
uint8_t i, j;
|
||||
struct core_target *target;
|
||||
struct core_dc *core_dc;
|
||||
struct resource_context *res_ctx;
|
||||
|
||||
if (NULL == dc_target) {
|
||||
dm_error("DC: dc_target is NULL!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (NULL == position) {
|
||||
dm_error("DC: cursor position is NULL!\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
target = DC_TARGET_TO_CORE(dc_target);
|
||||
core_dc = DC_TO_CORE(target->ctx->dc);
|
||||
res_ctx = &core_dc->current_context->res_ctx;
|
||||
|
||||
for (i = 0; i < target->public.stream_count; i++) {
|
||||
for (j = 0; j < MAX_PIPES; j++) {
|
||||
struct input_pixel_processor *ipp =
|
||||
res_ctx->pipe_ctx[j].ipp;
|
||||
|
||||
if (res_ctx->pipe_ctx[j].stream !=
|
||||
DC_STREAM_TO_CORE(target->public.streams[i]))
|
||||
continue;
|
||||
|
||||
/* As of writing of this code cursor is on the top
|
||||
* plane so we only need to set it on first pipe we
|
||||
* find. May need to make this code dce specific later.
|
||||
*/
|
||||
ipp->funcs->ipp_cursor_set_position(ipp, position);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target)
|
||||
{
|
||||
uint8_t i, j;
|
||||
struct core_target *target = DC_TARGET_TO_CORE(dc_target);
|
||||
struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc);
|
||||
struct resource_context *res_ctx =
|
||||
&core_dc->current_context->res_ctx;
|
||||
|
||||
for (i = 0; i < target->public.stream_count; i++) {
|
||||
for (j = 0; j < MAX_PIPES; j++) {
|
||||
struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
|
||||
|
||||
if (res_ctx->pipe_ctx[j].stream !=
|
||||
DC_STREAM_TO_CORE(target->public.streams[i]))
|
||||
continue;
|
||||
|
||||
return tg->funcs->get_frame_count(tg);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t dc_target_get_scanoutpos(
|
||||
const struct dc_target *dc_target,
|
||||
uint32_t *vbl,
|
||||
uint32_t *position)
|
||||
{
|
||||
uint8_t i, j;
|
||||
struct core_target *target = DC_TARGET_TO_CORE(dc_target);
|
||||
struct core_dc *core_dc = DC_TO_CORE(target->ctx->dc);
|
||||
struct resource_context *res_ctx =
|
||||
&core_dc->current_context->res_ctx;
|
||||
|
||||
for (i = 0; i < target->public.stream_count; i++) {
|
||||
for (j = 0; j < MAX_PIPES; j++) {
|
||||
struct timing_generator *tg = res_ctx->pipe_ctx[j].tg;
|
||||
|
||||
if (res_ctx->pipe_ctx[j].stream !=
|
||||
DC_STREAM_TO_CORE(target->public.streams[i]))
|
||||
continue;
|
||||
|
||||
return tg->funcs->get_scanoutpos(tg, vbl, position);
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void dc_target_log(
|
||||
const struct dc_target *dc_target,
|
||||
struct dal_logger *dm_logger,
|
||||
enum dc_log_type log_type)
|
||||
{
|
||||
int i;
|
||||
|
||||
const struct core_target *core_target =
|
||||
CONST_DC_TARGET_TO_CORE(dc_target);
|
||||
|
||||
dm_logger_write(dm_logger,
|
||||
log_type,
|
||||
"core_target 0x%x: stream_count=%d\n",
|
||||
core_target,
|
||||
core_target->public.stream_count);
|
||||
|
||||
for (i = 0; i < core_target->public.stream_count; i++) {
|
||||
const struct core_stream *core_stream =
|
||||
DC_STREAM_TO_CORE(core_target->public.streams[i]);
|
||||
|
||||
dm_logger_write(dm_logger,
|
||||
log_type,
|
||||
"core_stream 0x%x: src: %d, %d, %d, %d; dst: %d, %d, %d, %d;\n",
|
||||
core_stream,
|
||||
core_stream->public.src.x,
|
||||
core_stream->public.src.y,
|
||||
core_stream->public.src.width,
|
||||
core_stream->public.src.height,
|
||||
core_stream->public.dst.x,
|
||||
core_stream->public.dst.y,
|
||||
core_stream->public.dst.width,
|
||||
core_stream->public.dst.height);
|
||||
dm_logger_write(dm_logger,
|
||||
log_type,
|
||||
"\tpix_clk_khz: %d, h_total: %d, v_total: %d\n",
|
||||
core_stream->public.timing.pix_clk_khz,
|
||||
core_stream->public.timing.h_total,
|
||||
core_stream->public.timing.v_total);
|
||||
dm_logger_write(dm_logger,
|
||||
log_type,
|
||||
"\tsink name: %s, serial: %d\n",
|
||||
core_stream->sink->public.edid_caps.display_name,
|
||||
core_stream->sink->public.edid_caps.serial_number);
|
||||
dm_logger_write(dm_logger,
|
||||
log_type,
|
||||
"\tlink: %d\n",
|
||||
core_stream->sink->link->public.link_index);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,780 @@
|
|||
/*
|
||||
* Copyright 2012-14 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 DC_INTERFACE_H_
|
||||
#define DC_INTERFACE_H_
|
||||
|
||||
#include "dc_types.h"
|
||||
#include "dpcd_defs.h"
|
||||
#include "grph_object_defs.h"
|
||||
#include "logger_types.h"
|
||||
#include "gpio_types.h"
|
||||
#include "link_service_types.h"
|
||||
|
||||
#define MAX_TARGETS 6
|
||||
#define MAX_SURFACES 6
|
||||
#define MAX_SINKS_PER_LINK 4
|
||||
|
||||
/*******************************************************************************
|
||||
* Display Core Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
struct dc_caps {
|
||||
uint32_t max_targets;
|
||||
uint32_t max_links;
|
||||
uint32_t max_audios;
|
||||
uint32_t max_slave_planes;
|
||||
uint32_t max_downscale_ratio;
|
||||
uint32_t i2c_speed_in_khz;
|
||||
};
|
||||
|
||||
|
||||
struct dc_dcc_surface_param {
|
||||
enum surface_pixel_format format;
|
||||
struct dc_size surface_size;
|
||||
enum dc_scan_direction scan;
|
||||
};
|
||||
|
||||
struct dc_dcc_setting {
|
||||
unsigned int max_compressed_blk_size;
|
||||
unsigned int max_uncompressed_blk_size;
|
||||
bool independent_64b_blks;
|
||||
};
|
||||
|
||||
struct dc_surface_dcc_cap {
|
||||
bool capable;
|
||||
bool const_color_support;
|
||||
|
||||
union {
|
||||
struct {
|
||||
struct dc_dcc_setting rgb;
|
||||
} grph;
|
||||
|
||||
struct {
|
||||
struct dc_dcc_setting luma;
|
||||
struct dc_dcc_setting chroma;
|
||||
} video;
|
||||
};
|
||||
};
|
||||
|
||||
/* Forward declaration*/
|
||||
struct dc;
|
||||
struct dc_surface;
|
||||
struct validate_context;
|
||||
|
||||
struct dc_cap_funcs {
|
||||
int i;
|
||||
};
|
||||
|
||||
struct dc_stream_funcs {
|
||||
bool (*adjust_vmin_vmax)(struct dc *dc,
|
||||
const struct dc_stream **stream,
|
||||
int num_streams,
|
||||
int vmin,
|
||||
int vmax);
|
||||
|
||||
void (*stream_update_scaling)(const struct dc *dc,
|
||||
const struct dc_stream *dc_stream,
|
||||
const struct rect *src,
|
||||
const struct rect *dst);
|
||||
bool (*set_gamut_remap)(struct dc *dc,
|
||||
const struct dc_stream **stream, int num_streams);
|
||||
bool (*set_backlight)(struct dc *dc, unsigned int backlight_level,
|
||||
unsigned int frame_ramp, const struct dc_stream *stream);
|
||||
bool (*init_dmcu_backlight_settings)(struct dc *dc);
|
||||
bool (*set_abm_level)(struct dc *dc, unsigned int abm_level);
|
||||
bool (*set_psr_enable)(struct dc *dc, bool enable);
|
||||
bool (*setup_psr)(struct dc *dc, const struct dc_stream *stream);
|
||||
};
|
||||
|
||||
struct link_training_settings;
|
||||
|
||||
struct dc_link_funcs {
|
||||
void (*set_drive_settings)(struct dc *dc,
|
||||
struct link_training_settings *lt_settings);
|
||||
void (*perform_link_training)(struct dc *dc,
|
||||
struct dc_link_settings *link_setting,
|
||||
bool skip_video_pattern);
|
||||
void (*set_preferred_link_settings)(struct dc *dc,
|
||||
struct dc_link_settings *link_setting);
|
||||
void (*enable_hpd)(const struct dc_link *link);
|
||||
void (*disable_hpd)(const struct dc_link *link);
|
||||
void (*set_test_pattern)(
|
||||
const struct dc_link *link,
|
||||
enum dp_test_pattern test_pattern,
|
||||
const struct link_training_settings *p_link_settings,
|
||||
const unsigned char *p_custom_pattern,
|
||||
unsigned int cust_pattern_size);
|
||||
};
|
||||
|
||||
/* Structure to hold configuration flags set by dm at dc creation. */
|
||||
struct dc_config {
|
||||
bool gpu_vm_support;
|
||||
bool disable_disp_pll_sharing;
|
||||
};
|
||||
|
||||
struct dc_debug {
|
||||
bool surface_visual_confirm;
|
||||
bool max_disp_clk;
|
||||
bool target_trace;
|
||||
bool surface_trace;
|
||||
bool validation_trace;
|
||||
bool disable_stutter;
|
||||
bool disable_dcc;
|
||||
bool disable_dfs_bypass;
|
||||
bool disable_power_gate;
|
||||
bool disable_clock_gate;
|
||||
};
|
||||
|
||||
struct dc {
|
||||
struct dc_caps caps;
|
||||
struct dc_cap_funcs cap_funcs;
|
||||
struct dc_stream_funcs stream_funcs;
|
||||
struct dc_link_funcs link_funcs;
|
||||
struct dc_config config;
|
||||
struct dc_debug debug;
|
||||
};
|
||||
|
||||
enum frame_buffer_mode {
|
||||
FRAME_BUFFER_MODE_LOCAL_ONLY = 0,
|
||||
FRAME_BUFFER_MODE_ZFB_ONLY,
|
||||
FRAME_BUFFER_MODE_MIXED_ZFB_AND_LOCAL,
|
||||
} ;
|
||||
|
||||
struct dchub_init_data {
|
||||
bool dchub_initialzied;
|
||||
bool dchub_info_valid;
|
||||
int64_t zfb_phys_addr_base;
|
||||
int64_t zfb_mc_base_addr;
|
||||
uint64_t zfb_size_in_byte;
|
||||
enum frame_buffer_mode fb_mode;
|
||||
};
|
||||
|
||||
struct dc_init_data {
|
||||
struct hw_asic_id asic_id;
|
||||
void *driver; /* ctx */
|
||||
struct cgs_device *cgs_device;
|
||||
|
||||
int num_virtual_links;
|
||||
/*
|
||||
* If 'vbios_override' not NULL, it will be called instead
|
||||
* of the real VBIOS. Intended use is Diagnostics on FPGA.
|
||||
*/
|
||||
struct dc_bios *vbios_override;
|
||||
enum dce_environment dce_environment;
|
||||
|
||||
struct dc_config flags;
|
||||
};
|
||||
|
||||
struct dc *dc_create(const struct dc_init_data *init_params);
|
||||
|
||||
void dc_destroy(struct dc **dc);
|
||||
|
||||
bool dc_init_dchub(struct dc *dc, struct dchub_init_data *dh_data);
|
||||
|
||||
/*******************************************************************************
|
||||
* Surface Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
enum {
|
||||
RGB_256X3X16 = 256,
|
||||
FLOAT_GAMMA_RAMP_MAX = 1025
|
||||
};
|
||||
|
||||
enum dc_gamma_ramp_type {
|
||||
GAMMA_RAMP_RBG256X3X16,
|
||||
GAMMA_RAMP_FLOAT,
|
||||
};
|
||||
|
||||
struct float_rgb {
|
||||
struct fixed32_32 red;
|
||||
struct fixed32_32 green;
|
||||
struct fixed32_32 blue;
|
||||
};
|
||||
|
||||
struct dc_gamma_ramp_float {
|
||||
struct float_rgb scale;
|
||||
struct float_rgb offset;
|
||||
struct float_rgb gamma_curve[FLOAT_GAMMA_RAMP_MAX];
|
||||
};
|
||||
|
||||
struct dc_gamma_ramp_rgb256x3x16 {
|
||||
uint16_t red[RGB_256X3X16];
|
||||
uint16_t green[RGB_256X3X16];
|
||||
uint16_t blue[RGB_256X3X16];
|
||||
};
|
||||
|
||||
struct dc_gamma {
|
||||
enum dc_gamma_ramp_type type;
|
||||
union {
|
||||
struct dc_gamma_ramp_rgb256x3x16 gamma_ramp_rgb256x3x16;
|
||||
struct dc_gamma_ramp_float gamma_ramp_float;
|
||||
};
|
||||
uint32_t size;
|
||||
};
|
||||
|
||||
struct dc_surface {
|
||||
bool visible;
|
||||
bool flip_immediate;
|
||||
struct dc_plane_address address;
|
||||
|
||||
struct scaling_taps scaling_quality;
|
||||
struct rect src_rect;
|
||||
struct rect dst_rect;
|
||||
struct rect clip_rect;
|
||||
|
||||
union plane_size plane_size;
|
||||
union dc_tiling_info tiling_info;
|
||||
struct dc_plane_dcc_param dcc;
|
||||
enum dc_color_space color_space;
|
||||
|
||||
enum surface_pixel_format format;
|
||||
enum dc_rotation_angle rotation;
|
||||
bool horizontal_mirror;
|
||||
enum plane_stereo_format stereo_format;
|
||||
|
||||
const struct dc_gamma *gamma_correction;
|
||||
};
|
||||
|
||||
struct dc_plane_info {
|
||||
union plane_size plane_size;
|
||||
union dc_tiling_info tiling_info;
|
||||
enum surface_pixel_format format;
|
||||
enum dc_rotation_angle rotation;
|
||||
bool horizontal_mirror;
|
||||
enum plane_stereo_format stereo_format;
|
||||
enum dc_color_space color_space; /*todo: wrong place, fits in scaling info*/
|
||||
bool visible;
|
||||
};
|
||||
|
||||
struct dc_scaling_info {
|
||||
struct rect src_rect;
|
||||
struct rect dst_rect;
|
||||
struct rect clip_rect;
|
||||
struct scaling_taps scaling_quality;
|
||||
};
|
||||
|
||||
struct dc_surface_update {
|
||||
const struct dc_surface *surface;
|
||||
|
||||
/* isr safe update parameters. null means no updates */
|
||||
struct dc_flip_addrs *flip_addr;
|
||||
struct dc_plane_info *plane_info;
|
||||
struct dc_scaling_info *scaling_info;
|
||||
/* following updates require alloc/sleep/spin that is not isr safe,
|
||||
* null means no updates
|
||||
*/
|
||||
struct dc_gamma *gamma;
|
||||
|
||||
|
||||
};
|
||||
/*
|
||||
* This structure is filled in by dc_surface_get_status and contains
|
||||
* the last requested address and the currently active address so the called
|
||||
* can determine if there are any outstanding flips
|
||||
*/
|
||||
struct dc_surface_status {
|
||||
struct dc_plane_address requested_address;
|
||||
struct dc_plane_address current_address;
|
||||
bool is_flip_pending;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new surface with default parameters;
|
||||
*/
|
||||
struct dc_surface *dc_create_surface(const struct dc *dc);
|
||||
const struct dc_surface_status *dc_surface_get_status(
|
||||
const struct dc_surface *dc_surface);
|
||||
|
||||
void dc_surface_retain(const struct dc_surface *dc_surface);
|
||||
void dc_surface_release(const struct dc_surface *dc_surface);
|
||||
|
||||
void dc_gamma_release(const struct dc_gamma *dc_gamma);
|
||||
struct dc_gamma *dc_create_gamma(void);
|
||||
|
||||
/*
|
||||
* This structure holds a surface address. There could be multiple addresses
|
||||
* in cases such as Stereo 3D, Planar YUV, etc. Other per-flip attributes such
|
||||
* as frame durations and DCC format can also be set.
|
||||
*/
|
||||
struct dc_flip_addrs {
|
||||
struct dc_plane_address address;
|
||||
bool flip_immediate;
|
||||
/* TODO: DCC format info */
|
||||
/* TODO: add flip duration for FreeSync */
|
||||
};
|
||||
|
||||
/*
|
||||
* Optimized flip address update function.
|
||||
*
|
||||
* After this call:
|
||||
* Surface addresses and flip attributes are programmed.
|
||||
* Surface flip occur at next configured time (h_sync or v_sync flip)
|
||||
*/
|
||||
void dc_flip_surface_addrs(struct dc *dc,
|
||||
const struct dc_surface *const surfaces[],
|
||||
struct dc_flip_addrs flip_addrs[],
|
||||
uint32_t count);
|
||||
|
||||
/*
|
||||
* Set up surface attributes and associate to a target
|
||||
* The surfaces parameter is an absolute set of all surface active for the target.
|
||||
* If no surfaces are provided, the target will be blanked; no memory read.
|
||||
* Any flip related attribute changes must be done through this interface.
|
||||
*
|
||||
* After this call:
|
||||
* Surfaces attributes are programmed and configured to be composed into target.
|
||||
* This does not trigger a flip. No surface address is programmed.
|
||||
*/
|
||||
|
||||
bool dc_commit_surfaces_to_target(
|
||||
struct dc *dc,
|
||||
const struct dc_surface **dc_surfaces,
|
||||
uint8_t surface_count,
|
||||
struct dc_target *dc_target);
|
||||
|
||||
bool dc_pre_update_surfaces_to_target(
|
||||
struct dc *dc,
|
||||
const struct dc_surface *const *new_surfaces,
|
||||
uint8_t new_surface_count,
|
||||
struct dc_target *dc_target);
|
||||
|
||||
bool dc_post_update_surfaces_to_target(
|
||||
struct dc *dc);
|
||||
|
||||
void dc_update_surfaces_for_target(struct dc *dc, struct dc_surface_update *updates,
|
||||
int surface_count, struct dc_target *dc_target);
|
||||
|
||||
/*******************************************************************************
|
||||
* Target Interfaces
|
||||
******************************************************************************/
|
||||
#define MAX_STREAM_NUM 1
|
||||
|
||||
struct dc_target {
|
||||
uint8_t stream_count;
|
||||
const struct dc_stream *streams[MAX_STREAM_NUM];
|
||||
};
|
||||
|
||||
/*
|
||||
* Target status is returned from dc_target_get_status in order to get the
|
||||
* the IRQ source, current frame counter and currently attached surfaces.
|
||||
*/
|
||||
struct dc_target_status {
|
||||
int primary_otg_inst;
|
||||
int cur_frame_count;
|
||||
int surface_count;
|
||||
const struct dc_surface *surfaces[MAX_SURFACE_NUM];
|
||||
};
|
||||
|
||||
struct dc_target *dc_create_target_for_streams(
|
||||
struct dc_stream *dc_streams[],
|
||||
uint8_t stream_count);
|
||||
|
||||
/*
|
||||
* Get the current target status.
|
||||
*/
|
||||
const struct dc_target_status *dc_target_get_status(
|
||||
const struct dc_target* dc_target);
|
||||
|
||||
void dc_target_retain(const struct dc_target *dc_target);
|
||||
void dc_target_release(const struct dc_target *dc_target);
|
||||
void dc_target_log(
|
||||
const struct dc_target *dc_target,
|
||||
struct dal_logger *dc_logger,
|
||||
enum dc_log_type log_type);
|
||||
|
||||
uint8_t dc_get_current_target_count(const struct dc *dc);
|
||||
struct dc_target *dc_get_target_at_index(const struct dc *dc, uint8_t i);
|
||||
|
||||
bool dc_target_is_connected_to_sink(
|
||||
const struct dc_target *dc_target,
|
||||
const struct dc_sink *dc_sink);
|
||||
|
||||
uint32_t dc_target_get_vblank_counter(const struct dc_target *dc_target);
|
||||
|
||||
/* TODO: Return parsed values rather than direct register read
|
||||
* This has a dependency on the caller (amdgpu_get_crtc_scanoutpos)
|
||||
* being refactored properly to be dce-specific
|
||||
*/
|
||||
uint32_t dc_target_get_scanoutpos(
|
||||
const struct dc_target *dc_target,
|
||||
uint32_t *vbl,
|
||||
uint32_t *position);
|
||||
|
||||
/*
|
||||
* Structure to store surface/target associations for validation
|
||||
*/
|
||||
struct dc_validation_set {
|
||||
const struct dc_target *target;
|
||||
const struct dc_surface *surfaces[MAX_SURFACES];
|
||||
uint8_t surface_count;
|
||||
};
|
||||
|
||||
/*
|
||||
* This function takes a set of resources and checks that they are cofunctional.
|
||||
*
|
||||
* After this call:
|
||||
* No hardware is programmed for call. Only validation is done.
|
||||
*/
|
||||
bool dc_validate_resources(
|
||||
const struct dc *dc,
|
||||
const struct dc_validation_set set[],
|
||||
uint8_t set_count);
|
||||
|
||||
/*
|
||||
* This function takes a target and checks if it is guaranteed to be supported.
|
||||
* Guaranteed means that MAX_COFUNC*target is supported.
|
||||
*
|
||||
* After this call:
|
||||
* No hardware is programmed for call. Only validation is done.
|
||||
*/
|
||||
|
||||
bool dc_validate_guaranteed(
|
||||
const struct dc *dc,
|
||||
const struct dc_target *dc_target);
|
||||
|
||||
/*
|
||||
* Set up streams and links associated to targets to drive sinks
|
||||
* The targets parameter is an absolute set of all active targets.
|
||||
*
|
||||
* After this call:
|
||||
* Phy, Encoder, Timing Generator are programmed and enabled.
|
||||
* New targets are enabled with blank stream; no memory read.
|
||||
*/
|
||||
bool dc_commit_targets(
|
||||
struct dc *dc,
|
||||
struct dc_target *targets[],
|
||||
uint8_t target_count);
|
||||
|
||||
/*******************************************************************************
|
||||
* Stream Interfaces
|
||||
******************************************************************************/
|
||||
struct dc_stream {
|
||||
const struct dc_sink *sink;
|
||||
struct dc_crtc_timing timing;
|
||||
|
||||
enum dc_color_space output_color_space;
|
||||
|
||||
struct rect src; /* viewport in target space*/
|
||||
struct rect dst; /* stream addressable area */
|
||||
|
||||
struct audio_info audio_info;
|
||||
|
||||
bool ignore_msa_timing_param;
|
||||
|
||||
struct freesync_context freesync_ctx;
|
||||
|
||||
/* TODO: dithering */
|
||||
/* TODO: transfer function (CSC/regamma/gamut remap) */
|
||||
struct colorspace_transform gamut_remap_matrix;
|
||||
struct csc_transform csc_color_matrix;
|
||||
/* TODO: custom INFO packets */
|
||||
/* TODO: ABM info (DMCU) */
|
||||
/* TODO: PSR info */
|
||||
/* TODO: CEA VIC */
|
||||
};
|
||||
|
||||
/**
|
||||
* Create a new default stream for the requested sink
|
||||
*/
|
||||
struct dc_stream *dc_create_stream_for_sink(const struct dc_sink *dc_sink);
|
||||
|
||||
void dc_stream_retain(const struct dc_stream *dc_stream);
|
||||
void dc_stream_release(const struct dc_stream *dc_stream);
|
||||
|
||||
struct dc_stream_status {
|
||||
/*
|
||||
* link this stream passes through
|
||||
*/
|
||||
const struct dc_link *link;
|
||||
};
|
||||
|
||||
const struct dc_stream_status *dc_stream_get_status(
|
||||
const struct dc_stream *dc_stream);
|
||||
|
||||
/*******************************************************************************
|
||||
* Link Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* A link contains one or more sinks and their connected status.
|
||||
* The currently active signal type (HDMI, DP-SST, DP-MST) is also reported.
|
||||
*/
|
||||
struct dc_link {
|
||||
const struct dc_sink *remote_sinks[MAX_SINKS_PER_LINK];
|
||||
unsigned int sink_count;
|
||||
const struct dc_sink *local_sink;
|
||||
unsigned int link_index;
|
||||
enum dc_connection_type type;
|
||||
enum signal_type connector_signal;
|
||||
enum dc_irq_source irq_source_hpd;
|
||||
enum dc_irq_source irq_source_hpd_rx;/* aka DP Short Pulse */
|
||||
/* caps is the same as reported_link_cap. link_traing use
|
||||
* reported_link_cap. Will clean up. TODO
|
||||
*/
|
||||
struct dc_link_settings reported_link_cap;
|
||||
struct dc_link_settings verified_link_cap;
|
||||
struct dc_link_settings max_link_setting;
|
||||
struct dc_link_settings cur_link_settings;
|
||||
struct dc_lane_settings cur_lane_setting;
|
||||
|
||||
uint8_t ddc_hw_inst;
|
||||
uint8_t link_enc_hw_inst;
|
||||
|
||||
struct psr_caps psr_caps;
|
||||
bool test_pattern_enabled;
|
||||
union compliance_test_state compliance_test_state;
|
||||
};
|
||||
|
||||
struct dpcd_caps {
|
||||
union dpcd_rev dpcd_rev;
|
||||
union max_lane_count max_ln_count;
|
||||
union max_down_spread max_down_spread;
|
||||
|
||||
/* dongle type (DP converter, CV smart dongle) */
|
||||
enum display_dongle_type dongle_type;
|
||||
/* Dongle's downstream count. */
|
||||
union sink_count sink_count;
|
||||
/* If dongle_type == DISPLAY_DONGLE_DP_HDMI_CONVERTER,
|
||||
indicates 'Frame Sequential-to-lllFrame Pack' conversion capability.*/
|
||||
bool is_dp_hdmi_s3d_converter;
|
||||
|
||||
bool allow_invalid_MSA_timing_param;
|
||||
bool panel_mode_edp;
|
||||
uint32_t sink_dev_id;
|
||||
uint32_t branch_dev_id;
|
||||
int8_t branch_dev_name[6];
|
||||
int8_t branch_hw_revision;
|
||||
};
|
||||
|
||||
struct dc_link_status {
|
||||
struct dpcd_caps *dpcd_caps;
|
||||
};
|
||||
|
||||
const struct dc_link_status *dc_link_get_status(const struct dc_link *dc_link);
|
||||
|
||||
/*
|
||||
* Return an enumerated dc_link. dc_link order is constant and determined at
|
||||
* boot time. They cannot be created or destroyed.
|
||||
* Use dc_get_caps() to get number of links.
|
||||
*/
|
||||
const struct dc_link *dc_get_link_at_index(const struct dc *dc, uint32_t link_index);
|
||||
|
||||
/* Return id of physical connector represented by a dc_link at link_index.*/
|
||||
const struct graphics_object_id dc_get_link_id_at_index(
|
||||
struct dc *dc, uint32_t link_index);
|
||||
|
||||
/* Set backlight level of an embedded panel (eDP, LVDS). */
|
||||
bool dc_link_set_backlight_level(const struct dc_link *dc_link, uint32_t level,
|
||||
uint32_t frame_ramp, const struct dc_stream *stream);
|
||||
|
||||
bool dc_link_init_dmcu_backlight_settings(const struct dc_link *dc_link);
|
||||
|
||||
bool dc_link_set_abm_level(const struct dc_link *dc_link, uint32_t level);
|
||||
|
||||
bool dc_link_set_psr_enable(const struct dc_link *dc_link, bool enable);
|
||||
|
||||
bool dc_link_setup_psr(const struct dc_link *dc_link,
|
||||
const struct dc_stream *stream);
|
||||
|
||||
/* Request DC to detect if there is a Panel connected.
|
||||
* boot - If this call is during initial boot.
|
||||
* Return false for any type of detection failure or MST detection
|
||||
* true otherwise. True meaning further action is required (status update
|
||||
* and OS notification).
|
||||
*/
|
||||
bool dc_link_detect(const struct dc_link *dc_link, bool boot);
|
||||
|
||||
/* Notify DC about DP RX Interrupt (aka Short Pulse Interrupt).
|
||||
* Return:
|
||||
* true - Downstream port status changed. DM should call DC to do the
|
||||
* detection.
|
||||
* false - no change in Downstream port status. No further action required
|
||||
* from DM. */
|
||||
bool dc_link_handle_hpd_rx_irq(const struct dc_link *dc_link);
|
||||
|
||||
struct dc_sink_init_data;
|
||||
|
||||
struct dc_sink *dc_link_add_remote_sink(
|
||||
const struct dc_link *dc_link,
|
||||
const uint8_t *edid,
|
||||
int len,
|
||||
struct dc_sink_init_data *init_data);
|
||||
|
||||
void dc_link_remove_remote_sink(
|
||||
const struct dc_link *link,
|
||||
const struct dc_sink *sink);
|
||||
|
||||
/* Used by diagnostics for virtual link at the moment */
|
||||
void dc_link_set_sink(const struct dc_link *link, struct dc_sink *sink);
|
||||
|
||||
void dc_link_dp_set_drive_settings(
|
||||
struct dc_link *link,
|
||||
struct link_training_settings *lt_settings);
|
||||
|
||||
bool dc_link_dp_perform_link_training(
|
||||
struct dc_link *link,
|
||||
const struct dc_link_settings *link_setting,
|
||||
bool skip_video_pattern);
|
||||
|
||||
void dc_link_dp_enable_hpd(const struct dc_link *link);
|
||||
|
||||
void dc_link_dp_disable_hpd(const struct dc_link *link);
|
||||
|
||||
bool dc_link_dp_set_test_pattern(
|
||||
const struct dc_link *link,
|
||||
enum dp_test_pattern test_pattern,
|
||||
const struct link_training_settings *p_link_settings,
|
||||
const unsigned char *p_custom_pattern,
|
||||
unsigned int cust_pattern_size);
|
||||
|
||||
/*******************************************************************************
|
||||
* Sink Interfaces - A sink corresponds to a display output device
|
||||
******************************************************************************/
|
||||
|
||||
/*
|
||||
* The sink structure contains EDID and other display device properties
|
||||
*/
|
||||
struct dc_sink {
|
||||
enum signal_type sink_signal;
|
||||
struct dc_edid dc_edid; /* raw edid */
|
||||
struct dc_edid_caps edid_caps; /* parse display caps */
|
||||
};
|
||||
|
||||
void dc_sink_retain(const struct dc_sink *sink);
|
||||
void dc_sink_release(const struct dc_sink *sink);
|
||||
|
||||
const struct audio **dc_get_audios(struct dc *dc);
|
||||
|
||||
struct dc_sink_init_data {
|
||||
enum signal_type sink_signal;
|
||||
const struct dc_link *link;
|
||||
uint32_t dongle_max_pix_clk;
|
||||
bool converter_disable_audio;
|
||||
};
|
||||
|
||||
struct dc_sink *dc_sink_create(const struct dc_sink_init_data *init_params);
|
||||
|
||||
/*******************************************************************************
|
||||
* Cursor interfaces - To manages the cursor within a target
|
||||
******************************************************************************/
|
||||
/* TODO: Deprecated once we switch to dc_set_cursor_position */
|
||||
bool dc_target_set_cursor_attributes(
|
||||
struct dc_target *dc_target,
|
||||
const struct dc_cursor_attributes *attributes);
|
||||
|
||||
bool dc_target_set_cursor_position(
|
||||
struct dc_target *dc_target,
|
||||
const struct dc_cursor_position *position);
|
||||
|
||||
/* Newer interfaces */
|
||||
struct dc_cursor {
|
||||
struct dc_plane_address address;
|
||||
struct dc_cursor_attributes attributes;
|
||||
};
|
||||
|
||||
/*
|
||||
* Create a new cursor with default values for a given target.
|
||||
*/
|
||||
struct dc_cursor *dc_create_cursor_for_target(
|
||||
const struct dc *dc,
|
||||
struct dc_target *dc_target);
|
||||
|
||||
/**
|
||||
* Commit cursor attribute changes such as pixel format and dimensions and
|
||||
* surface address.
|
||||
*
|
||||
* After this call:
|
||||
* Cursor address and format is programmed to the new values.
|
||||
* Cursor position is unmodified.
|
||||
*/
|
||||
bool dc_commit_cursor(
|
||||
const struct dc *dc,
|
||||
struct dc_cursor *cursor);
|
||||
|
||||
/*
|
||||
* Optimized cursor position update
|
||||
*
|
||||
* After this call:
|
||||
* Cursor position will be programmed as well as enable/disable bit.
|
||||
*/
|
||||
bool dc_set_cursor_position(
|
||||
const struct dc *dc,
|
||||
struct dc_cursor *cursor,
|
||||
struct dc_cursor_position *pos);
|
||||
|
||||
/*******************************************************************************
|
||||
* Interrupt interfaces
|
||||
******************************************************************************/
|
||||
enum dc_irq_source dc_interrupt_to_irq_source(
|
||||
struct dc *dc,
|
||||
uint32_t src_id,
|
||||
uint32_t ext_id);
|
||||
void dc_interrupt_set(const struct dc *dc, enum dc_irq_source src, bool enable);
|
||||
void dc_interrupt_ack(struct dc *dc, enum dc_irq_source src);
|
||||
enum dc_irq_source dc_get_hpd_irq_source_at_index(
|
||||
struct dc *dc, uint32_t link_index);
|
||||
|
||||
/*******************************************************************************
|
||||
* Power Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
void dc_set_power_state(
|
||||
struct dc *dc,
|
||||
enum dc_acpi_cm_power_state power_state,
|
||||
enum dc_video_power_state video_power_state);
|
||||
void dc_resume(const struct dc *dc);
|
||||
|
||||
/*******************************************************************************
|
||||
* DDC Interfaces
|
||||
******************************************************************************/
|
||||
|
||||
const struct ddc_service *dc_get_ddc_at_index(
|
||||
struct dc *dc, uint32_t link_index);
|
||||
|
||||
/*
|
||||
* DPCD access interfaces
|
||||
*/
|
||||
|
||||
bool dc_read_dpcd(
|
||||
struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint32_t address,
|
||||
uint8_t *data,
|
||||
uint32_t size);
|
||||
|
||||
bool dc_write_dpcd(
|
||||
struct dc *dc,
|
||||
uint32_t link_index,
|
||||
uint32_t address,
|
||||
const uint8_t *data,
|
||||
uint32_t size);
|
||||
|
||||
bool dc_submit_i2c(
|
||||
struct dc *dc,
|
||||
uint32_t link_index,
|
||||
struct i2c_command *cmd);
|
||||
|
||||
#endif /* DC_INTERFACE_H_ */
|
|
@ -0,0 +1,224 @@
|
|||
/*
|
||||
* Copyright 2016 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 DC_BIOS_TYPES_H
|
||||
#define DC_BIOS_TYPES_H
|
||||
|
||||
/******************************************************************************
|
||||
* Interface file for VBIOS implementations.
|
||||
*
|
||||
* The default implementation is inside DC.
|
||||
* Display Manager (which instantiates DC) has the option to supply it's own
|
||||
* (external to DC) implementation of VBIOS, which will be called by DC, using
|
||||
* this interface.
|
||||
* (The intended use is Diagnostics, but other uses may appear.)
|
||||
*****************************************************************************/
|
||||
|
||||
#include "include/bios_parser_types.h"
|
||||
|
||||
struct dc_vbios_funcs {
|
||||
uint8_t (*get_connectors_number)(struct dc_bios *bios);
|
||||
|
||||
struct graphics_object_id (*get_encoder_id)(
|
||||
struct dc_bios *bios,
|
||||
uint32_t i);
|
||||
struct graphics_object_id (*get_connector_id)(
|
||||
struct dc_bios *bios,
|
||||
uint8_t connector_index);
|
||||
uint32_t (*get_dst_number)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id id);
|
||||
|
||||
uint32_t (*get_gpio_record)(
|
||||
struct dc_bios *dcb,
|
||||
struct graphics_object_id id,
|
||||
struct bp_gpio_cntl_info *gpio_record,
|
||||
uint32_t record_size);
|
||||
|
||||
enum bp_result (*get_src_obj)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id object_id, uint32_t index,
|
||||
struct graphics_object_id *src_object_id);
|
||||
enum bp_result (*get_dst_obj)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id object_id, uint32_t index,
|
||||
struct graphics_object_id *dest_object_id);
|
||||
|
||||
enum bp_result (*get_i2c_info)(
|
||||
struct dc_bios *dcb,
|
||||
struct graphics_object_id id,
|
||||
struct graphics_object_i2c_info *info);
|
||||
|
||||
enum bp_result (*get_voltage_ddc_info)(
|
||||
struct dc_bios *bios,
|
||||
uint32_t index,
|
||||
struct graphics_object_i2c_info *info);
|
||||
enum bp_result (*get_thermal_ddc_info)(
|
||||
struct dc_bios *bios,
|
||||
uint32_t i2c_channel_id,
|
||||
struct graphics_object_i2c_info *info);
|
||||
enum bp_result (*get_hpd_info)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id id,
|
||||
struct graphics_object_hpd_info *info);
|
||||
enum bp_result (*get_device_tag)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id connector_object_id,
|
||||
uint32_t device_tag_index,
|
||||
struct connector_device_tag_info *info);
|
||||
enum bp_result (*get_firmware_info)(
|
||||
struct dc_bios *bios,
|
||||
struct firmware_info *info);
|
||||
enum bp_result (*get_spread_spectrum_info)(
|
||||
struct dc_bios *bios,
|
||||
enum as_signal_type signal,
|
||||
uint32_t index,
|
||||
struct spread_spectrum_info *ss_info);
|
||||
uint32_t (*get_ss_entry_number)(
|
||||
struct dc_bios *bios,
|
||||
enum as_signal_type signal);
|
||||
enum bp_result (*get_embedded_panel_info)(
|
||||
struct dc_bios *bios,
|
||||
struct embedded_panel_info *info);
|
||||
enum bp_result (*get_gpio_pin_info)(
|
||||
struct dc_bios *bios,
|
||||
uint32_t gpio_id,
|
||||
struct gpio_pin_info *info);
|
||||
enum bp_result (*get_encoder_cap_info)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id object_id,
|
||||
struct bp_encoder_cap_info *info);
|
||||
|
||||
bool (*is_lid_status_changed)(
|
||||
struct dc_bios *bios);
|
||||
bool (*is_display_config_changed)(
|
||||
struct dc_bios *bios);
|
||||
bool (*is_accelerated_mode)(
|
||||
struct dc_bios *bios);
|
||||
void (*get_bios_event_info)(
|
||||
struct dc_bios *bios,
|
||||
struct bios_event_info *info);
|
||||
void (*update_requested_backlight_level)(
|
||||
struct dc_bios *bios,
|
||||
uint32_t backlight_8bit);
|
||||
uint32_t (*get_requested_backlight_level)(
|
||||
struct dc_bios *bios);
|
||||
void (*take_backlight_control)(
|
||||
struct dc_bios *bios,
|
||||
bool cntl);
|
||||
|
||||
bool (*is_active_display)(
|
||||
struct dc_bios *bios,
|
||||
enum signal_type signal,
|
||||
const struct connector_device_tag_info *device_tag);
|
||||
enum controller_id (*get_embedded_display_controller_id)(
|
||||
struct dc_bios *bios);
|
||||
uint32_t (*get_embedded_display_refresh_rate)(
|
||||
struct dc_bios *bios);
|
||||
|
||||
void (*set_scratch_critical_state)(
|
||||
struct dc_bios *bios,
|
||||
bool state);
|
||||
bool (*is_device_id_supported)(
|
||||
struct dc_bios *bios,
|
||||
struct device_id id);
|
||||
|
||||
/* COMMANDS */
|
||||
|
||||
enum bp_result (*encoder_control)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_encoder_control *cntl);
|
||||
enum bp_result (*transmitter_control)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_transmitter_control *cntl);
|
||||
enum bp_result (*crt_control)(
|
||||
struct dc_bios *bios,
|
||||
enum engine_id engine_id,
|
||||
bool enable,
|
||||
uint32_t pixel_clock);
|
||||
enum bp_result (*enable_crtc)(
|
||||
struct dc_bios *bios,
|
||||
enum controller_id id,
|
||||
bool enable);
|
||||
enum bp_result (*adjust_pixel_clock)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_adjust_pixel_clock_parameters *bp_params);
|
||||
enum bp_result (*set_pixel_clock)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_pixel_clock_parameters *bp_params);
|
||||
enum bp_result (*set_dce_clock)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_set_dce_clock_parameters *bp_params);
|
||||
unsigned int (*get_smu_clock_info)(
|
||||
struct dc_bios *bios);
|
||||
enum bp_result (*enable_spread_spectrum_on_ppll)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_spread_spectrum_parameters *bp_params,
|
||||
bool enable);
|
||||
enum bp_result (*program_crtc_timing)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_hw_crtc_timing_parameters *bp_params);
|
||||
|
||||
enum bp_result (*crtc_source_select)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_crtc_source_select *bp_params);
|
||||
enum bp_result (*program_display_engine_pll)(
|
||||
struct dc_bios *bios,
|
||||
struct bp_pixel_clock_parameters *bp_params);
|
||||
|
||||
enum signal_type (*dac_load_detect)(
|
||||
struct dc_bios *bios,
|
||||
struct graphics_object_id encoder,
|
||||
struct graphics_object_id connector,
|
||||
enum signal_type display_signal);
|
||||
|
||||
enum bp_result (*enable_disp_power_gating)(
|
||||
struct dc_bios *bios,
|
||||
enum controller_id controller_id,
|
||||
enum bp_pipe_control_action action);
|
||||
|
||||
void (*post_init)(struct dc_bios *bios);
|
||||
|
||||
void (*bios_parser_destroy)(struct dc_bios **dcb);
|
||||
};
|
||||
|
||||
struct bios_registers {
|
||||
uint32_t BIOS_SCRATCH_6;
|
||||
};
|
||||
|
||||
struct dc_bios {
|
||||
const struct dc_vbios_funcs *funcs;
|
||||
|
||||
uint8_t *bios;
|
||||
uint32_t bios_size;
|
||||
|
||||
uint8_t *bios_local_image;
|
||||
|
||||
struct dc_context *ctx;
|
||||
const struct bios_registers *regs;
|
||||
struct integrated_info *integrated_info;
|
||||
};
|
||||
|
||||
#endif /* DC_BIOS_TYPES_H */
|
|
@ -0,0 +1,115 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 DC_DDC_TYPES_H_
|
||||
#define DC_DDC_TYPES_H_
|
||||
|
||||
struct i2c_payload {
|
||||
bool write;
|
||||
uint8_t address;
|
||||
uint32_t length;
|
||||
uint8_t *data;
|
||||
};
|
||||
|
||||
enum i2c_command_engine {
|
||||
I2C_COMMAND_ENGINE_DEFAULT,
|
||||
I2C_COMMAND_ENGINE_SW,
|
||||
I2C_COMMAND_ENGINE_HW
|
||||
};
|
||||
|
||||
struct i2c_command {
|
||||
struct i2c_payload *payloads;
|
||||
uint8_t number_of_payloads;
|
||||
|
||||
enum i2c_command_engine engine;
|
||||
|
||||
/* expressed in KHz
|
||||
* zero means "use default value" */
|
||||
uint32_t speed;
|
||||
};
|
||||
|
||||
struct gpio_ddc_hw_info {
|
||||
bool hw_supported;
|
||||
uint32_t ddc_channel;
|
||||
};
|
||||
|
||||
struct ddc {
|
||||
struct gpio *pin_data;
|
||||
struct gpio *pin_clock;
|
||||
struct gpio_ddc_hw_info hw_info;
|
||||
struct dc_context *ctx;
|
||||
};
|
||||
|
||||
union ddc_wa {
|
||||
struct {
|
||||
uint32_t DP_SKIP_POWER_OFF:1;
|
||||
uint32_t DP_AUX_POWER_UP_WA_DELAY:1;
|
||||
} bits;
|
||||
uint32_t raw;
|
||||
};
|
||||
|
||||
struct ddc_flags {
|
||||
uint8_t EDID_QUERY_DONE_ONCE:1;
|
||||
uint8_t IS_INTERNAL_DISPLAY:1;
|
||||
uint8_t FORCE_READ_REPEATED_START:1;
|
||||
uint8_t EDID_STRESS_READ:1;
|
||||
|
||||
};
|
||||
|
||||
enum ddc_transaction_type {
|
||||
DDC_TRANSACTION_TYPE_NONE = 0,
|
||||
DDC_TRANSACTION_TYPE_I2C,
|
||||
DDC_TRANSACTION_TYPE_I2C_OVER_AUX,
|
||||
DDC_TRANSACTION_TYPE_I2C_OVER_AUX_WITH_DEFER,
|
||||
DDC_TRANSACTION_TYPE_I2C_OVER_AUX_RETRY_DEFER
|
||||
};
|
||||
|
||||
enum display_dongle_type {
|
||||
DISPLAY_DONGLE_NONE = 0,
|
||||
/* Active converter types*/
|
||||
DISPLAY_DONGLE_DP_VGA_CONVERTER,
|
||||
DISPLAY_DONGLE_DP_DVI_CONVERTER,
|
||||
DISPLAY_DONGLE_DP_HDMI_CONVERTER,
|
||||
/* DP-HDMI/DVI passive dongles (Type 1 and Type 2)*/
|
||||
DISPLAY_DONGLE_DP_DVI_DONGLE,
|
||||
DISPLAY_DONGLE_DP_HDMI_DONGLE,
|
||||
/* Other types of dongle*/
|
||||
DISPLAY_DONGLE_DP_HDMI_MISMATCHED_DONGLE,
|
||||
};
|
||||
|
||||
struct ddc_service {
|
||||
struct ddc *ddc_pin;
|
||||
struct ddc_flags flags;
|
||||
union ddc_wa wa;
|
||||
enum ddc_transaction_type transaction_type;
|
||||
enum display_dongle_type dongle_type;
|
||||
struct dc_context *ctx;
|
||||
struct core_link *link;
|
||||
|
||||
uint32_t address;
|
||||
uint32_t edid_buf_len;
|
||||
uint8_t edid_buf[MAX_EDID_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
#endif /* DC_DDC_TYPES_H_ */
|
|
@ -0,0 +1,105 @@
|
|||
/*
|
||||
* Copyright 2016 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 DC_DP_TYPES_H
|
||||
#define DC_DP_TYPES_H
|
||||
|
||||
enum dc_lane_count {
|
||||
LANE_COUNT_UNKNOWN = 0,
|
||||
LANE_COUNT_ONE = 1,
|
||||
LANE_COUNT_TWO = 2,
|
||||
LANE_COUNT_FOUR = 4,
|
||||
LANE_COUNT_EIGHT = 8,
|
||||
LANE_COUNT_DP_MAX = LANE_COUNT_FOUR
|
||||
};
|
||||
|
||||
/* This is actually a reference clock (27MHz) multiplier
|
||||
* 162MBps bandwidth for 1.62GHz like rate,
|
||||
* 270MBps for 2.70GHz,
|
||||
* 324MBps for 3.24Ghz,
|
||||
* 540MBps for 5.40GHz
|
||||
* 810MBps for 8.10GHz
|
||||
*/
|
||||
enum dc_link_rate {
|
||||
LINK_RATE_UNKNOWN = 0,
|
||||
LINK_RATE_LOW = 0x06,
|
||||
LINK_RATE_HIGH = 0x0A,
|
||||
LINK_RATE_RBR2 = 0x0C,
|
||||
LINK_RATE_HIGH2 = 0x14,
|
||||
LINK_RATE_HIGH3 = 0x1E
|
||||
};
|
||||
|
||||
enum dc_link_spread {
|
||||
LINK_SPREAD_DISABLED = 0x00,
|
||||
/* 0.5 % downspread 30 kHz */
|
||||
LINK_SPREAD_05_DOWNSPREAD_30KHZ = 0x10,
|
||||
/* 0.5 % downspread 33 kHz */
|
||||
LINK_SPREAD_05_DOWNSPREAD_33KHZ = 0x11
|
||||
};
|
||||
|
||||
enum dc_voltage_swing {
|
||||
VOLTAGE_SWING_LEVEL0 = 0, /* direct HW translation! */
|
||||
VOLTAGE_SWING_LEVEL1,
|
||||
VOLTAGE_SWING_LEVEL2,
|
||||
VOLTAGE_SWING_LEVEL3,
|
||||
VOLTAGE_SWING_MAX_LEVEL = VOLTAGE_SWING_LEVEL3
|
||||
};
|
||||
|
||||
enum dc_pre_emphasis {
|
||||
PRE_EMPHASIS_DISABLED = 0, /* direct HW translation! */
|
||||
PRE_EMPHASIS_LEVEL1,
|
||||
PRE_EMPHASIS_LEVEL2,
|
||||
PRE_EMPHASIS_LEVEL3,
|
||||
PRE_EMPHASIS_MAX_LEVEL = PRE_EMPHASIS_LEVEL3
|
||||
};
|
||||
/* Post Cursor 2 is optional for transmitter
|
||||
* and it applies only to the main link operating at HBR2
|
||||
*/
|
||||
enum dc_post_cursor2 {
|
||||
POST_CURSOR2_DISABLED = 0, /* direct HW translation! */
|
||||
POST_CURSOR2_LEVEL1,
|
||||
POST_CURSOR2_LEVEL2,
|
||||
POST_CURSOR2_LEVEL3,
|
||||
POST_CURSOR2_MAX_LEVEL = POST_CURSOR2_LEVEL3,
|
||||
};
|
||||
|
||||
struct dc_link_settings {
|
||||
enum dc_lane_count lane_count;
|
||||
enum dc_link_rate link_rate;
|
||||
enum dc_link_spread link_spread;
|
||||
};
|
||||
|
||||
struct dc_lane_settings {
|
||||
enum dc_voltage_swing VOLTAGE_SWING;
|
||||
enum dc_pre_emphasis PRE_EMPHASIS;
|
||||
enum dc_post_cursor2 POST_CURSOR2;
|
||||
};
|
||||
|
||||
struct dc_link_training_settings {
|
||||
struct dc_link_settings link;
|
||||
struct dc_lane_settings lane_settings[LANE_COUNT_DP_MAX];
|
||||
};
|
||||
|
||||
#endif /* DC_DP_TYPES_H */
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* dc_helper.c
|
||||
*
|
||||
* Created on: Aug 30, 2016
|
||||
* Author: agrodzov
|
||||
*/
|
||||
#include "dm_services.h"
|
||||
#include <stdarg.h>
|
||||
|
||||
uint32_t generic_reg_update_ex(const struct dc_context *ctx,
|
||||
uint32_t addr, uint32_t reg_val, int n,
|
||||
uint8_t shift1, uint32_t mask1, uint32_t field_value1,
|
||||
...)
|
||||
{
|
||||
uint32_t shift, mask, field_value;
|
||||
int i = 1;
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, field_value1);
|
||||
|
||||
reg_val = set_reg_field_value_ex(reg_val, field_value1, mask1, shift1);
|
||||
|
||||
while (i < n) {
|
||||
shift = va_arg(ap, uint32_t);
|
||||
mask = va_arg(ap, uint32_t);
|
||||
field_value = va_arg(ap, uint32_t);
|
||||
|
||||
reg_val = set_reg_field_value_ex(reg_val, field_value, mask, shift);
|
||||
i++;
|
||||
}
|
||||
|
||||
dm_write_reg(ctx, addr, reg_val);
|
||||
va_end(ap);
|
||||
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
uint32_t generic_reg_get(const struct dc_context *ctx, uint32_t addr,
|
||||
uint8_t shift, uint32_t mask, uint32_t *field_value)
|
||||
{
|
||||
uint32_t reg_val = dm_read_reg(ctx, addr);
|
||||
*field_value = get_reg_field_value_ex(reg_val, mask, shift);
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
uint32_t generic_reg_get2(const struct dc_context *ctx, uint32_t addr,
|
||||
uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
|
||||
uint8_t shift2, uint32_t mask2, uint32_t *field_value2)
|
||||
{
|
||||
uint32_t reg_val = dm_read_reg(ctx, addr);
|
||||
*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
|
||||
*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
uint32_t generic_reg_get3(const struct dc_context *ctx, uint32_t addr,
|
||||
uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
|
||||
uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
|
||||
uint8_t shift3, uint32_t mask3, uint32_t *field_value3)
|
||||
{
|
||||
uint32_t reg_val = dm_read_reg(ctx, addr);
|
||||
*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
|
||||
*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
|
||||
*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
uint32_t generic_reg_get5(const struct dc_context *ctx, uint32_t addr,
|
||||
uint8_t shift1, uint32_t mask1, uint32_t *field_value1,
|
||||
uint8_t shift2, uint32_t mask2, uint32_t *field_value2,
|
||||
uint8_t shift3, uint32_t mask3, uint32_t *field_value3,
|
||||
uint8_t shift4, uint32_t mask4, uint32_t *field_value4,
|
||||
uint8_t shift5, uint32_t mask5, uint32_t *field_value5)
|
||||
{
|
||||
uint32_t reg_val = dm_read_reg(ctx, addr);
|
||||
*field_value1 = get_reg_field_value_ex(reg_val, mask1, shift1);
|
||||
*field_value2 = get_reg_field_value_ex(reg_val, mask2, shift2);
|
||||
*field_value3 = get_reg_field_value_ex(reg_val, mask3, shift3);
|
||||
*field_value4 = get_reg_field_value_ex(reg_val, mask4, shift4);
|
||||
*field_value5 = get_reg_field_value_ex(reg_val, mask5, shift5);
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
/* note: va version of this is pretty bad idea, since there is a output parameter pass by pointer
|
||||
* compiler won't be able to check for size match and is prone to stack corruption type of bugs
|
||||
|
||||
uint32_t generic_reg_get(const struct dc_context *ctx,
|
||||
uint32_t addr, int n, ...)
|
||||
{
|
||||
uint32_t shift, mask;
|
||||
uint32_t *field_value;
|
||||
uint32_t reg_val;
|
||||
int i = 0;
|
||||
|
||||
reg_val = dm_read_reg(ctx, addr);
|
||||
|
||||
va_list ap;
|
||||
va_start(ap, n);
|
||||
|
||||
while (i < n) {
|
||||
shift = va_arg(ap, uint32_t);
|
||||
mask = va_arg(ap, uint32_t);
|
||||
field_value = va_arg(ap, uint32_t *);
|
||||
|
||||
*field_value = get_reg_field_value_ex(reg_val, mask, shift);
|
||||
i++;
|
||||
}
|
||||
|
||||
va_end(ap);
|
||||
|
||||
return reg_val;
|
||||
}
|
||||
*/
|
||||
|
||||
uint32_t generic_reg_wait(const struct dc_context *ctx,
|
||||
uint32_t addr, uint32_t shift, uint32_t mask, uint32_t condition_value,
|
||||
unsigned int delay_between_poll_us, unsigned int time_out_num_tries,
|
||||
const char *func_name)
|
||||
{
|
||||
uint32_t field_value;
|
||||
uint32_t reg_val;
|
||||
int i;
|
||||
|
||||
for (i = 0; i <= time_out_num_tries; i++) {
|
||||
if (i) {
|
||||
if (0 < delay_between_poll_us && delay_between_poll_us < 1000)
|
||||
udelay(delay_between_poll_us);
|
||||
|
||||
if (delay_between_poll_us > 1000)
|
||||
msleep(delay_between_poll_us/1000);
|
||||
}
|
||||
|
||||
reg_val = dm_read_reg(ctx, addr);
|
||||
|
||||
field_value = get_reg_field_value_ex(reg_val, mask, shift);
|
||||
|
||||
if (field_value == condition_value)
|
||||
return reg_val;
|
||||
}
|
||||
|
||||
DC_ERR("REG_WAIT timeout %dus * %d tries - %s",
|
||||
delay_between_poll_us, time_out_num_tries, func_name);
|
||||
return reg_val;
|
||||
}
|
|
@ -0,0 +1,588 @@
|
|||
/*
|
||||
* Copyright 2016 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 DC_HW_TYPES_H
|
||||
#define DC_HW_TYPES_H
|
||||
|
||||
#include "os_types.h"
|
||||
|
||||
/******************************************************************************
|
||||
* Data types for Virtual HW Layer of DAL3.
|
||||
* (see DAL3 design documents for HW Layer definition)
|
||||
*
|
||||
* The intended uses are:
|
||||
* 1. Generation pseudocode sequences for HW programming.
|
||||
* 2. Implementation of real HW programming by HW Sequencer of DAL3.
|
||||
*
|
||||
* Note: do *not* add any types which are *not* used for HW programming - this
|
||||
* will ensure separation of Logic layer from HW layer.
|
||||
******************************************************************************/
|
||||
|
||||
union large_integer {
|
||||
struct {
|
||||
uint32_t low_part;
|
||||
int32_t high_part;
|
||||
};
|
||||
|
||||
struct {
|
||||
uint32_t low_part;
|
||||
int32_t high_part;
|
||||
} u;
|
||||
|
||||
int64_t quad_part;
|
||||
};
|
||||
|
||||
#define PHYSICAL_ADDRESS_LOC union large_integer
|
||||
|
||||
enum dc_plane_addr_type {
|
||||
PLN_ADDR_TYPE_GRAPHICS = 0,
|
||||
PLN_ADDR_TYPE_GRPH_STEREO,
|
||||
PLN_ADDR_TYPE_VIDEO_PROGRESSIVE,
|
||||
};
|
||||
|
||||
struct dc_plane_address {
|
||||
enum dc_plane_addr_type type;
|
||||
union {
|
||||
struct{
|
||||
PHYSICAL_ADDRESS_LOC addr;
|
||||
PHYSICAL_ADDRESS_LOC meta_addr;
|
||||
union large_integer dcc_const_color;
|
||||
} grph;
|
||||
|
||||
/*stereo*/
|
||||
struct {
|
||||
PHYSICAL_ADDRESS_LOC left_addr;
|
||||
PHYSICAL_ADDRESS_LOC left_meta_addr;
|
||||
union large_integer left_dcc_const_color;
|
||||
|
||||
PHYSICAL_ADDRESS_LOC right_addr;
|
||||
PHYSICAL_ADDRESS_LOC right_meta_addr;
|
||||
union large_integer right_dcc_const_color;
|
||||
|
||||
} grph_stereo;
|
||||
|
||||
/*video progressive*/
|
||||
struct {
|
||||
PHYSICAL_ADDRESS_LOC luma_addr;
|
||||
PHYSICAL_ADDRESS_LOC luma_meta_addr;
|
||||
union large_integer luma_dcc_const_color;
|
||||
|
||||
PHYSICAL_ADDRESS_LOC chroma_addr;
|
||||
PHYSICAL_ADDRESS_LOC chroma_meta_addr;
|
||||
union large_integer chroma_dcc_const_color;
|
||||
} video_progressive;
|
||||
};
|
||||
};
|
||||
|
||||
struct dc_size {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct rect {
|
||||
int x;
|
||||
int y;
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
union plane_size {
|
||||
/* Grph or Video will be selected
|
||||
* based on format above:
|
||||
* Use Video structure if
|
||||
* format >= DalPixelFormat_VideoBegin
|
||||
* else use Grph structure
|
||||
*/
|
||||
struct {
|
||||
struct rect surface_size;
|
||||
/* Graphic surface pitch in pixels.
|
||||
* In LINEAR_GENERAL mode, pitch
|
||||
* is 32 pixel aligned.
|
||||
*/
|
||||
uint32_t surface_pitch;
|
||||
|
||||
uint32_t meta_pitch;
|
||||
} grph;
|
||||
|
||||
struct {
|
||||
struct rect luma_size;
|
||||
/* Graphic surface pitch in pixels.
|
||||
* In LINEAR_GENERAL mode, pitch is
|
||||
* 32 pixel aligned.
|
||||
*/
|
||||
uint32_t luma_pitch;
|
||||
uint32_t meta_luma_pitch;
|
||||
|
||||
struct rect chroma_size;
|
||||
/* Graphic surface pitch in pixels.
|
||||
* In LINEAR_GENERAL mode, pitch is
|
||||
* 32 pixel aligned.
|
||||
*/
|
||||
uint32_t chroma_pitch;
|
||||
uint32_t meta_chroma_pitch;
|
||||
} video;
|
||||
};
|
||||
|
||||
struct dc_plane_dcc_param {
|
||||
bool enable;
|
||||
|
||||
union {
|
||||
struct {
|
||||
uint32_t meta_pitch;
|
||||
bool independent_64b_blks;
|
||||
} grph;
|
||||
|
||||
struct {
|
||||
uint32_t meta_pitch_l;
|
||||
bool independent_64b_blks_l;
|
||||
|
||||
uint32_t meta_pitch_c;
|
||||
bool independent_64b_blks_c;
|
||||
} video;
|
||||
};
|
||||
};
|
||||
|
||||
/*Displayable pixel format in fb*/
|
||||
enum surface_pixel_format {
|
||||
SURFACE_PIXEL_FORMAT_GRPH_BEGIN = 0,
|
||||
/*TOBE REMOVED paletta 256 colors*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS =
|
||||
SURFACE_PIXEL_FORMAT_GRPH_BEGIN,
|
||||
/*16 bpp*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ARGB1555,
|
||||
/*16 bpp*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_RGB565,
|
||||
/*32 bpp*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ARGB8888,
|
||||
/*32 bpp swaped*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_BGRA8888,
|
||||
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010,
|
||||
/*swaped*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010,
|
||||
/*TOBE REMOVED swaped, XR_BIAS has no differance
|
||||
* for pixel layout than previous and we can
|
||||
* delete this after discusion*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS,
|
||||
/*64 bpp */
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616,
|
||||
/*float*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F,
|
||||
/*swaped & float*/
|
||||
SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F,
|
||||
/*grow graphics here if necessary */
|
||||
|
||||
SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
|
||||
SURFACE_PIXEL_FORMAT_VIDEO_420_YCbCr =
|
||||
SURFACE_PIXEL_FORMAT_VIDEO_BEGIN,
|
||||
SURFACE_PIXEL_FORMAT_VIDEO_420_YCrCb,
|
||||
SURFACE_PIXEL_FORMAT_INVALID
|
||||
|
||||
/*grow 444 video here if necessary */
|
||||
};
|
||||
|
||||
/* Pixel format */
|
||||
enum pixel_format {
|
||||
/*graph*/
|
||||
PIXEL_FORMAT_UNINITIALIZED,
|
||||
PIXEL_FORMAT_INDEX8,
|
||||
PIXEL_FORMAT_RGB565,
|
||||
PIXEL_FORMAT_ARGB8888,
|
||||
PIXEL_FORMAT_ARGB2101010,
|
||||
PIXEL_FORMAT_ARGB2101010_XRBIAS,
|
||||
PIXEL_FORMAT_FP16,
|
||||
/*video*/
|
||||
PIXEL_FORMAT_420BPP12,
|
||||
/*end of pixel format definition*/
|
||||
PIXEL_FORMAT_INVALID,
|
||||
|
||||
PIXEL_FORMAT_GRPH_BEGIN = PIXEL_FORMAT_INDEX8,
|
||||
PIXEL_FORMAT_GRPH_END = PIXEL_FORMAT_FP16,
|
||||
PIXEL_FORMAT_VIDEO_BEGIN = PIXEL_FORMAT_420BPP12,
|
||||
PIXEL_FORMAT_VIDEO_END = PIXEL_FORMAT_420BPP12,
|
||||
PIXEL_FORMAT_UNKNOWN
|
||||
};
|
||||
|
||||
enum tile_split_values {
|
||||
DC_DISPLAY_MICRO_TILING = 0x0,
|
||||
DC_THIN_MICRO_TILING = 0x1,
|
||||
DC_DEPTH_MICRO_TILING = 0x2,
|
||||
DC_ROTATED_MICRO_TILING = 0x3,
|
||||
};
|
||||
|
||||
/* TODO: These values come from hardware spec. We need to readdress this
|
||||
* if they ever change.
|
||||
*/
|
||||
enum array_mode_values {
|
||||
DC_ARRAY_LINEAR_GENERAL = 0,
|
||||
DC_ARRAY_LINEAR_ALLIGNED,
|
||||
DC_ARRAY_1D_TILED_THIN1,
|
||||
DC_ARRAY_1D_TILED_THICK,
|
||||
DC_ARRAY_2D_TILED_THIN1,
|
||||
DC_ARRAY_PRT_TILED_THIN1,
|
||||
DC_ARRAY_PRT_2D_TILED_THIN1,
|
||||
DC_ARRAY_2D_TILED_THICK,
|
||||
DC_ARRAY_2D_TILED_X_THICK,
|
||||
DC_ARRAY_PRT_TILED_THICK,
|
||||
DC_ARRAY_PRT_2D_TILED_THICK,
|
||||
DC_ARRAY_PRT_3D_TILED_THIN1,
|
||||
DC_ARRAY_3D_TILED_THIN1,
|
||||
DC_ARRAY_3D_TILED_THICK,
|
||||
DC_ARRAY_3D_TILED_X_THICK,
|
||||
DC_ARRAY_PRT_3D_TILED_THICK,
|
||||
};
|
||||
|
||||
enum tile_mode_values {
|
||||
DC_ADDR_SURF_MICRO_TILING_DISPLAY = 0x0,
|
||||
DC_ADDR_SURF_MICRO_TILING_NON_DISPLAY = 0x1,
|
||||
};
|
||||
|
||||
union dc_tiling_info {
|
||||
|
||||
struct {
|
||||
/* Specifies the number of memory banks for tiling
|
||||
* purposes.
|
||||
* Only applies to 2D and 3D tiling modes.
|
||||
* POSSIBLE VALUES: 2,4,8,16
|
||||
*/
|
||||
unsigned int num_banks;
|
||||
/* Specifies the number of tiles in the x direction
|
||||
* to be incorporated into the same bank.
|
||||
* Only applies to 2D and 3D tiling modes.
|
||||
* POSSIBLE VALUES: 1,2,4,8
|
||||
*/
|
||||
unsigned int bank_width;
|
||||
unsigned int bank_width_c;
|
||||
/* Specifies the number of tiles in the y direction to
|
||||
* be incorporated into the same bank.
|
||||
* Only applies to 2D and 3D tiling modes.
|
||||
* POSSIBLE VALUES: 1,2,4,8
|
||||
*/
|
||||
unsigned int bank_height;
|
||||
unsigned int bank_height_c;
|
||||
/* Specifies the macro tile aspect ratio. Only applies
|
||||
* to 2D and 3D tiling modes.
|
||||
*/
|
||||
unsigned int tile_aspect;
|
||||
unsigned int tile_aspect_c;
|
||||
/* Specifies the number of bytes that will be stored
|
||||
* contiguously for each tile.
|
||||
* If the tile data requires more storage than this
|
||||
* amount, it is split into multiple slices.
|
||||
* This field must not be larger than
|
||||
* GB_ADDR_CONFIG.DRAM_ROW_SIZE.
|
||||
* Only applies to 2D and 3D tiling modes.
|
||||
* For color render targets, TILE_SPLIT >= 256B.
|
||||
*/
|
||||
enum tile_split_values tile_split;
|
||||
enum tile_split_values tile_split_c;
|
||||
/* Specifies the addressing within a tile.
|
||||
* 0x0 - DISPLAY_MICRO_TILING
|
||||
* 0x1 - THIN_MICRO_TILING
|
||||
* 0x2 - DEPTH_MICRO_TILING
|
||||
* 0x3 - ROTATED_MICRO_TILING
|
||||
*/
|
||||
enum tile_mode_values tile_mode;
|
||||
enum tile_mode_values tile_mode_c;
|
||||
/* Specifies the number of pipes and how they are
|
||||
* interleaved in the surface.
|
||||
* Refer to memory addressing document for complete
|
||||
* details and constraints.
|
||||
*/
|
||||
unsigned int pipe_config;
|
||||
/* Specifies the tiling mode of the surface.
|
||||
* THIN tiles use an 8x8x1 tile size.
|
||||
* THICK tiles use an 8x8x4 tile size.
|
||||
* 2D tiling modes rotate banks for successive Z slices
|
||||
* 3D tiling modes rotate pipes and banks for Z slices
|
||||
* Refer to memory addressing document for complete
|
||||
* details and constraints.
|
||||
*/
|
||||
enum array_mode_values array_mode;
|
||||
} gfx8;
|
||||
|
||||
};
|
||||
|
||||
/* Rotation angle */
|
||||
enum dc_rotation_angle {
|
||||
ROTATION_ANGLE_0 = 0,
|
||||
ROTATION_ANGLE_90,
|
||||
ROTATION_ANGLE_180,
|
||||
ROTATION_ANGLE_270,
|
||||
ROTATION_ANGLE_COUNT
|
||||
};
|
||||
|
||||
enum dc_scan_direction {
|
||||
SCAN_DIRECTION_UNKNOWN = 0,
|
||||
SCAN_DIRECTION_HORIZONTAL = 1, /* 0, 180 rotation */
|
||||
SCAN_DIRECTION_VERTICAL = 2, /* 90, 270 rotation */
|
||||
};
|
||||
|
||||
struct dc_cursor_position {
|
||||
uint32_t x;
|
||||
uint32_t y;
|
||||
|
||||
uint32_t x_hotspot;
|
||||
uint32_t y_hotspot;
|
||||
|
||||
/*
|
||||
* This parameter indicates whether HW cursor should be enabled
|
||||
*/
|
||||
bool enable;
|
||||
|
||||
/*
|
||||
* This parameter indicates whether cursor hot spot should be
|
||||
* programmed
|
||||
*/
|
||||
bool hot_spot_enable;
|
||||
};
|
||||
|
||||
/* IPP related types */
|
||||
|
||||
/* Used by both ipp amd opp functions*/
|
||||
/* TODO: to be consolidated with enum color_space */
|
||||
|
||||
/*
|
||||
* This enum is for programming CURSOR_MODE register field. What this register
|
||||
* should be programmed to depends on OS requested cursor shape flags and what
|
||||
* we stored in the cursor surface.
|
||||
*/
|
||||
enum dc_cursor_color_format {
|
||||
CURSOR_MODE_MONO,
|
||||
CURSOR_MODE_COLOR_1BIT_AND,
|
||||
CURSOR_MODE_COLOR_PRE_MULTIPLIED_ALPHA,
|
||||
CURSOR_MODE_COLOR_UN_PRE_MULTIPLIED_ALPHA
|
||||
};
|
||||
|
||||
/*
|
||||
* This is all the parameters required by DAL in order to update the cursor
|
||||
* attributes, including the new cursor image surface address, size, hotspot
|
||||
* location, color format, etc.
|
||||
*/
|
||||
|
||||
union dc_cursor_attribute_flags {
|
||||
struct {
|
||||
uint32_t ENABLE_MAGNIFICATION:1;
|
||||
uint32_t INVERSE_TRANSPARENT_CLAMPING:1;
|
||||
uint32_t HORIZONTAL_MIRROR:1;
|
||||
uint32_t VERTICAL_MIRROR:1;
|
||||
uint32_t INVERT_PIXEL_DATA:1;
|
||||
uint32_t ZERO_EXPANSION:1;
|
||||
uint32_t MIN_MAX_INVERT:1;
|
||||
uint32_t RESERVED:25;
|
||||
} bits;
|
||||
uint32_t value;
|
||||
};
|
||||
|
||||
struct dc_cursor_attributes {
|
||||
PHYSICAL_ADDRESS_LOC address;
|
||||
|
||||
/* Width and height should correspond to cursor surface width x heigh */
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
uint32_t x_hot;
|
||||
uint32_t y_hot;
|
||||
|
||||
enum dc_cursor_color_format color_format;
|
||||
|
||||
/* In case we support HW Cursor rotation in the future */
|
||||
enum dc_rotation_angle rotation_angle;
|
||||
|
||||
union dc_cursor_attribute_flags attribute_flags;
|
||||
};
|
||||
|
||||
/* OPP */
|
||||
|
||||
enum dc_color_space {
|
||||
COLOR_SPACE_UNKNOWN,
|
||||
COLOR_SPACE_SRGB,
|
||||
COLOR_SPACE_SRGB_LIMITED,
|
||||
COLOR_SPACE_YPBPR601,
|
||||
COLOR_SPACE_YPBPR709,
|
||||
COLOR_SPACE_YCBCR601,
|
||||
COLOR_SPACE_YCBCR709,
|
||||
COLOR_SPACE_YCBCR601_LIMITED,
|
||||
COLOR_SPACE_YCBCR709_LIMITED
|
||||
};
|
||||
|
||||
enum dc_quantization_range {
|
||||
QUANTIZATION_RANGE_UNKNOWN,
|
||||
QUANTIZATION_RANGE_FULL,
|
||||
QUANTIZATION_RANGE_LIMITED
|
||||
};
|
||||
|
||||
/* XFM */
|
||||
|
||||
/* used in struct dc_surface */
|
||||
struct scaling_taps {
|
||||
uint32_t v_taps;
|
||||
uint32_t h_taps;
|
||||
uint32_t v_taps_c;
|
||||
uint32_t h_taps_c;
|
||||
};
|
||||
|
||||
enum dc_timing_standard {
|
||||
TIMING_STANDARD_UNDEFINED,
|
||||
TIMING_STANDARD_DMT,
|
||||
TIMING_STANDARD_GTF,
|
||||
TIMING_STANDARD_CVT,
|
||||
TIMING_STANDARD_CVT_RB,
|
||||
TIMING_STANDARD_CEA770,
|
||||
TIMING_STANDARD_CEA861,
|
||||
TIMING_STANDARD_HDMI,
|
||||
TIMING_STANDARD_TV_NTSC,
|
||||
TIMING_STANDARD_TV_NTSC_J,
|
||||
TIMING_STANDARD_TV_PAL,
|
||||
TIMING_STANDARD_TV_PAL_M,
|
||||
TIMING_STANDARD_TV_PAL_CN,
|
||||
TIMING_STANDARD_TV_SECAM,
|
||||
TIMING_STANDARD_EXPLICIT,
|
||||
/*!< For explicit timings from EDID, VBIOS, etc.*/
|
||||
TIMING_STANDARD_USER_OVERRIDE,
|
||||
/*!< For mode timing override by user*/
|
||||
TIMING_STANDARD_MAX
|
||||
};
|
||||
|
||||
enum dc_timing_3d_format {
|
||||
TIMING_3D_FORMAT_NONE,
|
||||
TIMING_3D_FORMAT_FRAME_ALTERNATE, /* No stereosync at all*/
|
||||
TIMING_3D_FORMAT_INBAND_FA, /* Inband Frame Alternate (DVI/DP)*/
|
||||
TIMING_3D_FORMAT_DP_HDMI_INBAND_FA, /* Inband FA to HDMI Frame Pack*/
|
||||
/* for active DP-HDMI dongle*/
|
||||
TIMING_3D_FORMAT_SIDEBAND_FA, /* Sideband Frame Alternate (eDP)*/
|
||||
TIMING_3D_FORMAT_HW_FRAME_PACKING,
|
||||
TIMING_3D_FORMAT_SW_FRAME_PACKING,
|
||||
TIMING_3D_FORMAT_ROW_INTERLEAVE,
|
||||
TIMING_3D_FORMAT_COLUMN_INTERLEAVE,
|
||||
TIMING_3D_FORMAT_PIXEL_INTERLEAVE,
|
||||
TIMING_3D_FORMAT_SIDE_BY_SIDE,
|
||||
TIMING_3D_FORMAT_TOP_AND_BOTTOM,
|
||||
TIMING_3D_FORMAT_SBS_SW_PACKED,
|
||||
/* Side-by-side, packed by application/driver into 2D frame*/
|
||||
TIMING_3D_FORMAT_TB_SW_PACKED,
|
||||
/* Top-and-bottom, packed by application/driver into 2D frame*/
|
||||
|
||||
TIMING_3D_FORMAT_MAX,
|
||||
};
|
||||
|
||||
enum dc_color_depth {
|
||||
COLOR_DEPTH_UNDEFINED,
|
||||
COLOR_DEPTH_666,
|
||||
COLOR_DEPTH_888,
|
||||
COLOR_DEPTH_101010,
|
||||
COLOR_DEPTH_121212,
|
||||
COLOR_DEPTH_141414,
|
||||
COLOR_DEPTH_161616,
|
||||
COLOR_DEPTH_COUNT
|
||||
};
|
||||
|
||||
enum dc_pixel_encoding {
|
||||
PIXEL_ENCODING_UNDEFINED,
|
||||
PIXEL_ENCODING_RGB,
|
||||
PIXEL_ENCODING_YCBCR422,
|
||||
PIXEL_ENCODING_YCBCR444,
|
||||
PIXEL_ENCODING_YCBCR420,
|
||||
PIXEL_ENCODING_COUNT
|
||||
};
|
||||
|
||||
enum dc_aspect_ratio {
|
||||
ASPECT_RATIO_NO_DATA,
|
||||
ASPECT_RATIO_4_3,
|
||||
ASPECT_RATIO_16_9,
|
||||
ASPECT_RATIO_64_27,
|
||||
ASPECT_RATIO_256_135,
|
||||
ASPECT_RATIO_FUTURE
|
||||
};
|
||||
|
||||
enum scanning_type {
|
||||
SCANNING_TYPE_NODATA = 0,
|
||||
SCANNING_TYPE_OVERSCAN,
|
||||
SCANNING_TYPE_UNDERSCAN,
|
||||
SCANNING_TYPE_FUTURE,
|
||||
SCANNING_TYPE_UNDEFINED
|
||||
};
|
||||
|
||||
struct dc_crtc_timing_flags {
|
||||
uint32_t INTERLACE :1;
|
||||
uint32_t HSYNC_POSITIVE_POLARITY :1; /* when set to 1,
|
||||
it is positive polarity --reversed with dal1 or video bios define*/
|
||||
uint32_t VSYNC_POSITIVE_POLARITY :1; /* when set to 1,
|
||||
it is positive polarity --reversed with dal1 or video bios define*/
|
||||
|
||||
uint32_t HORZ_COUNT_BY_TWO:1;
|
||||
|
||||
uint32_t EXCLUSIVE_3D :1; /* if this bit set,
|
||||
timing can be driven in 3D format only
|
||||
and there is no corresponding 2D timing*/
|
||||
uint32_t RIGHT_EYE_3D_POLARITY :1; /* 1 - means right eye polarity
|
||||
(right eye = '1', left eye = '0') */
|
||||
uint32_t SUB_SAMPLE_3D :1; /* 1 - means left/right images subsampled
|
||||
when mixed into 3D image. 0 - means summation (3D timing is doubled)*/
|
||||
uint32_t USE_IN_3D_VIEW_ONLY :1; /* Do not use this timing in 2D View,
|
||||
because corresponding 2D timing also present in the list*/
|
||||
uint32_t STEREO_3D_PREFERENCE :1; /* Means this is 2D timing
|
||||
and we want to match priority of corresponding 3D timing*/
|
||||
uint32_t Y_ONLY :1;
|
||||
|
||||
uint32_t YCBCR420 :1; /* TODO: shouldn't need this flag, should be a separate pixel format */
|
||||
uint32_t DTD_COUNTER :5; /* values 1 to 16 */
|
||||
|
||||
/* HDMI 2.0 - Support scrambling for TMDS character
|
||||
* rates less than or equal to 340Mcsc */
|
||||
uint32_t LTE_340MCSC_SCRAMBLE:1;
|
||||
|
||||
};
|
||||
|
||||
struct dc_crtc_timing {
|
||||
|
||||
uint32_t h_total;
|
||||
uint32_t h_border_left;
|
||||
uint32_t h_addressable;
|
||||
uint32_t h_border_right;
|
||||
uint32_t h_front_porch;
|
||||
uint32_t h_sync_width;
|
||||
|
||||
uint32_t v_total;
|
||||
uint32_t v_border_top;
|
||||
uint32_t v_addressable;
|
||||
uint32_t v_border_bottom;
|
||||
uint32_t v_front_porch;
|
||||
uint32_t v_sync_width;
|
||||
|
||||
uint32_t pix_clk_khz;
|
||||
|
||||
uint32_t vic;
|
||||
uint32_t hdmi_vic;
|
||||
enum dc_timing_3d_format timing_3d_format;
|
||||
enum dc_color_depth display_color_depth;
|
||||
enum dc_pixel_encoding pixel_encoding;
|
||||
enum dc_aspect_ratio aspect_ratio;
|
||||
enum scanning_type scan_type;
|
||||
|
||||
struct dc_crtc_timing_flags flags;
|
||||
};
|
||||
|
||||
#endif /* DC_HW_TYPES_H */
|
||||
|
|
@ -0,0 +1,493 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 DC_TYPES_H_
|
||||
#define DC_TYPES_H_
|
||||
|
||||
#include "fixed32_32.h"
|
||||
#include "fixed31_32.h"
|
||||
#include "irq_types.h"
|
||||
#include "dc_dp_types.h"
|
||||
#include "dc_hw_types.h"
|
||||
#include "dal_types.h"
|
||||
|
||||
/* forward declarations */
|
||||
struct dc_surface;
|
||||
struct dc_target;
|
||||
struct dc_stream;
|
||||
struct dc_link;
|
||||
struct dc_sink;
|
||||
struct dal;
|
||||
|
||||
/********************************
|
||||
* Environment definitions
|
||||
********************************/
|
||||
enum dce_environment {
|
||||
DCE_ENV_PRODUCTION_DRV = 0,
|
||||
/* Emulation on FPGA, in "Maximus" System.
|
||||
* This environment enforces that *only* DC registers accessed.
|
||||
* (access to non-DC registers will hang FPGA) */
|
||||
DCE_ENV_FPGA_MAXIMUS,
|
||||
/* Emulation on real HW or on FPGA. Used by Diagnostics, enforces
|
||||
* requirements of Diagnostics team. */
|
||||
DCE_ENV_DIAG
|
||||
};
|
||||
|
||||
/* Note: use these macro definitions instead of direct comparison! */
|
||||
#define IS_FPGA_MAXIMUS_DC(dce_environment) \
|
||||
(dce_environment == DCE_ENV_FPGA_MAXIMUS)
|
||||
|
||||
#define IS_DIAG_DC(dce_environment) \
|
||||
(IS_FPGA_MAXIMUS_DC(dce_environment) || (dce_environment == DCE_ENV_DIAG))
|
||||
|
||||
struct hw_asic_id {
|
||||
uint32_t chip_id;
|
||||
uint32_t chip_family;
|
||||
uint32_t pci_revision_id;
|
||||
uint32_t hw_internal_rev;
|
||||
uint32_t vram_type;
|
||||
uint32_t vram_width;
|
||||
uint32_t feature_flags;
|
||||
uint32_t fake_paths_num;
|
||||
void *atombios_base_address;
|
||||
};
|
||||
|
||||
struct dc_context {
|
||||
struct dc *dc;
|
||||
|
||||
void *driver_context; /* e.g. amdgpu_device */
|
||||
|
||||
struct dal_logger *logger;
|
||||
void *cgs_device;
|
||||
|
||||
enum dce_environment dce_environment;
|
||||
struct hw_asic_id asic_id;
|
||||
|
||||
/* todo: below should probably move to dc. to facilitate removal
|
||||
* of AS we will store these here
|
||||
*/
|
||||
enum dce_version dce_version;
|
||||
struct dc_bios *dc_bios;
|
||||
bool created_bios;
|
||||
struct gpio_service *gpio_service;
|
||||
struct i2caux *i2caux;
|
||||
};
|
||||
|
||||
|
||||
#define MAX_EDID_BUFFER_SIZE 512
|
||||
#define EDID_BLOCK_SIZE 128
|
||||
#define MAX_SURFACE_NUM 2
|
||||
#define NUM_PIXEL_FORMATS 10
|
||||
|
||||
#include "dc_ddc_types.h"
|
||||
|
||||
enum tiling_mode {
|
||||
TILING_MODE_INVALID,
|
||||
TILING_MODE_LINEAR,
|
||||
TILING_MODE_TILED,
|
||||
TILING_MODE_COUNT
|
||||
};
|
||||
|
||||
enum view_3d_format {
|
||||
VIEW_3D_FORMAT_NONE = 0,
|
||||
VIEW_3D_FORMAT_FRAME_SEQUENTIAL,
|
||||
VIEW_3D_FORMAT_SIDE_BY_SIDE,
|
||||
VIEW_3D_FORMAT_TOP_AND_BOTTOM,
|
||||
VIEW_3D_FORMAT_COUNT,
|
||||
VIEW_3D_FORMAT_FIRST = VIEW_3D_FORMAT_FRAME_SEQUENTIAL
|
||||
};
|
||||
|
||||
enum plane_stereo_format {
|
||||
PLANE_STEREO_FORMAT_NONE = 0,
|
||||
PLANE_STEREO_FORMAT_SIDE_BY_SIDE = 1,
|
||||
PLANE_STEREO_FORMAT_TOP_AND_BOTTOM = 2,
|
||||
PLANE_STEREO_FORMAT_FRAME_ALTERNATE = 3,
|
||||
PLANE_STEREO_FORMAT_ROW_INTERLEAVED = 5,
|
||||
PLANE_STEREO_FORMAT_COLUMN_INTERLEAVED = 6,
|
||||
PLANE_STEREO_FORMAT_CHECKER_BOARD = 7
|
||||
};
|
||||
|
||||
/* TODO: Find way to calculate number of bits
|
||||
* Please increase if pixel_format enum increases
|
||||
* num from PIXEL_FORMAT_INDEX8 to PIXEL_FORMAT_444BPP32
|
||||
*/
|
||||
|
||||
enum dc_edid_connector_type {
|
||||
EDID_CONNECTOR_UNKNOWN = 0,
|
||||
EDID_CONNECTOR_ANALOG = 1,
|
||||
EDID_CONNECTOR_DIGITAL = 10,
|
||||
EDID_CONNECTOR_DVI = 11,
|
||||
EDID_CONNECTOR_HDMIA = 12,
|
||||
EDID_CONNECTOR_MDDI = 14,
|
||||
EDID_CONNECTOR_DISPLAYPORT = 15
|
||||
};
|
||||
|
||||
enum dc_edid_status {
|
||||
EDID_OK,
|
||||
EDID_BAD_INPUT,
|
||||
EDID_NO_RESPONSE,
|
||||
EDID_BAD_CHECKSUM,
|
||||
};
|
||||
|
||||
/* audio capability from EDID*/
|
||||
struct dc_cea_audio_mode {
|
||||
uint8_t format_code; /* ucData[0] [6:3]*/
|
||||
uint8_t channel_count; /* ucData[0] [2:0]*/
|
||||
uint8_t sample_rate; /* ucData[1]*/
|
||||
union {
|
||||
uint8_t sample_size; /* for LPCM*/
|
||||
/* for Audio Formats 2-8 (Max bit rate divided by 8 kHz)*/
|
||||
uint8_t max_bit_rate;
|
||||
uint8_t audio_codec_vendor_specific; /* for Audio Formats 9-15*/
|
||||
};
|
||||
};
|
||||
|
||||
struct dc_edid {
|
||||
uint32_t length;
|
||||
uint8_t raw_edid[MAX_EDID_BUFFER_SIZE];
|
||||
};
|
||||
|
||||
/* When speaker location data block is not available, DEFAULT_SPEAKER_LOCATION
|
||||
* is used. In this case we assume speaker location are: front left, front
|
||||
* right and front center. */
|
||||
#define DEFAULT_SPEAKER_LOCATION 5
|
||||
|
||||
#define DC_MAX_AUDIO_DESC_COUNT 16
|
||||
|
||||
#define AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS 20
|
||||
|
||||
struct dc_edid_caps {
|
||||
/* sink identification */
|
||||
uint16_t manufacturer_id;
|
||||
uint16_t product_id;
|
||||
uint32_t serial_number;
|
||||
uint8_t manufacture_week;
|
||||
uint8_t manufacture_year;
|
||||
uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
|
||||
|
||||
/* audio caps */
|
||||
uint8_t speaker_flags;
|
||||
uint32_t audio_mode_count;
|
||||
struct dc_cea_audio_mode audio_modes[DC_MAX_AUDIO_DESC_COUNT];
|
||||
uint32_t audio_latency;
|
||||
uint32_t video_latency;
|
||||
|
||||
/*HDMI 2.0 caps*/
|
||||
bool lte_340mcsc_scramble;
|
||||
|
||||
bool edid_hdmi;
|
||||
};
|
||||
|
||||
struct view {
|
||||
uint32_t width;
|
||||
uint32_t height;
|
||||
};
|
||||
|
||||
struct dc_mode_flags {
|
||||
/* note: part of refresh rate flag*/
|
||||
uint32_t INTERLACE :1;
|
||||
/* native display timing*/
|
||||
uint32_t NATIVE :1;
|
||||
/* preferred is the recommended mode, one per display */
|
||||
uint32_t PREFERRED :1;
|
||||
/* true if this mode should use reduced blanking timings
|
||||
*_not_ related to the Reduced Blanking adjustment*/
|
||||
uint32_t REDUCED_BLANKING :1;
|
||||
/* note: part of refreshrate flag*/
|
||||
uint32_t VIDEO_OPTIMIZED_RATE :1;
|
||||
/* should be reported to upper layers as mode_flags*/
|
||||
uint32_t PACKED_PIXEL_FORMAT :1;
|
||||
/*< preferred view*/
|
||||
uint32_t PREFERRED_VIEW :1;
|
||||
/* this timing should be used only in tiled mode*/
|
||||
uint32_t TILED_MODE :1;
|
||||
uint32_t DSE_MODE :1;
|
||||
/* Refresh rate divider when Miracast sink is using a
|
||||
different rate than the output display device
|
||||
Must be zero for wired displays and non-zero for
|
||||
Miracast displays*/
|
||||
uint32_t MIRACAST_REFRESH_DIVIDER;
|
||||
};
|
||||
|
||||
|
||||
enum dc_timing_source {
|
||||
TIMING_SOURCE_UNDEFINED,
|
||||
|
||||
/* explicitly specifed by user, most important*/
|
||||
TIMING_SOURCE_USER_FORCED,
|
||||
TIMING_SOURCE_USER_OVERRIDE,
|
||||
TIMING_SOURCE_CUSTOM,
|
||||
TIMING_SOURCE_EXPLICIT,
|
||||
|
||||
/* explicitly specified by the display device, more important*/
|
||||
TIMING_SOURCE_EDID_CEA_SVD_3D,
|
||||
TIMING_SOURCE_EDID_CEA_SVD_PREFERRED,
|
||||
TIMING_SOURCE_EDID_CEA_SVD_420,
|
||||
TIMING_SOURCE_EDID_DETAILED,
|
||||
TIMING_SOURCE_EDID_ESTABLISHED,
|
||||
TIMING_SOURCE_EDID_STANDARD,
|
||||
TIMING_SOURCE_EDID_CEA_SVD,
|
||||
TIMING_SOURCE_EDID_CVT_3BYTE,
|
||||
TIMING_SOURCE_EDID_4BYTE,
|
||||
TIMING_SOURCE_VBIOS,
|
||||
TIMING_SOURCE_CV,
|
||||
TIMING_SOURCE_TV,
|
||||
TIMING_SOURCE_HDMI_VIC,
|
||||
|
||||
/* implicitly specified by display device, still safe but less important*/
|
||||
TIMING_SOURCE_DEFAULT,
|
||||
|
||||
/* only used for custom base modes */
|
||||
TIMING_SOURCE_CUSTOM_BASE,
|
||||
|
||||
/* these timing might not work, least important*/
|
||||
TIMING_SOURCE_RANGELIMIT,
|
||||
TIMING_SOURCE_OS_FORCED,
|
||||
TIMING_SOURCE_IMPLICIT,
|
||||
|
||||
/* only used by default mode list*/
|
||||
TIMING_SOURCE_BASICMODE,
|
||||
|
||||
TIMING_SOURCE_COUNT
|
||||
};
|
||||
|
||||
enum dc_timing_support_method {
|
||||
TIMING_SUPPORT_METHOD_UNDEFINED,
|
||||
TIMING_SUPPORT_METHOD_EXPLICIT,
|
||||
TIMING_SUPPORT_METHOD_IMPLICIT,
|
||||
TIMING_SUPPORT_METHOD_NATIVE
|
||||
};
|
||||
|
||||
struct dc_mode_info {
|
||||
uint32_t pixel_width;
|
||||
uint32_t pixel_height;
|
||||
uint32_t field_rate;
|
||||
/* Vertical refresh rate for progressive modes.
|
||||
* Field rate for interlaced modes.*/
|
||||
|
||||
enum dc_timing_standard timing_standard;
|
||||
enum dc_timing_source timing_source;
|
||||
struct dc_mode_flags flags;
|
||||
};
|
||||
|
||||
enum dc_power_state {
|
||||
DC_POWER_STATE_ON = 1,
|
||||
DC_POWER_STATE_STANDBY,
|
||||
DC_POWER_STATE_SUSPEND,
|
||||
DC_POWER_STATE_OFF
|
||||
};
|
||||
|
||||
/* DC PowerStates */
|
||||
enum dc_video_power_state {
|
||||
DC_VIDEO_POWER_UNSPECIFIED = 0,
|
||||
DC_VIDEO_POWER_ON = 1,
|
||||
DC_VIDEO_POWER_STANDBY,
|
||||
DC_VIDEO_POWER_SUSPEND,
|
||||
DC_VIDEO_POWER_OFF,
|
||||
DC_VIDEO_POWER_HIBERNATE,
|
||||
DC_VIDEO_POWER_SHUTDOWN,
|
||||
DC_VIDEO_POWER_ULPS, /* BACO or Ultra-Light-Power-State */
|
||||
DC_VIDEO_POWER_AFTER_RESET,
|
||||
DC_VIDEO_POWER_MAXIMUM
|
||||
};
|
||||
|
||||
enum dc_acpi_cm_power_state {
|
||||
DC_ACPI_CM_POWER_STATE_D0 = 1,
|
||||
DC_ACPI_CM_POWER_STATE_D1 = 2,
|
||||
DC_ACPI_CM_POWER_STATE_D2 = 4,
|
||||
DC_ACPI_CM_POWER_STATE_D3 = 8
|
||||
};
|
||||
|
||||
enum dc_connection_type {
|
||||
dc_connection_none,
|
||||
dc_connection_single,
|
||||
dc_connection_mst_branch,
|
||||
dc_connection_active_dongle
|
||||
};
|
||||
|
||||
struct dc_csc_adjustments {
|
||||
struct fixed31_32 contrast;
|
||||
struct fixed31_32 saturation;
|
||||
struct fixed31_32 brightness;
|
||||
struct fixed31_32 hue;
|
||||
};
|
||||
|
||||
enum {
|
||||
MAX_LANES = 2,
|
||||
MAX_COFUNC_PATH = 6,
|
||||
LAYER_INDEX_PRIMARY = -1,
|
||||
};
|
||||
|
||||
/* Scaling format */
|
||||
enum scaling_transformation {
|
||||
SCALING_TRANSFORMATION_UNINITIALIZED,
|
||||
SCALING_TRANSFORMATION_IDENTITY = 0x0001,
|
||||
SCALING_TRANSFORMATION_CENTER_TIMING = 0x0002,
|
||||
SCALING_TRANSFORMATION_FULL_SCREEN_SCALE = 0x0004,
|
||||
SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE = 0x0008,
|
||||
SCALING_TRANSFORMATION_DAL_DECIDE = 0x0010,
|
||||
SCALING_TRANSFORMATION_INVALID = 0x80000000,
|
||||
|
||||
/* Flag the first and last */
|
||||
SCALING_TRANSFORMATION_BEGING = SCALING_TRANSFORMATION_IDENTITY,
|
||||
SCALING_TRANSFORMATION_END =
|
||||
SCALING_TRANSFORMATION_PRESERVE_ASPECT_RATIO_SCALE
|
||||
};
|
||||
|
||||
/* audio*/
|
||||
|
||||
union audio_sample_rates {
|
||||
struct sample_rates {
|
||||
uint8_t RATE_32:1;
|
||||
uint8_t RATE_44_1:1;
|
||||
uint8_t RATE_48:1;
|
||||
uint8_t RATE_88_2:1;
|
||||
uint8_t RATE_96:1;
|
||||
uint8_t RATE_176_4:1;
|
||||
uint8_t RATE_192:1;
|
||||
} rate;
|
||||
|
||||
uint8_t all;
|
||||
};
|
||||
|
||||
struct audio_speaker_flags {
|
||||
uint32_t FL_FR:1;
|
||||
uint32_t LFE:1;
|
||||
uint32_t FC:1;
|
||||
uint32_t RL_RR:1;
|
||||
uint32_t RC:1;
|
||||
uint32_t FLC_FRC:1;
|
||||
uint32_t RLC_RRC:1;
|
||||
uint32_t SUPPORT_AI:1;
|
||||
};
|
||||
|
||||
struct audio_speaker_info {
|
||||
uint32_t ALLSPEAKERS:7;
|
||||
uint32_t SUPPORT_AI:1;
|
||||
};
|
||||
|
||||
|
||||
struct audio_info_flags {
|
||||
|
||||
union {
|
||||
|
||||
struct audio_speaker_flags speaker_flags;
|
||||
struct audio_speaker_info info;
|
||||
|
||||
uint8_t all;
|
||||
};
|
||||
};
|
||||
|
||||
enum audio_format_code {
|
||||
AUDIO_FORMAT_CODE_FIRST = 1,
|
||||
AUDIO_FORMAT_CODE_LINEARPCM = AUDIO_FORMAT_CODE_FIRST,
|
||||
|
||||
AUDIO_FORMAT_CODE_AC3,
|
||||
/*Layers 1 & 2 */
|
||||
AUDIO_FORMAT_CODE_MPEG1,
|
||||
/*MPEG1 Layer 3 */
|
||||
AUDIO_FORMAT_CODE_MP3,
|
||||
/*multichannel */
|
||||
AUDIO_FORMAT_CODE_MPEG2,
|
||||
AUDIO_FORMAT_CODE_AAC,
|
||||
AUDIO_FORMAT_CODE_DTS,
|
||||
AUDIO_FORMAT_CODE_ATRAC,
|
||||
AUDIO_FORMAT_CODE_1BITAUDIO,
|
||||
AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS,
|
||||
AUDIO_FORMAT_CODE_DTS_HD,
|
||||
AUDIO_FORMAT_CODE_MAT_MLP,
|
||||
AUDIO_FORMAT_CODE_DST,
|
||||
AUDIO_FORMAT_CODE_WMAPRO,
|
||||
AUDIO_FORMAT_CODE_LAST,
|
||||
AUDIO_FORMAT_CODE_COUNT =
|
||||
AUDIO_FORMAT_CODE_LAST - AUDIO_FORMAT_CODE_FIRST
|
||||
};
|
||||
|
||||
struct audio_mode {
|
||||
/* ucData[0] [6:3] */
|
||||
enum audio_format_code format_code;
|
||||
/* ucData[0] [2:0] */
|
||||
uint8_t channel_count;
|
||||
/* ucData[1] */
|
||||
union audio_sample_rates sample_rates;
|
||||
union {
|
||||
/* for LPCM */
|
||||
uint8_t sample_size;
|
||||
/* for Audio Formats 2-8 (Max bit rate divided by 8 kHz) */
|
||||
uint8_t max_bit_rate;
|
||||
/* for Audio Formats 9-15 */
|
||||
uint8_t vendor_specific;
|
||||
};
|
||||
};
|
||||
|
||||
struct audio_info {
|
||||
struct audio_info_flags flags;
|
||||
uint32_t video_latency;
|
||||
uint32_t audio_latency;
|
||||
uint32_t display_index;
|
||||
uint8_t display_name[AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS];
|
||||
uint32_t manufacture_id;
|
||||
uint32_t product_id;
|
||||
/* PortID used for ContainerID when defined */
|
||||
uint32_t port_id[2];
|
||||
uint32_t mode_count;
|
||||
/* this field must be last in this struct */
|
||||
struct audio_mode modes[DC_MAX_AUDIO_DESC_COUNT];
|
||||
};
|
||||
|
||||
struct freesync_context {
|
||||
bool supported;
|
||||
bool enabled;
|
||||
bool active;
|
||||
|
||||
unsigned int min_refresh_in_micro_hz;
|
||||
unsigned int nominal_refresh_in_micro_hz;
|
||||
};
|
||||
|
||||
struct colorspace_transform {
|
||||
struct fixed31_32 matrix[12];
|
||||
bool enable_remap;
|
||||
};
|
||||
|
||||
struct csc_transform {
|
||||
uint16_t matrix[12];
|
||||
bool enable_adjustment;
|
||||
};
|
||||
|
||||
struct psr_caps {
|
||||
/* These parameters are from PSR capabilities reported by Sink DPCD */
|
||||
unsigned char psr_version;
|
||||
unsigned int psr_rfb_setup_time;
|
||||
bool psr_exit_link_training_required;
|
||||
|
||||
/* These parameters are calculated in Driver,
|
||||
* based on display timing and Sink capabilities.
|
||||
* If VBLANK region is too small and Sink takes a long time
|
||||
* to set up RFB, it may take an extra frame to enter PSR state.
|
||||
*/
|
||||
bool psr_frame_capture_indication_req;
|
||||
unsigned int psr_sdp_transmit_line_num_deadline;
|
||||
};
|
||||
|
||||
#endif /* DC_TYPES_H_ */
|
|
@ -0,0 +1,14 @@
|
|||
#
|
||||
# Makefile for common 'dce' logic
|
||||
# HW object file under this folder follow similar pattern for HW programming
|
||||
# - register offset and/or shift + mask stored in the dec_hw struct
|
||||
# - register programming through common macros that look up register
|
||||
# offset/shift/mask stored in dce_hw struct
|
||||
|
||||
DCE = dce_audio.o dce_stream_encoder.o dce_link_encoder.o dce_hwseq.o \
|
||||
dce_mem_input.o dce_clock_source.o dce_scl_filters.o dce_transform.o
|
||||
|
||||
|
||||
AMD_DAL_DCE = $(addprefix $(AMDDALPATH)/dc/dce/,$(DCE))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DCE)
|
|
@ -0,0 +1,920 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 "reg_helper.h"
|
||||
#include "dce_audio.h"
|
||||
#include "dce/dce_11_0_d.h"
|
||||
#include "dce/dce_11_0_sh_mask.h"
|
||||
|
||||
#define DCE_AUD(audio)\
|
||||
container_of(audio, struct dce_audio, base)
|
||||
|
||||
#define CTX \
|
||||
aud->base.ctx
|
||||
#define REG(reg)\
|
||||
(aud->regs->reg)
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
aud->shifts->field_name, aud->masks->field_name
|
||||
|
||||
#define IX_REG(reg)\
|
||||
ix ## reg
|
||||
|
||||
#define AZ_REG_READ(reg_name) \
|
||||
read_indirect_azalia_reg(audio, IX_REG(reg_name))
|
||||
|
||||
#define AZ_REG_WRITE(reg_name, value) \
|
||||
write_indirect_azalia_reg(audio, IX_REG(reg_name), value)
|
||||
|
||||
static void write_indirect_azalia_reg(struct audio *audio,
|
||||
uint32_t reg_index,
|
||||
uint32_t reg_data)
|
||||
{
|
||||
struct dce_audio *aud = DCE_AUD(audio);
|
||||
|
||||
/* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */
|
||||
REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0,
|
||||
AZALIA_ENDPOINT_REG_INDEX, reg_index);
|
||||
|
||||
/* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */
|
||||
REG_SET(AZALIA_F0_CODEC_ENDPOINT_DATA, 0,
|
||||
AZALIA_ENDPOINT_REG_DATA, reg_data);
|
||||
|
||||
dm_logger_write(CTX->logger, LOG_HW_AUDIO,
|
||||
"AUDIO:write_indirect_azalia_reg: index: %u data: %u\n",
|
||||
reg_index, reg_data);
|
||||
}
|
||||
|
||||
static uint32_t read_indirect_azalia_reg(struct audio *audio, uint32_t reg_index)
|
||||
{
|
||||
struct dce_audio *aud = DCE_AUD(audio);
|
||||
|
||||
uint32_t value = 0;
|
||||
|
||||
/* AZALIA_F0_CODEC_ENDPOINT_INDEX endpoint index */
|
||||
REG_SET(AZALIA_F0_CODEC_ENDPOINT_INDEX, 0,
|
||||
AZALIA_ENDPOINT_REG_INDEX, reg_index);
|
||||
|
||||
/* AZALIA_F0_CODEC_ENDPOINT_DATA endpoint data */
|
||||
value = REG_READ(AZALIA_F0_CODEC_ENDPOINT_DATA);
|
||||
|
||||
dm_logger_write(CTX->logger, LOG_HW_AUDIO,
|
||||
"AUDIO:read_indirect_azalia_reg: index: %u data: %u\n",
|
||||
reg_index, value);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
static bool is_audio_format_supported(
|
||||
const struct audio_info *audio_info,
|
||||
enum audio_format_code audio_format_code,
|
||||
uint32_t *format_index)
|
||||
{
|
||||
uint32_t index;
|
||||
uint32_t max_channe_index = 0;
|
||||
bool found = false;
|
||||
|
||||
if (audio_info == NULL)
|
||||
return found;
|
||||
|
||||
/* pass through whole array */
|
||||
for (index = 0; index < audio_info->mode_count; index++) {
|
||||
if (audio_info->modes[index].format_code == audio_format_code) {
|
||||
if (found) {
|
||||
/* format has multiply entries, choose one with
|
||||
* highst number of channels */
|
||||
if (audio_info->modes[index].channel_count >
|
||||
audio_info->modes[max_channe_index].channel_count) {
|
||||
max_channe_index = index;
|
||||
}
|
||||
} else {
|
||||
/* format found, save it's index */
|
||||
found = true;
|
||||
max_channe_index = index;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* return index */
|
||||
if (found && format_index != NULL)
|
||||
*format_index = max_channe_index;
|
||||
|
||||
return found;
|
||||
}
|
||||
|
||||
/*For HDMI, calculate if specified sample rates can fit into a given timing */
|
||||
static void check_audio_bandwidth_hdmi(
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
uint32_t channel_count,
|
||||
union audio_sample_rates *sample_rates)
|
||||
{
|
||||
uint32_t samples;
|
||||
uint32_t h_blank;
|
||||
bool limit_freq_to_48_khz = false;
|
||||
bool limit_freq_to_88_2_khz = false;
|
||||
bool limit_freq_to_96_khz = false;
|
||||
bool limit_freq_to_174_4_khz = false;
|
||||
|
||||
/* For two channels supported return whatever sink support,unmodified*/
|
||||
if (channel_count > 2) {
|
||||
|
||||
/* Based on HDMI spec 1.3 Table 7.5 */
|
||||
if ((crtc_info->requested_pixel_clock <= 27000) &&
|
||||
(crtc_info->v_active <= 576) &&
|
||||
!(crtc_info->interlaced) &&
|
||||
!(crtc_info->pixel_repetition == 2 ||
|
||||
crtc_info->pixel_repetition == 4)) {
|
||||
limit_freq_to_48_khz = true;
|
||||
|
||||
} else if ((crtc_info->requested_pixel_clock <= 27000) &&
|
||||
(crtc_info->v_active <= 576) &&
|
||||
(crtc_info->interlaced) &&
|
||||
(crtc_info->pixel_repetition == 2)) {
|
||||
limit_freq_to_88_2_khz = true;
|
||||
|
||||
} else if ((crtc_info->requested_pixel_clock <= 54000) &&
|
||||
(crtc_info->v_active <= 576) &&
|
||||
!(crtc_info->interlaced)) {
|
||||
limit_freq_to_174_4_khz = true;
|
||||
}
|
||||
}
|
||||
|
||||
/* Also do some calculation for the available Audio Bandwidth for the
|
||||
* 8 ch (i.e. for the Layout 1 => ch > 2)
|
||||
*/
|
||||
h_blank = crtc_info->h_total - crtc_info->h_active;
|
||||
|
||||
if (crtc_info->pixel_repetition)
|
||||
h_blank *= crtc_info->pixel_repetition;
|
||||
|
||||
/*based on HDMI spec 1.3 Table 7.5 */
|
||||
h_blank -= 58;
|
||||
/*for Control Period */
|
||||
h_blank -= 16;
|
||||
|
||||
samples = h_blank * 10;
|
||||
/* Number of Audio Packets (multiplied by 10) per Line (for 8 ch number
|
||||
* of Audio samples per line multiplied by 10 - Layout 1)
|
||||
*/
|
||||
samples /= 32;
|
||||
samples *= crtc_info->v_active;
|
||||
/*Number of samples multiplied by 10, per second */
|
||||
samples *= crtc_info->refresh_rate;
|
||||
/*Number of Audio samples per second */
|
||||
samples /= 10;
|
||||
|
||||
/* @todo do it after deep color is implemented
|
||||
* 8xx - deep color bandwidth scaling
|
||||
* Extra bandwidth is avaliable in deep color b/c link runs faster than
|
||||
* pixel rate. This has the effect of allowing more tmds characters to
|
||||
* be transmitted during blank
|
||||
*/
|
||||
|
||||
switch (crtc_info->color_depth) {
|
||||
case COLOR_DEPTH_888:
|
||||
samples *= 4;
|
||||
break;
|
||||
case COLOR_DEPTH_101010:
|
||||
samples *= 5;
|
||||
break;
|
||||
case COLOR_DEPTH_121212:
|
||||
samples *= 6;
|
||||
break;
|
||||
default:
|
||||
samples *= 4;
|
||||
break;
|
||||
}
|
||||
|
||||
samples /= 4;
|
||||
|
||||
/*check limitation*/
|
||||
if (samples < 88200)
|
||||
limit_freq_to_48_khz = true;
|
||||
else if (samples < 96000)
|
||||
limit_freq_to_88_2_khz = true;
|
||||
else if (samples < 176400)
|
||||
limit_freq_to_96_khz = true;
|
||||
else if (samples < 192000)
|
||||
limit_freq_to_174_4_khz = true;
|
||||
|
||||
if (sample_rates != NULL) {
|
||||
/* limit frequencies */
|
||||
if (limit_freq_to_174_4_khz)
|
||||
sample_rates->rate.RATE_192 = 0;
|
||||
|
||||
if (limit_freq_to_96_khz) {
|
||||
sample_rates->rate.RATE_192 = 0;
|
||||
sample_rates->rate.RATE_176_4 = 0;
|
||||
}
|
||||
if (limit_freq_to_88_2_khz) {
|
||||
sample_rates->rate.RATE_192 = 0;
|
||||
sample_rates->rate.RATE_176_4 = 0;
|
||||
sample_rates->rate.RATE_96 = 0;
|
||||
}
|
||||
if (limit_freq_to_48_khz) {
|
||||
sample_rates->rate.RATE_192 = 0;
|
||||
sample_rates->rate.RATE_176_4 = 0;
|
||||
sample_rates->rate.RATE_96 = 0;
|
||||
sample_rates->rate.RATE_88_2 = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*For DP SST, calculate if specified sample rates can fit into a given timing */
|
||||
static void check_audio_bandwidth_dpsst(
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
uint32_t channel_count,
|
||||
union audio_sample_rates *sample_rates)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
/*For DP MST, calculate if specified sample rates can fit into a given timing */
|
||||
static void check_audio_bandwidth_dpmst(
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
uint32_t channel_count,
|
||||
union audio_sample_rates *sample_rates)
|
||||
{
|
||||
/* do nothing */
|
||||
}
|
||||
|
||||
static void check_audio_bandwidth(
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
uint32_t channel_count,
|
||||
enum signal_type signal,
|
||||
union audio_sample_rates *sample_rates)
|
||||
{
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
check_audio_bandwidth_hdmi(
|
||||
crtc_info, channel_count, sample_rates);
|
||||
break;
|
||||
case SIGNAL_TYPE_EDP:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
check_audio_bandwidth_dpsst(
|
||||
crtc_info, channel_count, sample_rates);
|
||||
break;
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
check_audio_bandwidth_dpmst(
|
||||
crtc_info, channel_count, sample_rates);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* expose/not expose HBR capability to Audio driver */
|
||||
static void set_high_bit_rate_capable(
|
||||
struct audio *audio,
|
||||
bool capable)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
/* set high bit rate audio capable*/
|
||||
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR);
|
||||
|
||||
set_reg_field_value(value, capable,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR,
|
||||
HBR_CAPABLE);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_HBR, value);
|
||||
}
|
||||
|
||||
/* set video latency in in ms/2+1 */
|
||||
static void set_video_latency(
|
||||
struct audio *audio,
|
||||
int latency_in_ms)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if ((latency_in_ms < 0) || (latency_in_ms > 255))
|
||||
return;
|
||||
|
||||
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
|
||||
|
||||
set_reg_field_value(value, latency_in_ms,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
|
||||
VIDEO_LIPSYNC);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
|
||||
value);
|
||||
}
|
||||
|
||||
/* set audio latency in in ms/2+1 */
|
||||
static void set_audio_latency(
|
||||
struct audio *audio,
|
||||
int latency_in_ms)
|
||||
{
|
||||
uint32_t value = 0;
|
||||
|
||||
if (latency_in_ms < 0)
|
||||
latency_in_ms = 0;
|
||||
|
||||
if (latency_in_ms > 255)
|
||||
latency_in_ms = 255;
|
||||
|
||||
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC);
|
||||
|
||||
set_reg_field_value(value, latency_in_ms,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
|
||||
AUDIO_LIPSYNC);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_LIPSYNC,
|
||||
value);
|
||||
}
|
||||
|
||||
void dce_aud_az_enable(struct audio *audio)
|
||||
{
|
||||
uint32_t value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
|
||||
|
||||
if (get_reg_field_value(value,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
|
||||
AUDIO_ENABLED) != 1)
|
||||
set_reg_field_value(value, 1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
|
||||
AUDIO_ENABLED);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
|
||||
}
|
||||
|
||||
void dce_aud_az_disable(struct audio *audio)
|
||||
{
|
||||
uint32_t value;
|
||||
|
||||
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL);
|
||||
|
||||
set_reg_field_value(value, 0,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL,
|
||||
AUDIO_ENABLED);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_HOT_PLUG_CONTROL, value);
|
||||
}
|
||||
|
||||
void dce_aud_az_configure(
|
||||
struct audio *audio,
|
||||
enum signal_type signal,
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
const struct audio_info *audio_info)
|
||||
{
|
||||
struct dce_audio *aud = DCE_AUD(audio);
|
||||
|
||||
uint32_t speakers = audio_info->flags.info.ALLSPEAKERS;
|
||||
uint32_t value;
|
||||
uint32_t field = 0;
|
||||
enum audio_format_code audio_format_code;
|
||||
uint32_t format_index;
|
||||
uint32_t index;
|
||||
bool is_ac3_supported = false;
|
||||
union audio_sample_rates sample_rate;
|
||||
uint32_t strlen = 0;
|
||||
|
||||
/* Speaker Allocation */
|
||||
/*
|
||||
uint32_t value;
|
||||
uint32_t field = 0;*/
|
||||
value = AZ_REG_READ(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER);
|
||||
|
||||
set_reg_field_value(value,
|
||||
speakers,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
SPEAKER_ALLOCATION);
|
||||
|
||||
/* LFE_PLAYBACK_LEVEL = LFEPBL
|
||||
* LFEPBL = 0 : Unknown or refer to other information
|
||||
* LFEPBL = 1 : 0dB playback
|
||||
* LFEPBL = 2 : +10dB playback
|
||||
* LFE_BL = 3 : Reserved
|
||||
*/
|
||||
set_reg_field_value(value,
|
||||
0,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
LFE_PLAYBACK_LEVEL);
|
||||
/* todo: according to reg spec LFE_PLAYBACK_LEVEL is read only.
|
||||
* why are we writing to it? DCE8 does not write this */
|
||||
|
||||
|
||||
set_reg_field_value(value,
|
||||
0,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
HDMI_CONNECTION);
|
||||
|
||||
set_reg_field_value(value,
|
||||
0,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
DP_CONNECTION);
|
||||
|
||||
field = get_reg_field_value(value,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
EXTRA_CONNECTION_INFO);
|
||||
|
||||
field &= ~0x1;
|
||||
|
||||
set_reg_field_value(value,
|
||||
field,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
EXTRA_CONNECTION_INFO);
|
||||
|
||||
/* set audio for output signal */
|
||||
switch (signal) {
|
||||
case SIGNAL_TYPE_HDMI_TYPE_A:
|
||||
set_reg_field_value(value,
|
||||
1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
HDMI_CONNECTION);
|
||||
|
||||
break;
|
||||
|
||||
case SIGNAL_TYPE_EDP:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT:
|
||||
case SIGNAL_TYPE_DISPLAY_PORT_MST:
|
||||
set_reg_field_value(value,
|
||||
1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER,
|
||||
DP_CONNECTION);
|
||||
break;
|
||||
default:
|
||||
BREAK_TO_DEBUGGER();
|
||||
break;
|
||||
}
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_CHANNEL_SPEAKER, value);
|
||||
|
||||
/* Audio Descriptors */
|
||||
/* pass through all formats */
|
||||
for (format_index = 0; format_index < AUDIO_FORMAT_CODE_COUNT;
|
||||
format_index++) {
|
||||
audio_format_code =
|
||||
(AUDIO_FORMAT_CODE_FIRST + format_index);
|
||||
|
||||
/* those are unsupported, skip programming */
|
||||
if (audio_format_code == AUDIO_FORMAT_CODE_1BITAUDIO ||
|
||||
audio_format_code == AUDIO_FORMAT_CODE_DST)
|
||||
continue;
|
||||
|
||||
value = 0;
|
||||
|
||||
/* check if supported */
|
||||
if (is_audio_format_supported(
|
||||
audio_info, audio_format_code, &index)) {
|
||||
const struct audio_mode *audio_mode =
|
||||
&audio_info->modes[index];
|
||||
union audio_sample_rates sample_rates =
|
||||
audio_mode->sample_rates;
|
||||
uint8_t byte2 = audio_mode->max_bit_rate;
|
||||
|
||||
/* adjust specific properties */
|
||||
switch (audio_format_code) {
|
||||
case AUDIO_FORMAT_CODE_LINEARPCM: {
|
||||
check_audio_bandwidth(
|
||||
crtc_info,
|
||||
audio_mode->channel_count,
|
||||
signal,
|
||||
&sample_rates);
|
||||
|
||||
byte2 = audio_mode->sample_size;
|
||||
|
||||
set_reg_field_value(value,
|
||||
sample_rates.all,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
SUPPORTED_FREQUENCIES_STEREO);
|
||||
}
|
||||
break;
|
||||
case AUDIO_FORMAT_CODE_AC3:
|
||||
is_ac3_supported = true;
|
||||
break;
|
||||
case AUDIO_FORMAT_CODE_DOLBYDIGITALPLUS:
|
||||
case AUDIO_FORMAT_CODE_DTS_HD:
|
||||
case AUDIO_FORMAT_CODE_MAT_MLP:
|
||||
case AUDIO_FORMAT_CODE_DST:
|
||||
case AUDIO_FORMAT_CODE_WMAPRO:
|
||||
byte2 = audio_mode->vendor_specific;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/* fill audio format data */
|
||||
set_reg_field_value(value,
|
||||
audio_mode->channel_count - 1,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
MAX_CHANNELS);
|
||||
|
||||
set_reg_field_value(value,
|
||||
sample_rates.all,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
SUPPORTED_FREQUENCIES);
|
||||
|
||||
set_reg_field_value(value,
|
||||
byte2,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0,
|
||||
DESCRIPTOR_BYTE_2);
|
||||
} /* if */
|
||||
|
||||
AZ_REG_WRITE(
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_AUDIO_DESCRIPTOR0 + format_index,
|
||||
value);
|
||||
} /* for */
|
||||
|
||||
if (is_ac3_supported)
|
||||
/* todo: this reg global. why program global register? */
|
||||
REG_WRITE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS,
|
||||
0x05);
|
||||
|
||||
/* check for 192khz/8-Ch support for HBR requirements */
|
||||
sample_rate.all = 0;
|
||||
sample_rate.rate.RATE_192 = 1;
|
||||
|
||||
check_audio_bandwidth(
|
||||
crtc_info,
|
||||
8,
|
||||
signal,
|
||||
&sample_rate);
|
||||
|
||||
set_high_bit_rate_capable(audio, sample_rate.rate.RATE_192);
|
||||
|
||||
/* Audio and Video Lipsync */
|
||||
set_video_latency(audio, audio_info->video_latency);
|
||||
set_audio_latency(audio, audio_info->audio_latency);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->manufacture_id,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
|
||||
MANUFACTURER_ID);
|
||||
|
||||
set_reg_field_value(value, audio_info->product_id,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
|
||||
PRODUCT_ID);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO0,
|
||||
value);
|
||||
|
||||
value = 0;
|
||||
|
||||
/*get display name string length */
|
||||
while (audio_info->display_name[strlen++] != '\0') {
|
||||
if (strlen >=
|
||||
MAX_HW_AUDIO_INFO_DISPLAY_NAME_SIZE_IN_CHARS)
|
||||
break;
|
||||
}
|
||||
set_reg_field_value(value, strlen,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
|
||||
SINK_DESCRIPTION_LEN);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO1,
|
||||
value);
|
||||
|
||||
/*
|
||||
*write the port ID:
|
||||
*PORT_ID0 = display index
|
||||
*PORT_ID1 = 16bit BDF
|
||||
*(format MSB->LSB: 8bit Bus, 5bit Device, 3bit Function)
|
||||
*/
|
||||
|
||||
value = 0;
|
||||
|
||||
set_reg_field_value(value, audio_info->port_id[0],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2,
|
||||
PORT_ID0);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO2, value);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->port_id[1],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3,
|
||||
PORT_ID1);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO3, value);
|
||||
|
||||
/*write the 18 char monitor string */
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->display_name[0],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
|
||||
DESCRIPTION0);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[1],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
|
||||
DESCRIPTION1);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[2],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
|
||||
DESCRIPTION2);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[3],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4,
|
||||
DESCRIPTION3);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO4, value);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->display_name[4],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
|
||||
DESCRIPTION4);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[5],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
|
||||
DESCRIPTION5);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[6],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
|
||||
DESCRIPTION6);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[7],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5,
|
||||
DESCRIPTION7);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO5, value);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->display_name[8],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
|
||||
DESCRIPTION8);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[9],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
|
||||
DESCRIPTION9);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[10],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
|
||||
DESCRIPTION10);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[11],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6,
|
||||
DESCRIPTION11);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO6, value);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->display_name[12],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
|
||||
DESCRIPTION12);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[13],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
|
||||
DESCRIPTION13);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[14],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
|
||||
DESCRIPTION14);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[15],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7,
|
||||
DESCRIPTION15);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO7, value);
|
||||
|
||||
value = 0;
|
||||
set_reg_field_value(value, audio_info->display_name[16],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
|
||||
DESCRIPTION16);
|
||||
|
||||
set_reg_field_value(value, audio_info->display_name[17],
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8,
|
||||
DESCRIPTION17);
|
||||
|
||||
AZ_REG_WRITE(AZALIA_F0_CODEC_PIN_CONTROL_SINK_INFO8, value);
|
||||
}
|
||||
|
||||
/*
|
||||
* todo: wall clk related functionality probably belong to clock_src.
|
||||
*/
|
||||
|
||||
/* search pixel clock value for Azalia HDMI Audio */
|
||||
static bool get_azalia_clock_info_hdmi(
|
||||
uint32_t crtc_pixel_clock_in_khz,
|
||||
uint32_t actual_pixel_clock_in_khz,
|
||||
struct azalia_clock_info *azalia_clock_info)
|
||||
{
|
||||
if (azalia_clock_info == NULL)
|
||||
return false;
|
||||
|
||||
/* audio_dto_phase= 24 * 10,000;
|
||||
* 24MHz in [100Hz] units */
|
||||
azalia_clock_info->audio_dto_phase =
|
||||
24 * 10000;
|
||||
|
||||
/* audio_dto_module = PCLKFrequency * 10,000;
|
||||
* [khz] -> [100Hz] */
|
||||
azalia_clock_info->audio_dto_module =
|
||||
actual_pixel_clock_in_khz * 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool get_azalia_clock_info_dp(
|
||||
uint32_t requested_pixel_clock_in_khz,
|
||||
const struct audio_pll_info *pll_info,
|
||||
struct azalia_clock_info *azalia_clock_info)
|
||||
{
|
||||
if (pll_info == NULL || azalia_clock_info == NULL)
|
||||
return false;
|
||||
|
||||
/* Reported dpDtoSourceClockInkhz value for
|
||||
* DCE8 already adjusted for SS, do not need any
|
||||
* adjustment here anymore
|
||||
*/
|
||||
|
||||
/*audio_dto_phase = 24 * 10,000;
|
||||
* 24MHz in [100Hz] units */
|
||||
azalia_clock_info->audio_dto_phase = 24 * 10000;
|
||||
|
||||
/*audio_dto_module = dpDtoSourceClockInkhz * 10,000;
|
||||
* [khz] ->[100Hz] */
|
||||
azalia_clock_info->audio_dto_module =
|
||||
pll_info->dp_dto_source_clock_in_khz * 10;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void dce_aud_wall_dto_setup(
|
||||
struct audio *audio,
|
||||
enum signal_type signal,
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
const struct audio_pll_info *pll_info)
|
||||
{
|
||||
struct dce_audio *aud = DCE_AUD(audio);
|
||||
|
||||
struct azalia_clock_info clock_info = { 0 };
|
||||
|
||||
if (dc_is_hdmi_signal(signal)) {
|
||||
uint32_t src_sel;
|
||||
|
||||
/*DTO0 Programming goal:
|
||||
-generate 24MHz, 128*Fs from 24MHz
|
||||
-use DTO0 when an active HDMI port is connected
|
||||
(optionally a DP is connected) */
|
||||
|
||||
/* calculate DTO settings */
|
||||
get_azalia_clock_info_hdmi(
|
||||
crtc_info->requested_pixel_clock,
|
||||
crtc_info->calculated_pixel_clock,
|
||||
&clock_info);
|
||||
|
||||
/* On TN/SI, Program DTO source select and DTO select before
|
||||
programming DTO modulo and DTO phase. These bits must be
|
||||
programmed first, otherwise there will be no HDMI audio at boot
|
||||
up. This is a HW sequence change (different from old ASICs).
|
||||
Caution when changing this programming sequence.
|
||||
|
||||
HDMI enabled, using DTO0
|
||||
program master CRTC for DTO0 */
|
||||
src_sel = pll_info->dto_source - DTO_SOURCE_ID0;
|
||||
REG_UPDATE_2(DCCG_AUDIO_DTO_SOURCE,
|
||||
DCCG_AUDIO_DTO0_SOURCE_SEL, src_sel,
|
||||
DCCG_AUDIO_DTO_SEL, 0);
|
||||
|
||||
/* module */
|
||||
REG_UPDATE(DCCG_AUDIO_DTO0_MODULE,
|
||||
DCCG_AUDIO_DTO0_MODULE, clock_info.audio_dto_module);
|
||||
|
||||
/* phase */
|
||||
REG_UPDATE(DCCG_AUDIO_DTO0_PHASE,
|
||||
DCCG_AUDIO_DTO0_PHASE, clock_info.audio_dto_phase);
|
||||
} else {
|
||||
/*DTO1 Programming goal:
|
||||
-generate 24MHz, 512*Fs, 128*Fs from 24MHz
|
||||
-default is to used DTO1, and switch to DTO0 when an audio
|
||||
master HDMI port is connected
|
||||
-use as default for DP
|
||||
|
||||
calculate DTO settings */
|
||||
get_azalia_clock_info_dp(
|
||||
crtc_info->requested_pixel_clock,
|
||||
pll_info,
|
||||
&clock_info);
|
||||
|
||||
/* Program DTO select before programming DTO modulo and DTO
|
||||
phase. default to use DTO1 */
|
||||
|
||||
REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
|
||||
DCCG_AUDIO_DTO_SEL, 1);
|
||||
|
||||
REG_UPDATE(DCCG_AUDIO_DTO_SOURCE,
|
||||
DCCG_AUDIO_DTO_SEL, 1);
|
||||
/* DCCG_AUDIO_DTO2_USE_512FBR_DTO, 1)
|
||||
* Select 512fs for DP TODO: web register definition
|
||||
* does not match register header file
|
||||
* DCE11 version it's commented out while DCE8 it's set to 1
|
||||
*/
|
||||
|
||||
/* module */
|
||||
REG_UPDATE(DCCG_AUDIO_DTO1_MODULE,
|
||||
DCCG_AUDIO_DTO1_MODULE, clock_info.audio_dto_module);
|
||||
|
||||
/* phase */
|
||||
REG_UPDATE(DCCG_AUDIO_DTO1_PHASE,
|
||||
DCCG_AUDIO_DTO1_PHASE, clock_info.audio_dto_phase);
|
||||
|
||||
/* DAL2 code separate DCCG_AUDIO_DTO_SEL and
|
||||
DCCG_AUDIO_DTO2_USE_512FBR_DTO programming into two different
|
||||
location. merge together should not hurt */
|
||||
/*value.bits.DCCG_AUDIO_DTO2_USE_512FBR_DTO = 1;
|
||||
dal_write_reg(mmDCCG_AUDIO_DTO_SOURCE, value);*/
|
||||
}
|
||||
}
|
||||
|
||||
bool dce_aud_endpoint_valid(
|
||||
struct audio *audio)
|
||||
{
|
||||
uint32_t value;
|
||||
uint32_t port_connectivity;
|
||||
|
||||
value = AZ_REG_READ(
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT);
|
||||
|
||||
port_connectivity = get_reg_field_value(value,
|
||||
AZALIA_F0_CODEC_PIN_CONTROL_RESPONSE_CONFIGURATION_DEFAULT,
|
||||
PORT_CONNECTIVITY);
|
||||
|
||||
return !(port_connectivity == 1);
|
||||
}
|
||||
|
||||
/* initialize HW state */
|
||||
void dce_aud_hw_init(
|
||||
struct audio *audio)
|
||||
{
|
||||
struct dce_audio *aud = DCE_AUD(audio);
|
||||
|
||||
/* we only need to program the following registers once, so we only do
|
||||
it for the inst 0*/
|
||||
if (audio->inst != 0)
|
||||
return;
|
||||
|
||||
/* Suport R5 - 32khz
|
||||
* Suport R6 - 44.1khz
|
||||
* Suport R7 - 48khz
|
||||
*/
|
||||
REG_UPDATE(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES,
|
||||
AUDIO_RATE_CAPABILITIES, 0x70);
|
||||
|
||||
/*Keep alive bit to verify HW block in BU. */
|
||||
REG_UPDATE_2(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES,
|
||||
CLKSTOP, 1,
|
||||
EPSS, 1);
|
||||
}
|
||||
|
||||
static const struct audio_funcs funcs = {
|
||||
.endpoint_valid = dce_aud_endpoint_valid,
|
||||
.hw_init = dce_aud_hw_init,
|
||||
.wall_dto_setup = dce_aud_wall_dto_setup,
|
||||
.az_enable = dce_aud_az_enable,
|
||||
.az_disable = dce_aud_az_disable,
|
||||
.az_configure = dce_aud_az_configure,
|
||||
.destroy = dce_aud_destroy,
|
||||
};
|
||||
|
||||
void dce_aud_destroy(struct audio **audio)
|
||||
{
|
||||
dm_free(*audio);
|
||||
*audio = NULL;
|
||||
}
|
||||
|
||||
struct audio *dce_audio_create(
|
||||
struct dc_context *ctx,
|
||||
unsigned int inst,
|
||||
const struct dce_audio_registers *reg,
|
||||
const struct dce_audio_shift *shifts,
|
||||
const struct dce_aduio_mask *masks
|
||||
)
|
||||
{
|
||||
struct dce_audio *audio = dm_alloc(sizeof(*audio));
|
||||
|
||||
if (audio == NULL) {
|
||||
ASSERT_CRITICAL(audio);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
audio->base.ctx = ctx;
|
||||
audio->base.inst = inst;
|
||||
audio->base.funcs = &funcs;
|
||||
|
||||
audio->regs = reg;
|
||||
audio->shifts = shifts;
|
||||
audio->masks = masks;
|
||||
|
||||
return &audio->base;
|
||||
}
|
||||
|
|
@ -0,0 +1,145 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DAL_AUDIO_DCE_110_H__
|
||||
#define __DAL_AUDIO_DCE_110_H__
|
||||
|
||||
#include "audio.h"
|
||||
|
||||
#define AUD_COMMON_REG_LIST(id)\
|
||||
SRI(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZF0ENDPOINT, id),\
|
||||
SRI(AZALIA_F0_CODEC_ENDPOINT_DATA, AZF0ENDPOINT, id),\
|
||||
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS),\
|
||||
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES),\
|
||||
SR(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES),\
|
||||
SR(DCCG_AUDIO_DTO_SOURCE),\
|
||||
SR(DCCG_AUDIO_DTO0_MODULE),\
|
||||
SR(DCCG_AUDIO_DTO0_PHASE),\
|
||||
SR(DCCG_AUDIO_DTO1_MODULE),\
|
||||
SR(DCCG_AUDIO_DTO1_PHASE)
|
||||
|
||||
|
||||
/* set field name */
|
||||
#define SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
|
||||
#define AUD_COMMON_MASK_SH_LIST_BASE(mask_sh)\
|
||||
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO0_SOURCE_SEL, mask_sh),\
|
||||
SF(DCCG_AUDIO_DTO_SOURCE, DCCG_AUDIO_DTO_SEL, mask_sh),\
|
||||
SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
|
||||
SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
|
||||
SF(DCCG_AUDIO_DTO0_MODULE, DCCG_AUDIO_DTO0_MODULE, mask_sh),\
|
||||
SF(DCCG_AUDIO_DTO0_PHASE, DCCG_AUDIO_DTO0_PHASE, mask_sh),\
|
||||
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES, AUDIO_RATE_CAPABILITIES, mask_sh),\
|
||||
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, CLKSTOP, mask_sh),\
|
||||
SF(AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES, EPSS, mask_sh)
|
||||
|
||||
#define AUD_COMMON_MASK_SH_LIST(mask_sh)\
|
||||
AUD_COMMON_MASK_SH_LIST_BASE(mask_sh),\
|
||||
SF(AZALIA_F0_CODEC_ENDPOINT_INDEX, AZALIA_ENDPOINT_REG_INDEX, mask_sh),\
|
||||
SF(AZALIA_F0_CODEC_ENDPOINT_DATA, AZALIA_ENDPOINT_REG_DATA, mask_sh)
|
||||
|
||||
|
||||
struct dce_audio_registers {
|
||||
uint32_t AZALIA_F0_CODEC_ENDPOINT_INDEX;
|
||||
uint32_t AZALIA_F0_CODEC_ENDPOINT_DATA;
|
||||
|
||||
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_STREAM_FORMATS;
|
||||
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_SUPPORTED_SIZE_RATES;
|
||||
uint32_t AZALIA_F0_CODEC_FUNCTION_PARAMETER_POWER_STATES;
|
||||
|
||||
uint32_t DCCG_AUDIO_DTO_SOURCE;
|
||||
uint32_t DCCG_AUDIO_DTO0_MODULE;
|
||||
uint32_t DCCG_AUDIO_DTO0_PHASE;
|
||||
uint32_t DCCG_AUDIO_DTO1_MODULE;
|
||||
uint32_t DCCG_AUDIO_DTO1_PHASE;
|
||||
|
||||
uint32_t AUDIO_RATE_CAPABILITIES;
|
||||
};
|
||||
|
||||
struct dce_audio_shift {
|
||||
uint8_t AZALIA_ENDPOINT_REG_INDEX;
|
||||
uint8_t AZALIA_ENDPOINT_REG_DATA;
|
||||
|
||||
uint8_t AUDIO_RATE_CAPABILITIES;
|
||||
uint8_t CLKSTOP;
|
||||
uint8_t EPSS;
|
||||
|
||||
uint8_t DCCG_AUDIO_DTO0_SOURCE_SEL;
|
||||
uint8_t DCCG_AUDIO_DTO_SEL;
|
||||
uint8_t DCCG_AUDIO_DTO0_MODULE;
|
||||
uint8_t DCCG_AUDIO_DTO0_PHASE;
|
||||
uint8_t DCCG_AUDIO_DTO1_MODULE;
|
||||
uint8_t DCCG_AUDIO_DTO1_PHASE;
|
||||
};
|
||||
|
||||
struct dce_aduio_mask {
|
||||
uint32_t AZALIA_ENDPOINT_REG_INDEX;
|
||||
uint32_t AZALIA_ENDPOINT_REG_DATA;
|
||||
|
||||
uint32_t AUDIO_RATE_CAPABILITIES;
|
||||
uint32_t CLKSTOP;
|
||||
uint32_t EPSS;
|
||||
|
||||
uint32_t DCCG_AUDIO_DTO0_SOURCE_SEL;
|
||||
uint32_t DCCG_AUDIO_DTO_SEL;
|
||||
uint32_t DCCG_AUDIO_DTO0_MODULE;
|
||||
uint32_t DCCG_AUDIO_DTO0_PHASE;
|
||||
uint32_t DCCG_AUDIO_DTO1_MODULE;
|
||||
uint32_t DCCG_AUDIO_DTO1_PHASE;
|
||||
};
|
||||
|
||||
struct dce_audio {
|
||||
struct audio base;
|
||||
const struct dce_audio_registers *regs;
|
||||
const struct dce_audio_shift *shifts;
|
||||
const struct dce_aduio_mask *masks;
|
||||
};
|
||||
|
||||
struct audio *dce_audio_create(
|
||||
struct dc_context *ctx,
|
||||
unsigned int inst,
|
||||
const struct dce_audio_registers *reg,
|
||||
const struct dce_audio_shift *shifts,
|
||||
const struct dce_aduio_mask *masks);
|
||||
|
||||
void dce_aud_destroy(struct audio **audio);
|
||||
|
||||
void dce_aud_hw_init(struct audio *audio);
|
||||
|
||||
void dce_aud_az_enable(struct audio *audio);
|
||||
void dce_aud_az_disable(struct audio *audio);
|
||||
|
||||
void dce_aud_az_configure(struct audio *audio,
|
||||
enum signal_type signal,
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
const struct audio_info *audio_info);
|
||||
|
||||
void dce_aud_wall_dto_setup(struct audio *audio,
|
||||
enum signal_type signal,
|
||||
const struct audio_crtc_info *crtc_info,
|
||||
const struct audio_pll_info *pll_info);
|
||||
|
||||
#endif /*__DAL_AUDIO_DCE_110_H__*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,109 @@
|
|||
/* Copyright 2012-15 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 __DC_CLOCK_SOURCE_DCE_H__
|
||||
#define __DC_CLOCK_SOURCE_DCE_H__
|
||||
|
||||
#include "../inc/clock_source.h"
|
||||
|
||||
#define TO_DCE110_CLK_SRC(clk_src)\
|
||||
container_of(clk_src, struct dce110_clk_src, base)
|
||||
|
||||
#define CS_COMMON_REG_LIST_DCE_100_110(id) \
|
||||
SRI(RESYNC_CNTL, PIXCLK, id), \
|
||||
SRI(PLL_CNTL, BPHYC_PLL, id)
|
||||
|
||||
#define CS_COMMON_REG_LIST_DCE_80(id) \
|
||||
SRI(RESYNC_CNTL, PIXCLK, id), \
|
||||
SRI(PLL_CNTL, DCCG_PLL, id)
|
||||
|
||||
#define CS_COMMON_REG_LIST_DCE_112(id) \
|
||||
SRI(PIXCLK_RESYNC_CNTL, PHYPLL, id)
|
||||
|
||||
#define CS_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
#define CS_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
|
||||
CS_SF(PLL_CNTL, PLL_REF_DIV_SRC, mask_sh),\
|
||||
CS_SF(PIXCLK1_RESYNC_CNTL, DCCG_DEEP_COLOR_CNTL1, mask_sh),\
|
||||
CS_SF(PLL_POST_DIV, PLL_POST_DIV_PIXCLK, mask_sh),\
|
||||
CS_SF(PLL_REF_DIV, PLL_REF_DIV, mask_sh),\
|
||||
|
||||
#define CS_COMMON_MASK_SH_LIST_DCE_112(mask_sh)\
|
||||
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_DCCG_DEEP_COLOR_CNTL, mask_sh),\
|
||||
CS_SF(PHYPLLA_PIXCLK_RESYNC_CNTL, PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE, mask_sh),\
|
||||
|
||||
#define CS_REG_FIELD_LIST(type) \
|
||||
type PLL_REF_DIV_SRC; \
|
||||
type DCCG_DEEP_COLOR_CNTL1; \
|
||||
type PHYPLLA_DCCG_DEEP_COLOR_CNTL; \
|
||||
type PHYPLLA_PIXCLK_DOUBLE_RATE_ENABLE; \
|
||||
type PLL_POST_DIV_PIXCLK; \
|
||||
type PLL_REF_DIV; \
|
||||
|
||||
struct dce110_clk_src_shift {
|
||||
CS_REG_FIELD_LIST(uint8_t)
|
||||
};
|
||||
|
||||
struct dce110_clk_src_mask{
|
||||
CS_REG_FIELD_LIST(uint32_t)
|
||||
};
|
||||
|
||||
struct dce110_clk_src_regs {
|
||||
uint32_t RESYNC_CNTL;
|
||||
uint32_t PIXCLK_RESYNC_CNTL;
|
||||
uint32_t PLL_CNTL;
|
||||
};
|
||||
|
||||
struct dce110_clk_src {
|
||||
struct clock_source base;
|
||||
const struct dce110_clk_src_regs *regs;
|
||||
const struct dce110_clk_src_mask *cs_mask;
|
||||
const struct dce110_clk_src_shift *cs_shift;
|
||||
struct dc_bios *bios;
|
||||
|
||||
struct spread_spectrum_data *dp_ss_params;
|
||||
uint32_t dp_ss_params_cnt;
|
||||
struct spread_spectrum_data *hdmi_ss_params;
|
||||
uint32_t hdmi_ss_params_cnt;
|
||||
struct spread_spectrum_data *dvi_ss_params;
|
||||
uint32_t dvi_ss_params_cnt;
|
||||
|
||||
uint32_t ext_clk_khz;
|
||||
uint32_t ref_freq_khz;
|
||||
|
||||
struct calc_pll_clock_source calc_pll;
|
||||
struct calc_pll_clock_source calc_pll_hdmi;
|
||||
};
|
||||
|
||||
bool dce110_clk_src_construct(
|
||||
struct dce110_clk_src *clk_src,
|
||||
struct dc_context *ctx,
|
||||
struct dc_bios *bios,
|
||||
enum clock_source_id,
|
||||
const struct dce110_clk_src_regs *regs,
|
||||
const struct dce110_clk_src_shift *cs_shift,
|
||||
const struct dce110_clk_src_mask *cs_mask);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,195 @@
|
|||
/*
|
||||
* Copyright 2016 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 "dce_hwseq.h"
|
||||
#include "reg_helper.h"
|
||||
#include "hw_sequencer.h"
|
||||
|
||||
#define CTX \
|
||||
hws->ctx
|
||||
#define REG(reg)\
|
||||
hws->regs->reg
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
hws->shifts->field_name, hws->masks->field_name
|
||||
|
||||
void dce_enable_fe_clock(struct dce_hwseq *hws,
|
||||
unsigned int fe_inst, bool enable)
|
||||
{
|
||||
REG_UPDATE(DCFE_CLOCK_CONTROL[fe_inst],
|
||||
DCFE_CLOCK_ENABLE, enable);
|
||||
}
|
||||
|
||||
void dce_pipe_control_lock(struct dce_hwseq *hws,
|
||||
unsigned int blnd_inst,
|
||||
enum pipe_lock_control control_mask,
|
||||
bool lock)
|
||||
{
|
||||
uint32_t lock_val = lock ? 1 : 0;
|
||||
uint32_t dcp_grph, scl, dcp_grph_surf, blnd, update_lock_mode;
|
||||
|
||||
uint32_t val = REG_GET_5(BLND_V_UPDATE_LOCK[blnd_inst],
|
||||
BLND_DCP_GRPH_V_UPDATE_LOCK, &dcp_grph,
|
||||
BLND_SCL_V_UPDATE_LOCK, &scl,
|
||||
BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, &dcp_grph_surf,
|
||||
BLND_BLND_V_UPDATE_LOCK, &blnd,
|
||||
BLND_V_UPDATE_LOCK_MODE, &update_lock_mode);
|
||||
|
||||
if (control_mask & PIPE_LOCK_CONTROL_GRAPHICS)
|
||||
dcp_grph = lock_val;
|
||||
|
||||
if (control_mask & PIPE_LOCK_CONTROL_SCL)
|
||||
scl = lock_val;
|
||||
|
||||
if (control_mask & PIPE_LOCK_CONTROL_SURFACE)
|
||||
dcp_grph_surf = lock_val;
|
||||
|
||||
if (control_mask & PIPE_LOCK_CONTROL_BLENDER)
|
||||
blnd = lock_val;
|
||||
|
||||
if (control_mask & PIPE_LOCK_CONTROL_MODE)
|
||||
update_lock_mode = lock_val;
|
||||
|
||||
REG_SET_5(BLND_V_UPDATE_LOCK[blnd_inst], val,
|
||||
BLND_DCP_GRPH_V_UPDATE_LOCK, dcp_grph,
|
||||
BLND_SCL_V_UPDATE_LOCK, scl,
|
||||
BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, dcp_grph_surf,
|
||||
BLND_BLND_V_UPDATE_LOCK, blnd,
|
||||
BLND_V_UPDATE_LOCK_MODE, update_lock_mode);
|
||||
|
||||
if (hws->wa.blnd_crtc_trigger)
|
||||
if (!lock && (control_mask & PIPE_LOCK_CONTROL_BLENDER)) {
|
||||
uint32_t value = REG_READ(CRTC_H_BLANK_START_END[blnd_inst]);
|
||||
REG_WRITE(CRTC_H_BLANK_START_END[blnd_inst], value);
|
||||
}
|
||||
}
|
||||
|
||||
void dce_set_blender_mode(struct dce_hwseq *hws,
|
||||
unsigned int blnd_inst,
|
||||
enum blnd_mode mode)
|
||||
{
|
||||
uint32_t feedthrough = 1;
|
||||
uint32_t blnd_mode = 0;
|
||||
uint32_t multiplied_mode = 0;
|
||||
uint32_t alpha_mode = 2;
|
||||
|
||||
switch (mode) {
|
||||
case BLND_MODE_OTHER_PIPE:
|
||||
feedthrough = 0;
|
||||
blnd_mode = 1;
|
||||
alpha_mode = 0;
|
||||
break;
|
||||
case BLND_MODE_BLENDING:
|
||||
feedthrough = 0;
|
||||
blnd_mode = 2;
|
||||
alpha_mode = 0;
|
||||
multiplied_mode = 1;
|
||||
break;
|
||||
case BLND_MODE_CURRENT_PIPE:
|
||||
default:
|
||||
if (REG(BLND_CONTROL[blnd_inst]) == REG(BLNDV_CONTROL) ||
|
||||
blnd_inst == 0)
|
||||
feedthrough = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
REG_UPDATE_4(BLND_CONTROL[blnd_inst],
|
||||
BLND_FEEDTHROUGH_EN, feedthrough,
|
||||
BLND_ALPHA_MODE, alpha_mode,
|
||||
BLND_MODE, blnd_mode,
|
||||
BLND_MULTIPLIED_MODE, multiplied_mode);
|
||||
}
|
||||
|
||||
|
||||
static void dce_disable_sram_shut_down(struct dce_hwseq *hws)
|
||||
{
|
||||
if (REG(DC_MEM_GLOBAL_PWR_REQ_CNTL))
|
||||
REG_UPDATE(DC_MEM_GLOBAL_PWR_REQ_CNTL,
|
||||
DC_MEM_GLOBAL_PWR_REQ_DIS, 1);
|
||||
}
|
||||
|
||||
static void dce_underlay_clock_enable(struct dce_hwseq *hws)
|
||||
{
|
||||
/* todo: why do we need this at boot? is dce_enable_fe_clock enough? */
|
||||
if (REG(DCFEV_CLOCK_CONTROL))
|
||||
REG_UPDATE(DCFEV_CLOCK_CONTROL,
|
||||
DCFEV_CLOCK_ENABLE, 1);
|
||||
}
|
||||
|
||||
static void enable_hw_base_light_sleep(void)
|
||||
{
|
||||
/* TODO: implement */
|
||||
}
|
||||
|
||||
static void disable_sw_manual_control_light_sleep(void)
|
||||
{
|
||||
/* TODO: implement */
|
||||
}
|
||||
|
||||
void dce_clock_gating_power_up(struct dce_hwseq *hws,
|
||||
bool enable)
|
||||
{
|
||||
if (enable) {
|
||||
enable_hw_base_light_sleep();
|
||||
disable_sw_manual_control_light_sleep();
|
||||
} else {
|
||||
dce_disable_sram_shut_down(hws);
|
||||
dce_underlay_clock_enable(hws);
|
||||
}
|
||||
}
|
||||
|
||||
void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
|
||||
struct clock_source *clk_src,
|
||||
unsigned int tg_inst)
|
||||
{
|
||||
if (clk_src->id == CLOCK_SOURCE_ID_DP_DTO) {
|
||||
REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
|
||||
DP_DTO0_ENABLE, 1);
|
||||
|
||||
} else if (clk_src->id >= CLOCK_SOURCE_COMBO_PHY_PLL0) {
|
||||
uint32_t rate_source = clk_src->id - CLOCK_SOURCE_COMBO_PHY_PLL0;
|
||||
|
||||
REG_UPDATE_2(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
|
||||
PHYPLL_PIXEL_RATE_SOURCE, rate_source,
|
||||
PIXEL_RATE_PLL_SOURCE, 0);
|
||||
|
||||
REG_UPDATE(PIXEL_RATE_CNTL[tg_inst],
|
||||
DP_DTO0_ENABLE, 0);
|
||||
|
||||
} else if (clk_src->id <= CLOCK_SOURCE_ID_PLL2) {
|
||||
uint32_t rate_source = clk_src->id - CLOCK_SOURCE_ID_PLL0;
|
||||
|
||||
REG_UPDATE_2(PIXEL_RATE_CNTL[tg_inst],
|
||||
PIXEL_RATE_SOURCE, rate_source,
|
||||
DP_DTO0_ENABLE, 0);
|
||||
|
||||
if (REG(PHYPLL_PIXEL_RATE_CNTL[tg_inst]))
|
||||
REG_UPDATE(PHYPLL_PIXEL_RATE_CNTL[tg_inst],
|
||||
PIXEL_RATE_PLL_SOURCE, 1);
|
||||
} else {
|
||||
DC_ERR("unknown clock source");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,250 @@
|
|||
/*
|
||||
* Copyright 2016 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 __DCE_HWSEQ_H__
|
||||
#define __DCE_HWSEQ_H__
|
||||
|
||||
#include "hw_sequencer.h"
|
||||
|
||||
#define HWSEQ_DCEF_REG_LIST_DCE8() \
|
||||
.DCFE_CLOCK_CONTROL[0] = mmCRTC0_CRTC_DCFE_CLOCK_CONTROL, \
|
||||
.DCFE_CLOCK_CONTROL[1] = mmCRTC1_CRTC_DCFE_CLOCK_CONTROL, \
|
||||
.DCFE_CLOCK_CONTROL[2] = mmCRTC2_CRTC_DCFE_CLOCK_CONTROL, \
|
||||
.DCFE_CLOCK_CONTROL[3] = mmCRTC3_CRTC_DCFE_CLOCK_CONTROL, \
|
||||
.DCFE_CLOCK_CONTROL[4] = mmCRTC4_CRTC_DCFE_CLOCK_CONTROL, \
|
||||
.DCFE_CLOCK_CONTROL[5] = mmCRTC5_CRTC_DCFE_CLOCK_CONTROL
|
||||
|
||||
#define HWSEQ_DCEF_REG_LIST() \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 3), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 4), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 5), \
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL)
|
||||
|
||||
#define HWSEQ_BLND_REG_LIST() \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 0), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 1), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 2), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 3), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 4), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 5), \
|
||||
SRII(BLND_CONTROL, BLND, 0), \
|
||||
SRII(BLND_CONTROL, BLND, 1), \
|
||||
SRII(BLND_CONTROL, BLND, 2), \
|
||||
SRII(BLND_CONTROL, BLND, 3), \
|
||||
SRII(BLND_CONTROL, BLND, 4), \
|
||||
SRII(BLND_CONTROL, BLND, 5)
|
||||
|
||||
#define HWSEQ_PIXEL_RATE_REG_LIST(blk) \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 0), \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 1), \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 2), \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 3), \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 4), \
|
||||
SRII(PIXEL_RATE_CNTL, blk, 5)
|
||||
|
||||
#define HWSEQ_PHYPLL_REG_LIST(blk) \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 0), \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 1), \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 2), \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 3), \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 4), \
|
||||
SRII(PHYPLL_PIXEL_RATE_CNTL, blk, 5)
|
||||
|
||||
#define HWSEQ_DCE11_REG_LIST_BASE() \
|
||||
SR(DC_MEM_GLOBAL_PWR_REQ_CNTL), \
|
||||
SR(DCFEV_CLOCK_CONTROL), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 0), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 1), \
|
||||
SRII(CRTC_H_BLANK_START_END, CRTC, 0),\
|
||||
SRII(CRTC_H_BLANK_START_END, CRTC, 1),\
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 0),\
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 1),\
|
||||
SRII(BLND_CONTROL, BLND, 0),\
|
||||
SRII(BLND_CONTROL, BLND, 1),\
|
||||
SR(BLNDV_CONTROL),\
|
||||
HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
|
||||
|
||||
#define HWSEQ_DCE8_REG_LIST() \
|
||||
HWSEQ_DCEF_REG_LIST_DCE8(), \
|
||||
HWSEQ_BLND_REG_LIST(), \
|
||||
HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
|
||||
|
||||
#define HWSEQ_DCE10_REG_LIST() \
|
||||
HWSEQ_DCEF_REG_LIST(), \
|
||||
HWSEQ_BLND_REG_LIST(), \
|
||||
HWSEQ_PIXEL_RATE_REG_LIST(CRTC)
|
||||
|
||||
#define HWSEQ_ST_REG_LIST() \
|
||||
HWSEQ_DCE11_REG_LIST_BASE(), \
|
||||
.DCFE_CLOCK_CONTROL[2] = mmDCFEV_CLOCK_CONTROL, \
|
||||
.CRTC_H_BLANK_START_END[2] = mmCRTCV_H_BLANK_START_END, \
|
||||
.BLND_V_UPDATE_LOCK[2] = mmBLNDV_V_UPDATE_LOCK, \
|
||||
.BLND_CONTROL[2] = mmBLNDV_CONTROL,
|
||||
|
||||
#define HWSEQ_CZ_REG_LIST() \
|
||||
HWSEQ_DCE11_REG_LIST_BASE(), \
|
||||
SRII(DCFE_CLOCK_CONTROL, DCFE, 2), \
|
||||
SRII(CRTC_H_BLANK_START_END, CRTC, 2), \
|
||||
SRII(BLND_V_UPDATE_LOCK, BLND, 2), \
|
||||
SRII(BLND_CONTROL, BLND, 2), \
|
||||
.DCFE_CLOCK_CONTROL[3] = mmDCFEV_CLOCK_CONTROL, \
|
||||
.CRTC_H_BLANK_START_END[3] = mmCRTCV_H_BLANK_START_END, \
|
||||
.BLND_V_UPDATE_LOCK[3] = mmBLNDV_V_UPDATE_LOCK, \
|
||||
.BLND_CONTROL[3] = mmBLNDV_CONTROL
|
||||
|
||||
#define HWSEQ_DCE112_REG_LIST() \
|
||||
HWSEQ_DCE10_REG_LIST(), \
|
||||
HWSEQ_PIXEL_RATE_REG_LIST(CRTC), \
|
||||
HWSEQ_PHYPLL_REG_LIST(CRTC)
|
||||
|
||||
struct dce_hwseq_registers {
|
||||
uint32_t DCFE_CLOCK_CONTROL[6];
|
||||
uint32_t DCFEV_CLOCK_CONTROL;
|
||||
uint32_t DC_MEM_GLOBAL_PWR_REQ_CNTL;
|
||||
uint32_t BLND_V_UPDATE_LOCK[6];
|
||||
uint32_t BLND_CONTROL[6];
|
||||
uint32_t BLNDV_CONTROL;
|
||||
|
||||
uint32_t CRTC_H_BLANK_START_END[6];
|
||||
uint32_t PIXEL_RATE_CNTL[6];
|
||||
uint32_t PHYPLL_PIXEL_RATE_CNTL[6];
|
||||
};
|
||||
/* set field name */
|
||||
#define HWS_SF(blk_name, reg_name, field_name, post_fix)\
|
||||
.field_name = blk_name ## reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
#define HWS_SF1(blk_name, reg_name, field_name, post_fix)\
|
||||
.field_name = blk_name ## reg_name ## __ ## blk_name ## field_name ## post_fix
|
||||
|
||||
|
||||
#define HWSEQ_DCEF_MASK_SH_LIST(mask_sh, blk)\
|
||||
HWS_SF(blk, CLOCK_CONTROL, DCFE_CLOCK_ENABLE, mask_sh),\
|
||||
SF(DC_MEM_GLOBAL_PWR_REQ_CNTL, DC_MEM_GLOBAL_PWR_REQ_DIS, mask_sh)
|
||||
|
||||
#define HWSEQ_BLND_MASK_SH_LIST(mask_sh, blk)\
|
||||
HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(blk, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(blk, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(blk, V_UPDATE_LOCK, BLND_BLND_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(blk, V_UPDATE_LOCK, BLND_V_UPDATE_LOCK_MODE, mask_sh),\
|
||||
HWS_SF(blk, CONTROL, BLND_FEEDTHROUGH_EN, mask_sh),\
|
||||
HWS_SF(blk, CONTROL, BLND_ALPHA_MODE, mask_sh),\
|
||||
HWS_SF(blk, CONTROL, BLND_MODE, mask_sh),\
|
||||
HWS_SF(blk, CONTROL, BLND_MULTIPLIED_MODE, mask_sh)
|
||||
|
||||
#define HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, blk)\
|
||||
HWS_SF1(blk, PIXEL_RATE_CNTL, PIXEL_RATE_SOURCE, mask_sh),\
|
||||
HWS_SF(blk, PIXEL_RATE_CNTL, DP_DTO0_ENABLE, mask_sh)
|
||||
|
||||
#define HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, blk)\
|
||||
HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PHYPLL_PIXEL_RATE_SOURCE, mask_sh),\
|
||||
HWS_SF1(blk, PHYPLL_PIXEL_RATE_CNTL, PIXEL_RATE_PLL_SOURCE, mask_sh)
|
||||
|
||||
#define HWSEQ_DCE8_MASK_SH_LIST(mask_sh)\
|
||||
.DCFE_CLOCK_ENABLE = CRTC_DCFE_CLOCK_CONTROL__CRTC_DCFE_CLOCK_ENABLE ## mask_sh, \
|
||||
HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(BLND_, V_UPDATE_LOCK, BLND_SCL_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(BLND_, V_UPDATE_LOCK, BLND_DCP_GRPH_SURF_V_UPDATE_LOCK, mask_sh),\
|
||||
HWS_SF(BLND_, CONTROL, BLND_MODE, mask_sh),\
|
||||
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
|
||||
|
||||
#define HWSEQ_DCE10_MASK_SH_LIST(mask_sh)\
|
||||
HWSEQ_DCEF_MASK_SH_LIST(mask_sh, DCFE_),\
|
||||
HWSEQ_BLND_MASK_SH_LIST(mask_sh, BLND_),\
|
||||
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
|
||||
|
||||
#define HWSEQ_DCE11_MASK_SH_LIST(mask_sh)\
|
||||
HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
|
||||
SF(DCFEV_CLOCK_CONTROL, DCFEV_CLOCK_ENABLE, mask_sh),\
|
||||
HWSEQ_PIXEL_RATE_MASK_SH_LIST(mask_sh, CRTC0_)
|
||||
|
||||
#define HWSEQ_DCE112_MASK_SH_LIST(mask_sh)\
|
||||
HWSEQ_DCE10_MASK_SH_LIST(mask_sh),\
|
||||
HWSEQ_PHYPLL_MASK_SH_LIST(mask_sh, CRTC0_)
|
||||
|
||||
#define HWSEQ_REG_FIED_LIST(type) \
|
||||
type DCFE_CLOCK_ENABLE; \
|
||||
type DCFEV_CLOCK_ENABLE; \
|
||||
type DC_MEM_GLOBAL_PWR_REQ_DIS; \
|
||||
type BLND_DCP_GRPH_V_UPDATE_LOCK; \
|
||||
type BLND_SCL_V_UPDATE_LOCK; \
|
||||
type BLND_DCP_GRPH_SURF_V_UPDATE_LOCK; \
|
||||
type BLND_BLND_V_UPDATE_LOCK; \
|
||||
type BLND_V_UPDATE_LOCK_MODE; \
|
||||
type BLND_FEEDTHROUGH_EN; \
|
||||
type BLND_ALPHA_MODE; \
|
||||
type BLND_MODE; \
|
||||
type BLND_MULTIPLIED_MODE; \
|
||||
type DP_DTO0_ENABLE; \
|
||||
type PIXEL_RATE_SOURCE; \
|
||||
type PHYPLL_PIXEL_RATE_SOURCE; \
|
||||
type PIXEL_RATE_PLL_SOURCE; \
|
||||
|
||||
struct dce_hwseq_shift {
|
||||
HWSEQ_REG_FIED_LIST(uint8_t)
|
||||
};
|
||||
|
||||
struct dce_hwseq_mask {
|
||||
HWSEQ_REG_FIED_LIST(uint32_t)
|
||||
};
|
||||
|
||||
struct dce_hwseq_wa {
|
||||
bool blnd_crtc_trigger;
|
||||
};
|
||||
|
||||
struct dce_hwseq {
|
||||
struct dc_context *ctx;
|
||||
const struct dce_hwseq_registers *regs;
|
||||
const struct dce_hwseq_shift *shifts;
|
||||
const struct dce_hwseq_mask *masks;
|
||||
struct dce_hwseq_wa wa;
|
||||
};
|
||||
|
||||
enum blnd_mode {
|
||||
BLND_MODE_CURRENT_PIPE = 0,/* Data from current pipe only */
|
||||
BLND_MODE_OTHER_PIPE, /* Data from other pipe only */
|
||||
BLND_MODE_BLENDING,/* Alpha blending - blend 'current' and 'other' */
|
||||
};
|
||||
|
||||
void dce_enable_fe_clock(struct dce_hwseq *hwss,
|
||||
unsigned int inst, bool enable);
|
||||
|
||||
void dce_pipe_control_lock(struct dce_hwseq *hws,
|
||||
unsigned int blnd_inst,
|
||||
enum pipe_lock_control control_mask,
|
||||
bool lock);
|
||||
|
||||
void dce_set_blender_mode(struct dce_hwseq *hws,
|
||||
unsigned int blnd_inst, enum blnd_mode mode);
|
||||
|
||||
void dce_clock_gating_power_up(struct dce_hwseq *hws,
|
||||
bool enable);
|
||||
|
||||
void dce_crtc_switch_to_clk_src(struct dce_hwseq *hws,
|
||||
struct clock_source *clk_src,
|
||||
unsigned int tg_inst);
|
||||
#endif /*__DCE_HWSEQ_H__*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,363 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DC_LINK_ENCODER__DCE110_H__
|
||||
#define __DC_LINK_ENCODER__DCE110_H__
|
||||
|
||||
#include "link_encoder.h"
|
||||
|
||||
#define TO_DCE110_LINK_ENC(link_encoder)\
|
||||
container_of(link_encoder, struct dce110_link_encoder, base)
|
||||
|
||||
#define AUX_REG_LIST(id)\
|
||||
SRI(AUX_CONTROL, DP_AUX, id), \
|
||||
SRI(AUX_DPHY_RX_CONTROL0, DP_AUX, id)
|
||||
|
||||
#define HPD_REG_LIST(id)\
|
||||
SRI(DC_HPD_CONTROL, HPD, id)
|
||||
|
||||
#define LE_COMMON_REG_LIST_BASE(id) \
|
||||
SR(BL_PWM_CNTL), \
|
||||
SR(BL_PWM_GRP1_REG_LOCK), \
|
||||
SR(BL_PWM_PERIOD_CNTL), \
|
||||
SR(LVTMA_PWRSEQ_CNTL), \
|
||||
SR(LVTMA_PWRSEQ_STATE), \
|
||||
SR(BL_PWM_CNTL2), \
|
||||
SR(LVTMA_PWRSEQ_REF_DIV), \
|
||||
SR(MASTER_COMM_DATA_REG1), \
|
||||
SR(MASTER_COMM_DATA_REG2), \
|
||||
SR(MASTER_COMM_DATA_REG3), \
|
||||
SR(MASTER_COMM_CMD_REG), \
|
||||
SR(MASTER_COMM_CNTL_REG), \
|
||||
SR(DMCU_RAM_ACCESS_CTRL), \
|
||||
SR(DMCU_IRAM_RD_CTRL), \
|
||||
SR(DMCU_IRAM_RD_DATA), \
|
||||
SR(DMCU_INTERRUPT_TO_UC_EN_MASK), \
|
||||
SR(SMU_INTERRUPT_CONTROL), \
|
||||
SRI(DIG_BE_CNTL, DIG, id), \
|
||||
SRI(DIG_BE_EN_CNTL, DIG, id), \
|
||||
SRI(DP_CONFIG, DP, id), \
|
||||
SRI(DP_DPHY_CNTL, DP, id), \
|
||||
SRI(DP_DPHY_PRBS_CNTL, DP, id), \
|
||||
SRI(DP_DPHY_SCRAM_CNTL, DP, id),\
|
||||
SRI(DP_DPHY_SYM0, DP, id), \
|
||||
SRI(DP_DPHY_SYM1, DP, id), \
|
||||
SRI(DP_DPHY_SYM2, DP, id), \
|
||||
SRI(DP_DPHY_TRAINING_PATTERN_SEL, DP, id), \
|
||||
SRI(DP_LINK_CNTL, DP, id), \
|
||||
SRI(DP_LINK_FRAMING_CNTL, DP, id), \
|
||||
SRI(DP_MSE_SAT0, DP, id), \
|
||||
SRI(DP_MSE_SAT1, DP, id), \
|
||||
SRI(DP_MSE_SAT2, DP, id), \
|
||||
SRI(DP_MSE_SAT_UPDATE, DP, id), \
|
||||
SRI(DP_SEC_CNTL, DP, id), \
|
||||
SRI(DP_VID_STREAM_CNTL, DP, id), \
|
||||
SRI(DP_DPHY_FAST_TRAINING, DP, id), \
|
||||
SRI(DP_SEC_CNTL1, DP, id)
|
||||
|
||||
#define LE_COMMON_REG_LIST(id)\
|
||||
LE_COMMON_REG_LIST_BASE(id), \
|
||||
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
|
||||
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
|
||||
SR(BIOS_SCRATCH_2), \
|
||||
SR(BL1_PWM_USER_LEVEL), \
|
||||
SR(DCI_MEM_PWR_STATUS)
|
||||
|
||||
#define LE_DCE110_REG_LIST(id)\
|
||||
LE_COMMON_REG_LIST_BASE(id), \
|
||||
SRI(DP_DPHY_BS_SR_SWAP_CNTL, DP, id), \
|
||||
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
|
||||
SR(BIOS_SCRATCH_2), \
|
||||
SR(BL1_PWM_USER_LEVEL), \
|
||||
SR(DCI_MEM_PWR_STATUS)
|
||||
|
||||
#define LE_DCE80_REG_LIST(id)\
|
||||
SR(BIOS_SCRATCH_2), \
|
||||
SRI(DP_DPHY_INTERNAL_CTRL, DP, id), \
|
||||
SR(BL1_PWM_USER_LEVEL), \
|
||||
LE_COMMON_REG_LIST_BASE(id)
|
||||
|
||||
|
||||
struct dce110_link_enc_aux_registers {
|
||||
uint32_t AUX_CONTROL;
|
||||
uint32_t AUX_DPHY_RX_CONTROL0;
|
||||
};
|
||||
|
||||
struct dce110_link_enc_hpd_registers {
|
||||
uint32_t DC_HPD_CONTROL;
|
||||
};
|
||||
|
||||
struct dce110_link_enc_registers {
|
||||
/* BL registers */
|
||||
uint32_t BL_PWM_CNTL;
|
||||
uint32_t BL_PWM_GRP1_REG_LOCK;
|
||||
uint32_t BL_PWM_PERIOD_CNTL;
|
||||
uint32_t LVTMA_PWRSEQ_CNTL;
|
||||
uint32_t LVTMA_PWRSEQ_STATE;
|
||||
uint32_t BL_PWM_CNTL2;
|
||||
uint32_t LVTMA_PWRSEQ_REF_DIV;
|
||||
|
||||
/* DMCU registers */
|
||||
uint32_t BL1_PWM_USER_LEVEL;
|
||||
uint32_t ABM0_BL1_PWM_USER_LEVEL;
|
||||
uint32_t MASTER_COMM_DATA_REG1;
|
||||
uint32_t MASTER_COMM_DATA_REG2;
|
||||
uint32_t MASTER_COMM_DATA_REG3;
|
||||
uint32_t MASTER_COMM_CMD_REG;
|
||||
uint32_t MASTER_COMM_CNTL_REG;
|
||||
uint32_t BIOS_SCRATCH_2;
|
||||
uint32_t DMCU_RAM_ACCESS_CTRL;
|
||||
uint32_t DCI_MEM_PWR_STATUS;
|
||||
uint32_t DMU_MEM_PWR_CNTL;
|
||||
uint32_t DMCU_IRAM_RD_CTRL;
|
||||
uint32_t DMCU_IRAM_RD_DATA;
|
||||
uint32_t DMCU_INTERRUPT_TO_UC_EN_MASK;
|
||||
uint32_t SMU_INTERRUPT_CONTROL;
|
||||
|
||||
|
||||
/* Common DP registers */
|
||||
uint32_t DIG_BE_CNTL;
|
||||
uint32_t DIG_BE_EN_CNTL;
|
||||
uint32_t DP_CONFIG;
|
||||
uint32_t DP_DPHY_CNTL;
|
||||
uint32_t DP_DPHY_INTERNAL_CTRL;
|
||||
uint32_t DP_DPHY_PRBS_CNTL;
|
||||
uint32_t DP_DPHY_SCRAM_CNTL;
|
||||
uint32_t DP_DPHY_SYM0;
|
||||
uint32_t DP_DPHY_SYM1;
|
||||
uint32_t DP_DPHY_SYM2;
|
||||
uint32_t DP_DPHY_TRAINING_PATTERN_SEL;
|
||||
uint32_t DP_LINK_CNTL;
|
||||
uint32_t DP_LINK_FRAMING_CNTL;
|
||||
uint32_t DP_MSE_SAT0;
|
||||
uint32_t DP_MSE_SAT1;
|
||||
uint32_t DP_MSE_SAT2;
|
||||
uint32_t DP_MSE_SAT_UPDATE;
|
||||
uint32_t DP_SEC_CNTL;
|
||||
uint32_t DP_VID_STREAM_CNTL;
|
||||
uint32_t DP_DPHY_FAST_TRAINING;
|
||||
uint32_t DP_DPHY_BS_SR_SWAP_CNTL;
|
||||
uint32_t DP_SEC_CNTL1;
|
||||
};
|
||||
|
||||
struct dce110_link_encoder {
|
||||
struct link_encoder base;
|
||||
const struct dce110_link_enc_registers *link_regs;
|
||||
const struct dce110_link_enc_aux_registers *aux_regs;
|
||||
const struct dce110_link_enc_hpd_registers *hpd_regs;
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
* MASTER_COMM_DATA_REG1 Bit position Data
|
||||
* 7:0 hyst_frames[7:0]
|
||||
* 14:8 hyst_lines[6:0]
|
||||
* 15 RFB_UPDATE_AUTO_EN
|
||||
* 18:16 phy_num[2:0]
|
||||
* 21:19 dcp_sel[2:0]
|
||||
* 22 phy_type
|
||||
* 23 frame_cap_ind
|
||||
* 26:24 aux_chan[2:0]
|
||||
* 30:27 aux_repeat[3:0]
|
||||
* 31:31 reserved[31:31]
|
||||
*******************************************************************/
|
||||
union dce110_dmcu_psr_config_data_reg1 {
|
||||
struct {
|
||||
unsigned int timehyst_frames:8; /*[7:0]*/
|
||||
unsigned int hyst_lines:7; /*[14:8]*/
|
||||
unsigned int rfb_update_auto_en:1; /*[15:15]*/
|
||||
unsigned int dp_port_num:3; /*[18:16]*/
|
||||
unsigned int dcp_sel:3; /*[21:19]*/
|
||||
unsigned int phy_type:1; /*[22:22]*/
|
||||
unsigned int frame_cap_ind:1; /*[23:23]*/
|
||||
unsigned int aux_chan:3; /*[26:24]*/
|
||||
unsigned int aux_repeat:4; /*[30:27]*/
|
||||
unsigned int reserved:1; /*[31:31]*/
|
||||
} bits;
|
||||
unsigned int u32All;
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
* MASTER_COMM_DATA_REG2
|
||||
*******************************************************************/
|
||||
union dce110_dmcu_psr_config_data_reg2 {
|
||||
struct {
|
||||
unsigned int dig_fe:3; /*[2:0]*/
|
||||
unsigned int dig_be:3; /*[5:3]*/
|
||||
unsigned int skip_wait_for_pll_lock:1; /*[6:6]*/
|
||||
unsigned int reserved:9; /*[15:7]*/
|
||||
unsigned int frame_delay:8; /*[23:16]*/
|
||||
unsigned int smu_phy_id:4; /*[27:24]*/
|
||||
unsigned int num_of_controllers:4; /*[31:28]*/
|
||||
} bits;
|
||||
unsigned int u32All;
|
||||
};
|
||||
|
||||
/*******************************************************************
|
||||
* MASTER_COMM_DATA_REG3
|
||||
*******************************************************************/
|
||||
union dce110_dmcu_psr_config_data_reg3 {
|
||||
struct {
|
||||
unsigned int psr_level:16; /*[15:0]*/
|
||||
unsigned int link_rate:4; /*[19:16]*/
|
||||
unsigned int reserved:12; /*[31:20]*/
|
||||
} bits;
|
||||
unsigned int u32All;
|
||||
};
|
||||
|
||||
struct dce110_abm_backlight_registers {
|
||||
unsigned int vBL_PWM_CNTL;
|
||||
unsigned int vBL_PWM_CNTL2;
|
||||
unsigned int vBL_PWM_PERIOD_CNTL;
|
||||
unsigned int vLVTMA_PWRSEQ_REF_DIV_BL_PWM_REF_DIV;
|
||||
};
|
||||
|
||||
bool dce110_link_encoder_construct(
|
||||
struct dce110_link_encoder *enc110,
|
||||
const struct encoder_init_data *init_data,
|
||||
const struct dce110_link_enc_registers *link_regs,
|
||||
const struct dce110_link_enc_aux_registers *aux_regs,
|
||||
const struct dce110_link_enc_hpd_registers *hpd_regs);
|
||||
|
||||
bool dce110_link_encoder_validate_dvi_output(
|
||||
const struct dce110_link_encoder *enc110,
|
||||
enum signal_type connector_signal,
|
||||
enum signal_type signal,
|
||||
const struct dc_crtc_timing *crtc_timing);
|
||||
|
||||
bool dce110_link_encoder_validate_rgb_output(
|
||||
const struct dce110_link_encoder *enc110,
|
||||
const struct dc_crtc_timing *crtc_timing);
|
||||
|
||||
bool dce110_link_encoder_validate_dp_output(
|
||||
const struct dce110_link_encoder *enc110,
|
||||
const struct dc_crtc_timing *crtc_timing);
|
||||
|
||||
bool dce110_link_encoder_validate_wireless_output(
|
||||
const struct dce110_link_encoder *enc110,
|
||||
const struct dc_crtc_timing *crtc_timing);
|
||||
|
||||
bool dce110_link_encoder_validate_output_with_stream(
|
||||
struct link_encoder *enc,
|
||||
struct pipe_ctx *pipe_ctx);
|
||||
|
||||
/****************** HW programming ************************/
|
||||
|
||||
/* initialize HW */ /* why do we initialze aux in here? */
|
||||
void dce110_link_encoder_hw_init(struct link_encoder *enc);
|
||||
|
||||
void dce110_link_encoder_destroy(struct link_encoder **enc);
|
||||
|
||||
/* program DIG_MODE in DIG_BE */
|
||||
/* TODO can this be combined with enable_output? */
|
||||
void dce110_link_encoder_setup(
|
||||
struct link_encoder *enc,
|
||||
enum signal_type signal);
|
||||
|
||||
/* enables TMDS PHY output */
|
||||
/* TODO: still need depth or just pass in adjusted pixel clock? */
|
||||
void dce110_link_encoder_enable_tmds_output(
|
||||
struct link_encoder *enc,
|
||||
enum clock_source_id clock_source,
|
||||
enum dc_color_depth color_depth,
|
||||
bool hdmi,
|
||||
bool dual_link,
|
||||
uint32_t pixel_clock);
|
||||
|
||||
/* enables DP PHY output */
|
||||
void dce110_link_encoder_enable_dp_output(
|
||||
struct link_encoder *enc,
|
||||
const struct dc_link_settings *link_settings,
|
||||
enum clock_source_id clock_source);
|
||||
|
||||
/* enables DP PHY output in MST mode */
|
||||
void dce110_link_encoder_enable_dp_mst_output(
|
||||
struct link_encoder *enc,
|
||||
const struct dc_link_settings *link_settings,
|
||||
enum clock_source_id clock_source);
|
||||
|
||||
/* disable PHY output */
|
||||
void dce110_link_encoder_disable_output(
|
||||
struct link_encoder *link_enc,
|
||||
enum signal_type signal);
|
||||
|
||||
/* set DP lane settings */
|
||||
void dce110_link_encoder_dp_set_lane_settings(
|
||||
struct link_encoder *enc,
|
||||
const struct link_training_settings *link_settings);
|
||||
|
||||
void dce110_link_encoder_dp_set_phy_pattern(
|
||||
struct link_encoder *enc,
|
||||
const struct encoder_set_dp_phy_pattern_param *param);
|
||||
|
||||
/* programs DP MST VC payload allocation */
|
||||
void dce110_link_encoder_update_mst_stream_allocation_table(
|
||||
struct link_encoder *enc,
|
||||
const struct link_mst_stream_allocation_table *table);
|
||||
|
||||
void dce110_link_encoder_set_lcd_backlight_level(
|
||||
struct link_encoder *enc,
|
||||
uint32_t level);
|
||||
|
||||
void dce110_link_encoder_set_dmcu_backlight_level(
|
||||
struct link_encoder *enc,
|
||||
uint32_t level,
|
||||
uint32_t frame_ramp,
|
||||
uint32_t controller_id);
|
||||
|
||||
void dce110_link_encoder_init_dmcu_backlight_settings(
|
||||
struct link_encoder *enc);
|
||||
|
||||
void dce110_link_encoder_set_dmcu_abm_level(
|
||||
struct link_encoder *enc,
|
||||
uint32_t level);
|
||||
|
||||
void dce110_link_encoder_set_dmcu_psr_enable(
|
||||
struct link_encoder *enc, bool enable);
|
||||
|
||||
void dce110_link_encoder_setup_dmcu_psr(struct link_encoder *enc,
|
||||
struct psr_dmcu_context *psr_context);
|
||||
|
||||
void dce110_link_encoder_edp_backlight_control(
|
||||
struct link_encoder *enc,
|
||||
bool enable);
|
||||
|
||||
void dce110_link_encoder_edp_power_control(
|
||||
struct link_encoder *enc,
|
||||
bool power_up);
|
||||
|
||||
void dce110_link_encoder_connect_dig_be_to_fe(
|
||||
struct link_encoder *enc,
|
||||
enum engine_id engine,
|
||||
bool connect);
|
||||
|
||||
void dce110_link_encoder_set_dp_phy_pattern_training_pattern(
|
||||
struct link_encoder *enc,
|
||||
uint32_t index);
|
||||
|
||||
void dce110_link_encoder_enable_hpd(struct link_encoder *enc);
|
||||
|
||||
void dce110_link_encoder_disable_hpd(struct link_encoder *enc);
|
||||
|
||||
#endif /* __DC_LINK_ENCODER__DCE110_H__ */
|
|
@ -0,0 +1,384 @@
|
|||
/*
|
||||
* Copyright 2016 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 "mem_input.h"
|
||||
#include "reg_helper.h"
|
||||
|
||||
#define CTX \
|
||||
mi->ctx
|
||||
#define REG(reg)\
|
||||
mi->regs->reg
|
||||
|
||||
#undef FN
|
||||
#define FN(reg_name, field_name) \
|
||||
mi->shifts->field_name, mi->masks->field_name
|
||||
|
||||
|
||||
static void program_urgency_watermark(struct mem_input *mi,
|
||||
uint32_t wm_select,
|
||||
uint32_t urgency_low_wm,
|
||||
uint32_t urgency_high_wm)
|
||||
{
|
||||
REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
|
||||
URGENCY_WATERMARK_MASK, wm_select);
|
||||
|
||||
REG_SET_2(DPG_PIPE_URGENCY_CONTROL, 0,
|
||||
URGENCY_LOW_WATERMARK, urgency_low_wm,
|
||||
URGENCY_HIGH_WATERMARK, urgency_high_wm);
|
||||
}
|
||||
|
||||
static void program_nbp_watermark(struct mem_input *mi,
|
||||
uint32_t wm_select,
|
||||
uint32_t nbp_wm)
|
||||
{
|
||||
if (REG(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL)) {
|
||||
REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
|
||||
NB_PSTATE_CHANGE_WATERMARK_MASK, wm_select);
|
||||
|
||||
REG_UPDATE_3(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
|
||||
NB_PSTATE_CHANGE_ENABLE, 1,
|
||||
NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, 1,
|
||||
NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, 1);
|
||||
|
||||
REG_UPDATE(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL,
|
||||
NB_PSTATE_CHANGE_WATERMARK, nbp_wm);
|
||||
}
|
||||
}
|
||||
|
||||
static void program_stutter_watermark(struct mem_input *mi,
|
||||
uint32_t wm_select,
|
||||
uint32_t stutter_mark)
|
||||
{
|
||||
REG_UPDATE(DPG_WATERMARK_MASK_CONTROL,
|
||||
STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, wm_select);
|
||||
|
||||
REG_UPDATE(DPG_PIPE_STUTTER_CONTROL,
|
||||
STUTTER_EXIT_SELF_REFRESH_WATERMARK, stutter_mark);
|
||||
}
|
||||
|
||||
void dce_mem_input_program_display_marks(struct mem_input *mi,
|
||||
struct bw_watermarks nbp,
|
||||
struct bw_watermarks stutter,
|
||||
struct bw_watermarks urgent,
|
||||
uint32_t total_dest_line_time_ns)
|
||||
{
|
||||
uint32_t stutter_en = mi->ctx->dc->debug.disable_stutter ? 0 : 1;
|
||||
|
||||
program_urgency_watermark(mi, 0, /* set a */
|
||||
urgent.a_mark, total_dest_line_time_ns);
|
||||
program_urgency_watermark(mi, 1, /* set b */
|
||||
urgent.b_mark, total_dest_line_time_ns);
|
||||
program_urgency_watermark(mi, 2, /* set c */
|
||||
urgent.c_mark, total_dest_line_time_ns);
|
||||
program_urgency_watermark(mi, 3, /* set d */
|
||||
urgent.d_mark, total_dest_line_time_ns);
|
||||
|
||||
REG_UPDATE_2(DPG_PIPE_STUTTER_CONTROL,
|
||||
STUTTER_ENABLE, stutter_en,
|
||||
STUTTER_IGNORE_FBC, 1);
|
||||
program_nbp_watermark(mi, 0, nbp.a_mark); /* set a */
|
||||
program_nbp_watermark(mi, 1, nbp.b_mark); /* set b */
|
||||
program_nbp_watermark(mi, 2, nbp.c_mark); /* set c */
|
||||
program_nbp_watermark(mi, 3, nbp.d_mark); /* set d */
|
||||
|
||||
program_stutter_watermark(mi, 0, stutter.a_mark); /* set a */
|
||||
program_stutter_watermark(mi, 1, stutter.b_mark); /* set b */
|
||||
program_stutter_watermark(mi, 2, stutter.c_mark); /* set c */
|
||||
program_stutter_watermark(mi, 3, stutter.d_mark); /* set d */
|
||||
}
|
||||
|
||||
static void program_tiling(struct mem_input *mi,
|
||||
const union dc_tiling_info *info)
|
||||
{
|
||||
if (mi->masks->GRPH_ARRAY_MODE) { /* GFX8 */
|
||||
REG_UPDATE_9(GRPH_CONTROL,
|
||||
GRPH_NUM_BANKS, info->gfx8.num_banks,
|
||||
GRPH_BANK_WIDTH, info->gfx8.bank_width,
|
||||
GRPH_BANK_HEIGHT, info->gfx8.bank_height,
|
||||
GRPH_MACRO_TILE_ASPECT, info->gfx8.tile_aspect,
|
||||
GRPH_TILE_SPLIT, info->gfx8.tile_split,
|
||||
GRPH_MICRO_TILE_MODE, info->gfx8.tile_mode,
|
||||
GRPH_PIPE_CONFIG, info->gfx8.pipe_config,
|
||||
GRPH_ARRAY_MODE, info->gfx8.array_mode,
|
||||
GRPH_COLOR_EXPANSION_MODE, 1);
|
||||
/* 01 - DCP_GRPH_COLOR_EXPANSION_MODE_ZEXP: zero expansion for YCbCr */
|
||||
/*
|
||||
GRPH_Z, 0);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void program_size_and_rotation(
|
||||
struct mem_input *mi,
|
||||
enum dc_rotation_angle rotation,
|
||||
const union plane_size *plane_size)
|
||||
{
|
||||
const struct rect *in_rect = &plane_size->grph.surface_size;
|
||||
struct rect hw_rect = plane_size->grph.surface_size;
|
||||
const uint32_t rotation_angles[ROTATION_ANGLE_COUNT] = {
|
||||
[ROTATION_ANGLE_0] = 0,
|
||||
[ROTATION_ANGLE_90] = 1,
|
||||
[ROTATION_ANGLE_180] = 2,
|
||||
[ROTATION_ANGLE_270] = 3,
|
||||
};
|
||||
|
||||
if (rotation == ROTATION_ANGLE_90 || rotation == ROTATION_ANGLE_270) {
|
||||
hw_rect.x = in_rect->y;
|
||||
hw_rect.y = in_rect->x;
|
||||
|
||||
hw_rect.height = in_rect->width;
|
||||
hw_rect.width = in_rect->height;
|
||||
}
|
||||
|
||||
REG_SET(GRPH_X_START, 0,
|
||||
GRPH_X_START, hw_rect.x);
|
||||
|
||||
REG_SET(GRPH_Y_START, 0,
|
||||
GRPH_Y_START, hw_rect.y);
|
||||
|
||||
REG_SET(GRPH_X_END, 0,
|
||||
GRPH_X_END, hw_rect.width);
|
||||
|
||||
REG_SET(GRPH_Y_END, 0,
|
||||
GRPH_Y_END, hw_rect.height);
|
||||
|
||||
REG_SET(GRPH_PITCH, 0,
|
||||
GRPH_PITCH, plane_size->grph.surface_pitch);
|
||||
|
||||
REG_SET(HW_ROTATION, 0,
|
||||
GRPH_ROTATION_ANGLE, rotation_angles[rotation]);
|
||||
}
|
||||
|
||||
static void program_grph_pixel_format(
|
||||
struct mem_input *mi,
|
||||
enum surface_pixel_format format)
|
||||
{
|
||||
uint32_t red_xbar = 0, blue_xbar = 0; /* no swap */
|
||||
uint32_t grph_depth, grph_format;
|
||||
uint32_t sign = 0, floating = 0;
|
||||
|
||||
if (format == SURFACE_PIXEL_FORMAT_GRPH_BGRA8888 ||
|
||||
/*todo: doesn't look like we handle BGRA here,
|
||||
* should problem swap endian*/
|
||||
format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010 ||
|
||||
format == SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS ||
|
||||
format == SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F) {
|
||||
/* ABGR formats */
|
||||
red_xbar = 2;
|
||||
blue_xbar = 2;
|
||||
}
|
||||
|
||||
REG_SET_2(GRPH_SWAP_CNTL, 0,
|
||||
GRPH_RED_CROSSBAR, red_xbar,
|
||||
GRPH_BLUE_CROSSBAR, blue_xbar);
|
||||
|
||||
switch (format) {
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_PALETA_256_COLORS:
|
||||
grph_depth = 0;
|
||||
grph_format = 0;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB1555:
|
||||
grph_depth = 1;
|
||||
grph_format = 0;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_RGB565:
|
||||
grph_depth = 1;
|
||||
grph_format = 1;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB8888:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_BGRA8888:
|
||||
grph_depth = 2;
|
||||
grph_format = 0;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB2101010:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010:
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR2101010_XR_BIAS:
|
||||
grph_depth = 2;
|
||||
grph_format = 1;
|
||||
break;
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ABGR16161616F:
|
||||
sign = 1;
|
||||
floating = 1;
|
||||
/* no break */
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616F: /* shouldn't this get float too? */
|
||||
case SURFACE_PIXEL_FORMAT_GRPH_ARGB16161616:
|
||||
grph_depth = 3;
|
||||
grph_format = 0;
|
||||
break;
|
||||
default:
|
||||
DC_ERR("unsupported grph pixel format");
|
||||
break;
|
||||
}
|
||||
|
||||
REG_UPDATE_2(GRPH_CONTROL,
|
||||
GRPH_DEPTH, grph_depth,
|
||||
GRPH_FORMAT, grph_format);
|
||||
|
||||
REG_UPDATE_4(PRESCALE_GRPH_CONTROL,
|
||||
GRPH_PRESCALE_SELECT, floating,
|
||||
GRPH_PRESCALE_R_SIGN, sign,
|
||||
GRPH_PRESCALE_G_SIGN, sign,
|
||||
GRPH_PRESCALE_B_SIGN, sign);
|
||||
}
|
||||
|
||||
bool dce_mem_input_program_surface_config(struct mem_input *mi,
|
||||
enum surface_pixel_format format,
|
||||
union dc_tiling_info *tiling_info,
|
||||
union plane_size *plane_size,
|
||||
enum dc_rotation_angle rotation,
|
||||
struct dc_plane_dcc_param *dcc,
|
||||
bool horizontal_mirror)
|
||||
{
|
||||
REG_UPDATE(GRPH_ENABLE, GRPH_ENABLE, 1);
|
||||
|
||||
program_tiling(mi, tiling_info);
|
||||
program_size_and_rotation(mi, rotation, plane_size);
|
||||
|
||||
if (format >= SURFACE_PIXEL_FORMAT_GRPH_BEGIN &&
|
||||
format < SURFACE_PIXEL_FORMAT_VIDEO_BEGIN)
|
||||
program_grph_pixel_format(mi, format);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static uint32_t get_dmif_switch_time_us(
|
||||
uint32_t h_total,
|
||||
uint32_t v_total,
|
||||
uint32_t pix_clk_khz)
|
||||
{
|
||||
uint32_t frame_time;
|
||||
uint32_t pixels_per_second;
|
||||
uint32_t pixels_per_frame;
|
||||
uint32_t refresh_rate;
|
||||
const uint32_t us_in_sec = 1000000;
|
||||
const uint32_t min_single_frame_time_us = 30000;
|
||||
/*return double of frame time*/
|
||||
const uint32_t single_frame_time_multiplier = 2;
|
||||
|
||||
if (!h_total || v_total || !pix_clk_khz)
|
||||
return single_frame_time_multiplier * min_single_frame_time_us;
|
||||
|
||||
/*TODO: should we use pixel format normalized pixel clock here?*/
|
||||
pixels_per_second = pix_clk_khz * 1000;
|
||||
pixels_per_frame = h_total * v_total;
|
||||
|
||||
if (!pixels_per_second || !pixels_per_frame) {
|
||||
/* avoid division by zero */
|
||||
ASSERT(pixels_per_frame);
|
||||
ASSERT(pixels_per_second);
|
||||
return single_frame_time_multiplier * min_single_frame_time_us;
|
||||
}
|
||||
|
||||
refresh_rate = pixels_per_second / pixels_per_frame;
|
||||
|
||||
if (!refresh_rate) {
|
||||
/* avoid division by zero*/
|
||||
ASSERT(refresh_rate);
|
||||
return single_frame_time_multiplier * min_single_frame_time_us;
|
||||
}
|
||||
|
||||
frame_time = us_in_sec / refresh_rate;
|
||||
|
||||
if (frame_time < min_single_frame_time_us)
|
||||
frame_time = min_single_frame_time_us;
|
||||
|
||||
frame_time *= single_frame_time_multiplier;
|
||||
|
||||
return frame_time;
|
||||
}
|
||||
|
||||
void dce_mem_input_allocate_dmif(struct mem_input *mi,
|
||||
uint32_t h_total,
|
||||
uint32_t v_total,
|
||||
uint32_t pix_clk_khz,
|
||||
uint32_t total_stream_num)
|
||||
{
|
||||
const uint32_t retry_delay = 10;
|
||||
uint32_t retry_count = get_dmif_switch_time_us(
|
||||
h_total,
|
||||
v_total,
|
||||
pix_clk_khz) / retry_delay;
|
||||
|
||||
uint32_t pix_dur;
|
||||
uint32_t buffers_allocated;
|
||||
uint32_t dmif_buffer_control;
|
||||
|
||||
dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
|
||||
DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
|
||||
|
||||
if (buffers_allocated == 2)
|
||||
return;
|
||||
|
||||
REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
|
||||
DMIF_BUFFERS_ALLOCATED, 2);
|
||||
|
||||
REG_WAIT(DMIF_BUFFER_CONTROL,
|
||||
DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
|
||||
retry_delay, retry_count);
|
||||
|
||||
if (pix_clk_khz != 0) {
|
||||
pix_dur = 1000000000ULL / pix_clk_khz;
|
||||
|
||||
REG_UPDATE(DPG_PIPE_ARBITRATION_CONTROL1,
|
||||
PIXEL_DURATION, pix_dur);
|
||||
}
|
||||
|
||||
if (mi->wa.single_head_rdreq_dmif_limit) {
|
||||
uint32_t eanble = (total_stream_num > 1) ? 0 :
|
||||
mi->wa.single_head_rdreq_dmif_limit;
|
||||
|
||||
REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
|
||||
ENABLE, eanble);
|
||||
}
|
||||
}
|
||||
|
||||
void dce_mem_input_free_dmif(struct mem_input *mi,
|
||||
uint32_t total_stream_num)
|
||||
{
|
||||
uint32_t buffers_allocated;
|
||||
uint32_t dmif_buffer_control;
|
||||
|
||||
dmif_buffer_control = REG_GET(DMIF_BUFFER_CONTROL,
|
||||
DMIF_BUFFERS_ALLOCATED, &buffers_allocated);
|
||||
|
||||
if (buffers_allocated == 0)
|
||||
return;
|
||||
|
||||
REG_SET(DMIF_BUFFER_CONTROL, dmif_buffer_control,
|
||||
DMIF_BUFFERS_ALLOCATED, 0);
|
||||
|
||||
REG_WAIT(DMIF_BUFFER_CONTROL,
|
||||
DMIF_BUFFERS_ALLOCATION_COMPLETED, 1,
|
||||
10, 0xBB8);
|
||||
|
||||
if (mi->wa.single_head_rdreq_dmif_limit) {
|
||||
uint32_t eanble = (total_stream_num > 1) ? 0 :
|
||||
mi->wa.single_head_rdreq_dmif_limit;
|
||||
|
||||
REG_UPDATE(MC_HUB_RDREQ_DMIF_LIMIT,
|
||||
ENABLE, eanble);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,217 @@
|
|||
/*
|
||||
* Copyright 2016 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 __DCE_MEM_INPUT_H__
|
||||
#define __DCE_MEM_INPUT_H__
|
||||
|
||||
#define MI_DCE_BASE_REG_LIST(id)\
|
||||
SRI(GRPH_ENABLE, DCP, id),\
|
||||
SRI(GRPH_CONTROL, DCP, id),\
|
||||
SRI(GRPH_X_START, DCP, id),\
|
||||
SRI(GRPH_Y_START, DCP, id),\
|
||||
SRI(GRPH_X_END, DCP, id),\
|
||||
SRI(GRPH_Y_END, DCP, id),\
|
||||
SRI(GRPH_PITCH, DCP, id),\
|
||||
SRI(HW_ROTATION, DCP, id),\
|
||||
SRI(GRPH_SWAP_CNTL, DCP, id),\
|
||||
SRI(PRESCALE_GRPH_CONTROL, DCP, id),\
|
||||
SRI(DPG_PIPE_ARBITRATION_CONTROL1, DMIF_PG, id),\
|
||||
SRI(DPG_WATERMARK_MASK_CONTROL, DMIF_PG, id),\
|
||||
SRI(DPG_PIPE_URGENCY_CONTROL, DMIF_PG, id),\
|
||||
SRI(DPG_PIPE_STUTTER_CONTROL, DMIF_PG, id),\
|
||||
SRI(DMIF_BUFFER_CONTROL, PIPE, id)
|
||||
|
||||
#define MI_REG_LIST(id)\
|
||||
MI_DCE_BASE_REG_LIST(id),\
|
||||
SRI(DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, DMIF_PG, id)
|
||||
|
||||
struct dce_mem_input_registers {
|
||||
/* DCP */
|
||||
uint32_t GRPH_ENABLE;
|
||||
uint32_t GRPH_CONTROL;
|
||||
uint32_t GRPH_X_START;
|
||||
uint32_t GRPH_Y_START;
|
||||
uint32_t GRPH_X_END;
|
||||
uint32_t GRPH_Y_END;
|
||||
uint32_t GRPH_PITCH;
|
||||
uint32_t HW_ROTATION;
|
||||
uint32_t GRPH_SWAP_CNTL;
|
||||
uint32_t PRESCALE_GRPH_CONTROL;
|
||||
/* DMIF_PG */
|
||||
uint32_t DPG_PIPE_ARBITRATION_CONTROL1;
|
||||
uint32_t DPG_WATERMARK_MASK_CONTROL;
|
||||
uint32_t DPG_PIPE_URGENCY_CONTROL;
|
||||
uint32_t DPG_PIPE_NB_PSTATE_CHANGE_CONTROL;
|
||||
uint32_t DPG_PIPE_LOW_POWER_CONTROL;
|
||||
uint32_t DPG_PIPE_STUTTER_CONTROL;
|
||||
uint32_t DPG_PIPE_STUTTER_CONTROL2;
|
||||
/* DCI */
|
||||
uint32_t DMIF_BUFFER_CONTROL;
|
||||
/* MC_HUB */
|
||||
uint32_t MC_HUB_RDREQ_DMIF_LIMIT;
|
||||
};
|
||||
|
||||
/* Set_Filed_for_Block */
|
||||
#define SFB(blk_name, reg_name, field_name, post_fix)\
|
||||
.field_name = blk_name ## reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
#define MI_GFX8_TILE_MASK_SH_LIST(mask_sh, blk)\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_BANK_HEIGHT, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_MACRO_TILE_ASPECT, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_TILE_SPLIT, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_MICRO_TILE_MODE, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_PIPE_CONFIG, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_ARRAY_MODE, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_COLOR_EXPANSION_MODE, mask_sh)
|
||||
|
||||
#define MI_DCP_MASK_SH_LIST(mask_sh, blk)\
|
||||
SFB(blk, GRPH_ENABLE, GRPH_ENABLE, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_DEPTH, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_FORMAT, mask_sh),\
|
||||
SFB(blk, GRPH_CONTROL, GRPH_NUM_BANKS, mask_sh),\
|
||||
SFB(blk, GRPH_X_START, GRPH_X_START, mask_sh),\
|
||||
SFB(blk, GRPH_Y_START, GRPH_Y_START, mask_sh),\
|
||||
SFB(blk, GRPH_X_END, GRPH_X_END, mask_sh),\
|
||||
SFB(blk, GRPH_Y_END, GRPH_Y_END, mask_sh),\
|
||||
SFB(blk, GRPH_PITCH, GRPH_PITCH, mask_sh),\
|
||||
SFB(blk, HW_ROTATION, GRPH_ROTATION_ANGLE, mask_sh),\
|
||||
SFB(blk, GRPH_SWAP_CNTL, GRPH_RED_CROSSBAR, mask_sh),\
|
||||
SFB(blk, GRPH_SWAP_CNTL, GRPH_BLUE_CROSSBAR, mask_sh),\
|
||||
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_SELECT, mask_sh),\
|
||||
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_R_SIGN, mask_sh),\
|
||||
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_G_SIGN, mask_sh),\
|
||||
SFB(blk, PRESCALE_GRPH_CONTROL, GRPH_PRESCALE_B_SIGN, mask_sh)
|
||||
|
||||
#define MI_DMIF_PG_MASK_SH_LIST(mask_sh, blk)\
|
||||
SFB(blk, DPG_PIPE_ARBITRATION_CONTROL1, PIXEL_DURATION, mask_sh),\
|
||||
SFB(blk, DPG_WATERMARK_MASK_CONTROL, URGENCY_WATERMARK_MASK, mask_sh),\
|
||||
SFB(blk, DPG_WATERMARK_MASK_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_LOW_WATERMARK, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_URGENCY_CONTROL, URGENCY_HIGH_WATERMARK, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_ENABLE, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_IGNORE_FBC, mask_sh),\
|
||||
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATED, mask_sh),\
|
||||
SF(PIPE0_DMIF_BUFFER_CONTROL, DMIF_BUFFERS_ALLOCATION_COMPLETED, mask_sh)
|
||||
|
||||
#define MI_DMIF_PG_MASK_SH_DCE(mask_sh, blk)\
|
||||
SFB(blk, DPG_PIPE_STUTTER_CONTROL, STUTTER_EXIT_SELF_REFRESH_WATERMARK, mask_sh),\
|
||||
SFB(blk, DPG_WATERMARK_MASK_CONTROL, NB_PSTATE_CHANGE_WATERMARK_MASK, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_ENABLE, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_URGENT_DURING_REQUEST, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST, mask_sh),\
|
||||
SFB(blk, DPG_PIPE_NB_PSTATE_CHANGE_CONTROL, NB_PSTATE_CHANGE_WATERMARK, mask_sh)
|
||||
|
||||
#define MI_DCE_MASK_SH_LIST(mask_sh)\
|
||||
MI_DCP_MASK_SH_LIST(mask_sh,),\
|
||||
MI_DMIF_PG_MASK_SH_LIST(mask_sh,),\
|
||||
MI_DMIF_PG_MASK_SH_DCE(mask_sh,),\
|
||||
MI_GFX8_TILE_MASK_SH_LIST(mask_sh,)
|
||||
|
||||
#define MI_REG_FIELD_LIST(type) \
|
||||
type GRPH_ENABLE; \
|
||||
type GRPH_X_START; \
|
||||
type GRPH_Y_START; \
|
||||
type GRPH_X_END; \
|
||||
type GRPH_Y_END; \
|
||||
type GRPH_PITCH; \
|
||||
type GRPH_ROTATION_ANGLE; \
|
||||
type GRPH_RED_CROSSBAR; \
|
||||
type GRPH_BLUE_CROSSBAR; \
|
||||
type GRPH_PRESCALE_SELECT; \
|
||||
type GRPH_PRESCALE_R_SIGN; \
|
||||
type GRPH_PRESCALE_G_SIGN; \
|
||||
type GRPH_PRESCALE_B_SIGN; \
|
||||
type GRPH_DEPTH; \
|
||||
type GRPH_FORMAT; \
|
||||
type GRPH_NUM_BANKS; \
|
||||
type GRPH_BANK_WIDTH;\
|
||||
type GRPH_BANK_HEIGHT;\
|
||||
type GRPH_MACRO_TILE_ASPECT;\
|
||||
type GRPH_TILE_SPLIT;\
|
||||
type GRPH_MICRO_TILE_MODE;\
|
||||
type GRPH_PIPE_CONFIG;\
|
||||
type GRPH_ARRAY_MODE;\
|
||||
type GRPH_COLOR_EXPANSION_MODE;\
|
||||
type GRPH_SW_MODE; \
|
||||
type GRPH_NUM_SHADER_ENGINES; \
|
||||
type GRPH_NUM_PIPES; \
|
||||
type PIXEL_DURATION; \
|
||||
type URGENCY_WATERMARK_MASK; \
|
||||
type PSTATE_CHANGE_WATERMARK_MASK; \
|
||||
type NB_PSTATE_CHANGE_WATERMARK_MASK; \
|
||||
type STUTTER_EXIT_SELF_REFRESH_WATERMARK_MASK; \
|
||||
type URGENCY_LOW_WATERMARK; \
|
||||
type URGENCY_HIGH_WATERMARK; \
|
||||
type NB_PSTATE_CHANGE_ENABLE; \
|
||||
type NB_PSTATE_CHANGE_URGENT_DURING_REQUEST; \
|
||||
type NB_PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
|
||||
type NB_PSTATE_CHANGE_WATERMARK; \
|
||||
type PSTATE_CHANGE_ENABLE; \
|
||||
type PSTATE_CHANGE_URGENT_DURING_REQUEST; \
|
||||
type PSTATE_CHANGE_NOT_SELF_REFRESH_DURING_REQUEST; \
|
||||
type PSTATE_CHANGE_WATERMARK; \
|
||||
type STUTTER_ENABLE; \
|
||||
type STUTTER_IGNORE_FBC; \
|
||||
type STUTTER_EXIT_SELF_REFRESH_WATERMARK; \
|
||||
type DMIF_BUFFERS_ALLOCATED; \
|
||||
type DMIF_BUFFERS_ALLOCATION_COMPLETED; \
|
||||
type ENABLE; /* MC_HUB_RDREQ_DMIF_LIMIT */\
|
||||
|
||||
struct dce_mem_input_shift {
|
||||
MI_REG_FIELD_LIST(uint8_t)
|
||||
};
|
||||
|
||||
struct dce_mem_input_mask {
|
||||
MI_REG_FIELD_LIST(uint32_t)
|
||||
};
|
||||
|
||||
struct dce_mem_input_wa {
|
||||
uint8_t single_head_rdreq_dmif_limit;
|
||||
};
|
||||
|
||||
struct mem_input;
|
||||
bool dce_mem_input_program_surface_config(struct mem_input *mi,
|
||||
enum surface_pixel_format format,
|
||||
union dc_tiling_info *tiling_info,
|
||||
union plane_size *plane_size,
|
||||
enum dc_rotation_angle rotation,
|
||||
struct dc_plane_dcc_param *dcc,
|
||||
bool horizontal_mirror);
|
||||
|
||||
void dce_mem_input_allocate_dmif(struct mem_input *mi,
|
||||
uint32_t h_total,
|
||||
uint32_t v_total,
|
||||
uint32_t pix_clk_khz,
|
||||
uint32_t total_stream_num);
|
||||
|
||||
void dce_mem_input_free_dmif(struct mem_input *mi,
|
||||
uint32_t total_stream_num);
|
||||
|
||||
void dce_mem_input_program_display_marks(struct mem_input *mi,
|
||||
struct bw_watermarks nbp,
|
||||
struct bw_watermarks stutter,
|
||||
struct bw_watermarks urgent,
|
||||
uint32_t total_dest_line_time_ns);
|
||||
|
||||
#endif /*__DCE_MEM_INPUT_H__*/
|
|
@ -0,0 +1,501 @@
|
|||
/*
|
||||
* Copyright 2012-16 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 "transform.h"
|
||||
|
||||
const uint16_t filter_2tap_16p[18] = {
|
||||
4096, 0,
|
||||
3840, 256,
|
||||
3584, 512,
|
||||
3328, 768,
|
||||
3072, 1024,
|
||||
2816, 1280,
|
||||
2560, 1536,
|
||||
2304, 1792,
|
||||
2048, 2048
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_16p_upscale[27] = {
|
||||
2048, 2048, 0,
|
||||
1708, 2424, 16348,
|
||||
1372, 2796, 16308,
|
||||
1056, 3148, 16272,
|
||||
768, 3464, 16244,
|
||||
512, 3728, 16236,
|
||||
296, 3928, 16252,
|
||||
124, 4052, 16296,
|
||||
0, 4096, 0
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_16p_117[27] = {
|
||||
2048, 2048, 0,
|
||||
1824, 2276, 16376,
|
||||
1600, 2496, 16380,
|
||||
1376, 2700, 16,
|
||||
1156, 2880, 52,
|
||||
948, 3032, 108,
|
||||
756, 3144, 192,
|
||||
580, 3212, 296,
|
||||
428, 3236, 428
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_16p_150[27] = {
|
||||
2048, 2048, 0,
|
||||
1872, 2184, 36,
|
||||
1692, 2308, 88,
|
||||
1516, 2420, 156,
|
||||
1340, 2516, 236,
|
||||
1168, 2592, 328,
|
||||
1004, 2648, 440,
|
||||
844, 2684, 560,
|
||||
696, 2696, 696
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_16p_183[27] = {
|
||||
2048, 2048, 0,
|
||||
1892, 2104, 92,
|
||||
1744, 2152, 196,
|
||||
1592, 2196, 300,
|
||||
1448, 2232, 412,
|
||||
1304, 2256, 528,
|
||||
1168, 2276, 648,
|
||||
1032, 2288, 772,
|
||||
900, 2292, 900
|
||||
};
|
||||
|
||||
const uint16_t filter_4tap_16p_upscale[36] = {
|
||||
0, 4096, 0, 0,
|
||||
16240, 4056, 180, 16380,
|
||||
16136, 3952, 404, 16364,
|
||||
16072, 3780, 664, 16344,
|
||||
16040, 3556, 952, 16312,
|
||||
16036, 3284, 1268, 16272,
|
||||
16052, 2980, 1604, 16224,
|
||||
16084, 2648, 1952, 16176,
|
||||
16128, 2304, 2304, 16128
|
||||
};
|
||||
|
||||
const uint16_t filter_4tap_16p_117[36] = {
|
||||
428, 3236, 428, 0,
|
||||
276, 3232, 604, 16364,
|
||||
148, 3184, 800, 16340,
|
||||
44, 3104, 1016, 16312,
|
||||
16344, 2984, 1244, 16284,
|
||||
16284, 2832, 1488, 16256,
|
||||
16244, 2648, 1732, 16236,
|
||||
16220, 2440, 1976, 16220,
|
||||
16212, 2216, 2216, 16212
|
||||
};
|
||||
|
||||
const uint16_t filter_4tap_16p_150[36] = {
|
||||
696, 2700, 696, 0,
|
||||
560, 2700, 848, 16364,
|
||||
436, 2676, 1008, 16348,
|
||||
328, 2628, 1180, 16336,
|
||||
232, 2556, 1356, 16328,
|
||||
152, 2460, 1536, 16328,
|
||||
84, 2344, 1716, 16332,
|
||||
28, 2208, 1888, 16348,
|
||||
16376, 2052, 2052, 16376
|
||||
};
|
||||
|
||||
const uint16_t filter_4tap_16p_183[36] = {
|
||||
940, 2208, 940, 0,
|
||||
832, 2200, 1052, 4,
|
||||
728, 2180, 1164, 16,
|
||||
628, 2148, 1280, 36,
|
||||
536, 2100, 1392, 60,
|
||||
448, 2044, 1504, 92,
|
||||
368, 1976, 1612, 132,
|
||||
296, 1900, 1716, 176,
|
||||
232, 1812, 1812, 232
|
||||
};
|
||||
|
||||
const uint16_t filter_2tap_64p[66] = {
|
||||
4096, 0,
|
||||
4032, 64,
|
||||
3968, 128,
|
||||
3904, 192,
|
||||
3840, 256,
|
||||
3776, 320,
|
||||
3712, 384,
|
||||
3648, 448,
|
||||
3584, 512,
|
||||
3520, 576,
|
||||
3456, 640,
|
||||
3392, 704,
|
||||
3328, 768,
|
||||
3264, 832,
|
||||
3200, 896,
|
||||
3136, 960,
|
||||
3072, 1024,
|
||||
3008, 1088,
|
||||
2944, 1152,
|
||||
2880, 1216,
|
||||
2816, 1280,
|
||||
2752, 1344,
|
||||
2688, 1408,
|
||||
2624, 1472,
|
||||
2560, 1536,
|
||||
2496, 1600,
|
||||
2432, 1664,
|
||||
2368, 1728,
|
||||
2304, 1792,
|
||||
2240, 1856,
|
||||
2176, 1920,
|
||||
2112, 1984,
|
||||
2048, 2048 };
|
||||
|
||||
const uint16_t filter_3tap_64p_upscale[99] = {
|
||||
2048, 2048, 0,
|
||||
1960, 2140, 16376,
|
||||
1876, 2236, 16364,
|
||||
1792, 2328, 16356,
|
||||
1708, 2424, 16348,
|
||||
1620, 2516, 16336,
|
||||
1540, 2612, 16328,
|
||||
1456, 2704, 16316,
|
||||
1372, 2796, 16308,
|
||||
1292, 2884, 16296,
|
||||
1212, 2976, 16288,
|
||||
1136, 3060, 16280,
|
||||
1056, 3148, 16272,
|
||||
984, 3228, 16264,
|
||||
908, 3312, 16256,
|
||||
836, 3388, 16248,
|
||||
768, 3464, 16244,
|
||||
700, 3536, 16240,
|
||||
636, 3604, 16236,
|
||||
572, 3668, 16236,
|
||||
512, 3728, 16236,
|
||||
456, 3784, 16236,
|
||||
400, 3836, 16240,
|
||||
348, 3884, 16244,
|
||||
296, 3928, 16252,
|
||||
252, 3964, 16260,
|
||||
204, 4000, 16268,
|
||||
164, 4028, 16284,
|
||||
124, 4052, 16296,
|
||||
88, 4072, 16316,
|
||||
56, 4084, 16336,
|
||||
24, 4092, 16356,
|
||||
0, 4096, 0
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_64p_117[99] = {
|
||||
2048, 2048, 0,
|
||||
1992, 2104, 16380,
|
||||
1936, 2160, 16380,
|
||||
1880, 2220, 16376,
|
||||
1824, 2276, 16376,
|
||||
1768, 2332, 16376,
|
||||
1712, 2388, 16376,
|
||||
1656, 2444, 16376,
|
||||
1600, 2496, 16380,
|
||||
1544, 2548, 0,
|
||||
1488, 2600, 4,
|
||||
1432, 2652, 8,
|
||||
1376, 2700, 16,
|
||||
1320, 2748, 20,
|
||||
1264, 2796, 32,
|
||||
1212, 2840, 40,
|
||||
1156, 2880, 52,
|
||||
1104, 2920, 64,
|
||||
1052, 2960, 80,
|
||||
1000, 2996, 92,
|
||||
948, 3032, 108,
|
||||
900, 3060, 128,
|
||||
852, 3092, 148,
|
||||
804, 3120, 168,
|
||||
756, 3144, 192,
|
||||
712, 3164, 216,
|
||||
668, 3184, 240,
|
||||
624, 3200, 268,
|
||||
580, 3212, 296,
|
||||
540, 3220, 328,
|
||||
500, 3228, 360,
|
||||
464, 3232, 392,
|
||||
428, 3236, 428
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_64p_150[99] = {
|
||||
2048, 2048, 0,
|
||||
2004, 2080, 8,
|
||||
1960, 2116, 16,
|
||||
1916, 2148, 28,
|
||||
1872, 2184, 36,
|
||||
1824, 2216, 48,
|
||||
1780, 2248, 60,
|
||||
1736, 2280, 76,
|
||||
1692, 2308, 88,
|
||||
1648, 2336, 104,
|
||||
1604, 2368, 120,
|
||||
1560, 2392, 136,
|
||||
1516, 2420, 156,
|
||||
1472, 2444, 172,
|
||||
1428, 2472, 192,
|
||||
1384, 2492, 212,
|
||||
1340, 2516, 236,
|
||||
1296, 2536, 256,
|
||||
1252, 2556, 280,
|
||||
1212, 2576, 304,
|
||||
1168, 2592, 328,
|
||||
1124, 2608, 356,
|
||||
1084, 2624, 384,
|
||||
1044, 2636, 412,
|
||||
1004, 2648, 440,
|
||||
964, 2660, 468,
|
||||
924, 2668, 500,
|
||||
884, 2676, 528,
|
||||
844, 2684, 560,
|
||||
808, 2688, 596,
|
||||
768, 2692, 628,
|
||||
732, 2696, 664,
|
||||
696, 2696, 696
|
||||
};
|
||||
|
||||
const uint16_t filter_3tap_64p_183[99] = {
|
||||
2048, 2048, 0,
|
||||
2008, 2060, 20,
|
||||
1968, 2076, 44,
|
||||
1932, 2088, 68,
|
||||
1892, 2104, 92,
|
||||
1856, 2116, 120,
|
||||
1816, 2128, 144,
|
||||
1780, 2140, 168,
|
||||
1744, 2152, 196,
|
||||
1704, 2164, 220,
|
||||
1668, 2176, 248,
|
||||
1632, 2188, 272,
|
||||
1592, 2196, 300,
|
||||
1556, 2204, 328,
|
||||
1520, 2216, 356,
|
||||
1484, 2224, 384,
|
||||
1448, 2232, 412,
|
||||
1412, 2240, 440,
|
||||
1376, 2244, 468,
|
||||
1340, 2252, 496,
|
||||
1304, 2256, 528,
|
||||
1272, 2264, 556,
|
||||
1236, 2268, 584,
|
||||
1200, 2272, 616,
|
||||
1168, 2276, 648,
|
||||
1132, 2280, 676,
|
||||
1100, 2284, 708,
|
||||
1064, 2288, 740,
|
||||
1032, 2288, 772,
|
||||
996, 2292, 800,
|
||||
964, 2292, 832,
|
||||
932, 2292, 868,
|
||||
900, 2292, 900
|
||||
};
|
||||
|
||||
const uint16_t filter_4tap_64p_upscale[132] = {
|
||||
0, 4096, 0, 0,
|
||||
16344, 4092, 40, 0,
|
||||
16308, 4084, 84, 16380,
|
||||
16272, 4072, 132, 16380,
|
||||
16240, 4056, 180, 16380,
|
||||
16212, 4036, 232, 16376,
|
||||
16184, 4012, 288, 16372,
|
||||
16160, 3984, 344, 16368,
|
||||
16136, 3952, 404, 16364,
|
||||
16116, 3916, 464, 16360,
|
||||
16100, 3872, 528, 16356,
|
||||
16084, 3828, 596, 16348,
|
||||
16072, 3780, 664, 16344,
|
||||
16060, 3728, 732, 16336,
|
||||
16052, 3676, 804, 16328,
|
||||
16044, 3616, 876, 16320,
|
||||
16040, 3556, 952, 16312,
|
||||
16036, 3492, 1028, 16300,
|
||||
16032, 3424, 1108, 16292,
|
||||
16032, 3356, 1188, 16280,
|
||||
16036, 3284, 1268, 16272,
|
||||
16036, 3212, 1352, 16260,
|
||||
16040, 3136, 1436, 16248,
|
||||
16044, 3056, 1520, 16236,
|
||||
16052, 2980, 1604, 16224,
|
||||
16060, 2896, 1688, 16212,
|
||||
16064, 2816, 1776, 16200,
|
||||
16076, 2732, 1864, 16188,
|
||||
16084, 2648, 1952, 16176,
|
||||
16092, 2564, 2040, 16164,
|
||||
16104, 2476, 2128, 16152,
|
||||
16116, 2388, 2216, 16140,
|
||||
16128, 2304, 2304, 16128 };
|
||||
|
||||
const uint16_t filter_4tap_64p_117[132] = {
|
||||
420, 3248, 420, 0,
|
||||
380, 3248, 464, 16380,
|
||||
344, 3248, 508, 16372,
|
||||
308, 3248, 552, 16368,
|
||||
272, 3240, 596, 16364,
|
||||
236, 3236, 644, 16356,
|
||||
204, 3224, 692, 16352,
|
||||
172, 3212, 744, 16344,
|
||||
144, 3196, 796, 16340,
|
||||
116, 3180, 848, 16332,
|
||||
88, 3160, 900, 16324,
|
||||
60, 3136, 956, 16320,
|
||||
36, 3112, 1012, 16312,
|
||||
16, 3084, 1068, 16304,
|
||||
16380, 3056, 1124, 16296,
|
||||
16360, 3024, 1184, 16292,
|
||||
16340, 2992, 1244, 16284,
|
||||
16324, 2956, 1304, 16276,
|
||||
16308, 2920, 1364, 16268,
|
||||
16292, 2880, 1424, 16264,
|
||||
16280, 2836, 1484, 16256,
|
||||
16268, 2792, 1548, 16252,
|
||||
16256, 2748, 1608, 16244,
|
||||
16248, 2700, 1668, 16240,
|
||||
16240, 2652, 1732, 16232,
|
||||
16232, 2604, 1792, 16228,
|
||||
16228, 2552, 1856, 16224,
|
||||
16220, 2500, 1916, 16220,
|
||||
16216, 2444, 1980, 16216,
|
||||
16216, 2388, 2040, 16216,
|
||||
16212, 2332, 2100, 16212,
|
||||
16212, 2276, 2160, 16212,
|
||||
16212, 2220, 2220, 16212 };
|
||||
|
||||
const uint16_t filter_4tap_64p_150[132] = {
|
||||
696, 2700, 696, 0,
|
||||
660, 2704, 732, 16380,
|
||||
628, 2704, 768, 16376,
|
||||
596, 2704, 804, 16372,
|
||||
564, 2700, 844, 16364,
|
||||
532, 2696, 884, 16360,
|
||||
500, 2692, 924, 16356,
|
||||
472, 2684, 964, 16352,
|
||||
440, 2676, 1004, 16352,
|
||||
412, 2668, 1044, 16348,
|
||||
384, 2656, 1088, 16344,
|
||||
360, 2644, 1128, 16340,
|
||||
332, 2632, 1172, 16336,
|
||||
308, 2616, 1216, 16336,
|
||||
284, 2600, 1260, 16332,
|
||||
260, 2580, 1304, 16332,
|
||||
236, 2560, 1348, 16328,
|
||||
216, 2540, 1392, 16328,
|
||||
196, 2516, 1436, 16328,
|
||||
176, 2492, 1480, 16324,
|
||||
156, 2468, 1524, 16324,
|
||||
136, 2440, 1568, 16328,
|
||||
120, 2412, 1612, 16328,
|
||||
104, 2384, 1656, 16328,
|
||||
88, 2352, 1700, 16332,
|
||||
72, 2324, 1744, 16332,
|
||||
60, 2288, 1788, 16336,
|
||||
48, 2256, 1828, 16340,
|
||||
36, 2220, 1872, 16344,
|
||||
24, 2184, 1912, 16352,
|
||||
12, 2148, 1952, 16356,
|
||||
4, 2112, 1996, 16364,
|
||||
16380, 2072, 2036, 16372 };
|
||||
|
||||
const uint16_t filter_4tap_64p_183[132] = {
|
||||
944, 2204, 944, 0,
|
||||
916, 2204, 972, 0,
|
||||
888, 2200, 996, 0,
|
||||
860, 2200, 1024, 4,
|
||||
832, 2196, 1052, 4,
|
||||
808, 2192, 1080, 8,
|
||||
780, 2188, 1108, 12,
|
||||
756, 2180, 1140, 12,
|
||||
728, 2176, 1168, 16,
|
||||
704, 2168, 1196, 20,
|
||||
680, 2160, 1224, 24,
|
||||
656, 2152, 1252, 28,
|
||||
632, 2144, 1280, 36,
|
||||
608, 2132, 1308, 40,
|
||||
584, 2120, 1336, 48,
|
||||
560, 2112, 1364, 52,
|
||||
536, 2096, 1392, 60,
|
||||
516, 2084, 1420, 68,
|
||||
492, 2072, 1448, 76,
|
||||
472, 2056, 1476, 84,
|
||||
452, 2040, 1504, 92,
|
||||
428, 2024, 1532, 100,
|
||||
408, 2008, 1560, 112,
|
||||
392, 1992, 1584, 120,
|
||||
372, 1972, 1612, 132,
|
||||
352, 1956, 1636, 144,
|
||||
336, 1936, 1664, 156,
|
||||
316, 1916, 1688, 168,
|
||||
300, 1896, 1712, 180,
|
||||
284, 1876, 1736, 192,
|
||||
268, 1852, 1760, 208,
|
||||
252, 1832, 1784, 220,
|
||||
236, 1808, 1808, 236 };
|
||||
|
||||
const uint16_t *get_filter_3tap_16p(struct fixed31_32 ratio)
|
||||
{
|
||||
if (ratio.value < dal_fixed31_32_one.value)
|
||||
return filter_3tap_16p_upscale;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
|
||||
return filter_3tap_16p_117;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
|
||||
return filter_3tap_16p_150;
|
||||
else
|
||||
return filter_3tap_16p_183;
|
||||
}
|
||||
|
||||
const uint16_t *get_filter_3tap_64p(struct fixed31_32 ratio)
|
||||
{
|
||||
if (ratio.value < dal_fixed31_32_one.value)
|
||||
return filter_3tap_64p_upscale;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
|
||||
return filter_3tap_64p_117;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
|
||||
return filter_3tap_64p_150;
|
||||
else
|
||||
return filter_3tap_64p_183;
|
||||
}
|
||||
|
||||
const uint16_t *get_filter_4tap_16p(struct fixed31_32 ratio)
|
||||
{
|
||||
if (ratio.value < dal_fixed31_32_one.value)
|
||||
return filter_4tap_16p_upscale;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
|
||||
return filter_4tap_16p_117;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
|
||||
return filter_4tap_16p_150;
|
||||
else
|
||||
return filter_4tap_16p_183;
|
||||
}
|
||||
|
||||
const uint16_t *get_filter_4tap_64p(struct fixed31_32 ratio)
|
||||
{
|
||||
if (ratio.value < dal_fixed31_32_one.value)
|
||||
return filter_4tap_64p_upscale;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(4, 3).value)
|
||||
return filter_4tap_64p_117;
|
||||
else if (ratio.value < dal_fixed31_32_from_fraction(5, 3).value)
|
||||
return filter_4tap_64p_150;
|
||||
else
|
||||
return filter_4tap_64p_183;
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,564 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DC_STREAM_ENCODER_DCE110_H__
|
||||
#define __DC_STREAM_ENCODER_DCE110_H__
|
||||
|
||||
#include "stream_encoder.h"
|
||||
|
||||
#define DCE110STRENC_FROM_STRENC(stream_encoder)\
|
||||
container_of(stream_encoder, struct dce110_stream_encoder, base)
|
||||
|
||||
#ifndef TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK
|
||||
#define TMDS_CNTL__TMDS_PIXEL_ENCODING_MASK 0x00000010L
|
||||
#define TMDS_CNTL__TMDS_COLOR_FORMAT_MASK 0x00000300L
|
||||
#define TMDS_CNTL__TMDS_PIXEL_ENCODING__SHIFT 0x00000004
|
||||
#define TMDS_CNTL__TMDS_COLOR_FORMAT__SHIFT 0x00000008
|
||||
#endif
|
||||
|
||||
|
||||
#define SE_COMMON_REG_LIST_DCE_BASE(id) \
|
||||
SE_COMMON_REG_LIST_BASE(id),\
|
||||
SRI(AFMT_AVI_INFO0, DIG, id), \
|
||||
SRI(AFMT_AVI_INFO1, DIG, id), \
|
||||
SRI(AFMT_AVI_INFO2, DIG, id), \
|
||||
SRI(AFMT_AVI_INFO3, DIG, id)
|
||||
|
||||
#define SE_COMMON_REG_LIST_BASE(id) \
|
||||
SRI(AFMT_GENERIC_0, DIG, id), \
|
||||
SRI(AFMT_GENERIC_1, DIG, id), \
|
||||
SRI(AFMT_GENERIC_2, DIG, id), \
|
||||
SRI(AFMT_GENERIC_3, DIG, id), \
|
||||
SRI(AFMT_GENERIC_4, DIG, id), \
|
||||
SRI(AFMT_GENERIC_5, DIG, id), \
|
||||
SRI(AFMT_GENERIC_6, DIG, id), \
|
||||
SRI(AFMT_GENERIC_7, DIG, id), \
|
||||
SRI(AFMT_GENERIC_HDR, DIG, id), \
|
||||
SRI(AFMT_INFOFRAME_CONTROL0, DIG, id), \
|
||||
SRI(AFMT_VBI_PACKET_CONTROL, DIG, id), \
|
||||
SRI(AFMT_AUDIO_PACKET_CONTROL, DIG, id), \
|
||||
SRI(AFMT_AUDIO_PACKET_CONTROL2, DIG, id), \
|
||||
SRI(AFMT_AUDIO_SRC_CONTROL, DIG, id), \
|
||||
SRI(AFMT_60958_0, DIG, id), \
|
||||
SRI(AFMT_60958_1, DIG, id), \
|
||||
SRI(AFMT_60958_2, DIG, id), \
|
||||
SRI(DIG_FE_CNTL, DIG, id), \
|
||||
SRI(HDMI_CONTROL, DIG, id), \
|
||||
SRI(HDMI_GC, DIG, id), \
|
||||
SRI(HDMI_GENERIC_PACKET_CONTROL0, DIG, id), \
|
||||
SRI(HDMI_GENERIC_PACKET_CONTROL1, DIG, id), \
|
||||
SRI(HDMI_INFOFRAME_CONTROL0, DIG, id), \
|
||||
SRI(HDMI_INFOFRAME_CONTROL1, DIG, id), \
|
||||
SRI(HDMI_VBI_PACKET_CONTROL, DIG, id), \
|
||||
SRI(HDMI_AUDIO_PACKET_CONTROL, DIG, id),\
|
||||
SRI(HDMI_ACR_PACKET_CONTROL, DIG, id),\
|
||||
SRI(HDMI_ACR_32_0, DIG, id),\
|
||||
SRI(HDMI_ACR_32_1, DIG, id),\
|
||||
SRI(HDMI_ACR_44_0, DIG, id),\
|
||||
SRI(HDMI_ACR_44_1, DIG, id),\
|
||||
SRI(HDMI_ACR_48_0, DIG, id),\
|
||||
SRI(HDMI_ACR_48_1, DIG, id),\
|
||||
SRI(TMDS_CNTL, DIG, id), \
|
||||
SRI(DP_MSE_RATE_CNTL, DP, id), \
|
||||
SRI(DP_MSE_RATE_UPDATE, DP, id), \
|
||||
SRI(DP_PIXEL_FORMAT, DP, id), \
|
||||
SRI(DP_SEC_CNTL, DP, id), \
|
||||
SRI(DP_STEER_FIFO, DP, id), \
|
||||
SRI(DP_VID_M, DP, id), \
|
||||
SRI(DP_VID_N, DP, id), \
|
||||
SRI(DP_VID_STREAM_CNTL, DP, id), \
|
||||
SRI(DP_VID_TIMING, DP, id), \
|
||||
SRI(DP_SEC_AUD_N, DP, id), \
|
||||
SRI(DP_SEC_TIMESTAMP, DP, id)
|
||||
|
||||
#define SE_COMMON_REG_LIST(id)\
|
||||
SE_COMMON_REG_LIST_DCE_BASE(id), \
|
||||
SRI(AFMT_CNTL, DIG, id)
|
||||
|
||||
#define SE_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)\
|
||||
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC_INDEX, mask_sh),\
|
||||
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC0_UPDATE, mask_sh),\
|
||||
SE_SF(AFMT_VBI_PACKET_CONTROL, AFMT_GENERIC2_UPDATE, mask_sh),\
|
||||
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB0, mask_sh),\
|
||||
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB1, mask_sh),\
|
||||
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB2, mask_sh),\
|
||||
SE_SF(AFMT_GENERIC_HDR, AFMT_GENERIC_HB3, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_CONT, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_SEND, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC0_LINE, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_CONT, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_SEND, mask_sh),\
|
||||
SE_SF(HDMI_GENERIC_PACKET_CONTROL0, HDMI_GENERIC1_LINE, mask_sh),\
|
||||
SE_SF(DP_PIXEL_FORMAT, DP_PIXEL_ENCODING, mask_sh),\
|
||||
SE_SF(DP_PIXEL_FORMAT, DP_COMPONENT_DEPTH, mask_sh),\
|
||||
SE_SF(DP_PIXEL_FORMAT, DP_DYN_RANGE, mask_sh),\
|
||||
SE_SF(DP_PIXEL_FORMAT, DP_YCBCR_RANGE, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_PACKET_GEN_VERSION, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_KEEPOUT_MODE, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_ENABLE, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_DEEP_COLOR_DEPTH, mask_sh),\
|
||||
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_CONT, mask_sh),\
|
||||
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_GC_SEND, mask_sh),\
|
||||
SE_SF(HDMI_VBI_PACKET_CONTROL, HDMI_NULL_SEND, mask_sh),\
|
||||
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AUDIO_INFO_SEND, mask_sh),\
|
||||
SE_SF(AFMT_INFOFRAME_CONTROL0, AFMT_AUDIO_INFO_UPDATE, mask_sh),\
|
||||
SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AUDIO_INFO_LINE, mask_sh),\
|
||||
SE_SF(HDMI_GC, HDMI_GC_AVMUTE, mask_sh),\
|
||||
SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_X, mask_sh),\
|
||||
SE_SF(DP_MSE_RATE_CNTL, DP_MSE_RATE_Y, mask_sh),\
|
||||
SE_SF(DP_MSE_RATE_UPDATE, DP_MSE_RATE_UPDATE_PENDING, mask_sh),\
|
||||
SE_SF(AFMT_AVI_INFO3, AFMT_AVI_INFO_VERSION, mask_sh),\
|
||||
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_SEND, mask_sh),\
|
||||
SE_SF(HDMI_INFOFRAME_CONTROL0, HDMI_AVI_INFO_CONT, mask_sh),\
|
||||
SE_SF(HDMI_INFOFRAME_CONTROL1, HDMI_AVI_INFO_LINE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_GSP0_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_STREAM_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_GSP1_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_GSP2_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_GSP3_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_AVI_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_MPG_ENABLE, mask_sh),\
|
||||
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_DIS_DEFER, mask_sh),\
|
||||
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_ENABLE, mask_sh),\
|
||||
SE_SF(DP_VID_STREAM_CNTL, DP_VID_STREAM_STATUS, mask_sh),\
|
||||
SE_SF(DP_STEER_FIFO, DP_STEER_FIFO_RESET, mask_sh),\
|
||||
SE_SF(DP_VID_TIMING, DP_VID_M_N_GEN_EN, mask_sh),\
|
||||
SE_SF(DP_VID_N, DP_VID_N, mask_sh),\
|
||||
SE_SF(DP_VID_M, DP_VID_M, mask_sh),\
|
||||
SE_SF(DIG_FE_CNTL, DIG_START, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_SRC_CONTROL, AFMT_AUDIO_SRC_SELECT, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_CHANNEL_ENABLE, mask_sh),\
|
||||
SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_PACKETS_PER_LINE, mask_sh),\
|
||||
SE_SF(HDMI_AUDIO_PACKET_CONTROL, HDMI_AUDIO_DELAY_EN, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_60958_CS_UPDATE, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_AUDIO_LAYOUT_OVRD, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_PACKET_CONTROL2, AFMT_60958_OSF_OVRD, mask_sh),\
|
||||
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUTO_SEND, mask_sh),\
|
||||
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_SOURCE, mask_sh),\
|
||||
SE_SF(HDMI_ACR_PACKET_CONTROL, HDMI_ACR_AUDIO_PRIORITY, mask_sh),\
|
||||
SE_SF(HDMI_ACR_32_0, HDMI_ACR_CTS_32, mask_sh),\
|
||||
SE_SF(HDMI_ACR_32_1, HDMI_ACR_N_32, mask_sh),\
|
||||
SE_SF(HDMI_ACR_44_0, HDMI_ACR_CTS_44, mask_sh),\
|
||||
SE_SF(HDMI_ACR_44_1, HDMI_ACR_N_44, mask_sh),\
|
||||
SE_SF(HDMI_ACR_48_0, HDMI_ACR_CTS_48, mask_sh),\
|
||||
SE_SF(HDMI_ACR_48_1, HDMI_ACR_N_48, mask_sh),\
|
||||
SE_SF(AFMT_60958_0, AFMT_60958_CS_CHANNEL_NUMBER_L, mask_sh),\
|
||||
SE_SF(AFMT_60958_0, AFMT_60958_CS_CLOCK_ACCURACY, mask_sh),\
|
||||
SE_SF(AFMT_60958_1, AFMT_60958_CS_CHANNEL_NUMBER_R, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_2, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_3, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_4, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_5, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_6, mask_sh),\
|
||||
SE_SF(AFMT_60958_2, AFMT_60958_CS_CHANNEL_NUMBER_7, mask_sh),\
|
||||
SE_SF(DP_SEC_AUD_N, DP_SEC_AUD_N, mask_sh),\
|
||||
SE_SF(DP_SEC_TIMESTAMP, DP_SEC_TIMESTAMP_MODE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_ASP_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_ATP_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_AIP_ENABLE, mask_sh),\
|
||||
SE_SF(DP_SEC_CNTL, DP_SEC_ACM_ENABLE, mask_sh),\
|
||||
SE_SF(AFMT_AUDIO_PACKET_CONTROL, AFMT_AUDIO_SAMPLE_SEND, mask_sh)
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh)
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE80_100(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
|
||||
SE_SF(TMDS_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
|
||||
SE_SF(TMDS_CNTL, TMDS_COLOR_FORMAT, mask_sh)
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE110(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
|
||||
SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
|
||||
SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
|
||||
SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh)
|
||||
|
||||
#define SE_COMMON_MASK_SH_LIST_DCE112(mask_sh)\
|
||||
SE_COMMON_MASK_SH_LIST_DCE_COMMON(mask_sh),\
|
||||
SE_SF(AFMT_CNTL, AFMT_AUDIO_CLOCK_EN, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_CLOCK_CHANNEL_RATE, mask_sh),\
|
||||
SE_SF(HDMI_CONTROL, HDMI_DATA_SCRAMBLE_EN, mask_sh),\
|
||||
SE_SF(DIG_FE_CNTL, TMDS_PIXEL_ENCODING, mask_sh),\
|
||||
SE_SF(DIG_FE_CNTL, TMDS_COLOR_FORMAT, mask_sh),\
|
||||
SE_SF(DP_VID_TIMING, DP_VID_M_DOUBLE_VALUE_EN, mask_sh)
|
||||
|
||||
struct dce_stream_encoder_shift {
|
||||
uint8_t AFMT_GENERIC_INDEX;
|
||||
uint8_t AFMT_GENERIC0_UPDATE;
|
||||
uint8_t AFMT_GENERIC2_UPDATE;
|
||||
uint8_t AFMT_GENERIC_HB0;
|
||||
uint8_t AFMT_GENERIC_HB1;
|
||||
uint8_t AFMT_GENERIC_HB2;
|
||||
uint8_t AFMT_GENERIC_HB3;
|
||||
uint8_t AFMT_GENERIC_LOCK_STATUS;
|
||||
uint8_t AFMT_GENERIC_CONFLICT;
|
||||
uint8_t AFMT_GENERIC_CONFLICT_CLR;
|
||||
uint8_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
|
||||
uint8_t AFMT_GENERIC0_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC1_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC2_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC3_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC4_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC5_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC6_FRAME_UPDATE;
|
||||
uint8_t AFMT_GENERIC7_FRAME_UPDATE;
|
||||
uint8_t HDMI_GENERIC0_CONT;
|
||||
uint8_t HDMI_GENERIC0_SEND;
|
||||
uint8_t HDMI_GENERIC0_LINE;
|
||||
uint8_t HDMI_GENERIC1_CONT;
|
||||
uint8_t HDMI_GENERIC1_SEND;
|
||||
uint8_t HDMI_GENERIC1_LINE;
|
||||
uint8_t DP_PIXEL_ENCODING;
|
||||
uint8_t DP_COMPONENT_DEPTH;
|
||||
uint8_t DP_DYN_RANGE;
|
||||
uint8_t DP_YCBCR_RANGE;
|
||||
uint8_t HDMI_PACKET_GEN_VERSION;
|
||||
uint8_t HDMI_KEEPOUT_MODE;
|
||||
uint8_t HDMI_DEEP_COLOR_ENABLE;
|
||||
uint8_t HDMI_CLOCK_CHANNEL_RATE;
|
||||
uint8_t HDMI_DEEP_COLOR_DEPTH;
|
||||
uint8_t HDMI_GC_CONT;
|
||||
uint8_t HDMI_GC_SEND;
|
||||
uint8_t HDMI_NULL_SEND;
|
||||
uint8_t HDMI_DATA_SCRAMBLE_EN;
|
||||
uint8_t HDMI_AUDIO_INFO_SEND;
|
||||
uint8_t AFMT_AUDIO_INFO_UPDATE;
|
||||
uint8_t HDMI_AUDIO_INFO_LINE;
|
||||
uint8_t HDMI_GC_AVMUTE;
|
||||
uint8_t DP_MSE_RATE_X;
|
||||
uint8_t DP_MSE_RATE_Y;
|
||||
uint8_t DP_MSE_RATE_UPDATE_PENDING;
|
||||
uint8_t AFMT_AVI_INFO_VERSION;
|
||||
uint8_t HDMI_AVI_INFO_SEND;
|
||||
uint8_t HDMI_AVI_INFO_CONT;
|
||||
uint8_t HDMI_AVI_INFO_LINE;
|
||||
uint8_t DP_SEC_GSP0_ENABLE;
|
||||
uint8_t DP_SEC_STREAM_ENABLE;
|
||||
uint8_t DP_SEC_GSP1_ENABLE;
|
||||
uint8_t DP_SEC_GSP2_ENABLE;
|
||||
uint8_t DP_SEC_GSP3_ENABLE;
|
||||
uint8_t DP_SEC_GSP4_ENABLE;
|
||||
uint8_t DP_SEC_GSP5_ENABLE;
|
||||
uint8_t DP_SEC_GSP6_ENABLE;
|
||||
uint8_t DP_SEC_GSP7_ENABLE;
|
||||
uint8_t DP_SEC_AVI_ENABLE;
|
||||
uint8_t DP_SEC_MPG_ENABLE;
|
||||
uint8_t DP_VID_STREAM_DIS_DEFER;
|
||||
uint8_t DP_VID_STREAM_ENABLE;
|
||||
uint8_t DP_VID_STREAM_STATUS;
|
||||
uint8_t DP_STEER_FIFO_RESET;
|
||||
uint8_t DP_VID_M_N_GEN_EN;
|
||||
uint8_t DP_VID_N;
|
||||
uint8_t DP_VID_M;
|
||||
uint8_t DIG_START;
|
||||
uint8_t AFMT_AUDIO_SRC_SELECT;
|
||||
uint8_t AFMT_AUDIO_CHANNEL_ENABLE;
|
||||
uint8_t HDMI_AUDIO_PACKETS_PER_LINE;
|
||||
uint8_t HDMI_AUDIO_DELAY_EN;
|
||||
uint8_t AFMT_60958_CS_UPDATE;
|
||||
uint8_t AFMT_AUDIO_LAYOUT_OVRD;
|
||||
uint8_t AFMT_60958_OSF_OVRD;
|
||||
uint8_t HDMI_ACR_AUTO_SEND;
|
||||
uint8_t HDMI_ACR_SOURCE;
|
||||
uint8_t HDMI_ACR_AUDIO_PRIORITY;
|
||||
uint8_t HDMI_ACR_CTS_32;
|
||||
uint8_t HDMI_ACR_N_32;
|
||||
uint8_t HDMI_ACR_CTS_44;
|
||||
uint8_t HDMI_ACR_N_44;
|
||||
uint8_t HDMI_ACR_CTS_48;
|
||||
uint8_t HDMI_ACR_N_48;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_L;
|
||||
uint8_t AFMT_60958_CS_CLOCK_ACCURACY;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_R;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_2;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_3;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_4;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_5;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_6;
|
||||
uint8_t AFMT_60958_CS_CHANNEL_NUMBER_7;
|
||||
uint8_t DP_SEC_AUD_N;
|
||||
uint8_t DP_SEC_TIMESTAMP_MODE;
|
||||
uint8_t DP_SEC_ASP_ENABLE;
|
||||
uint8_t DP_SEC_ATP_ENABLE;
|
||||
uint8_t DP_SEC_AIP_ENABLE;
|
||||
uint8_t DP_SEC_ACM_ENABLE;
|
||||
uint8_t AFMT_AUDIO_SAMPLE_SEND;
|
||||
uint8_t AFMT_AUDIO_CLOCK_EN;
|
||||
uint8_t TMDS_PIXEL_ENCODING;
|
||||
uint8_t TMDS_COLOR_FORMAT;
|
||||
uint8_t DP_DB_DISABLE;
|
||||
uint8_t DP_MSA_MISC0;
|
||||
uint8_t DP_MSA_HTOTAL;
|
||||
uint8_t DP_MSA_VTOTAL;
|
||||
uint8_t DP_MSA_HSTART;
|
||||
uint8_t DP_MSA_VSTART;
|
||||
uint8_t DP_MSA_HSYNCWIDTH;
|
||||
uint8_t DP_MSA_HSYNCPOLARITY;
|
||||
uint8_t DP_MSA_VSYNCWIDTH;
|
||||
uint8_t DP_MSA_VSYNCPOLARITY;
|
||||
uint8_t DP_MSA_HWIDTH;
|
||||
uint8_t DP_MSA_VHEIGHT;
|
||||
uint8_t HDMI_DB_DISABLE;
|
||||
uint8_t DP_VID_N_MUL;
|
||||
uint8_t DP_VID_M_DOUBLE_VALUE_EN;
|
||||
};
|
||||
|
||||
struct dce_stream_encoder_mask {
|
||||
uint32_t AFMT_GENERIC_INDEX;
|
||||
uint32_t AFMT_GENERIC0_UPDATE;
|
||||
uint32_t AFMT_GENERIC2_UPDATE;
|
||||
uint32_t AFMT_GENERIC_HB0;
|
||||
uint32_t AFMT_GENERIC_HB1;
|
||||
uint32_t AFMT_GENERIC_HB2;
|
||||
uint32_t AFMT_GENERIC_HB3;
|
||||
uint32_t AFMT_GENERIC_LOCK_STATUS;
|
||||
uint32_t AFMT_GENERIC_CONFLICT;
|
||||
uint32_t AFMT_GENERIC_CONFLICT_CLR;
|
||||
uint32_t AFMT_GENERIC0_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC1_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC2_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC3_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC4_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC5_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC6_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC7_FRAME_UPDATE_PENDING;
|
||||
uint32_t AFMT_GENERIC0_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC1_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC2_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC3_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC4_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC5_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC6_FRAME_UPDATE;
|
||||
uint32_t AFMT_GENERIC7_FRAME_UPDATE;
|
||||
uint32_t HDMI_GENERIC0_CONT;
|
||||
uint32_t HDMI_GENERIC0_SEND;
|
||||
uint32_t HDMI_GENERIC0_LINE;
|
||||
uint32_t HDMI_GENERIC1_CONT;
|
||||
uint32_t HDMI_GENERIC1_SEND;
|
||||
uint32_t HDMI_GENERIC1_LINE;
|
||||
uint32_t DP_PIXEL_ENCODING;
|
||||
uint32_t DP_COMPONENT_DEPTH;
|
||||
uint32_t DP_DYN_RANGE;
|
||||
uint32_t DP_YCBCR_RANGE;
|
||||
uint32_t HDMI_PACKET_GEN_VERSION;
|
||||
uint32_t HDMI_KEEPOUT_MODE;
|
||||
uint32_t HDMI_DEEP_COLOR_ENABLE;
|
||||
uint32_t HDMI_CLOCK_CHANNEL_RATE;
|
||||
uint32_t HDMI_DEEP_COLOR_DEPTH;
|
||||
uint32_t HDMI_GC_CONT;
|
||||
uint32_t HDMI_GC_SEND;
|
||||
uint32_t HDMI_NULL_SEND;
|
||||
uint32_t HDMI_DATA_SCRAMBLE_EN;
|
||||
uint32_t HDMI_AUDIO_INFO_SEND;
|
||||
uint32_t AFMT_AUDIO_INFO_UPDATE;
|
||||
uint32_t HDMI_AUDIO_INFO_LINE;
|
||||
uint32_t HDMI_GC_AVMUTE;
|
||||
uint32_t DP_MSE_RATE_X;
|
||||
uint32_t DP_MSE_RATE_Y;
|
||||
uint32_t DP_MSE_RATE_UPDATE_PENDING;
|
||||
uint32_t AFMT_AVI_INFO_VERSION;
|
||||
uint32_t HDMI_AVI_INFO_SEND;
|
||||
uint32_t HDMI_AVI_INFO_CONT;
|
||||
uint32_t HDMI_AVI_INFO_LINE;
|
||||
uint32_t DP_SEC_GSP0_ENABLE;
|
||||
uint32_t DP_SEC_STREAM_ENABLE;
|
||||
uint32_t DP_SEC_GSP1_ENABLE;
|
||||
uint32_t DP_SEC_GSP2_ENABLE;
|
||||
uint32_t DP_SEC_GSP3_ENABLE;
|
||||
uint32_t DP_SEC_GSP4_ENABLE;
|
||||
uint32_t DP_SEC_GSP5_ENABLE;
|
||||
uint32_t DP_SEC_GSP6_ENABLE;
|
||||
uint32_t DP_SEC_GSP7_ENABLE;
|
||||
uint32_t DP_SEC_AVI_ENABLE;
|
||||
uint32_t DP_SEC_MPG_ENABLE;
|
||||
uint32_t DP_VID_STREAM_DIS_DEFER;
|
||||
uint32_t DP_VID_STREAM_ENABLE;
|
||||
uint32_t DP_VID_STREAM_STATUS;
|
||||
uint32_t DP_STEER_FIFO_RESET;
|
||||
uint32_t DP_VID_M_N_GEN_EN;
|
||||
uint32_t DP_VID_N;
|
||||
uint32_t DP_VID_M;
|
||||
uint32_t DIG_START;
|
||||
uint32_t AFMT_AUDIO_SRC_SELECT;
|
||||
uint32_t AFMT_AUDIO_CHANNEL_ENABLE;
|
||||
uint32_t HDMI_AUDIO_PACKETS_PER_LINE;
|
||||
uint32_t HDMI_AUDIO_DELAY_EN;
|
||||
uint32_t AFMT_60958_CS_UPDATE;
|
||||
uint32_t AFMT_AUDIO_LAYOUT_OVRD;
|
||||
uint32_t AFMT_60958_OSF_OVRD;
|
||||
uint32_t HDMI_ACR_AUTO_SEND;
|
||||
uint32_t HDMI_ACR_SOURCE;
|
||||
uint32_t HDMI_ACR_AUDIO_PRIORITY;
|
||||
uint32_t HDMI_ACR_CTS_32;
|
||||
uint32_t HDMI_ACR_N_32;
|
||||
uint32_t HDMI_ACR_CTS_44;
|
||||
uint32_t HDMI_ACR_N_44;
|
||||
uint32_t HDMI_ACR_CTS_48;
|
||||
uint32_t HDMI_ACR_N_48;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_L;
|
||||
uint32_t AFMT_60958_CS_CLOCK_ACCURACY;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_R;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_2;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_3;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_4;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_5;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_6;
|
||||
uint32_t AFMT_60958_CS_CHANNEL_NUMBER_7;
|
||||
uint32_t DP_SEC_AUD_N;
|
||||
uint32_t DP_SEC_TIMESTAMP_MODE;
|
||||
uint32_t DP_SEC_ASP_ENABLE;
|
||||
uint32_t DP_SEC_ATP_ENABLE;
|
||||
uint32_t DP_SEC_AIP_ENABLE;
|
||||
uint32_t DP_SEC_ACM_ENABLE;
|
||||
uint32_t AFMT_AUDIO_SAMPLE_SEND;
|
||||
uint32_t AFMT_AUDIO_CLOCK_EN;
|
||||
uint32_t TMDS_PIXEL_ENCODING;
|
||||
uint32_t TMDS_COLOR_FORMAT;
|
||||
uint32_t DP_DB_DISABLE;
|
||||
uint32_t DP_MSA_MISC0;
|
||||
uint32_t DP_MSA_HTOTAL;
|
||||
uint32_t DP_MSA_VTOTAL;
|
||||
uint32_t DP_MSA_HSTART;
|
||||
uint32_t DP_MSA_VSTART;
|
||||
uint32_t DP_MSA_HSYNCWIDTH;
|
||||
uint32_t DP_MSA_HSYNCPOLARITY;
|
||||
uint32_t DP_MSA_VSYNCWIDTH;
|
||||
uint32_t DP_MSA_VSYNCPOLARITY;
|
||||
uint32_t DP_MSA_HWIDTH;
|
||||
uint32_t DP_MSA_VHEIGHT;
|
||||
uint32_t HDMI_DB_DISABLE;
|
||||
uint32_t DP_VID_N_MUL;
|
||||
uint32_t DP_VID_M_DOUBLE_VALUE_EN;
|
||||
};
|
||||
|
||||
struct dce110_stream_enc_registers {
|
||||
uint32_t AFMT_CNTL;
|
||||
uint32_t AFMT_AVI_INFO0;
|
||||
uint32_t AFMT_AVI_INFO1;
|
||||
uint32_t AFMT_AVI_INFO2;
|
||||
uint32_t AFMT_AVI_INFO3;
|
||||
uint32_t AFMT_GENERIC_0;
|
||||
uint32_t AFMT_GENERIC_1;
|
||||
uint32_t AFMT_GENERIC_2;
|
||||
uint32_t AFMT_GENERIC_3;
|
||||
uint32_t AFMT_GENERIC_4;
|
||||
uint32_t AFMT_GENERIC_5;
|
||||
uint32_t AFMT_GENERIC_6;
|
||||
uint32_t AFMT_GENERIC_7;
|
||||
uint32_t AFMT_GENERIC_HDR;
|
||||
uint32_t AFMT_INFOFRAME_CONTROL0;
|
||||
uint32_t AFMT_VBI_PACKET_CONTROL;
|
||||
uint32_t AFMT_VBI_PACKET_CONTROL1;
|
||||
uint32_t AFMT_AUDIO_PACKET_CONTROL;
|
||||
uint32_t AFMT_AUDIO_PACKET_CONTROL2;
|
||||
uint32_t AFMT_AUDIO_SRC_CONTROL;
|
||||
uint32_t AFMT_60958_0;
|
||||
uint32_t AFMT_60958_1;
|
||||
uint32_t AFMT_60958_2;
|
||||
uint32_t DIG_FE_CNTL;
|
||||
uint32_t DP_MSE_RATE_CNTL;
|
||||
uint32_t DP_MSE_RATE_UPDATE;
|
||||
uint32_t DP_PIXEL_FORMAT;
|
||||
uint32_t DP_SEC_CNTL;
|
||||
uint32_t DP_STEER_FIFO;
|
||||
uint32_t DP_VID_M;
|
||||
uint32_t DP_VID_N;
|
||||
uint32_t DP_VID_STREAM_CNTL;
|
||||
uint32_t DP_VID_TIMING;
|
||||
uint32_t DP_SEC_AUD_N;
|
||||
uint32_t DP_SEC_TIMESTAMP;
|
||||
uint32_t HDMI_CONTROL;
|
||||
uint32_t HDMI_GC;
|
||||
uint32_t HDMI_GENERIC_PACKET_CONTROL0;
|
||||
uint32_t HDMI_GENERIC_PACKET_CONTROL1;
|
||||
uint32_t HDMI_GENERIC_PACKET_CONTROL2;
|
||||
uint32_t HDMI_GENERIC_PACKET_CONTROL3;
|
||||
uint32_t HDMI_INFOFRAME_CONTROL0;
|
||||
uint32_t HDMI_INFOFRAME_CONTROL1;
|
||||
uint32_t HDMI_VBI_PACKET_CONTROL;
|
||||
uint32_t HDMI_AUDIO_PACKET_CONTROL;
|
||||
uint32_t HDMI_ACR_PACKET_CONTROL;
|
||||
uint32_t HDMI_ACR_32_0;
|
||||
uint32_t HDMI_ACR_32_1;
|
||||
uint32_t HDMI_ACR_44_0;
|
||||
uint32_t HDMI_ACR_44_1;
|
||||
uint32_t HDMI_ACR_48_0;
|
||||
uint32_t HDMI_ACR_48_1;
|
||||
uint32_t TMDS_CNTL;
|
||||
};
|
||||
|
||||
struct dce110_stream_encoder {
|
||||
struct stream_encoder base;
|
||||
const struct dce110_stream_enc_registers *regs;
|
||||
const struct dce_stream_encoder_shift *se_shift;
|
||||
const struct dce_stream_encoder_mask *se_mask;
|
||||
};
|
||||
|
||||
bool dce110_stream_encoder_construct(
|
||||
struct dce110_stream_encoder *enc110,
|
||||
struct dc_context *ctx,
|
||||
struct dc_bios *bp,
|
||||
enum engine_id eng_id,
|
||||
const struct dce110_stream_enc_registers *regs,
|
||||
const struct dce_stream_encoder_shift *se_shift,
|
||||
const struct dce_stream_encoder_mask *se_mask);
|
||||
|
||||
|
||||
void dce110_se_audio_mute_control(
|
||||
struct stream_encoder *enc, bool mute);
|
||||
|
||||
void dce110_se_dp_audio_setup(
|
||||
struct stream_encoder *enc,
|
||||
unsigned int az_inst,
|
||||
struct audio_info *info);
|
||||
|
||||
void dce110_se_dp_audio_enable(
|
||||
struct stream_encoder *enc);
|
||||
|
||||
void dce110_se_dp_audio_disable(
|
||||
struct stream_encoder *enc);
|
||||
|
||||
void dce110_se_hdmi_audio_setup(
|
||||
struct stream_encoder *enc,
|
||||
unsigned int az_inst,
|
||||
struct audio_info *info,
|
||||
struct audio_crtc_info *audio_crtc_info);
|
||||
|
||||
void dce110_se_hdmi_audio_disable(
|
||||
struct stream_encoder *enc);
|
||||
|
||||
#endif /* __DC_STREAM_ENCODER_DCE110_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,313 @@
|
|||
/*
|
||||
* Copyright 2012-16 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 _DCE_DCE_TRANSFORM_H_
|
||||
#define _DCE_DCE_TRANSFORM_H_
|
||||
|
||||
|
||||
#include "transform.h"
|
||||
|
||||
#define TO_DCE_TRANSFORM(transform)\
|
||||
container_of(transform, struct dce_transform, base)
|
||||
|
||||
#define LB_TOTAL_NUMBER_OF_ENTRIES 1712
|
||||
#define LB_BITS_PER_ENTRY 144
|
||||
|
||||
#define XFM_COMMON_REG_LIST_DCE_BASE(id) \
|
||||
SRI(LB_DATA_FORMAT, LB, id), \
|
||||
SRI(GAMUT_REMAP_CONTROL, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C11_C12, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C13_C14, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C21_C22, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C23_C24, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C31_C32, DCP, id), \
|
||||
SRI(GAMUT_REMAP_C33_C34, DCP, id), \
|
||||
SRI(DENORM_CONTROL, DCP, id), \
|
||||
SRI(DCP_SPATIAL_DITHER_CNTL, DCP, id), \
|
||||
SRI(OUT_ROUND_CONTROL, DCP, id), \
|
||||
SRI(OUT_CLAMP_CONTROL_R_CR, DCP, id), \
|
||||
SRI(OUT_CLAMP_CONTROL_G_Y, DCP, id), \
|
||||
SRI(OUT_CLAMP_CONTROL_B_CB, DCP, id), \
|
||||
SRI(SCL_MODE, SCL, id), \
|
||||
SRI(SCL_TAP_CONTROL, SCL, id), \
|
||||
SRI(SCL_CONTROL, SCL, id), \
|
||||
SRI(EXT_OVERSCAN_LEFT_RIGHT, SCL, id), \
|
||||
SRI(EXT_OVERSCAN_TOP_BOTTOM, SCL, id), \
|
||||
SRI(SCL_VERT_FILTER_CONTROL, SCL, id), \
|
||||
SRI(SCL_HORZ_FILTER_CONTROL, SCL, id), \
|
||||
SRI(SCL_COEF_RAM_SELECT, SCL, id), \
|
||||
SRI(SCL_COEF_RAM_TAP_DATA, SCL, id), \
|
||||
SRI(VIEWPORT_START, SCL, id), \
|
||||
SRI(VIEWPORT_SIZE, SCL, id), \
|
||||
SRI(SCL_HORZ_FILTER_SCALE_RATIO, SCL, id), \
|
||||
SRI(SCL_VERT_FILTER_SCALE_RATIO, SCL, id), \
|
||||
SRI(SCL_HORZ_FILTER_INIT, SCL, id), \
|
||||
SRI(SCL_VERT_FILTER_INIT, SCL, id), \
|
||||
SRI(SCL_AUTOMATIC_MODE_CONTROL, SCL, id), \
|
||||
SRI(LB_MEMORY_CTRL, LB, id), \
|
||||
SRI(SCL_UPDATE, SCL, id)
|
||||
|
||||
#define XFM_COMMON_REG_LIST_DCE100(id) \
|
||||
XFM_COMMON_REG_LIST_DCE_BASE(id), \
|
||||
SRI(DCFE_MEM_PWR_CTRL, CRTC, id), \
|
||||
SRI(DCFE_MEM_PWR_STATUS, CRTC, id)
|
||||
|
||||
#define XFM_COMMON_REG_LIST_DCE110(id) \
|
||||
XFM_COMMON_REG_LIST_DCE_BASE(id), \
|
||||
SRI(DCFE_MEM_PWR_CTRL, DCFE, id), \
|
||||
SRI(DCFE_MEM_PWR_STATUS, DCFE, id)
|
||||
|
||||
#define XFM_SF(reg_name, field_name, post_fix)\
|
||||
.field_name = reg_name ## __ ## field_name ## post_fix
|
||||
|
||||
#define XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh) \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MIN_B_CB, mask_sh), \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_B_CB, OUT_CLAMP_MAX_B_CB, mask_sh), \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MIN_G_Y, mask_sh), \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_G_Y, OUT_CLAMP_MAX_G_Y, mask_sh), \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MIN_R_CR, mask_sh), \
|
||||
XFM_SF(OUT_CLAMP_CONTROL_R_CR, OUT_CLAMP_MAX_R_CR, mask_sh), \
|
||||
XFM_SF(OUT_ROUND_CONTROL, OUT_ROUND_TRUNC_MODE, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_EN, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_MODE, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_SPATIAL_DITHER_DEPTH, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_FRAME_RANDOM_ENABLE, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_RGB_RANDOM_ENABLE, mask_sh), \
|
||||
XFM_SF(DCP_SPATIAL_DITHER_CNTL, DCP_HIGHPASS_RANDOM_ENABLE, mask_sh), \
|
||||
XFM_SF(DENORM_CONTROL, DENORM_MODE, mask_sh), \
|
||||
XFM_SF(LB_DATA_FORMAT, PIXEL_DEPTH, mask_sh), \
|
||||
XFM_SF(LB_DATA_FORMAT, PIXEL_EXPAN_MODE, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C11, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C11_C12, GAMUT_REMAP_C12, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C13, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C13_C14, GAMUT_REMAP_C14, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C21, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C21_C22, GAMUT_REMAP_C22, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C23, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C23_C24, GAMUT_REMAP_C24, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C31, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C31_C32, GAMUT_REMAP_C32, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C33, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_C33_C34, GAMUT_REMAP_C34, mask_sh), \
|
||||
XFM_SF(GAMUT_REMAP_CONTROL, GRPH_GAMUT_REMAP_MODE, mask_sh), \
|
||||
XFM_SF(SCL_MODE, SCL_MODE, mask_sh), \
|
||||
XFM_SF(SCL_TAP_CONTROL, SCL_H_NUM_OF_TAPS, mask_sh), \
|
||||
XFM_SF(SCL_TAP_CONTROL, SCL_V_NUM_OF_TAPS, mask_sh), \
|
||||
XFM_SF(SCL_CONTROL, SCL_BOUNDARY_MODE, mask_sh), \
|
||||
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_LEFT, mask_sh), \
|
||||
XFM_SF(EXT_OVERSCAN_LEFT_RIGHT, EXT_OVERSCAN_RIGHT, mask_sh), \
|
||||
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_TOP, mask_sh), \
|
||||
XFM_SF(EXT_OVERSCAN_TOP_BOTTOM, EXT_OVERSCAN_BOTTOM, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_FILTER_TYPE, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_PHASE, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_SELECT, SCL_C_RAM_TAP_PAIR_IDX, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF_EN, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_EVEN_TAP_COEF, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF_EN, mask_sh), \
|
||||
XFM_SF(SCL_COEF_RAM_TAP_DATA, SCL_C_RAM_ODD_TAP_COEF, mask_sh), \
|
||||
XFM_SF(VIEWPORT_START, VIEWPORT_X_START, mask_sh), \
|
||||
XFM_SF(VIEWPORT_START, VIEWPORT_Y_START, mask_sh), \
|
||||
XFM_SF(VIEWPORT_SIZE, VIEWPORT_HEIGHT, mask_sh), \
|
||||
XFM_SF(VIEWPORT_SIZE, VIEWPORT_WIDTH, mask_sh), \
|
||||
XFM_SF(SCL_HORZ_FILTER_SCALE_RATIO, SCL_H_SCALE_RATIO, mask_sh), \
|
||||
XFM_SF(SCL_VERT_FILTER_SCALE_RATIO, SCL_V_SCALE_RATIO, mask_sh), \
|
||||
XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_INT, mask_sh), \
|
||||
XFM_SF(SCL_HORZ_FILTER_INIT, SCL_H_INIT_FRAC, mask_sh), \
|
||||
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_INT, mask_sh), \
|
||||
XFM_SF(SCL_VERT_FILTER_INIT, SCL_V_INIT_FRAC, mask_sh), \
|
||||
XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_CONFIG, mask_sh), \
|
||||
XFM_SF(LB_MEMORY_CTRL, LB_MEMORY_SIZE, mask_sh), \
|
||||
XFM_SF(SCL_VERT_FILTER_CONTROL, SCL_V_2TAP_HARDCODE_COEF_EN, mask_sh), \
|
||||
XFM_SF(SCL_HORZ_FILTER_CONTROL, SCL_H_2TAP_HARDCODE_COEF_EN, mask_sh), \
|
||||
XFM_SF(SCL_UPDATE, SCL_COEF_UPDATE_COMPLETE, mask_sh), \
|
||||
XFM_SF(LB_DATA_FORMAT, ALPHA_EN, mask_sh)
|
||||
|
||||
#define XFM_COMMON_MASK_SH_LIST_DCE110(mask_sh) \
|
||||
XFM_COMMON_MASK_SH_LIST_DCE_COMMON_BASE(mask_sh), \
|
||||
XFM_SF(DCFE_MEM_PWR_CTRL, SCL_COEFF_MEM_PWR_DIS, mask_sh), \
|
||||
XFM_SF(DCFE_MEM_PWR_STATUS, SCL_COEFF_MEM_PWR_STATE, mask_sh), \
|
||||
XFM_SF(SCL_MODE, SCL_PSCL_EN, mask_sh)
|
||||
|
||||
#define XFM_REG_FIELD_LIST(type) \
|
||||
type OUT_CLAMP_MIN_B_CB; \
|
||||
type OUT_CLAMP_MAX_B_CB; \
|
||||
type OUT_CLAMP_MIN_G_Y; \
|
||||
type OUT_CLAMP_MAX_G_Y; \
|
||||
type OUT_CLAMP_MIN_R_CR; \
|
||||
type OUT_CLAMP_MAX_R_CR; \
|
||||
type OUT_ROUND_TRUNC_MODE; \
|
||||
type DCP_SPATIAL_DITHER_EN; \
|
||||
type DCP_SPATIAL_DITHER_MODE; \
|
||||
type DCP_SPATIAL_DITHER_DEPTH; \
|
||||
type DCP_FRAME_RANDOM_ENABLE; \
|
||||
type DCP_RGB_RANDOM_ENABLE; \
|
||||
type DCP_HIGHPASS_RANDOM_ENABLE; \
|
||||
type DENORM_MODE; \
|
||||
type PIXEL_DEPTH; \
|
||||
type PIXEL_EXPAN_MODE; \
|
||||
type GAMUT_REMAP_C11; \
|
||||
type GAMUT_REMAP_C12; \
|
||||
type GAMUT_REMAP_C13; \
|
||||
type GAMUT_REMAP_C14; \
|
||||
type GAMUT_REMAP_C21; \
|
||||
type GAMUT_REMAP_C22; \
|
||||
type GAMUT_REMAP_C23; \
|
||||
type GAMUT_REMAP_C24; \
|
||||
type GAMUT_REMAP_C31; \
|
||||
type GAMUT_REMAP_C32; \
|
||||
type GAMUT_REMAP_C33; \
|
||||
type GAMUT_REMAP_C34; \
|
||||
type GRPH_GAMUT_REMAP_MODE; \
|
||||
type SCL_MODE; \
|
||||
type SCL_PSCL_EN; \
|
||||
type SCL_H_NUM_OF_TAPS; \
|
||||
type SCL_V_NUM_OF_TAPS; \
|
||||
type SCL_BOUNDARY_MODE; \
|
||||
type EXT_OVERSCAN_LEFT; \
|
||||
type EXT_OVERSCAN_RIGHT; \
|
||||
type EXT_OVERSCAN_TOP; \
|
||||
type EXT_OVERSCAN_BOTTOM; \
|
||||
type SCL_COEFF_MEM_PWR_DIS; \
|
||||
type SCL_COEFF_MEM_PWR_STATE; \
|
||||
type SCL_C_RAM_FILTER_TYPE; \
|
||||
type SCL_C_RAM_PHASE; \
|
||||
type SCL_C_RAM_TAP_PAIR_IDX; \
|
||||
type SCL_C_RAM_EVEN_TAP_COEF_EN; \
|
||||
type SCL_C_RAM_EVEN_TAP_COEF; \
|
||||
type SCL_C_RAM_ODD_TAP_COEF_EN; \
|
||||
type SCL_C_RAM_ODD_TAP_COEF; \
|
||||
type VIEWPORT_X_START; \
|
||||
type VIEWPORT_Y_START; \
|
||||
type VIEWPORT_HEIGHT; \
|
||||
type VIEWPORT_WIDTH; \
|
||||
type SCL_H_SCALE_RATIO; \
|
||||
type SCL_V_SCALE_RATIO; \
|
||||
type SCL_H_INIT_INT; \
|
||||
type SCL_H_INIT_FRAC; \
|
||||
type SCL_V_INIT_INT; \
|
||||
type SCL_V_INIT_FRAC; \
|
||||
type LB_MEMORY_CONFIG; \
|
||||
type LB_MEMORY_SIZE; \
|
||||
type SCL_V_2TAP_HARDCODE_COEF_EN; \
|
||||
type SCL_H_2TAP_HARDCODE_COEF_EN; \
|
||||
type SCL_COEF_UPDATE_COMPLETE; \
|
||||
type ALPHA_EN
|
||||
|
||||
struct dce_transform_shift {
|
||||
XFM_REG_FIELD_LIST(uint8_t);
|
||||
};
|
||||
|
||||
struct dce_transform_mask {
|
||||
XFM_REG_FIELD_LIST(uint32_t);
|
||||
};
|
||||
|
||||
struct dce_transform_registers {
|
||||
uint32_t LB_DATA_FORMAT;
|
||||
uint32_t GAMUT_REMAP_CONTROL;
|
||||
uint32_t GAMUT_REMAP_C11_C12;
|
||||
uint32_t GAMUT_REMAP_C13_C14;
|
||||
uint32_t GAMUT_REMAP_C21_C22;
|
||||
uint32_t GAMUT_REMAP_C23_C24;
|
||||
uint32_t GAMUT_REMAP_C31_C32;
|
||||
uint32_t GAMUT_REMAP_C33_C34;
|
||||
uint32_t DENORM_CONTROL;
|
||||
uint32_t DCP_SPATIAL_DITHER_CNTL;
|
||||
uint32_t OUT_ROUND_CONTROL;
|
||||
uint32_t OUT_CLAMP_CONTROL_R_CR;
|
||||
uint32_t OUT_CLAMP_CONTROL_G_Y;
|
||||
uint32_t OUT_CLAMP_CONTROL_B_CB;
|
||||
uint32_t SCL_MODE;
|
||||
uint32_t SCL_TAP_CONTROL;
|
||||
uint32_t SCL_CONTROL;
|
||||
uint32_t EXT_OVERSCAN_LEFT_RIGHT;
|
||||
uint32_t EXT_OVERSCAN_TOP_BOTTOM;
|
||||
uint32_t SCL_VERT_FILTER_CONTROL;
|
||||
uint32_t SCL_HORZ_FILTER_CONTROL;
|
||||
uint32_t DCFE_MEM_PWR_CTRL;
|
||||
uint32_t DCFE_MEM_PWR_STATUS;
|
||||
uint32_t SCL_COEF_RAM_SELECT;
|
||||
uint32_t SCL_COEF_RAM_TAP_DATA;
|
||||
uint32_t VIEWPORT_START;
|
||||
uint32_t VIEWPORT_SIZE;
|
||||
uint32_t SCL_HORZ_FILTER_SCALE_RATIO;
|
||||
uint32_t SCL_VERT_FILTER_SCALE_RATIO;
|
||||
uint32_t SCL_HORZ_FILTER_INIT;
|
||||
uint32_t SCL_VERT_FILTER_INIT;
|
||||
uint32_t SCL_AUTOMATIC_MODE_CONTROL;
|
||||
uint32_t LB_MEMORY_CTRL;
|
||||
uint32_t SCL_UPDATE;
|
||||
};
|
||||
|
||||
struct init_int_and_frac {
|
||||
uint32_t integer;
|
||||
uint32_t fraction;
|
||||
};
|
||||
|
||||
struct scl_ratios_inits {
|
||||
uint32_t h_int_scale_ratio;
|
||||
uint32_t v_int_scale_ratio;
|
||||
struct init_int_and_frac h_init;
|
||||
struct init_int_and_frac v_init;
|
||||
};
|
||||
|
||||
enum ram_filter_type {
|
||||
FILTER_TYPE_RGB_Y_VERTICAL = 0, /* 0 - RGB/Y Vertical filter */
|
||||
FILTER_TYPE_CBCR_VERTICAL = 1, /* 1 - CbCr Vertical filter */
|
||||
FILTER_TYPE_RGB_Y_HORIZONTAL = 2, /* 1 - RGB/Y Horizontal filter */
|
||||
FILTER_TYPE_CBCR_HORIZONTAL = 3, /* 3 - CbCr Horizontal filter */
|
||||
FILTER_TYPE_ALPHA_VERTICAL = 4, /* 4 - Alpha Vertical filter. */
|
||||
FILTER_TYPE_ALPHA_HORIZONTAL = 5, /* 5 - Alpha Horizontal filter. */
|
||||
};
|
||||
|
||||
struct dce_transform {
|
||||
struct transform base;
|
||||
const struct dce_transform_registers *regs;
|
||||
const struct dce_transform_shift *xfm_shift;
|
||||
const struct dce_transform_mask *xfm_mask;
|
||||
|
||||
const uint16_t *filter_v;
|
||||
const uint16_t *filter_h;
|
||||
const uint16_t *filter_v_c;
|
||||
const uint16_t *filter_h_c;
|
||||
int lb_pixel_depth_supported;
|
||||
int lb_memory_size;
|
||||
int lb_bits_per_entry;
|
||||
bool prescaler_on;
|
||||
};
|
||||
|
||||
bool dce_transform_construct(struct dce_transform *xfm110,
|
||||
struct dc_context *ctx,
|
||||
uint32_t inst,
|
||||
const struct dce_transform_registers *regs,
|
||||
const struct dce_transform_shift *xfm_shift,
|
||||
const struct dce_transform_mask *xfm_mask);
|
||||
|
||||
bool dce_transform_get_optimal_number_of_taps(
|
||||
struct transform *xfm,
|
||||
struct scaler_data *scl_data,
|
||||
const struct scaling_taps *in_taps);
|
||||
|
||||
|
||||
#endif /* _DCE_DCE_TRANSFORM_H_ */
|
|
@ -0,0 +1,23 @@
|
|||
#
|
||||
# Makefile for the 'controller' sub-component of DAL.
|
||||
# It provides the control and status of HW CRTC block.
|
||||
|
||||
DCE100 = dce100_resource.o dce100_hw_sequencer.o
|
||||
|
||||
AMD_DAL_DCE100 = $(addprefix $(AMDDALPATH)/dc/dce100/,$(DCE100))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_DCE100)
|
||||
|
||||
|
||||
###############################################################################
|
||||
# DCE 10x
|
||||
###############################################################################
|
||||
ifdef 0#CONFIG_DRM_AMD_DC_DCE11_0
|
||||
TG_DCE100 = dce100_resource.o
|
||||
|
||||
AMD_DAL_TG_DCE100 = $(addprefix \
|
||||
$(AMDDALPATH)/dc/dce100/,$(TG_DCE100))
|
||||
|
||||
AMD_DISPLAY_FILES += $(AMD_DAL_TG_DCE100)
|
||||
endif
|
||||
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* 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 "dm_services.h"
|
||||
#include "dc.h"
|
||||
#include "core_dc.h"
|
||||
#include "core_types.h"
|
||||
#include "hw_sequencer.h"
|
||||
#include "dce100_hw_sequencer.h"
|
||||
#include "dce110/dce110_hw_sequencer.h"
|
||||
|
||||
/* include DCE10 register header files */
|
||||
#include "dce/dce_10_0_d.h"
|
||||
#include "dce/dce_10_0_sh_mask.h"
|
||||
|
||||
struct dce100_hw_seq_reg_offsets {
|
||||
uint32_t blnd;
|
||||
uint32_t crtc;
|
||||
};
|
||||
|
||||
static const struct dce100_hw_seq_reg_offsets reg_offsets[] = {
|
||||
{
|
||||
.crtc = (mmCRTC0_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
},
|
||||
{
|
||||
.crtc = (mmCRTC1_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
},
|
||||
{
|
||||
.crtc = (mmCRTC2_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
},
|
||||
{
|
||||
.crtc = (mmCRTC3_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
},
|
||||
{
|
||||
.crtc = (mmCRTC4_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
},
|
||||
{
|
||||
.crtc = (mmCRTC5_CRTC_GSL_CONTROL - mmCRTC_GSL_CONTROL),
|
||||
}
|
||||
};
|
||||
|
||||
#define HW_REG_CRTC(reg, id)\
|
||||
(reg + reg_offsets[id].crtc)
|
||||
|
||||
/*******************************************************************************
|
||||
* Private definitions
|
||||
******************************************************************************/
|
||||
/***************************PIPE_CONTROL***********************************/
|
||||
|
||||
static bool dce100_enable_display_power_gating(
|
||||
struct core_dc *dc,
|
||||
uint8_t controller_id,
|
||||
struct dc_bios *dcb,
|
||||
enum pipe_gating_control power_gating)
|
||||
{
|
||||
enum bp_result bp_result = BP_RESULT_OK;
|
||||
enum bp_pipe_control_action cntl;
|
||||
struct dc_context *ctx = dc->ctx;
|
||||
|
||||
if (power_gating == PIPE_GATING_CONTROL_INIT)
|
||||
cntl = ASIC_PIPE_INIT;
|
||||
else if (power_gating == PIPE_GATING_CONTROL_ENABLE)
|
||||
cntl = ASIC_PIPE_ENABLE;
|
||||
else
|
||||
cntl = ASIC_PIPE_DISABLE;
|
||||
|
||||
if (!(power_gating == PIPE_GATING_CONTROL_INIT && controller_id != 0)){
|
||||
|
||||
bp_result = dcb->funcs->enable_disp_power_gating(
|
||||
dcb, controller_id + 1, cntl);
|
||||
|
||||
/* Revert MASTER_UPDATE_MODE to 0 because bios sets it 2
|
||||
* by default when command table is called
|
||||
*/
|
||||
dm_write_reg(ctx,
|
||||
HW_REG_CRTC(mmMASTER_UPDATE_MODE, controller_id),
|
||||
0);
|
||||
}
|
||||
|
||||
if (bp_result == BP_RESULT_OK)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
static void set_display_mark_for_pipe_if_needed(struct core_dc *dc,
|
||||
struct pipe_ctx *pipe_ctx,
|
||||
struct validate_context *context)
|
||||
{
|
||||
/* Do nothing until we have proper bandwitdth calcs */
|
||||
}
|
||||
|
||||
static void set_displaymarks(
|
||||
const struct core_dc *dc, struct validate_context *context)
|
||||
{
|
||||
/* Do nothing until we have proper bandwitdth calcs */
|
||||
}
|
||||
|
||||
static void set_bandwidth(struct core_dc *dc)
|
||||
{
|
||||
/* Do nothing until we have proper bandwitdth calcs */
|
||||
}
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
|
||||
bool dce100_hw_sequencer_construct(struct core_dc *dc)
|
||||
{
|
||||
dce110_hw_sequencer_construct(dc);
|
||||
|
||||
/* TODO: dce80 is empty implementation at the moment*/
|
||||
dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
|
||||
dc->hwss.set_displaymarks = set_displaymarks;
|
||||
dc->hwss.increase_watermarks_for_pipe = set_display_mark_for_pipe_if_needed;
|
||||
dc->hwss.set_bandwidth = set_bandwidth;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,36 @@
|
|||
/*
|
||||
* Copyright 2012-15 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 __DC_HWSS_DCE100_H__
|
||||
#define __DC_HWSS_DCE100_H__
|
||||
|
||||
#include "core_types.h"
|
||||
|
||||
struct core_dc;
|
||||
|
||||
bool dce100_hw_sequencer_construct(struct core_dc *dc);
|
||||
|
||||
#endif /* __DC_HWSS_DCE100_H__ */
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* dce100_resource.h
|
||||
*
|
||||
* Created on: 2016-01-20
|
||||
* Author: qyang
|
||||
*/
|
||||
|
||||
#ifndef DCE100_RESOURCE_H_
|
||||
#define DCE100_RESOURCE_H_
|
||||
|
||||
struct core_dc;
|
||||
struct resource_pool;
|
||||
struct dc_validation_set;
|
||||
|
||||
struct resource_pool *dce100_create_resource_pool(
|
||||
uint8_t num_virtual_links,
|
||||
struct core_dc *dc);
|
||||
|
||||
#endif /* DCE100_RESOURCE_H_ */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue