mirror of
git://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-03-22 07:27:12 +08:00
Merge tag 'drm-fixes-2026-01-16' of https://gitlab.freedesktop.org/drm/kernel
Pull drm fixes from Simona Vetter:
"We've had nothing aside of a compiler noise fix until today, when the
amd and drm-misc fixes showed up after Dave already went into weekend
mode. So it's on me to push these out, since there's a bunch of
important fixes in here I think that shouldn't be delayed for a week.
Core Changes:
- take gem lock when preallocating in gpuvm
- add single byte read fallback to dp for broken usb-c adapters
- remove duplicate drm_sysfb declarations
Driver Changes:
- i915: compiler noise fix
- amdgpu/amdkfd: pile of fixes all over
- vmwgfx:
- v10 cursor regression fix
- other fixes
- rockchip:
- waiting for cfgdone regression fix
- other fixes
- gud: fix oops on disconnect
- simple-panel:
- regression fix when connector is not set
- fix for DataImage SCF0700C48GGU18
- nouveau: cursor handling locking fix"
* tag 'drm-fixes-2026-01-16' of https://gitlab.freedesktop.org/drm/kernel: (33 commits)
drm/amd/display: Add an hdmi_hpd_debounce_delay_ms module
drm/amdgpu/userq: Fix fence reference leak on queue teardown v2
drm/amdkfd: No need to suspend whole MES to evict process
Revert "drm/amdgpu: don't attach the tlb fence for SI"
drm/amdgpu: validate the flush_gpu_tlb_pasid()
drm/amd/pm: fix smu overdrive data type wrong issue on smu 14.0.2
drm/amd/display: Initialise backlight level values from hw
drm/amd/display: Bump the HDMI clock to 340MHz
drm/amd/display: Show link name in PSR status message
drm/amdkfd: fix a memory leak in device_queue_manager_init()
drm/amdgpu: make sure userqs are enabled in userq IOCTLs
drm/amdgpu: Use correct address to setup gart page table for vram access
Revert duplicate "drm/amdgpu: disable peer-to-peer access for DCC-enabled GC12 VRAM surfaces"
drm/amd: Clean up kfd node on surprise disconnect
drm/amdgpu: fix drm panic null pointer when driver not support atomic
drm/amdgpu: Fix gfx9 update PTE mtype flag
drm/sysfb: Remove duplicate declarations
drm/nouveau/kms/nv50-: Assert we hold nv50_disp->lock in nv50_head_flush_*
drm/nouveau/disp/nv50-: Set lock_core in curs507a_prepare
drm/gud: fix NULL fb and crtc dereferences on USB disconnect
...
This commit is contained in:
@@ -274,6 +274,8 @@ extern int amdgpu_rebar;
|
||||
extern int amdgpu_wbrf;
|
||||
extern int amdgpu_user_queue;
|
||||
|
||||
extern uint amdgpu_hdmi_hpd_debounce_delay_ms;
|
||||
|
||||
#define AMDGPU_VM_MAX_NUM_CTX 4096
|
||||
#define AMDGPU_SG_THRESHOLD (256*1024*1024)
|
||||
#define AMDGPU_WAIT_IDLE_TIMEOUT_IN_MS 3000
|
||||
|
||||
@@ -5063,6 +5063,14 @@ void amdgpu_device_fini_hw(struct amdgpu_device *adev)
|
||||
|
||||
amdgpu_ttm_set_buffer_funcs_status(adev, false);
|
||||
|
||||
/*
|
||||
* device went through surprise hotplug; we need to destroy topology
|
||||
* before ip_fini_early to prevent kfd locking refcount issues by calling
|
||||
* amdgpu_amdkfd_suspend()
|
||||
*/
|
||||
if (drm_dev_is_unplugged(adev_to_drm(adev)))
|
||||
amdgpu_amdkfd_device_fini_sw(adev);
|
||||
|
||||
amdgpu_device_ip_fini_early(adev);
|
||||
|
||||
amdgpu_irq_fini_hw(adev);
|
||||
|
||||
@@ -1880,7 +1880,12 @@ int amdgpu_display_get_scanout_buffer(struct drm_plane *plane,
|
||||
struct drm_scanout_buffer *sb)
|
||||
{
|
||||
struct amdgpu_bo *abo;
|
||||
struct drm_framebuffer *fb = plane->state->fb;
|
||||
struct drm_framebuffer *fb;
|
||||
|
||||
if (drm_drv_uses_atomic_modeset(plane->dev))
|
||||
fb = plane->state->fb;
|
||||
else
|
||||
fb = plane->fb;
|
||||
|
||||
if (!fb)
|
||||
return -EINVAL;
|
||||
|
||||
@@ -83,18 +83,6 @@ static int amdgpu_dma_buf_attach(struct dma_buf *dmabuf,
|
||||
struct amdgpu_device *adev = amdgpu_ttm_adev(bo->tbo.bdev);
|
||||
int r;
|
||||
|
||||
/*
|
||||
* Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
|
||||
* Such buffers cannot be safely accessed over P2P due to device-local
|
||||
* compression metadata. Fallback to system-memory path instead.
|
||||
* Device supports GFX12 (GC 12.x or newer)
|
||||
* BO was created with the AMDGPU_GEM_CREATE_GFX12_DCC flag
|
||||
*
|
||||
*/
|
||||
if (amdgpu_ip_version(adev, GC_HWIP, 0) >= IP_VERSION(12, 0, 0) &&
|
||||
bo->flags & AMDGPU_GEM_CREATE_GFX12_DCC)
|
||||
attach->peer2peer = false;
|
||||
|
||||
/*
|
||||
* Disable peer-to-peer access for DCC-enabled VRAM surfaces on GFX12+.
|
||||
* Such buffers cannot be safely accessed over P2P due to device-local
|
||||
|
||||
@@ -247,6 +247,7 @@ int amdgpu_damage_clips = -1; /* auto */
|
||||
int amdgpu_umsch_mm_fwlog;
|
||||
int amdgpu_rebar = -1; /* auto */
|
||||
int amdgpu_user_queue = -1;
|
||||
uint amdgpu_hdmi_hpd_debounce_delay_ms;
|
||||
|
||||
DECLARE_DYNDBG_CLASSMAP(drm_debug_classes, DD_CLASS_TYPE_DISJOINT_BITS, 0,
|
||||
"DRM_UT_CORE",
|
||||
@@ -1123,6 +1124,16 @@ module_param_named(rebar, amdgpu_rebar, int, 0444);
|
||||
MODULE_PARM_DESC(user_queue, "Enable user queues (-1 = auto (default), 0 = disable, 1 = enable, 2 = enable UQs and disable KQs)");
|
||||
module_param_named(user_queue, amdgpu_user_queue, int, 0444);
|
||||
|
||||
/*
|
||||
* DOC: hdmi_hpd_debounce_delay_ms (uint)
|
||||
* HDMI HPD disconnect debounce delay in milliseconds.
|
||||
*
|
||||
* Used to filter short disconnect->reconnect HPD toggles some HDMI sinks
|
||||
* generate while entering/leaving power save. Set to 0 to disable by default.
|
||||
*/
|
||||
MODULE_PARM_DESC(hdmi_hpd_debounce_delay_ms, "HDMI HPD disconnect debounce delay in milliseconds (0 to disable (by default), 1500 is common)");
|
||||
module_param_named(hdmi_hpd_debounce_delay_ms, amdgpu_hdmi_hpd_debounce_delay_ms, uint, 0644);
|
||||
|
||||
/* These devices are not supported by amdgpu.
|
||||
* They are supported by the mach64, r128, radeon drivers
|
||||
*/
|
||||
|
||||
@@ -375,7 +375,7 @@ void amdgpu_gart_map(struct amdgpu_device *adev, uint64_t offset,
|
||||
* @start_page: first page to map in the GART aperture
|
||||
* @num_pages: number of pages to be mapped
|
||||
* @flags: page table entry flags
|
||||
* @dst: CPU address of the GART table
|
||||
* @dst: valid CPU address of GART table, cannot be null
|
||||
*
|
||||
* Binds a BO that is allocated in VRAM to the GART page table
|
||||
* (all ASICs).
|
||||
@@ -396,7 +396,7 @@ void amdgpu_gart_map_vram_range(struct amdgpu_device *adev, uint64_t pa,
|
||||
return;
|
||||
|
||||
for (i = 0; i < num_pages; ++i) {
|
||||
amdgpu_gmc_set_pte_pde(adev, adev->gart.ptr,
|
||||
amdgpu_gmc_set_pte_pde(adev, dst,
|
||||
start_page + i, pa + AMDGPU_GPU_PAGE_SIZE * i, flags);
|
||||
}
|
||||
|
||||
|
||||
@@ -732,6 +732,10 @@ int amdgpu_gmc_flush_gpu_tlb_pasid(struct amdgpu_device *adev, uint16_t pasid,
|
||||
return 0;
|
||||
|
||||
if (!adev->gmc.flush_pasid_uses_kiq || !ring->sched.ready) {
|
||||
|
||||
if (!adev->gmc.gmc_funcs->flush_gpu_tlb_pasid)
|
||||
return 0;
|
||||
|
||||
if (adev->gmc.flush_tlb_needs_extra_type_2)
|
||||
adev->gmc.gmc_funcs->flush_gpu_tlb_pasid(adev, pasid,
|
||||
2, all_hub,
|
||||
|
||||
@@ -885,12 +885,28 @@ static int amdgpu_userq_input_args_validate(struct drm_device *dev,
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool amdgpu_userq_enabled(struct drm_device *dev)
|
||||
{
|
||||
struct amdgpu_device *adev = drm_to_adev(dev);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < AMDGPU_HW_IP_NUM; i++) {
|
||||
if (adev->userq_funcs[i])
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
int amdgpu_userq_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_file *filp)
|
||||
{
|
||||
union drm_amdgpu_userq *args = data;
|
||||
int r;
|
||||
|
||||
if (!amdgpu_userq_enabled(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
if (amdgpu_userq_input_args_validate(dev, args, filp) < 0)
|
||||
return -EINVAL;
|
||||
|
||||
|
||||
@@ -141,6 +141,7 @@ uint64_t amdgpu_userq_get_doorbell_index(struct amdgpu_userq_mgr *uq_mgr,
|
||||
struct drm_file *filp);
|
||||
|
||||
u32 amdgpu_userq_get_supported_ip_mask(struct amdgpu_device *adev);
|
||||
bool amdgpu_userq_enabled(struct drm_device *dev);
|
||||
|
||||
int amdgpu_userq_suspend(struct amdgpu_device *adev);
|
||||
int amdgpu_userq_resume(struct amdgpu_device *adev);
|
||||
|
||||
@@ -141,6 +141,8 @@ static void amdgpu_userq_walk_and_drop_fence_drv(struct xarray *xa)
|
||||
void
|
||||
amdgpu_userq_fence_driver_free(struct amdgpu_usermode_queue *userq)
|
||||
{
|
||||
dma_fence_put(userq->last_fence);
|
||||
|
||||
amdgpu_userq_walk_and_drop_fence_drv(&userq->fence_drv_xa);
|
||||
xa_destroy(&userq->fence_drv_xa);
|
||||
/* Drop the fence_drv reference held by user queue */
|
||||
@@ -471,6 +473,9 @@ int amdgpu_userq_signal_ioctl(struct drm_device *dev, void *data,
|
||||
struct drm_exec exec;
|
||||
u64 wptr;
|
||||
|
||||
if (!amdgpu_userq_enabled(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
num_syncobj_handles = args->num_syncobj_handles;
|
||||
syncobj_handles = memdup_user(u64_to_user_ptr(args->syncobj_handles),
|
||||
size_mul(sizeof(u32), num_syncobj_handles));
|
||||
@@ -653,6 +658,9 @@ int amdgpu_userq_wait_ioctl(struct drm_device *dev, void *data,
|
||||
int r, i, rentry, wentry, cnt;
|
||||
struct drm_exec exec;
|
||||
|
||||
if (!amdgpu_userq_enabled(dev))
|
||||
return -ENOTSUPP;
|
||||
|
||||
num_read_bo_handles = wait_info->num_bo_read_handles;
|
||||
bo_handles_read = memdup_user(u64_to_user_ptr(wait_info->bo_read_handles),
|
||||
size_mul(sizeof(u32), num_read_bo_handles));
|
||||
|
||||
@@ -1069,9 +1069,7 @@ amdgpu_vm_tlb_flush(struct amdgpu_vm_update_params *params,
|
||||
}
|
||||
|
||||
/* Prepare a TLB flush fence to be attached to PTs */
|
||||
if (!params->unlocked &&
|
||||
/* SI doesn't support pasid or KIQ/MES */
|
||||
params->adev->family > AMDGPU_FAMILY_SI) {
|
||||
if (!params->unlocked) {
|
||||
amdgpu_vm_tlb_fence_create(params->adev, vm, fence);
|
||||
|
||||
/* Makes sure no PD/PT is freed before the flush */
|
||||
|
||||
@@ -1235,16 +1235,16 @@ static void gmc_v9_0_get_vm_pte(struct amdgpu_device *adev,
|
||||
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_NC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_WC:
|
||||
*flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_WC);
|
||||
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_WC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_RW:
|
||||
*flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_RW);
|
||||
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_RW);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_CC:
|
||||
*flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_CC);
|
||||
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_CC);
|
||||
break;
|
||||
case AMDGPU_VM_MTYPE_UC:
|
||||
*flags |= AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_UC);
|
||||
*flags = AMDGPU_PTE_MTYPE_VG10(*flags, MTYPE_UC);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -1209,14 +1209,8 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
|
||||
pr_debug_ratelimited("Evicting process pid %d queues\n",
|
||||
pdd->process->lead_thread->pid);
|
||||
|
||||
if (dqm->dev->kfd->shared_resources.enable_mes) {
|
||||
if (dqm->dev->kfd->shared_resources.enable_mes)
|
||||
pdd->last_evict_timestamp = get_jiffies_64();
|
||||
retval = suspend_all_queues_mes(dqm);
|
||||
if (retval) {
|
||||
dev_err(dev, "Suspending all queues failed");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark all queues as evicted. Deactivate all active queues on
|
||||
* the qpd.
|
||||
@@ -1246,10 +1240,6 @@ static int evict_process_queues_cpsch(struct device_queue_manager *dqm,
|
||||
KFD_UNMAP_QUEUES_FILTER_ALL_QUEUES :
|
||||
KFD_UNMAP_QUEUES_FILTER_DYNAMIC_QUEUES, 0,
|
||||
USE_DEFAULT_GRACE_PERIOD);
|
||||
} else {
|
||||
retval = resume_all_queues_mes(dqm);
|
||||
if (retval)
|
||||
dev_err(dev, "Resuming all queues failed");
|
||||
}
|
||||
|
||||
out:
|
||||
@@ -2919,6 +2909,14 @@ static int allocate_hiq_sdma_mqd(struct device_queue_manager *dqm)
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
|
||||
struct kfd_mem_obj *mqd)
|
||||
{
|
||||
WARN(!mqd, "No hiq sdma mqd trunk to free");
|
||||
|
||||
amdgpu_amdkfd_free_gtt_mem(dev->adev, &mqd->gtt_mem);
|
||||
}
|
||||
|
||||
struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
|
||||
{
|
||||
struct device_queue_manager *dqm;
|
||||
@@ -3042,19 +3040,14 @@ struct device_queue_manager *device_queue_manager_init(struct kfd_node *dev)
|
||||
return dqm;
|
||||
}
|
||||
|
||||
if (!dev->kfd->shared_resources.enable_mes)
|
||||
deallocate_hiq_sdma_mqd(dev, &dqm->hiq_sdma_mqd);
|
||||
|
||||
out_free:
|
||||
kfree(dqm);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void deallocate_hiq_sdma_mqd(struct kfd_node *dev,
|
||||
struct kfd_mem_obj *mqd)
|
||||
{
|
||||
WARN(!mqd, "No hiq sdma mqd trunk to free");
|
||||
|
||||
amdgpu_amdkfd_free_gtt_mem(dev->adev, &mqd->gtt_mem);
|
||||
}
|
||||
|
||||
void device_queue_manager_uninit(struct device_queue_manager *dqm)
|
||||
{
|
||||
dqm->ops.stop(dqm);
|
||||
|
||||
@@ -5266,6 +5266,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
||||
struct amdgpu_dm_backlight_caps *caps;
|
||||
char bl_name[16];
|
||||
int min, max;
|
||||
int real_brightness;
|
||||
int init_brightness;
|
||||
|
||||
if (aconnector->bl_idx == -1)
|
||||
return;
|
||||
@@ -5290,6 +5292,8 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
||||
} else
|
||||
props.brightness = props.max_brightness = MAX_BACKLIGHT_LEVEL;
|
||||
|
||||
init_brightness = props.brightness;
|
||||
|
||||
if (caps->data_points && !(amdgpu_dc_debug_mask & DC_DISABLE_CUSTOM_BRIGHTNESS_CURVE)) {
|
||||
drm_info(drm, "Using custom brightness curve\n");
|
||||
props.scale = BACKLIGHT_SCALE_NON_LINEAR;
|
||||
@@ -5308,8 +5312,20 @@ amdgpu_dm_register_backlight_device(struct amdgpu_dm_connector *aconnector)
|
||||
if (IS_ERR(dm->backlight_dev[aconnector->bl_idx])) {
|
||||
drm_err(drm, "DM: Backlight registration failed!\n");
|
||||
dm->backlight_dev[aconnector->bl_idx] = NULL;
|
||||
} else
|
||||
} else {
|
||||
/*
|
||||
* dm->brightness[x] can be inconsistent just after startup until
|
||||
* ops.get_brightness is called.
|
||||
*/
|
||||
real_brightness =
|
||||
amdgpu_dm_backlight_ops.get_brightness(dm->backlight_dev[aconnector->bl_idx]);
|
||||
|
||||
if (real_brightness != init_brightness) {
|
||||
dm->actual_brightness[aconnector->bl_idx] = real_brightness;
|
||||
dm->brightness[aconnector->bl_idx] = real_brightness;
|
||||
}
|
||||
drm_dbg_driver(drm, "DM: Registered Backlight device: %s\n", bl_name);
|
||||
}
|
||||
}
|
||||
|
||||
static int initialize_plane(struct amdgpu_display_manager *dm,
|
||||
@@ -5626,7 +5642,8 @@ static int amdgpu_dm_initialize_drm_device(struct amdgpu_device *adev)
|
||||
|
||||
if (psr_feature_enabled) {
|
||||
amdgpu_dm_set_psr_caps(link);
|
||||
drm_info(adev_to_drm(adev), "PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n",
|
||||
drm_info(adev_to_drm(adev), "%s: PSR support %d, DC PSR ver %d, sink PSR ver %d DPCD caps 0x%x su_y_granularity %d\n",
|
||||
aconnector->base.name,
|
||||
link->psr_settings.psr_feature_enabled,
|
||||
link->psr_settings.psr_version,
|
||||
link->dpcd_caps.psr_info.psr_version,
|
||||
@@ -8930,9 +8947,18 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
|
||||
mutex_init(&aconnector->hpd_lock);
|
||||
mutex_init(&aconnector->handle_mst_msg_ready);
|
||||
|
||||
aconnector->hdmi_hpd_debounce_delay_ms = AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS;
|
||||
INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
|
||||
aconnector->hdmi_prev_sink = NULL;
|
||||
/*
|
||||
* If HDMI HPD debounce delay is set, use the minimum between selected
|
||||
* value and AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS
|
||||
*/
|
||||
if (amdgpu_hdmi_hpd_debounce_delay_ms) {
|
||||
aconnector->hdmi_hpd_debounce_delay_ms = min(amdgpu_hdmi_hpd_debounce_delay_ms,
|
||||
AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS);
|
||||
INIT_DELAYED_WORK(&aconnector->hdmi_hpd_debounce_work, hdmi_hpd_debounce_work);
|
||||
aconnector->hdmi_prev_sink = NULL;
|
||||
} else {
|
||||
aconnector->hdmi_hpd_debounce_delay_ms = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* configure support HPD hot plug connector_>polled default value is 0
|
||||
|
||||
@@ -59,7 +59,10 @@
|
||||
|
||||
#define AMDGPU_HDR_MULT_DEFAULT (0x100000000LL)
|
||||
|
||||
#define AMDGPU_DM_HDMI_HPD_DEBOUNCE_MS 1500
|
||||
/*
|
||||
* Maximum HDMI HPD debounce delay in milliseconds
|
||||
*/
|
||||
#define AMDGPU_DM_MAX_HDMI_HPD_DEBOUNCE_MS 5000
|
||||
/*
|
||||
#include "include/amdgpu_dal_power_if.h"
|
||||
#include "amdgpu_dm_irq.h"
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
/* kHZ*/
|
||||
#define DP_ADAPTOR_DVI_MAX_TMDS_CLK 165000
|
||||
/* kHZ*/
|
||||
#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 165000
|
||||
#define DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK 340000
|
||||
|
||||
struct dp_hdmi_dongle_signature_data {
|
||||
int8_t id[15];/* "DP-HDMI ADAPTOR"*/
|
||||
|
||||
@@ -336,7 +336,7 @@ static void query_dp_dual_mode_adaptor(
|
||||
|
||||
/* Assume we have no valid DP passive dongle connected */
|
||||
*dongle = DISPLAY_DONGLE_NONE;
|
||||
sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
|
||||
sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_DVI_MAX_TMDS_CLK;
|
||||
|
||||
/* Read DP-HDMI dongle I2c (no response interpreted as DP-DVI dongle)*/
|
||||
if (!i2c_read(
|
||||
@@ -392,6 +392,8 @@ static void query_dp_dual_mode_adaptor(
|
||||
|
||||
}
|
||||
}
|
||||
if (is_valid_hdmi_signature)
|
||||
sink_cap->max_hdmi_pixel_clock = DP_ADAPTOR_HDMI_SAFE_MAX_TMDS_CLK;
|
||||
|
||||
if (is_type2_dongle) {
|
||||
uint32_t max_tmds_clk =
|
||||
|
||||
@@ -1702,8 +1702,9 @@ static int smu_v14_0_2_get_power_limit(struct smu_context *smu,
|
||||
table_context->power_play_table;
|
||||
PPTable_t *pptable = table_context->driver_pptable;
|
||||
CustomSkuTable_t *skutable = &pptable->CustomSkuTable;
|
||||
uint32_t power_limit, od_percent_upper = 0, od_percent_lower = 0;
|
||||
int16_t od_percent_upper = 0, od_percent_lower = 0;
|
||||
uint32_t msg_limit = pptable->SkuTable.MsgLimits.Power[PPT_THROTTLER_PPT0][POWER_SOURCE_AC];
|
||||
uint32_t power_limit;
|
||||
|
||||
if (smu_v14_0_get_current_power_limit(smu, &power_limit))
|
||||
power_limit = smu->adev->pm.ac_power ?
|
||||
|
||||
@@ -163,6 +163,7 @@ struct dw_hdmi_qp {
|
||||
|
||||
unsigned long ref_clk_rate;
|
||||
struct regmap *regm;
|
||||
int main_irq;
|
||||
|
||||
unsigned long tmds_char_rate;
|
||||
};
|
||||
@@ -1271,6 +1272,7 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
|
||||
|
||||
dw_hdmi_qp_init_hw(hdmi);
|
||||
|
||||
hdmi->main_irq = plat_data->main_irq;
|
||||
ret = devm_request_threaded_irq(dev, plat_data->main_irq,
|
||||
dw_hdmi_qp_main_hardirq, NULL,
|
||||
IRQF_SHARED, dev_name(dev), hdmi);
|
||||
@@ -1331,9 +1333,16 @@ struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_qp_bind);
|
||||
|
||||
void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi)
|
||||
{
|
||||
disable_irq(hdmi->main_irq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_qp_suspend);
|
||||
|
||||
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi)
|
||||
{
|
||||
dw_hdmi_qp_init_hw(hdmi);
|
||||
enable_irq(hdmi->main_irq);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(dw_hdmi_qp_resume);
|
||||
|
||||
|
||||
@@ -1602,24 +1602,23 @@ drm_gpuvm_bo_create(struct drm_gpuvm *gpuvm,
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_create);
|
||||
|
||||
/*
|
||||
* drm_gpuvm_bo_destroy_not_in_lists() - final part of drm_gpuvm_bo cleanup
|
||||
* @vm_bo: the &drm_gpuvm_bo to destroy
|
||||
*
|
||||
* It is illegal to call this method if the @vm_bo is present in the GEMs gpuva
|
||||
* list, the extobj list, or the evicted list.
|
||||
*
|
||||
* Note that this puts a refcount on the GEM object, which may destroy the GEM
|
||||
* object if the refcount reaches zero. It's illegal for this to happen if the
|
||||
* caller holds the GEMs gpuva mutex because it would free the mutex.
|
||||
*/
|
||||
static void
|
||||
drm_gpuvm_bo_destroy(struct kref *kref)
|
||||
drm_gpuvm_bo_destroy_not_in_lists(struct drm_gpuvm_bo *vm_bo)
|
||||
{
|
||||
struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
|
||||
kref);
|
||||
struct drm_gpuvm *gpuvm = vm_bo->vm;
|
||||
const struct drm_gpuvm_ops *ops = gpuvm->ops;
|
||||
struct drm_gem_object *obj = vm_bo->obj;
|
||||
bool lock = !drm_gpuvm_resv_protected(gpuvm);
|
||||
|
||||
if (!lock)
|
||||
drm_gpuvm_resv_assert_held(gpuvm);
|
||||
|
||||
drm_gpuvm_bo_list_del(vm_bo, extobj, lock);
|
||||
drm_gpuvm_bo_list_del(vm_bo, evict, lock);
|
||||
|
||||
drm_gem_gpuva_assert_lock_held(gpuvm, obj);
|
||||
list_del(&vm_bo->list.entry.gem);
|
||||
|
||||
if (ops && ops->vm_bo_free)
|
||||
ops->vm_bo_free(vm_bo);
|
||||
@@ -1630,6 +1629,35 @@ drm_gpuvm_bo_destroy(struct kref *kref)
|
||||
drm_gem_object_put(obj);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_gpuvm_bo_destroy_not_in_lists_kref(struct kref *kref)
|
||||
{
|
||||
struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
|
||||
kref);
|
||||
|
||||
drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
|
||||
}
|
||||
|
||||
static void
|
||||
drm_gpuvm_bo_destroy(struct kref *kref)
|
||||
{
|
||||
struct drm_gpuvm_bo *vm_bo = container_of(kref, struct drm_gpuvm_bo,
|
||||
kref);
|
||||
struct drm_gpuvm *gpuvm = vm_bo->vm;
|
||||
bool lock = !drm_gpuvm_resv_protected(gpuvm);
|
||||
|
||||
if (!lock)
|
||||
drm_gpuvm_resv_assert_held(gpuvm);
|
||||
|
||||
drm_gpuvm_bo_list_del(vm_bo, extobj, lock);
|
||||
drm_gpuvm_bo_list_del(vm_bo, evict, lock);
|
||||
|
||||
drm_gem_gpuva_assert_lock_held(gpuvm, vm_bo->obj);
|
||||
list_del(&vm_bo->list.entry.gem);
|
||||
|
||||
drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_gpuvm_bo_put() - drop a struct drm_gpuvm_bo reference
|
||||
* @vm_bo: the &drm_gpuvm_bo to release the reference of
|
||||
@@ -1745,9 +1773,7 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_put_deferred);
|
||||
void
|
||||
drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
|
||||
{
|
||||
const struct drm_gpuvm_ops *ops = gpuvm->ops;
|
||||
struct drm_gpuvm_bo *vm_bo;
|
||||
struct drm_gem_object *obj;
|
||||
struct llist_node *bo_defer;
|
||||
|
||||
bo_defer = llist_del_all(&gpuvm->bo_defer);
|
||||
@@ -1766,14 +1792,7 @@ drm_gpuvm_bo_deferred_cleanup(struct drm_gpuvm *gpuvm)
|
||||
while (bo_defer) {
|
||||
vm_bo = llist_entry(bo_defer, struct drm_gpuvm_bo, list.entry.bo_defer);
|
||||
bo_defer = bo_defer->next;
|
||||
obj = vm_bo->obj;
|
||||
if (ops && ops->vm_bo_free)
|
||||
ops->vm_bo_free(vm_bo);
|
||||
else
|
||||
kfree(vm_bo);
|
||||
|
||||
drm_gpuvm_put(gpuvm);
|
||||
drm_gem_object_put(obj);
|
||||
drm_gpuvm_bo_destroy_not_in_lists(vm_bo);
|
||||
}
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(drm_gpuvm_bo_deferred_cleanup);
|
||||
@@ -1861,6 +1880,9 @@ EXPORT_SYMBOL_GPL(drm_gpuvm_bo_obtain);
|
||||
* count is decreased. If not found @__vm_bo is returned without further
|
||||
* increase of the reference count.
|
||||
*
|
||||
* The provided @__vm_bo must not already be in the gpuva, evict, or extobj
|
||||
* lists prior to calling this method.
|
||||
*
|
||||
* A new &drm_gpuvm_bo is added to the GEMs gpuva list.
|
||||
*
|
||||
* Returns: a pointer to the found &drm_gpuvm_bo or @__vm_bo if no existing
|
||||
@@ -1873,14 +1895,19 @@ drm_gpuvm_bo_obtain_prealloc(struct drm_gpuvm_bo *__vm_bo)
|
||||
struct drm_gem_object *obj = __vm_bo->obj;
|
||||
struct drm_gpuvm_bo *vm_bo;
|
||||
|
||||
drm_WARN_ON(gpuvm->drm, !drm_gpuvm_immediate_mode(gpuvm));
|
||||
|
||||
mutex_lock(&obj->gpuva.lock);
|
||||
vm_bo = drm_gpuvm_bo_find(gpuvm, obj);
|
||||
if (vm_bo) {
|
||||
drm_gpuvm_bo_put(__vm_bo);
|
||||
mutex_unlock(&obj->gpuva.lock);
|
||||
kref_put(&__vm_bo->kref, drm_gpuvm_bo_destroy_not_in_lists_kref);
|
||||
return vm_bo;
|
||||
}
|
||||
|
||||
drm_gem_gpuva_assert_lock_held(gpuvm, obj);
|
||||
list_add_tail(&__vm_bo->list.entry.gem, &obj->gpuva.list);
|
||||
mutex_unlock(&obj->gpuva.lock);
|
||||
|
||||
return __vm_bo;
|
||||
}
|
||||
|
||||
@@ -457,27 +457,20 @@ int gud_plane_atomic_check(struct drm_plane *plane,
|
||||
struct drm_plane_state *old_plane_state = drm_atomic_get_old_plane_state(state, plane);
|
||||
struct drm_plane_state *new_plane_state = drm_atomic_get_new_plane_state(state, plane);
|
||||
struct drm_crtc *crtc = new_plane_state->crtc;
|
||||
struct drm_crtc_state *crtc_state;
|
||||
struct drm_crtc_state *crtc_state = NULL;
|
||||
const struct drm_display_mode *mode;
|
||||
struct drm_framebuffer *old_fb = old_plane_state->fb;
|
||||
struct drm_connector_state *connector_state = NULL;
|
||||
struct drm_framebuffer *fb = new_plane_state->fb;
|
||||
const struct drm_format_info *format = fb->format;
|
||||
const struct drm_format_info *format;
|
||||
struct drm_connector *connector;
|
||||
unsigned int i, num_properties;
|
||||
struct gud_state_req *req;
|
||||
int idx, ret;
|
||||
size_t len;
|
||||
|
||||
if (drm_WARN_ON_ONCE(plane->dev, !fb))
|
||||
return -EINVAL;
|
||||
|
||||
if (drm_WARN_ON_ONCE(plane->dev, !crtc))
|
||||
return -EINVAL;
|
||||
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
|
||||
mode = &crtc_state->mode;
|
||||
if (crtc)
|
||||
crtc_state = drm_atomic_get_new_crtc_state(state, crtc);
|
||||
|
||||
ret = drm_atomic_helper_check_plane_state(new_plane_state, crtc_state,
|
||||
DRM_PLANE_NO_SCALING,
|
||||
@@ -492,6 +485,9 @@ int gud_plane_atomic_check(struct drm_plane *plane,
|
||||
if (old_plane_state->rotation != new_plane_state->rotation)
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
mode = &crtc_state->mode;
|
||||
format = fb->format;
|
||||
|
||||
if (old_fb && old_fb->format != format)
|
||||
crtc_state->mode_changed = true;
|
||||
|
||||
@@ -598,7 +594,7 @@ void gud_plane_atomic_update(struct drm_plane *plane,
|
||||
struct drm_atomic_helper_damage_iter iter;
|
||||
int ret, idx;
|
||||
|
||||
if (crtc->state->mode_changed || !crtc->state->enable) {
|
||||
if (!crtc || crtc->state->mode_changed || !crtc->state->enable) {
|
||||
cancel_work_sync(&gdrm->work);
|
||||
mutex_lock(&gdrm->damage_lock);
|
||||
if (gdrm->fb) {
|
||||
|
||||
@@ -686,7 +686,7 @@ static void err_print_guc_ctb(struct drm_i915_error_state_buf *m,
|
||||
}
|
||||
|
||||
/* This list includes registers that are useful in debugging GuC hangs. */
|
||||
const struct {
|
||||
static const struct {
|
||||
u32 start;
|
||||
u32 count;
|
||||
} guc_hw_reg_state[] = {
|
||||
|
||||
@@ -84,6 +84,7 @@ curs507a_prepare(struct nv50_wndw *wndw, struct nv50_head_atom *asyh,
|
||||
asyh->curs.handle = handle;
|
||||
asyh->curs.offset = offset;
|
||||
asyh->set.curs = asyh->curs.visible;
|
||||
nv50_atom(asyh->state.state)->lock_core = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,9 @@ nv50_head_flush_clr(struct nv50_head *head,
|
||||
union nv50_head_atom_mask clr = {
|
||||
.mask = asyh->clr.mask & ~(flush ? 0 : asyh->set.mask),
|
||||
};
|
||||
|
||||
lockdep_assert_held(&head->disp->mutex);
|
||||
|
||||
if (clr.crc) nv50_crc_atomic_clr(head);
|
||||
if (clr.olut) head->func->olut_clr(head);
|
||||
if (clr.core) head->func->core_clr(head);
|
||||
@@ -65,6 +68,8 @@ nv50_head_flush_set_wndw(struct nv50_head *head, struct nv50_head_atom *asyh)
|
||||
void
|
||||
nv50_head_flush_set(struct nv50_head *head, struct nv50_head_atom *asyh)
|
||||
{
|
||||
lockdep_assert_held(&head->disp->mutex);
|
||||
|
||||
if (asyh->set.view ) head->func->view (head, asyh);
|
||||
if (asyh->set.mode ) head->func->mode (head, asyh);
|
||||
if (asyh->set.core ) head->func->core_set(head, asyh);
|
||||
|
||||
@@ -623,8 +623,61 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
|
||||
if (IS_ERR(desc))
|
||||
return ERR_CAST(desc);
|
||||
|
||||
connector_type = desc->connector_type;
|
||||
/* Catch common mistakes for panels. */
|
||||
switch (connector_type) {
|
||||
case 0:
|
||||
dev_warn(dev, "Specify missing connector_type\n");
|
||||
connector_type = DRM_MODE_CONNECTOR_DPI;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
WARN_ON(desc->bus_flags &
|
||||
~(DRM_BUS_FLAG_DE_LOW |
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_DATA_MSB_TO_LSB |
|
||||
DRM_BUS_FLAG_DATA_LSB_TO_MSB));
|
||||
WARN_ON(desc->bus_format != MEDIA_BUS_FMT_RGB666_1X7X3_SPWG &&
|
||||
desc->bus_format != MEDIA_BUS_FMT_RGB888_1X7X4_SPWG &&
|
||||
desc->bus_format != MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA);
|
||||
WARN_ON(desc->bus_format == MEDIA_BUS_FMT_RGB666_1X7X3_SPWG &&
|
||||
desc->bpc != 6);
|
||||
WARN_ON((desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_SPWG ||
|
||||
desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA) &&
|
||||
desc->bpc != 8);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
dev_warn(dev, "eDP panels moved to panel-edp\n");
|
||||
return ERR_PTR(-EINVAL);
|
||||
case DRM_MODE_CONNECTOR_DSI:
|
||||
if (desc->bpc != 6 && desc->bpc != 8)
|
||||
dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DPI:
|
||||
bus_flags = DRM_BUS_FLAG_DE_LOW |
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
|
||||
DRM_BUS_FLAG_DATA_MSB_TO_LSB |
|
||||
DRM_BUS_FLAG_DATA_LSB_TO_MSB |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE;
|
||||
if (desc->bus_flags & ~bus_flags)
|
||||
dev_warn(dev, "Unexpected bus_flags(%d)\n", desc->bus_flags & ~bus_flags);
|
||||
if (!(desc->bus_flags & bus_flags))
|
||||
dev_warn(dev, "Specify missing bus_flags\n");
|
||||
if (desc->bus_format == 0)
|
||||
dev_warn(dev, "Specify missing bus_format\n");
|
||||
if (desc->bpc != 6 && desc->bpc != 8)
|
||||
dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "Specify a valid connector_type: %d\n", desc->connector_type);
|
||||
connector_type = DRM_MODE_CONNECTOR_DPI;
|
||||
break;
|
||||
}
|
||||
|
||||
panel = devm_drm_panel_alloc(dev, struct panel_simple, base,
|
||||
&panel_simple_funcs, desc->connector_type);
|
||||
&panel_simple_funcs, connector_type);
|
||||
if (IS_ERR(panel))
|
||||
return ERR_CAST(panel);
|
||||
|
||||
@@ -666,60 +719,6 @@ static struct panel_simple *panel_simple_probe(struct device *dev)
|
||||
goto free_ddc;
|
||||
}
|
||||
|
||||
connector_type = desc->connector_type;
|
||||
/* Catch common mistakes for panels. */
|
||||
switch (connector_type) {
|
||||
case 0:
|
||||
dev_warn(dev, "Specify missing connector_type\n");
|
||||
connector_type = DRM_MODE_CONNECTOR_DPI;
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_LVDS:
|
||||
WARN_ON(desc->bus_flags &
|
||||
~(DRM_BUS_FLAG_DE_LOW |
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_DATA_MSB_TO_LSB |
|
||||
DRM_BUS_FLAG_DATA_LSB_TO_MSB));
|
||||
WARN_ON(desc->bus_format != MEDIA_BUS_FMT_RGB666_1X7X3_SPWG &&
|
||||
desc->bus_format != MEDIA_BUS_FMT_RGB888_1X7X4_SPWG &&
|
||||
desc->bus_format != MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA);
|
||||
WARN_ON(desc->bus_format == MEDIA_BUS_FMT_RGB666_1X7X3_SPWG &&
|
||||
desc->bpc != 6);
|
||||
WARN_ON((desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_SPWG ||
|
||||
desc->bus_format == MEDIA_BUS_FMT_RGB888_1X7X4_JEIDA) &&
|
||||
desc->bpc != 8);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_eDP:
|
||||
dev_warn(dev, "eDP panels moved to panel-edp\n");
|
||||
err = -EINVAL;
|
||||
goto free_ddc;
|
||||
case DRM_MODE_CONNECTOR_DSI:
|
||||
if (desc->bpc != 6 && desc->bpc != 8)
|
||||
dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
|
||||
break;
|
||||
case DRM_MODE_CONNECTOR_DPI:
|
||||
bus_flags = DRM_BUS_FLAG_DE_LOW |
|
||||
DRM_BUS_FLAG_DE_HIGH |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_POSEDGE |
|
||||
DRM_BUS_FLAG_PIXDATA_SAMPLE_NEGEDGE |
|
||||
DRM_BUS_FLAG_DATA_MSB_TO_LSB |
|
||||
DRM_BUS_FLAG_DATA_LSB_TO_MSB |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_POSEDGE |
|
||||
DRM_BUS_FLAG_SYNC_SAMPLE_NEGEDGE;
|
||||
if (desc->bus_flags & ~bus_flags)
|
||||
dev_warn(dev, "Unexpected bus_flags(%d)\n", desc->bus_flags & ~bus_flags);
|
||||
if (!(desc->bus_flags & bus_flags))
|
||||
dev_warn(dev, "Specify missing bus_flags\n");
|
||||
if (desc->bus_format == 0)
|
||||
dev_warn(dev, "Specify missing bus_format\n");
|
||||
if (desc->bpc != 6 && desc->bpc != 8)
|
||||
dev_warn(dev, "Expected bpc in {6,8} but got: %u\n", desc->bpc);
|
||||
break;
|
||||
default:
|
||||
dev_warn(dev, "Specify a valid connector_type: %d\n", desc->connector_type);
|
||||
connector_type = DRM_MODE_CONNECTOR_DPI;
|
||||
break;
|
||||
}
|
||||
|
||||
dev_set_drvdata(dev, panel);
|
||||
|
||||
/*
|
||||
@@ -1900,6 +1899,7 @@ static const struct panel_desc dataimage_scf0700c48ggu18 = {
|
||||
},
|
||||
.bus_format = MEDIA_BUS_FMT_RGB888_1X24,
|
||||
.bus_flags = DRM_BUS_FLAG_DE_HIGH | DRM_BUS_FLAG_PIXDATA_DRIVE_POSEDGE,
|
||||
.connector_type = DRM_MODE_CONNECTOR_DPI,
|
||||
};
|
||||
|
||||
static const struct display_timing dlc_dlc0700yzg_1_timing = {
|
||||
|
||||
@@ -1252,17 +1252,7 @@ static int panthor_vm_prepare_map_op_ctx(struct panthor_vm_op_ctx *op_ctx,
|
||||
goto err_cleanup;
|
||||
}
|
||||
|
||||
/* drm_gpuvm_bo_obtain_prealloc() will call drm_gpuvm_bo_put() on our
|
||||
* pre-allocated BO if the <BO,VM> association exists. Given we
|
||||
* only have one ref on preallocated_vm_bo, drm_gpuvm_bo_destroy() will
|
||||
* be called immediately, and we have to hold the VM resv lock when
|
||||
* calling this function.
|
||||
*/
|
||||
dma_resv_lock(panthor_vm_resv(vm), NULL);
|
||||
mutex_lock(&bo->base.base.gpuva.lock);
|
||||
op_ctx->map.vm_bo = drm_gpuvm_bo_obtain_prealloc(preallocated_vm_bo);
|
||||
mutex_unlock(&bo->base.base.gpuva.lock);
|
||||
dma_resv_unlock(panthor_vm_resv(vm));
|
||||
|
||||
op_ctx->map.bo_offset = offset;
|
||||
|
||||
|
||||
@@ -121,7 +121,7 @@ static void dw_hdmi_qp_rockchip_encoder_enable(struct drm_encoder *encoder)
|
||||
struct drm_crtc *crtc = encoder->crtc;
|
||||
|
||||
/* Unconditionally switch to TMDS as FRL is not yet supported */
|
||||
gpiod_set_value(hdmi->frl_enable_gpio, 0);
|
||||
gpiod_set_value_cansleep(hdmi->frl_enable_gpio, 0);
|
||||
|
||||
if (!crtc || !crtc->state)
|
||||
return;
|
||||
@@ -640,6 +640,15 @@ static void dw_hdmi_qp_rockchip_remove(struct platform_device *pdev)
|
||||
component_del(&pdev->dev, &dw_hdmi_qp_rockchip_ops);
|
||||
}
|
||||
|
||||
static int __maybe_unused dw_hdmi_qp_rockchip_suspend(struct device *dev)
|
||||
{
|
||||
struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
|
||||
|
||||
dw_hdmi_qp_suspend(dev, hdmi->hdmi);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
|
||||
{
|
||||
struct rockchip_hdmi_qp *hdmi = dev_get_drvdata(dev);
|
||||
@@ -655,7 +664,8 @@ static int __maybe_unused dw_hdmi_qp_rockchip_resume(struct device *dev)
|
||||
}
|
||||
|
||||
static const struct dev_pm_ops dw_hdmi_qp_rockchip_pm = {
|
||||
SET_SYSTEM_SLEEP_PM_OPS(NULL, dw_hdmi_qp_rockchip_resume)
|
||||
SET_SYSTEM_SLEEP_PM_OPS(dw_hdmi_qp_rockchip_suspend,
|
||||
dw_hdmi_qp_rockchip_resume)
|
||||
};
|
||||
|
||||
struct platform_driver dw_hdmi_qp_rockchip_pltfm_driver = {
|
||||
|
||||
@@ -2104,7 +2104,7 @@ static void rk3568_vop2_wait_for_port_mux_done(struct vop2 *vop2)
|
||||
* Spin until the previous port_mux figuration is done.
|
||||
*/
|
||||
ret = readx_poll_timeout_atomic(rk3568_vop2_read_port_mux, vop2, port_mux_sel,
|
||||
port_mux_sel == vop2->old_port_sel, 0, 50 * 1000);
|
||||
port_mux_sel == vop2->old_port_sel, 10, 50 * 1000);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(vop2->dev, "wait port_mux done timeout: 0x%x--0x%x\n",
|
||||
port_mux_sel, vop2->old_port_sel);
|
||||
@@ -2124,7 +2124,7 @@ static void rk3568_vop2_wait_for_layer_cfg_done(struct vop2 *vop2, u32 cfg)
|
||||
* Spin until the previous layer configuration is done.
|
||||
*/
|
||||
ret = readx_poll_timeout_atomic(rk3568_vop2_read_layer_cfg, vop2, atv_layer_cfg,
|
||||
atv_layer_cfg == cfg, 0, 50 * 1000);
|
||||
atv_layer_cfg == cfg, 10, 50 * 1000);
|
||||
if (ret)
|
||||
DRM_DEV_ERROR(vop2->dev, "wait layer cfg done timeout: 0x%x--0x%x\n",
|
||||
atv_layer_cfg, cfg);
|
||||
@@ -2144,6 +2144,7 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
u8 layer_sel_id;
|
||||
unsigned int ofs;
|
||||
u32 ovl_ctrl;
|
||||
u32 cfg_done;
|
||||
int i;
|
||||
struct vop2_video_port *vp0 = &vop2->vps[0];
|
||||
struct vop2_video_port *vp1 = &vop2->vps[1];
|
||||
@@ -2298,8 +2299,16 @@ static void rk3568_vop2_setup_layer_mixer(struct vop2_video_port *vp)
|
||||
rk3568_vop2_wait_for_port_mux_done(vop2);
|
||||
}
|
||||
|
||||
if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel)
|
||||
rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
|
||||
if (layer_sel != old_layer_sel && atv_layer_sel != old_layer_sel) {
|
||||
cfg_done = vop2_readl(vop2, RK3568_REG_CFG_DONE);
|
||||
cfg_done &= (BIT(vop2->data->nr_vps) - 1);
|
||||
cfg_done &= ~BIT(vp->id);
|
||||
/*
|
||||
* Changes of other VPs' overlays have not taken effect
|
||||
*/
|
||||
if (cfg_done)
|
||||
rk3568_vop2_wait_for_layer_cfg_done(vop2, vop2->old_layer_sel);
|
||||
}
|
||||
|
||||
vop2_writel(vop2, RK3568_OVL_LAYER_SEL, layer_sel);
|
||||
mutex_unlock(&vop2->ovl_lock);
|
||||
|
||||
@@ -54,15 +54,6 @@ const struct drm_format_info *drm_sysfb_get_format_si(struct drm_device *dev,
|
||||
const struct screen_info *si);
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Input parsing
|
||||
*/
|
||||
|
||||
int drm_sysfb_get_validated_int(struct drm_device *dev, const char *name,
|
||||
u64 value, u32 max);
|
||||
int drm_sysfb_get_validated_int0(struct drm_device *dev, const char *name,
|
||||
u64 value, u32 max);
|
||||
|
||||
/*
|
||||
* Display modes
|
||||
*/
|
||||
|
||||
@@ -32,9 +32,15 @@
|
||||
|
||||
#include <drm/ttm/ttm_placement.h>
|
||||
|
||||
static void vmw_bo_release(struct vmw_bo *vbo)
|
||||
/**
|
||||
* vmw_bo_free - vmw_bo destructor
|
||||
*
|
||||
* @bo: Pointer to the embedded struct ttm_buffer_object
|
||||
*/
|
||||
static void vmw_bo_free(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct vmw_resource *res;
|
||||
struct vmw_bo *vbo = to_vmw_bo(&bo->base);
|
||||
|
||||
WARN_ON(kref_read(&vbo->tbo.base.refcount) != 0);
|
||||
vmw_bo_unmap(vbo);
|
||||
@@ -62,20 +68,8 @@ static void vmw_bo_release(struct vmw_bo *vbo)
|
||||
}
|
||||
vmw_surface_unreference(&vbo->dumb_surface);
|
||||
}
|
||||
drm_gem_object_release(&vbo->tbo.base);
|
||||
}
|
||||
|
||||
/**
|
||||
* vmw_bo_free - vmw_bo destructor
|
||||
*
|
||||
* @bo: Pointer to the embedded struct ttm_buffer_object
|
||||
*/
|
||||
static void vmw_bo_free(struct ttm_buffer_object *bo)
|
||||
{
|
||||
struct vmw_bo *vbo = to_vmw_bo(&bo->base);
|
||||
|
||||
WARN_ON(!RB_EMPTY_ROOT(&vbo->res_tree));
|
||||
vmw_bo_release(vbo);
|
||||
drm_gem_object_release(&vbo->tbo.base);
|
||||
WARN_ON(vbo->dirty);
|
||||
kfree(vbo);
|
||||
}
|
||||
|
||||
@@ -515,12 +515,12 @@ int vmw_fence_obj_unref_ioctl(struct drm_device *dev, void *data,
|
||||
/**
|
||||
* vmw_event_fence_action_seq_passed
|
||||
*
|
||||
* @action: The struct vmw_fence_action embedded in a struct
|
||||
* vmw_event_fence_action.
|
||||
* @f: The struct dma_fence which provides timestamp for the action event
|
||||
* @cb: The struct dma_fence_cb callback for the action event.
|
||||
*
|
||||
* This function is called when the seqno of the fence where @action is
|
||||
* attached has passed. It queues the event on the submitter's event list.
|
||||
* This function is always called from atomic context.
|
||||
* This function is called when the seqno of the fence has passed
|
||||
* and it is always called from atomic context.
|
||||
* It queues the event on the submitter's event list.
|
||||
*/
|
||||
static void vmw_event_fence_action_seq_passed(struct dma_fence *f,
|
||||
struct dma_fence_cb *cb)
|
||||
|
||||
@@ -766,13 +766,15 @@ err_out:
|
||||
return ERR_PTR(ret);
|
||||
}
|
||||
|
||||
ttm_bo_reserve(&bo->tbo, false, false, NULL);
|
||||
ret = vmw_bo_dirty_add(bo);
|
||||
if (!ret && surface && surface->res.func->dirty_alloc) {
|
||||
surface->res.coherent = true;
|
||||
ret = surface->res.func->dirty_alloc(&surface->res);
|
||||
if (bo) {
|
||||
ttm_bo_reserve(&bo->tbo, false, false, NULL);
|
||||
ret = vmw_bo_dirty_add(bo);
|
||||
if (!ret && surface && surface->res.func->dirty_alloc) {
|
||||
surface->res.coherent = true;
|
||||
ret = surface->res.func->dirty_alloc(&surface->res);
|
||||
}
|
||||
ttm_bo_unreserve(&bo->tbo);
|
||||
}
|
||||
ttm_bo_unreserve(&bo->tbo);
|
||||
|
||||
return &vfb->base;
|
||||
}
|
||||
|
||||
@@ -923,8 +923,10 @@ int vmw_compat_shader_add(struct vmw_private *dev_priv,
|
||||
ttm_bo_unreserve(&buf->tbo);
|
||||
|
||||
res = vmw_shader_alloc(dev_priv, buf, size, 0, shader_type);
|
||||
if (unlikely(ret != 0))
|
||||
if (IS_ERR(res)) {
|
||||
ret = PTR_ERR(res);
|
||||
goto no_reserve;
|
||||
}
|
||||
|
||||
ret = vmw_cmdbuf_res_add(man, vmw_cmdbuf_res_shader,
|
||||
vmw_shader_key(user_key, shader_type),
|
||||
|
||||
@@ -34,5 +34,6 @@ struct dw_hdmi_qp_plat_data {
|
||||
struct dw_hdmi_qp *dw_hdmi_qp_bind(struct platform_device *pdev,
|
||||
struct drm_encoder *encoder,
|
||||
const struct dw_hdmi_qp_plat_data *plat_data);
|
||||
void dw_hdmi_qp_suspend(struct device *dev, struct dw_hdmi_qp *hdmi);
|
||||
void dw_hdmi_qp_resume(struct device *dev, struct dw_hdmi_qp *hdmi);
|
||||
#endif /* __DW_HDMI_QP__ */
|
||||
|
||||
@@ -551,6 +551,22 @@ ssize_t drm_dp_dpcd_read(struct drm_dp_aux *aux, unsigned int offset,
|
||||
ssize_t drm_dp_dpcd_write(struct drm_dp_aux *aux, unsigned int offset,
|
||||
void *buffer, size_t size);
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_readb() - read a single byte from the DPCD
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @offset: address of the register to read
|
||||
* @valuep: location where the value of the register will be stored
|
||||
*
|
||||
* Returns the number of bytes transferred (1) on success, or a negative
|
||||
* error code on failure. In most of the cases you should be using
|
||||
* drm_dp_dpcd_read_byte() instead.
|
||||
*/
|
||||
static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux,
|
||||
unsigned int offset, u8 *valuep)
|
||||
{
|
||||
return drm_dp_dpcd_read(aux, offset, valuep, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_read_data() - read a series of bytes from the DPCD
|
||||
* @aux: DisplayPort AUX channel (SST or MST)
|
||||
@@ -570,12 +586,29 @@ static inline int drm_dp_dpcd_read_data(struct drm_dp_aux *aux,
|
||||
void *buffer, size_t size)
|
||||
{
|
||||
int ret;
|
||||
size_t i;
|
||||
u8 *buf = buffer;
|
||||
|
||||
ret = drm_dp_dpcd_read(aux, offset, buffer, size);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
if (ret < size)
|
||||
return -EPROTO;
|
||||
if (ret >= 0) {
|
||||
if (ret < size)
|
||||
return -EPROTO;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Workaround for USB-C hubs/adapters with buggy firmware that fail
|
||||
* multi-byte AUX reads but work with single-byte reads.
|
||||
* Known affected devices:
|
||||
* - Lenovo USB-C to VGA adapter (VIA VL817, idVendor=17ef, idProduct=7217)
|
||||
* - Dell DA310 USB-C hub (idVendor=413c, idProduct=c010)
|
||||
* Attempt byte-by-byte reading as a fallback.
|
||||
*/
|
||||
for (i = 0; i < size; i++) {
|
||||
ret = drm_dp_dpcd_readb(aux, offset + i, &buf[i]);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -609,22 +642,6 @@ static inline int drm_dp_dpcd_write_data(struct drm_dp_aux *aux,
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_readb() - read a single byte from the DPCD
|
||||
* @aux: DisplayPort AUX channel
|
||||
* @offset: address of the register to read
|
||||
* @valuep: location where the value of the register will be stored
|
||||
*
|
||||
* Returns the number of bytes transferred (1) on success, or a negative
|
||||
* error code on failure. In most of the cases you should be using
|
||||
* drm_dp_dpcd_read_byte() instead.
|
||||
*/
|
||||
static inline ssize_t drm_dp_dpcd_readb(struct drm_dp_aux *aux,
|
||||
unsigned int offset, u8 *valuep)
|
||||
{
|
||||
return drm_dp_dpcd_read(aux, offset, valuep, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* drm_dp_dpcd_writeb() - write a single byte to the DPCD
|
||||
* @aux: DisplayPort AUX channel
|
||||
|
||||
Reference in New Issue
Block a user