drm-misc-next for 6.11:

UAPI Changes:
   - New monochrome TV mode variant
 
 Cross-subsystem Changes:
   - dma heaps: Change slightly the allocation hook prototype
 
 Core Changes:
 
 Driver Changes:
  - ivpu: various improvements over firmware handling, clocks, power
    management, scheduling and logging.
  - mgag200: Add BMC output, enable polling
  - panfrost: Enable MT8188 support
  - tidss: drm_panic support
  - zynqmp_dp: IRQ cleanups, debugfs DP compliance testing API
  - bridge:
    - sii902x: state validation improvements
  - panel:
    - edp: Drop legacy panel compatibles
    - simple-bridge: Switch to devm_drm_bridge_add
 -----BEGIN PGP SIGNATURE-----
 
 iHUEABYKAB0WIQRcEzekXsqa64kGDp7j7w1vZxhRxQUCZnPhvwAKCRDj7w1vZxhR
 xZPbAP9+43f9IIXMscOBvs1+bQRXCsu5Fp4zG9jTwC/XdXMKDwD/VlAVMKKCGQSC
 T+2/igKmeJQF674/rPIqKDd7UyRpBQY=
 =c8ky
 -----END PGP SIGNATURE-----

Merge tag 'drm-misc-next-2024-06-20' of https://gitlab.freedesktop.org/drm/misc/kernel into drm-next

drm-misc-next for 6.11:

UAPI Changes:
  - New monochrome TV mode variant

Cross-subsystem Changes:
  - dma heaps: Change slightly the allocation hook prototype

Core Changes:

Driver Changes:
 - ivpu: various improvements over firmware handling, clocks, power
   management, scheduling and logging.
 - mgag200: Add BMC output, enable polling
 - panfrost: Enable MT8188 support
 - tidss: drm_panic support
 - zynqmp_dp: IRQ cleanups, debugfs DP compliance testing API
 - bridge:
   - sii902x: state validation improvements
 - panel:
   - edp: Drop legacy panel compatibles
   - simple-bridge: Switch to devm_drm_bridge_add

Signed-off-by: Dave Airlie <airlied@redhat.com>

From: Maxime Ripard <mripard@redhat.com>
Link: https://patchwork.freedesktop.org/patch/msgid/20240620-heretic-honored-macaque-b40f8a@houat
This commit is contained in:
Dave Airlie 2024-06-21 11:06:48 +10:00
commit ab3d847962
73 changed files with 1227 additions and 827 deletions

View File

@ -31,13 +31,9 @@ properties:
# AUO B116XAK01 eDP TFT LCD panel
- auo,b116xa01
# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
- auo,b133han05
# AU Optronics Corporation 13.3" FHD (1920x1080) color TFT-LCD panel
- auo,b133htn01
# AU Optronics Corporation 13.3" WXGA (1366x768) TFT LCD panel
- auo,b133xtn01
# AU Optronics Corporation 14.0" FHD (1920x1080) color TFT-LCD panel
- auo,b140han06
# BOE OPTOELECTRONICS TECHNOLOGY 10.1" WXGA TFT LCD panel
- boe,nv101wxmn51
# BOE NV133FHM-N61 13.3" FHD (1920x1080) TFT LCD Panel
@ -56,8 +52,6 @@ properties:
- innolux,n125hce-gn1
# Innolux P120ZDG-BF1 12.02 inch eDP 2K display panel
- innolux,p120zdg-bf1
# InfoVision Optoelectronics M133NWF4 R0 13.3" FHD (1920x1080) TFT LCD panel
- ivo,m133nwf4-r0
# King & Display KD116N21-30NV-A010 eDP TFT LCD panel
- kingdisplay,kd116n21-30nv-a010
# LG LP079QX1-SP0V 7.9" (1536x2048 pixels) TFT LCD panel
@ -78,10 +72,6 @@ properties:
- sharp,ld-d5116z01b
# Sharp 12.3" (2400x1600 pixels) TFT LCD panel
- sharp,lq123p1jx31
# Sharp 14" (1920x1080 pixels) TFT LCD panel
- sharp,lq140m1jw46
# Starry 12.2" (1920x1200 pixels) TFT LCD panel
- starry,kr122ea0sra
backlight: true
ddc-i2c-bus: true

View File

@ -34,6 +34,7 @@ properties:
- const: arm,mali-valhall-jm # Mali Valhall GPU model/revision is fully discoverable
- items:
- enum:
- mediatek,mt8188-mali
- mediatek,mt8192-mali
- const: arm,mali-valhall-jm # Mali Valhall GPU model/revision is fully discoverable
@ -195,7 +196,9 @@ allOf:
properties:
compatible:
contains:
const: mediatek,mt8183b-mali
enum:
- mediatek,mt8183b-mali
- mediatek,mt8188-mali
then:
properties:
power-domains:

View File

@ -7196,6 +7196,7 @@ L: dri-devel@lists.freedesktop.org
S: Maintained
T: git https://gitlab.freedesktop.org/drm/misc/kernel.git
F: Documentation/gpu/vkms.rst
F: drivers/gpu/drm/ci/xfails/vkms*
F: drivers/gpu/drm/vkms/
DRM DRIVER FOR VIRTUALBOX VIRTUAL GPU

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#include <linux/debugfs.h>
@ -381,6 +381,39 @@ static const struct file_operations ivpu_resume_engine_fops = {
.write = ivpu_resume_engine_fn,
};
static int dct_active_get(void *data, u64 *active_percent)
{
struct ivpu_device *vdev = data;
*active_percent = vdev->pm->dct_active_percent;
return 0;
}
static int dct_active_set(void *data, u64 active_percent)
{
struct ivpu_device *vdev = data;
int ret;
if (active_percent > 100)
return -EINVAL;
ret = ivpu_rpm_get(vdev);
if (ret)
return ret;
if (active_percent)
ret = ivpu_pm_dct_enable(vdev, active_percent);
else
ret = ivpu_pm_dct_disable(vdev);
ivpu_rpm_put(vdev);
return ret;
}
DEFINE_DEBUGFS_ATTRIBUTE(ivpu_dct_fops, dct_active_get, dct_active_set, "%llu\n");
void ivpu_debugfs_init(struct ivpu_device *vdev)
{
struct dentry *debugfs_root = vdev->drm.debugfs_root;
@ -409,7 +442,9 @@ void ivpu_debugfs_init(struct ivpu_device *vdev)
debugfs_create_file("resume_engine", 0200, debugfs_root, vdev,
&ivpu_resume_engine_fops);
if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX)
if (ivpu_hw_ip_gen(vdev) >= IVPU_HW_IP_40XX) {
debugfs_create_file("fw_profiling_freq_drive", 0200,
debugfs_root, vdev, &fw_profiling_freq_fops);
debugfs_create_file("dct", 0644, debugfs_root, vdev, &ivpu_dct_fops);
}
}

View File

@ -58,11 +58,11 @@ module_param_named(sched_mode, ivpu_sched_mode, int, 0444);
MODULE_PARM_DESC(sched_mode, "Scheduler mode: 0 - Default scheduler, 1 - Force HW scheduler");
bool ivpu_disable_mmu_cont_pages;
module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0644);
module_param_named(disable_mmu_cont_pages, ivpu_disable_mmu_cont_pages, bool, 0444);
MODULE_PARM_DESC(disable_mmu_cont_pages, "Disable MMU contiguous pages optimization");
bool ivpu_force_snoop;
module_param_named(force_snoop, ivpu_force_snoop, bool, 0644);
module_param_named(force_snoop, ivpu_force_snoop, bool, 0444);
MODULE_PARM_DESC(force_snoop, "Force snooping for NPU host memory access");
struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv)
@ -391,8 +391,13 @@ int ivpu_boot(struct ivpu_device *vdev)
ivpu_hw_irq_enable(vdev);
ivpu_ipc_enable(vdev);
if (ivpu_fw_is_cold_boot(vdev))
if (ivpu_fw_is_cold_boot(vdev)) {
ret = ivpu_pm_dct_init(vdev);
if (ret)
return ret;
return ivpu_hw_sched_init(vdev);
}
return 0;
}
@ -446,6 +451,26 @@ static const struct drm_driver driver = {
.minor = DRM_IVPU_DRIVER_MINOR,
};
static void ivpu_context_abort_invalid(struct ivpu_device *vdev)
{
struct ivpu_file_priv *file_priv;
unsigned long ctx_id;
mutex_lock(&vdev->context_list_lock);
xa_for_each(&vdev->context_xa, ctx_id, file_priv) {
if (!file_priv->has_mmu_faults || file_priv->aborted)
continue;
mutex_lock(&file_priv->lock);
ivpu_context_abort_locked(file_priv);
file_priv->aborted = true;
mutex_unlock(&file_priv->lock);
}
mutex_unlock(&vdev->context_list_lock);
}
static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
{
struct ivpu_device *vdev = arg;
@ -459,6 +484,12 @@ static irqreturn_t ivpu_irq_thread_handler(int irq, void *arg)
case IVPU_HW_IRQ_SRC_IPC:
ivpu_ipc_irq_thread_handler(vdev);
break;
case IVPU_HW_IRQ_SRC_MMU_EVTQ:
ivpu_context_abort_invalid(vdev);
break;
case IVPU_HW_IRQ_SRC_DCT:
ivpu_pm_dct_irq_thread_handler(vdev);
break;
default:
ivpu_err_ratelimited(vdev, "Unknown IRQ source: %u\n", irq_src);
break;
@ -664,14 +695,14 @@ static void ivpu_bo_unbind_all_user_contexts(struct ivpu_device *vdev)
static void ivpu_dev_fini(struct ivpu_device *vdev)
{
ivpu_jobs_abort_all(vdev);
ivpu_pm_cancel_recovery(vdev);
ivpu_pm_disable(vdev);
ivpu_prepare_for_reset(vdev);
ivpu_shutdown(vdev);
ivpu_ms_cleanup_all(vdev);
ivpu_jobs_abort_all(vdev);
ivpu_job_done_consumer_fini(vdev);
ivpu_pm_cancel_recovery(vdev);
ivpu_bo_unbind_all_user_contexts(vdev);
ivpu_ipc_fini(vdev);

View File

@ -32,6 +32,8 @@
#define IVPU_HW_IP_50XX 50
#define IVPU_HW_IP_60XX 60
#define IVPU_HW_IP_REV_LNL_B0 4
#define IVPU_HW_BTRS_MTL 1
#define IVPU_HW_BTRS_LNL 2
@ -102,6 +104,7 @@ struct ivpu_wa_table {
bool interrupt_clear_with_0;
bool disable_clock_relinquish;
bool disable_d0i3_msg;
bool wp0_during_power_up;
};
struct ivpu_hw_info;
@ -147,7 +150,6 @@ struct ivpu_device {
int boot;
int jsm;
int tdr;
int reschedule_suspend;
int autosuspend;
int d0i3_entry_msg;
} timeout;
@ -168,6 +170,7 @@ struct ivpu_file_priv {
struct ivpu_bo *ms_info_bo;
bool has_mmu_faults;
bool bound;
bool aborted;
};
extern int ivpu_dbg_mask;
@ -184,6 +187,7 @@ extern bool ivpu_force_snoop;
#define IVPU_TEST_MODE_D0I3_MSG_ENABLE BIT(5)
#define IVPU_TEST_MODE_PREEMPTION_DISABLE BIT(6)
#define IVPU_TEST_MODE_HWS_EXTRA_EVENTS BIT(7)
#define IVPU_TEST_MODE_DISABLE_TIMEOUTS BIT(8)
extern int ivpu_test_mode;
struct ivpu_file_priv *ivpu_file_priv_get(struct ivpu_file_priv *file_priv);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#include <linux/firmware.h>
@ -123,6 +123,14 @@ ivpu_fw_check_api_ver_lt(struct ivpu_device *vdev, const struct vpu_firmware_hea
return false;
}
static bool is_within_range(u64 addr, size_t size, u64 range_start, size_t range_size)
{
if (addr < range_start || addr + size > range_start + range_size)
return false;
return true;
}
static int ivpu_fw_parse(struct ivpu_device *vdev)
{
struct ivpu_fw_info *fw = vdev->fw;
@ -205,10 +213,24 @@ static int ivpu_fw_parse(struct ivpu_device *vdev)
fw->primary_preempt_buf_size = fw_hdr->preemption_buffer_1_size;
fw->secondary_preempt_buf_size = fw_hdr->preemption_buffer_2_size;
if (fw_hdr->ro_section_start_address && !is_within_range(fw_hdr->ro_section_start_address,
fw_hdr->ro_section_size,
fw_hdr->image_load_address,
fw_hdr->image_size)) {
ivpu_err(vdev, "Invalid read-only section: start address 0x%llx, size %u\n",
fw_hdr->ro_section_start_address, fw_hdr->ro_section_size);
return -EINVAL;
}
fw->read_only_addr = fw_hdr->ro_section_start_address;
fw->read_only_size = fw_hdr->ro_section_size;
ivpu_dbg(vdev, FW_BOOT, "Size: file %lu image %u runtime %u shavenn %u\n",
fw->file->size, fw->image_size, fw->runtime_size, fw->shave_nn_size);
ivpu_dbg(vdev, FW_BOOT, "Address: runtime 0x%llx, load 0x%llx, entry point 0x%llx\n",
fw->runtime_addr, image_load_addr, fw->entry_point);
ivpu_dbg(vdev, FW_BOOT, "Read-only section: address 0x%llx, size %u\n",
fw->read_only_addr, fw->read_only_size);
return 0;
}
@ -270,6 +292,13 @@ static int ivpu_fw_mem_init(struct ivpu_device *vdev)
return -ENOMEM;
}
ret = ivpu_mmu_context_set_pages_ro(vdev, &vdev->gctx, fw->read_only_addr,
fw->read_only_size);
if (ret) {
ivpu_err(vdev, "Failed to set firmware image read-only\n");
goto err_free_fw_mem;
}
fw->mem_log_crit = ivpu_bo_create_global(vdev, IVPU_FW_CRITICAL_BUFFER_SIZE,
DRM_IVPU_BO_CACHED | DRM_IVPU_BO_MAPPABLE);
if (!fw->mem_log_crit) {

View File

@ -30,6 +30,8 @@ struct ivpu_fw_info {
u32 dvfs_mode;
u32 primary_preempt_buf_size;
u32 secondary_preempt_buf_size;
u64 read_only_addr;
u32 read_only_size;
};
int ivpu_fw_init(struct ivpu_device *vdev);

View File

@ -61,37 +61,48 @@ static void wa_init(struct ivpu_device *vdev)
if (ivpu_hw_btrs_gen(vdev) == IVPU_HW_BTRS_MTL)
vdev->wa.interrupt_clear_with_0 = ivpu_hw_btrs_irqs_clear_with_0_mtl(vdev);
if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL)
if (ivpu_device_id(vdev) == PCI_DEVICE_ID_LNL &&
ivpu_revision(vdev) < IVPU_HW_IP_REV_LNL_B0)
vdev->wa.disable_clock_relinquish = true;
if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
vdev->wa.wp0_during_power_up = true;
IVPU_PRINT_WA(punit_disabled);
IVPU_PRINT_WA(clear_runtime_mem);
IVPU_PRINT_WA(interrupt_clear_with_0);
IVPU_PRINT_WA(disable_clock_relinquish);
IVPU_PRINT_WA(wp0_during_power_up);
}
static void timeouts_init(struct ivpu_device *vdev)
{
if (ivpu_is_fpga(vdev)) {
if (ivpu_test_mode & IVPU_TEST_MODE_DISABLE_TIMEOUTS) {
vdev->timeout.boot = -1;
vdev->timeout.jsm = -1;
vdev->timeout.tdr = -1;
vdev->timeout.autosuspend = -1;
vdev->timeout.d0i3_entry_msg = -1;
} else if (ivpu_is_fpga(vdev)) {
vdev->timeout.boot = 100000;
vdev->timeout.jsm = 50000;
vdev->timeout.tdr = 2000000;
vdev->timeout.reschedule_suspend = 1000;
vdev->timeout.autosuspend = -1;
vdev->timeout.d0i3_entry_msg = 500;
} else if (ivpu_is_simics(vdev)) {
vdev->timeout.boot = 50;
vdev->timeout.jsm = 500;
vdev->timeout.tdr = 10000;
vdev->timeout.reschedule_suspend = 10;
vdev->timeout.autosuspend = -1;
vdev->timeout.d0i3_entry_msg = 100;
} else {
vdev->timeout.boot = 1000;
vdev->timeout.jsm = 500;
vdev->timeout.tdr = 2000;
vdev->timeout.reschedule_suspend = 10;
vdev->timeout.autosuspend = 10;
if (ivpu_hw_ip_gen(vdev) == IVPU_HW_IP_37XX)
vdev->timeout.autosuspend = 10;
else
vdev->timeout.autosuspend = 100;
vdev->timeout.d0i3_entry_msg = 5;
}
}
@ -125,6 +136,13 @@ int ivpu_hw_power_up(struct ivpu_device *vdev)
{
int ret;
if (IVPU_WA(wp0_during_power_up)) {
/* WP requests may fail when powering down, so issue WP 0 here */
ret = wp_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable workpoint: %d\n", ret);
}
ret = ivpu_hw_btrs_d0i3_disable(vdev);
if (ret)
ivpu_warn(vdev, "Failed to disable D0I3: %d\n", ret);

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020 - 2024 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __IVPU_HW_H__
@ -15,6 +15,8 @@
#define IVPU_HW_IRQ_FIFO_LENGTH 1024
#define IVPU_HW_IRQ_SRC_IPC 1
#define IVPU_HW_IRQ_SRC_MMU_EVTQ 2
#define IVPU_HW_IRQ_SRC_DCT 3
struct ivpu_addr_range {
resource_size_t start;

View File

@ -504,6 +504,8 @@ static int ip_reset_lnl(struct ivpu_device *vdev)
int ret;
u32 val;
ivpu_hw_btrs_clock_relinquish_disable_lnl(vdev);
ret = REGB_POLL_FLD(VPU_HW_BTRS_LNL_IP_RESET, TRIGGER, 0, TIMEOUT_US);
if (ret) {
ivpu_err(vdev, "Wait for *_TRIGGER timed out\n");
@ -641,8 +643,11 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
if (!status)
return false;
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status))
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, SURV_ERR, status)) {
ivpu_dbg(vdev, IRQ, "Survivability IRQ\n");
if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_DCT))
ivpu_err_ratelimited(vdev, "IRQ FIFO full\n");
}
if (REG_TEST_FLD(VPU_HW_BTRS_LNL_INTERRUPT_STAT, FREQ_CHANGE, status))
ivpu_dbg(vdev, IRQ, "FREQ_CHANGE irq: %08x", REGB_RD32(VPU_HW_BTRS_LNL_PLL_FREQ));
@ -692,21 +697,40 @@ bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq)
return true;
}
static void dct_drive_40xx(struct ivpu_device *vdev, u32 dct_val)
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable)
{
u32 val = REGB_RD32(VPU_HW_BTRS_LNL_PCODE_MAILBOX);
u32 val = REGB_RD32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW);
u32 cmd = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, CMD, val);
u32 param1 = REG_GET_FLD(VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW, PARAM1, val);
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, CMD, DCT_REQ, val);
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, PARAM1,
dct_val ? DCT_ENABLE : DCT_DISABLE, val);
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX, PARAM2, dct_val, val);
if (cmd != DCT_REQ) {
ivpu_err_ratelimited(vdev, "Unsupported PCODE command: 0x%x\n", cmd);
return -EBADR;
}
REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX, val);
switch (param1) {
case DCT_ENABLE:
*enable = true;
return 0;
case DCT_DISABLE:
*enable = false;
return 0;
default:
ivpu_err_ratelimited(vdev, "Invalid PARAM1 value: %u\n", param1);
return -EINVAL;
}
}
void ivpu_hw_btrs_dct_drive(struct ivpu_device *vdev, u32 dct_val)
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 active_percent)
{
return dct_drive_40xx(vdev, dct_val);
u32 val = 0;
u32 cmd = enable ? DCT_ENABLE : DCT_DISABLE;
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, CMD, DCT_REQ, val);
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM1, cmd, val);
val = REG_SET_FLD_NUM(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, PARAM2, active_percent, val);
REGB_WR32(VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS, val);
}
static u32 pll_ratio_to_freq_mtl(u32 ratio, u32 config)

View File

@ -15,6 +15,9 @@
#define PLL_PROFILING_FREQ_HIGH 400000000
#define PLL_RATIO_TO_FREQ(x) ((x) * PLL_REF_CLK_FREQ)
#define DCT_DEFAULT_ACTIVE_PERCENT 15u
#define DCT_PERIOD_US 35300u
int ivpu_hw_btrs_info_init(struct ivpu_device *vdev);
void ivpu_hw_btrs_freq_ratios_init(struct ivpu_device *vdev);
int ivpu_hw_btrs_irqs_clear_with_0_mtl(struct ivpu_device *vdev);
@ -31,7 +34,8 @@ void ivpu_hw_btrs_ats_print_lnl(struct ivpu_device *vdev);
void ivpu_hw_btrs_clock_relinquish_disable_lnl(struct ivpu_device *vdev);
bool ivpu_hw_btrs_irq_handler_mtl(struct ivpu_device *vdev, int irq);
bool ivpu_hw_btrs_irq_handler_lnl(struct ivpu_device *vdev, int irq);
void ivpu_hw_btrs_dct_drive(struct ivpu_device *vdev, u32 dct_val);
int ivpu_hw_btrs_dct_get_request(struct ivpu_device *vdev, bool *enable);
void ivpu_hw_btrs_dct_set_status(struct ivpu_device *vdev, bool enable, u32 dct_percent);
u32 ivpu_hw_btrs_pll_freq_get(struct ivpu_device *vdev);
u32 ivpu_hw_btrs_ratio_to_freq(struct ivpu_device *vdev, u32 ratio);
u32 ivpu_hw_btrs_telemetry_offset_get(struct ivpu_device *vdev);

View File

@ -44,11 +44,11 @@
#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_HIGH 0x0000005cu
#define VPU_HW_BTRS_LNL_IMR_ERR_CFI1_CLEAR 0x00000060u
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX 0x00000070u
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_CMD_MASK GENMASK(7, 0)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM1_MASK GENMASK(15, 8)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM2_MASK GENMASK(23, 16)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_PARAM3_MASK GENMASK(31, 24)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS 0x00000070u
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_CMD_MASK GENMASK(7, 0)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM1_MASK GENMASK(15, 8)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM2_MASK GENMASK(23, 16)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_STATUS_PARAM3_MASK GENMASK(31, 24)
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW 0x00000074u
#define VPU_HW_BTRS_LNL_PCODE_MAILBOX_SHADOW_CMD_MASK GENMASK(7, 0)

View File

@ -210,8 +210,7 @@ void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c
ivpu_ipc_tx_release(vdev, cons->tx_vpu_addr);
}
static int
ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req)
int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons, struct vpu_jsm_msg *req)
{
struct ivpu_ipc_info *ipc = vdev->ipc;
int ret;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __IVPU_IPC_H__
@ -96,6 +96,8 @@ void ivpu_ipc_consumer_add(struct ivpu_device *vdev, struct ivpu_ipc_consumer *c
u32 channel, ivpu_ipc_rx_callback_t callback);
void ivpu_ipc_consumer_del(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons);
int ivpu_ipc_send(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
struct vpu_jsm_msg *req);
int ivpu_ipc_receive(struct ivpu_device *vdev, struct ivpu_ipc_consumer *cons,
struct ivpu_ipc_hdr *ipc_buf, struct vpu_jsm_msg *jsm_msg,
unsigned long timeout_ms);

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#include <drm/drm_file.h>
@ -312,6 +312,33 @@ void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev)
mutex_unlock(&vdev->context_list_lock);
}
static void ivpu_cmdq_fini_all(struct ivpu_file_priv *file_priv)
{
u16 engine;
u8 priority;
for (engine = 0; engine < IVPU_NUM_ENGINES; engine++) {
for (priority = 0; priority < IVPU_NUM_PRIORITIES; priority++) {
int cmdq_idx = IVPU_CMDQ_INDEX(engine, priority);
if (file_priv->cmdq[cmdq_idx])
ivpu_cmdq_fini(file_priv, file_priv->cmdq[cmdq_idx]);
}
}
}
void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv)
{
struct ivpu_device *vdev = file_priv->vdev;
lockdep_assert_held(&file_priv->lock);
ivpu_cmdq_fini_all(file_priv);
if (vdev->hw->sched_mode == VPU_SCHEDULING_MODE_OS)
ivpu_jsm_context_release(vdev, file_priv->ctx.id);
}
static int ivpu_cmdq_push_job(struct ivpu_cmdq *cmdq, struct ivpu_job *job)
{
struct ivpu_device *vdev = job->vdev;

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __IVPU_JOB_H__
@ -57,6 +57,8 @@ struct ivpu_job {
int ivpu_submit_ioctl(struct drm_device *dev, void *data, struct drm_file *file);
void ivpu_context_abort_locked(struct ivpu_file_priv *file_priv);
void ivpu_cmdq_release_all_locked(struct ivpu_file_priv *file_priv);
void ivpu_cmdq_reset_all_contexts(struct ivpu_device *vdev);

View File

@ -103,14 +103,10 @@ int ivpu_jsm_register_db(struct ivpu_device *vdev, u32 ctx_id, u32 db_id,
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_REGISTER_DB_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
ivpu_err_ratelimited(vdev, "Failed to register doorbell %d: %d\n", db_id, ret);
return ret;
}
if (ret)
ivpu_err_ratelimited(vdev, "Failed to register doorbell %u: %d\n", db_id, ret);
ivpu_dbg(vdev, JSM, "Doorbell %d registered to context %d\n", db_id, ctx_id);
return 0;
return ret;
}
int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id)
@ -123,14 +119,10 @@ int ivpu_jsm_unregister_db(struct ivpu_device *vdev, u32 db_id)
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_UNREGISTER_DB_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret) {
ivpu_warn_ratelimited(vdev, "Failed to unregister doorbell %d: %d\n", db_id, ret);
return ret;
}
if (ret)
ivpu_warn_ratelimited(vdev, "Failed to unregister doorbell %u: %d\n", db_id, ret);
ivpu_dbg(vdev, JSM, "Doorbell %d unregistered\n", db_id);
return 0;
return ret;
}
int ivpu_jsm_get_heartbeat(struct ivpu_device *vdev, u32 engine, u64 *heartbeat)
@ -255,11 +247,16 @@ int ivpu_jsm_context_release(struct ivpu_device *vdev, u32 host_ssid)
{
struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_SSID_RELEASE };
struct vpu_jsm_msg resp;
int ret;
req.payload.ssid_release.host_ssid = host_ssid;
return ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
ret = ivpu_ipc_send_receive(vdev, &req, VPU_JSM_MSG_SSID_RELEASE_DONE, &resp,
VPU_IPC_CHAN_ASYNC_CMD, vdev->timeout.jsm);
if (ret)
ivpu_warn_ratelimited(vdev, "Failed to release context: %d\n", ret);
return ret;
}
int ivpu_jsm_pwr_d0i3_enter(struct ivpu_device *vdev)
@ -538,3 +535,26 @@ int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mas
return ret;
}
int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us)
{
struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DCT_ENABLE };
struct vpu_jsm_msg resp;
req.payload.pwr_dct_control.dct_active_us = active_us;
req.payload.pwr_dct_control.dct_inactive_us = inactive_us;
return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_ENABLE_DONE,
&resp, VPU_IPC_CHAN_ASYNC_CMD,
vdev->timeout.jsm);
}
int ivpu_jsm_dct_disable(struct ivpu_device *vdev)
{
struct vpu_jsm_msg req = { .type = VPU_JSM_MSG_DCT_DISABLE };
struct vpu_jsm_msg resp;
return ivpu_ipc_send_receive_active(vdev, &req, VPU_JSM_MSG_DCT_DISABLE_DONE,
&resp, VPU_IPC_CHAN_ASYNC_CMD,
vdev->timeout.jsm);
}

View File

@ -41,4 +41,6 @@ int ivpu_jsm_metric_streamer_update(struct ivpu_device *vdev, u64 metric_group_m
u64 buffer_addr, u64 buffer_size, u64 *bytes_written);
int ivpu_jsm_metric_streamer_info(struct ivpu_device *vdev, u64 metric_group_mask, u64 buffer_addr,
u64 buffer_size, u32 *sample_size, u64 *info_size);
int ivpu_jsm_dct_enable(struct ivpu_device *vdev, u32 active_us, u32 inactive_us);
int ivpu_jsm_dct_disable(struct ivpu_device *vdev);
#endif

View File

@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#include <linux/circ_buf.h>
@ -878,8 +878,9 @@ static void ivpu_mmu_dump_event(struct ivpu_device *vdev, u32 *event)
u64 in_addr = ((u64)event[5]) << 32 | event[4];
u32 sid = event[1];
ivpu_err(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n",
op, ivpu_mmu_event_to_str(op), ssid, sid, event[2], event[3], in_addr, fetch_addr);
ivpu_err_ratelimited(vdev, "MMU EVTQ: 0x%x (%s) SSID: %d SID: %d, e[2] %08x, e[3] %08x, in addr: 0x%llx, fetch addr: 0x%llx\n",
op, ivpu_mmu_event_to_str(op), ssid, sid,
event[2], event[3], in_addr, fetch_addr);
}
static u32 *ivpu_mmu_get_event(struct ivpu_device *vdev)
@ -915,6 +916,9 @@ void ivpu_mmu_irq_evtq_handler(struct ivpu_device *vdev)
ivpu_mmu_user_context_mark_invalid(vdev, ssid);
REGV_WR32(IVPU_MMU_REG_EVTQ_CONS_SEC, vdev->mmu->evtq.cons);
}
if (!kfifo_put(&vdev->hw->irq.fifo, IVPU_HW_IRQ_SRC_MMU_EVTQ))
ivpu_err_ratelimited(vdev, "IRQ FIFO full\n");
}
void ivpu_mmu_evtq_dump(struct ivpu_device *vdev)

View File

@ -24,6 +24,7 @@
#define IVPU_MMU_ENTRY_FLAG_CONT BIT(52)
#define IVPU_MMU_ENTRY_FLAG_NG BIT(11)
#define IVPU_MMU_ENTRY_FLAG_AF BIT(10)
#define IVPU_MMU_ENTRY_FLAG_RO BIT(7)
#define IVPU_MMU_ENTRY_FLAG_USER BIT(6)
#define IVPU_MMU_ENTRY_FLAG_LLC_COHERENT BIT(2)
#define IVPU_MMU_ENTRY_FLAG_TYPE_PAGE BIT(1)
@ -319,6 +320,91 @@ ivpu_mmu_context_map_pages(struct ivpu_device *vdev, struct ivpu_mmu_context *ct
return 0;
}
static void ivpu_mmu_context_set_page_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr)
{
int pgd_idx = FIELD_GET(IVPU_MMU_PGD_INDEX_MASK, vpu_addr);
int pud_idx = FIELD_GET(IVPU_MMU_PUD_INDEX_MASK, vpu_addr);
int pmd_idx = FIELD_GET(IVPU_MMU_PMD_INDEX_MASK, vpu_addr);
int pte_idx = FIELD_GET(IVPU_MMU_PTE_INDEX_MASK, vpu_addr);
ctx->pgtable.pte_ptrs[pgd_idx][pud_idx][pmd_idx][pte_idx] |= IVPU_MMU_ENTRY_FLAG_RO;
}
static void ivpu_mmu_context_split_page(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr)
{
int pgd_idx = FIELD_GET(IVPU_MMU_PGD_INDEX_MASK, vpu_addr);
int pud_idx = FIELD_GET(IVPU_MMU_PUD_INDEX_MASK, vpu_addr);
int pmd_idx = FIELD_GET(IVPU_MMU_PMD_INDEX_MASK, vpu_addr);
int pte_idx = FIELD_GET(IVPU_MMU_PTE_INDEX_MASK, vpu_addr);
ctx->pgtable.pte_ptrs[pgd_idx][pud_idx][pmd_idx][pte_idx] &= ~IVPU_MMU_ENTRY_FLAG_CONT;
}
static void ivpu_mmu_context_split_64k_page(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr)
{
u64 start = ALIGN_DOWN(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE);
u64 end = ALIGN(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE);
u64 offset = 0;
ivpu_dbg(vdev, MMU_MAP, "Split 64K page ctx: %u vpu_addr: 0x%llx\n", ctx->id, vpu_addr);
while (start + offset < end) {
ivpu_mmu_context_split_page(vdev, ctx, start + offset);
offset += IVPU_MMU_PAGE_SIZE;
}
}
int
ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx, u64 vpu_addr,
size_t size)
{
u64 end = vpu_addr + size;
size_t size_left = size;
int ret;
if (size == 0)
return 0;
if (drm_WARN_ON(&vdev->drm, !IS_ALIGNED(vpu_addr | size, IVPU_MMU_PAGE_SIZE)))
return -EINVAL;
mutex_lock(&ctx->lock);
ivpu_dbg(vdev, MMU_MAP, "Set read-only pages ctx: %u vpu_addr: 0x%llx size: %lu\n",
ctx->id, vpu_addr, size);
if (!ivpu_disable_mmu_cont_pages) {
/* Split 64K contiguous page at the beginning if needed */
if (!IS_ALIGNED(vpu_addr, IVPU_MMU_CONT_PAGES_SIZE))
ivpu_mmu_context_split_64k_page(vdev, ctx, vpu_addr);
/* Split 64K contiguous page at the end if needed */
if (!IS_ALIGNED(vpu_addr + size, IVPU_MMU_CONT_PAGES_SIZE))
ivpu_mmu_context_split_64k_page(vdev, ctx, vpu_addr + size);
}
while (size_left) {
if (vpu_addr < end)
ivpu_mmu_context_set_page_ro(vdev, ctx, vpu_addr);
vpu_addr += IVPU_MMU_PAGE_SIZE;
size_left -= IVPU_MMU_PAGE_SIZE;
}
/* Ensure page table modifications are flushed from wc buffers to memory */
wmb();
mutex_unlock(&ctx->lock);
ret = ivpu_mmu_invalidate_tlb(vdev, ctx->id);
if (ret)
ivpu_err(vdev, "Failed to invalidate TLB for ctx %u: %d\n", ctx->id, ret);
return 0;
}
static void ivpu_mmu_context_unmap_pages(struct ivpu_mmu_context *ctx, u64 vpu_addr, size_t size)
{
while (size) {

View File

@ -46,5 +46,7 @@ int ivpu_mmu_context_map_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *
u64 vpu_addr, struct sg_table *sgt, bool llc_coherent);
void ivpu_mmu_context_unmap_sgt(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr, struct sg_table *sgt);
int ivpu_mmu_context_set_pages_ro(struct ivpu_device *vdev, struct ivpu_mmu_context *ctx,
u64 vpu_addr, size_t size);
#endif /* __IVPU_MMU_CONTEXT_H__ */

View File

@ -237,33 +237,30 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev)
{
struct drm_device *drm = dev_get_drvdata(dev);
struct ivpu_device *vdev = to_ivpu_device(drm);
bool hw_is_idle = true;
int ret;
int ret, ret_d0i3;
bool is_idle;
drm_WARN_ON(&vdev->drm, !xa_empty(&vdev->submitted_jobs_xa));
drm_WARN_ON(&vdev->drm, work_pending(&vdev->pm->recovery_work));
ivpu_dbg(vdev, PM, "Runtime suspend..\n");
if (!ivpu_hw_is_idle(vdev) && vdev->pm->suspend_reschedule_counter) {
ivpu_dbg(vdev, PM, "Failed to enter idle, rescheduling suspend, retries left %d\n",
vdev->pm->suspend_reschedule_counter);
pm_schedule_suspend(dev, vdev->timeout.reschedule_suspend);
vdev->pm->suspend_reschedule_counter--;
return -EAGAIN;
}
ivpu_mmu_disable(vdev);
if (!vdev->pm->suspend_reschedule_counter)
hw_is_idle = false;
else if (ivpu_jsm_pwr_d0i3_enter(vdev))
hw_is_idle = false;
is_idle = ivpu_hw_is_idle(vdev) || vdev->pm->dct_active_percent;
if (!is_idle)
ivpu_err(vdev, "NPU is not idle before autosuspend\n");
ret_d0i3 = ivpu_jsm_pwr_d0i3_enter(vdev);
if (ret_d0i3)
ivpu_err(vdev, "Failed to prepare for d0i3: %d\n", ret_d0i3);
ret = ivpu_suspend(vdev);
if (ret)
ivpu_err(vdev, "Failed to suspend NPU: %d\n", ret);
if (!hw_is_idle) {
ivpu_err(vdev, "NPU failed to enter idle, force suspended.\n");
if (!is_idle || ret_d0i3) {
ivpu_err(vdev, "Forcing cold boot due to previous errors\n");
atomic_inc(&vdev->pm->reset_counter);
ivpu_fw_log_dump(vdev);
ivpu_pm_prepare_cold_boot(vdev);
@ -271,8 +268,6 @@ int ivpu_pm_runtime_suspend_cb(struct device *dev)
ivpu_pm_prepare_warm_boot(vdev);
}
vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
ivpu_dbg(vdev, PM, "Runtime suspend done.\n");
return 0;
@ -300,17 +295,6 @@ int ivpu_rpm_get(struct ivpu_device *vdev)
int ret;
ret = pm_runtime_resume_and_get(vdev->drm.dev);
if (!drm_WARN_ON(&vdev->drm, ret < 0))
vdev->pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
return ret;
}
int ivpu_rpm_get_if_active(struct ivpu_device *vdev)
{
int ret;
ret = pm_runtime_get_if_in_use(vdev->drm.dev);
drm_WARN_ON(&vdev->drm, ret < 0);
return ret;
@ -365,7 +349,6 @@ void ivpu_pm_init(struct ivpu_device *vdev)
int delay;
pm->vdev = vdev;
pm->suspend_reschedule_counter = PM_RESCHEDULE_LIMIT;
init_rwsem(&pm->reset_lock);
atomic_set(&pm->reset_pending, 0);
@ -406,3 +389,68 @@ void ivpu_pm_disable(struct ivpu_device *vdev)
pm_runtime_get_noresume(vdev->drm.dev);
pm_runtime_forbid(vdev->drm.dev);
}
int ivpu_pm_dct_init(struct ivpu_device *vdev)
{
if (vdev->pm->dct_active_percent)
return ivpu_pm_dct_enable(vdev, vdev->pm->dct_active_percent);
return 0;
}
int ivpu_pm_dct_enable(struct ivpu_device *vdev, u8 active_percent)
{
u32 active_us, inactive_us;
int ret;
if (active_percent == 0 || active_percent > 100)
return -EINVAL;
active_us = (DCT_PERIOD_US * active_percent) / 100;
inactive_us = DCT_PERIOD_US - active_us;
ret = ivpu_jsm_dct_enable(vdev, active_us, inactive_us);
if (ret) {
ivpu_err_ratelimited(vdev, "Filed to enable DCT: %d\n", ret);
return ret;
}
vdev->pm->dct_active_percent = active_percent;
ivpu_dbg(vdev, PM, "DCT set to %u%% (D0: %uus, D0i2: %uus)\n",
active_percent, active_us, inactive_us);
return 0;
}
int ivpu_pm_dct_disable(struct ivpu_device *vdev)
{
int ret;
ret = ivpu_jsm_dct_disable(vdev);
if (ret) {
ivpu_err_ratelimited(vdev, "Filed to disable DCT: %d\n", ret);
return ret;
}
vdev->pm->dct_active_percent = 0;
ivpu_dbg(vdev, PM, "DCT disabled\n");
return 0;
}
void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev)
{
bool enable;
int ret;
if (ivpu_hw_btrs_dct_get_request(vdev, &enable))
return;
if (vdev->pm->dct_active_percent)
ret = ivpu_pm_dct_enable(vdev, DCT_DEFAULT_ACTIVE_PERCENT);
else
ret = ivpu_pm_dct_disable(vdev);
if (!ret)
ivpu_hw_btrs_dct_set_status(vdev, enable, vdev->pm->dct_active_percent);
}

View File

@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2020-2023 Intel Corporation
* Copyright (C) 2020-2024 Intel Corporation
*/
#ifndef __IVPU_PM_H__
@ -19,7 +19,7 @@ struct ivpu_pm_info {
atomic_t reset_counter;
atomic_t reset_pending;
bool is_warmboot;
u32 suspend_reschedule_counter;
u8 dct_active_percent;
};
void ivpu_pm_init(struct ivpu_device *vdev);
@ -36,11 +36,15 @@ void ivpu_pm_reset_prepare_cb(struct pci_dev *pdev);
void ivpu_pm_reset_done_cb(struct pci_dev *pdev);
int __must_check ivpu_rpm_get(struct ivpu_device *vdev);
int __must_check ivpu_rpm_get_if_active(struct ivpu_device *vdev);
void ivpu_rpm_put(struct ivpu_device *vdev);
void ivpu_pm_trigger_recovery(struct ivpu_device *vdev, const char *reason);
void ivpu_start_job_timeout_detection(struct ivpu_device *vdev);
void ivpu_stop_job_timeout_detection(struct ivpu_device *vdev);
int ivpu_pm_dct_init(struct ivpu_device *vdev);
int ivpu_pm_dct_enable(struct ivpu_device *vdev, u8 active_percent);
int ivpu_pm_dct_disable(struct ivpu_device *vdev);
void ivpu_pm_dct_irq_thread_handler(struct ivpu_device *vdev);
#endif /* __IVPU_PM_H__ */

View File

@ -27,7 +27,7 @@
* Minor version changes when API backward compatibility is preserved.
* Resets to 0 if Major version is incremented.
*/
#define VPU_BOOT_API_VER_MINOR 22
#define VPU_BOOT_API_VER_MINOR 24
/*
* API header changed (field names, documentation, formatting) but API itself has not been changed
@ -80,6 +80,11 @@ struct vpu_firmware_header {
u32 preemption_buffer_2_size;
/* Space reserved for future preemption-related fields. */
u32 preemption_reserved[6];
/* FW image read only section start address, 4KB aligned */
u64 ro_section_start_address;
/* FW image read only section size, 4KB aligned */
u32 ro_section_size;
u32 reserved;
};
/*
@ -333,7 +338,14 @@ struct vpu_boot_params {
* The KMD is required to update this value on every VPU reset.
*/
u64 system_time_us;
u32 pad4[18];
u32 pad4[2];
/*
* The delta between device monotonic time and the current value of the
* HW timestamp register, in ticks. Written by the firmware during boot.
* Can be used by the KMD to calculate device time.
*/
u64 device_time_delta_ticks;
u32 pad7[14];
/* Warm boot information: 0x400 - 0x43F */
u32 warm_boot_sections_count;
u32 warm_boot_start_address_reference;

View File

@ -274,8 +274,8 @@ static const struct dma_buf_ops cma_heap_buf_ops = {
static struct dma_buf *cma_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
u32 fd_flags,
u64 heap_flags)
{
struct cma_heap *cma_heap = dma_heap_get_drvdata(heap);
struct cma_heap_buffer *buffer;

View File

@ -333,8 +333,8 @@ static struct page *alloc_largest_available(unsigned long size,
static struct dma_buf *system_heap_allocate(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags)
u32 fd_flags,
u64 heap_flags)
{
struct system_heap_buffer *buffer;
DEFINE_DMA_BUF_EXPORT_INFO(exp_info);

View File

@ -107,7 +107,7 @@ config DRM_KMS_HELPER
config DRM_PANIC
bool "Display a user-friendly message when a kernel panic occurs"
depends on DRM && !FRAMEBUFFER_CONSOLE
depends on DRM && !(FRAMEBUFFER_CONSOLE && VT_CONSOLE)
select DRM_KMS_HELPER
select FONT_SUPPORT
help

View File

@ -163,6 +163,14 @@
#define SII902X_AUDIO_PORT_INDEX 3
/*
* The maximum resolution supported by the HDMI bridge is 1080p@60Hz
* and 1920x1200 requiring a pixel clock of 165MHz and the minimum
* resolution supported is 480p@60Hz requiring a pixel clock of 25MHz
*/
#define SII902X_MIN_PIXEL_CLOCK_KHZ 25000
#define SII902X_MAX_PIXEL_CLOCK_KHZ 165000
struct sii902x {
struct i2c_client *i2c;
struct regmap *regmap;
@ -310,20 +318,12 @@ static int sii902x_get_modes(struct drm_connector *connector)
return num;
}
static enum drm_mode_status sii902x_mode_valid(struct drm_connector *connector,
struct drm_display_mode *mode)
{
/* TODO: check mode */
return MODE_OK;
}
static const struct drm_connector_helper_funcs sii902x_connector_helper_funcs = {
.get_modes = sii902x_get_modes,
.mode_valid = sii902x_mode_valid,
};
static void sii902x_bridge_disable(struct drm_bridge *bridge)
static void sii902x_bridge_atomic_disable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct sii902x *sii902x = bridge_to_sii902x(bridge);
@ -336,7 +336,8 @@ static void sii902x_bridge_disable(struct drm_bridge *bridge)
mutex_unlock(&sii902x->mutex);
}
static void sii902x_bridge_enable(struct drm_bridge *bridge)
static void sii902x_bridge_atomic_enable(struct drm_bridge *bridge,
struct drm_bridge_state *old_bridge_state)
{
struct sii902x *sii902x = bridge_to_sii902x(bridge);
@ -495,6 +496,10 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge,
struct drm_crtc_state *crtc_state,
struct drm_connector_state *conn_state)
{
if (crtc_state->mode.clock < SII902X_MIN_PIXEL_CLOCK_KHZ ||
crtc_state->mode.clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
return -EINVAL;
/*
* There might be flags negotiation supported in future but
* set the bus flags in atomic_check statically for now.
@ -504,11 +509,25 @@ static int sii902x_bridge_atomic_check(struct drm_bridge *bridge,
return 0;
}
static enum drm_mode_status
sii902x_bridge_mode_valid(struct drm_bridge *bridge,
const struct drm_display_info *info,
const struct drm_display_mode *mode)
{
if (mode->clock < SII902X_MIN_PIXEL_CLOCK_KHZ)
return MODE_CLOCK_LOW;
if (mode->clock > SII902X_MAX_PIXEL_CLOCK_KHZ)
return MODE_CLOCK_HIGH;
return MODE_OK;
}
static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.attach = sii902x_bridge_attach,
.mode_set = sii902x_bridge_mode_set,
.disable = sii902x_bridge_disable,
.enable = sii902x_bridge_enable,
.atomic_disable = sii902x_bridge_atomic_disable,
.atomic_enable = sii902x_bridge_atomic_enable,
.detect = sii902x_bridge_detect,
.edid_read = sii902x_bridge_edid_read,
.atomic_reset = drm_atomic_helper_bridge_reset,
@ -516,6 +535,7 @@ static const struct drm_bridge_funcs sii902x_bridge_funcs = {
.atomic_destroy_state = drm_atomic_helper_bridge_destroy_state,
.atomic_get_input_bus_fmts = sii902x_bridge_atomic_get_input_bus_fmts,
.atomic_check = sii902x_bridge_atomic_check,
.mode_valid = sii902x_bridge_mode_valid,
};
static int sii902x_mute(struct sii902x *sii902x, bool mute)

View File

@ -170,7 +170,6 @@ static int simple_bridge_probe(struct platform_device *pdev)
sbridge = devm_kzalloc(&pdev->dev, sizeof(*sbridge), GFP_KERNEL);
if (!sbridge)
return -ENOMEM;
platform_set_drvdata(pdev, sbridge);
sbridge->info = of_device_get_match_data(&pdev->dev);
@ -208,16 +207,7 @@ static int simple_bridge_probe(struct platform_device *pdev)
sbridge->bridge.of_node = pdev->dev.of_node;
sbridge->bridge.timings = sbridge->info->timings;
drm_bridge_add(&sbridge->bridge);
return 0;
}
static void simple_bridge_remove(struct platform_device *pdev)
{
struct simple_bridge *sbridge = platform_get_drvdata(pdev);
drm_bridge_remove(&sbridge->bridge);
return devm_drm_bridge_add(&pdev->dev, &sbridge->bridge);
}
/*
@ -294,7 +284,6 @@ MODULE_DEVICE_TABLE(of, simple_bridge_match);
static struct platform_driver simple_bridge_driver = {
.probe = simple_bridge_probe,
.remove_new = simple_bridge_remove,
.driver = {
.name = "simple-bridge",
.of_match_table = simple_bridge_match,

View File

@ -160,7 +160,6 @@ fi
mkdir -p artifacts/install/lib
mv install/* artifacts/install/.
rm -rf artifacts/install/modules
ln -s common artifacts/install/ci-common
cp .config artifacts/${CI_JOB_NAME}_config

View File

@ -123,6 +123,7 @@ stages:
- msm
- rockchip
- virtio-gpu
- software-driver
# YAML anchors for rule conditions
# --------------------------------

View File

@ -30,10 +30,10 @@ case "$DRIVER_NAME" in
export IGT_FORCE_DRIVER="panfrost"
fi
;;
amdgpu)
amdgpu|vkms)
# Cannot use HWCI_KERNEL_MODULES as at that point we don't have the module in /lib
mv /install/modules/lib/modules/* /lib/modules/.
modprobe amdgpu
mv /install/modules/lib/modules/* /lib/modules/. || true
modprobe --first-time $DRIVER_NAME
;;
esac

View File

@ -4,7 +4,7 @@ variables:
DEBIAN_BASE_TAG: "${CONTAINER_TAG}"
DEBIAN_X86_64_BUILD_IMAGE_PATH: "debian/x86_64_build"
DEBIAN_BUILD_TAG: "2023-10-08-config"
DEBIAN_BUILD_TAG: "2024-06-10-vkms"
KERNEL_ROOTFS_TAG: "2023-10-06-amd"

View File

@ -338,7 +338,7 @@ meson:g12b:
RUNNER_TAG: mesa-ci-x86-64-lava-meson-g12b-a311d-khadas-vim3
virtio_gpu:none:
stage: virtio-gpu
stage: software-driver
variables:
CROSVM_GALLIUM_DRIVER: llvmpipe
DRIVER_NAME: virtio_gpu
@ -358,3 +358,25 @@ virtio_gpu:none:
- debian/x86_64_test-gl
- testing:x86_64
- igt:x86_64
vkms:none:
stage: software-driver
variables:
DRIVER_NAME: vkms
GPU_VERSION: none
extends:
- .test-gl
- .test-rules
tags:
- kvm
script:
- ln -sf $CI_PROJECT_DIR/install /install
- mv install/bzImage /lava-files/bzImage
- mkdir -p /lib/modules
- mkdir -p $CI_PROJECT_DIR/results
- ln -sf $CI_PROJECT_DIR/results /results
- ./install/crosvm-runner.sh ./install/igt_runner.sh
needs:
- debian/x86_64_test-gl
- testing:x86_64
- igt:x86_64

View File

@ -24,6 +24,7 @@ CONFIG_DRM=y
CONFIG_DRM_PANEL_SIMPLE=y
CONFIG_PWM_CROS_EC=y
CONFIG_BACKLIGHT_PWM=y
CONFIG_DRM_VKMS=m
# Strip out some stuff we don't need for graphics testing, to reduce
# the build.

View File

@ -4,7 +4,6 @@ device_reset@unbind-cold-reset-rebind,Fail
device_reset@unbind-reset-rebind,Fail
dumb_buffer@invalid-bpp,Fail
kms_3d,Fail
kms_addfb_basic@addfb25-bad-modifier,Fail
kms_cursor_legacy@forked-move,Fail
kms_cursor_legacy@single-bo,Fail
kms_cursor_legacy@torture-bo,Fail

View File

@ -4,6 +4,5 @@ device_reset@unbind-cold-reset-rebind,Fail
device_reset@unbind-reset-rebind,Fail
dumb_buffer@invalid-bpp,Fail
kms_3d,Fail
kms_addfb_basic@addfb25-bad-modifier,Fail
kms_lease@lease-uevent,Fail
tools_test@tools_test,Fail

View File

@ -0,0 +1,57 @@
core_hotunplug@hotrebind,Fail
core_hotunplug@hotrebind-lateclose,Fail
core_hotunplug@hotreplug,Fail
core_hotunplug@hotreplug-lateclose,Fail
core_hotunplug@hotunbind-rebind,Fail
core_hotunplug@hotunplug-rescan,Fail
core_hotunplug@unbind-rebind,Fail
core_hotunplug@unplug-rescan,Fail
device_reset@cold-reset-bound,Fail
device_reset@reset-bound,Fail
device_reset@unbind-cold-reset-rebind,Fail
device_reset@unbind-reset-rebind,Fail
dumb_buffer@invalid-bpp,Fail
kms_content_protection@atomic,Crash
kms_content_protection@atomic-dpms,Crash
kms_content_protection@content-type-change,Crash
kms_content_protection@lic-type-0,Crash
kms_content_protection@lic-type-1,Crash
kms_content_protection@srm,Crash
kms_content_protection@type1,Crash
kms_content_protection@uevent,Crash
kms_cursor_crc@cursor-rapid-movement-128x128,Fail
kms_cursor_crc@cursor-rapid-movement-128x42,Fail
kms_cursor_crc@cursor-rapid-movement-256x256,Fail
kms_cursor_crc@cursor-rapid-movement-256x85,Fail
kms_cursor_crc@cursor-rapid-movement-32x10,Fail
kms_cursor_crc@cursor-rapid-movement-32x32,Fail
kms_cursor_crc@cursor-rapid-movement-512x170,Fail
kms_cursor_crc@cursor-rapid-movement-512x512,Fail
kms_cursor_crc@cursor-rapid-movement-64x21,Fail
kms_cursor_crc@cursor-rapid-movement-64x64,Fail
kms_cursor_legacy@basic-flip-before-cursor-atomic,Fail
kms_cursor_legacy@basic-flip-before-cursor-legacy,Fail
kms_cursor_legacy@cursor-vs-flip-atomic,Fail
kms_cursor_legacy@cursor-vs-flip-legacy,Fail
kms_cursor_legacy@cursor-vs-flip-toggle,Fail
kms_cursor_legacy@cursor-vs-flip-varying-size,Fail
kms_cursor_legacy@flip-vs-cursor-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-crc-atomic,Fail
kms_cursor_legacy@flip-vs-cursor-crc-legacy,Fail
kms_cursor_legacy@flip-vs-cursor-legacy,Fail
kms_flip@flip-vs-modeset-vs-hang,Fail
kms_flip@flip-vs-panning-vs-hang,Fail
kms_flip@flip-vs-suspend,Timeout
kms_flip@flip-vs-suspend-interruptible,Timeout
kms_flip@plain-flip-fb-recreate,Fail
kms_lease@lease-uevent,Fail
kms_pipe_crc_basic@nonblocking-crc,Fail
kms_pipe_crc_basic@nonblocking-crc-frame-sequence,Fail
kms_writeback@writeback-check-output,Fail
kms_writeback@writeback-check-output-XRGB2101010,Fail
kms_writeback@writeback-fb-id,Fail
kms_writeback@writeback-fb-id-XRGB2101010,Fail
kms_writeback@writeback-invalid-parameters,Fail
kms_writeback@writeback-pixel-formats,Fail
perf@i915-ref-count,Fail
tools_test@tools_test,Fail

View File

@ -0,0 +1,69 @@
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_cursor_legacy@long-nonblocking-modeset-vs-cursor-atomic
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@basic-flip-vs-wf_vblank
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@flip-vs-expired-vblank-interruptible
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@flip-vs-wf_vblank-interruptible
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@plain-flip-fb-recreate-interruptible
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@plain-flip-ts-check
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@plain-flip-ts-check-interruptible
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@flip-vs-absolute-wf_vblank
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@flip-vs-absolute-wf_vblank-interruptible
# Board Name: vkms
# Bug Report: https://lore.kernel.org/dri-devel/61ed26af-062c-443c-9df2-d1ee319f3fb0@collabora.com/T/#u
# Failure Rate: 50
# IGT Version: 1.28-g0df7b9b97
# Linux Version: 6.9.0-rc7
kms_flip@flip-vs-blocking-wf-vblank

View File

@ -0,0 +1,119 @@
# keeps printing vkms_vblank_simulate: vblank timer overrun and never ends
kms_invalid_mode@int-max-clock
# Kernel panic
kms_cursor_crc@cursor-rapid-movement-32x10
# Oops: 0000 [#1] PREEMPT SMP NOPTI
# CPU: 0 PID: 2635 Comm: kworker/u8:13 Not tainted 6.9.0-rc7-g40935263a1fd #1
# Hardware name: ChromiumOS crosvm, BIOS 0
# Workqueue: vkms_composer vkms_composer_worker [vkms]
# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246
# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8
# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700
# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000
# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000
# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
# CR2: 0000000000000078 CR3: 000000010bd30000 CR4: 0000000000350ef0
# Call Trace:
# <TASK>
# ? __die+0x1e/0x60
# ? page_fault_oops+0x17b/0x490
# ? exc_page_fault+0x6d/0x230
# ? asm_exc_page_fault+0x26/0x30
# ? compose_active_planes+0x1c7/0x4e0 [vkms]
# ? compose_active_planes+0x2a3/0x4e0 [vkms]
# ? srso_return_thunk+0x5/0x5f
# vkms_composer_worker+0x205/0x240 [vkms]
# process_one_work+0x1f4/0x6b0
# ? lock_is_held_type+0x9e/0x110
# worker_thread+0x17e/0x350
# ? __pfx_worker_thread+0x10/0x10
# kthread+0xce/0x100
# ? __pfx_kthread+0x10/0x10
# ret_from_fork+0x2f/0x50
# ? __pfx_kthread+0x10/0x10
# ret_from_fork_asm+0x1a/0x30
# </TASK>
# Modules linked in: vkms
# CR2: 0000000000000078
# ---[ end trace 0000000000000000 ]---
# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
# RSP: 0018:ffffbb4700c17d58 EFLAGS: 00010246
# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
# RDX: 0000000000000000 RSI: ffffa2ad0788c000 RDI: 00000000fff479a8
# RBP: 0000000000000004 R08: 0000000000000000 R09: 0000000000000000
# R10: ffffa2ad0bb14000 R11: 0000000000000000 R12: ffffa2ad03e21700
# R13: 0000000000000003 R14: 0000000000000004 R15: 0000000000000000
# FS: 0000000000000000(0000) GS:ffffa2ad2bc00000(0000) knlGS:0000000000000000
# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
kms_cursor_crc@cursor-rapid-movement-256x85
# [drm:drm_crtc_add_crc_entry] *ERROR* Overflow of CRC buffer, userspace reads too slow.
# Oops: 0000 [#1] PREEMPT SMP NOPTI
# CPU: 1 PID: 10 Comm: kworker/u8:0 Not tainted 6.9.0-rc7-g646381cde463 #1
# Hardware name: ChromiumOS crosvm, BIOS 0
# Workqueue: vkms_composer vkms_composer_worker [vkms]
# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246
# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f
# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590
# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000
# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0
# Call Trace:
# <TASK>
# ? __die+0x1e/0x60
# ? page_fault_oops+0x17b/0x490
# ? exc_page_fault+0x6d/0x230
# ? asm_exc_page_fault+0x26/0x30
# ? compose_active_planes+0x1c7/0x4e0 [vkms]
# ? compose_active_planes+0x2a3/0x4e0 [vkms]
# ? srso_return_thunk+0x5/0x5f
# vkms_composer_worker+0x205/0x240 [vkms]
# process_one_work+0x1f4/0x6b0
# ? lock_is_held_type+0x9e/0x110
# worker_thread+0x17e/0x350
# ? __pfx_worker_thread+0x10/0x10
# kthread+0xce/0x100
# ? __pfx_kthread+0x10/0x10
# ret_from_fork+0x2f/0x50
# ? __pfx_kthread+0x10/0x10
# ret_from_fork_asm+0x1a/0x30
# </TASK>
# Modules linked in: vkms
# CR2: 0000000000000078
# ---[ end trace 0000000000000000 ]---
# RIP: 0010:compose_active_planes+0x1c7/0x4e0 [vkms]
# Code: c9 0f 84 6a 01 00 00 8b 42 30 2b 42 28 41 39 c5 0f 8c 6f 01 00 00 49 83 c7 01 49 39 df 74 3b 4b 8b 34 fc 48 8b 96 48 01 00 00 <8b> 42 78 89 c1 83 e1 0a a8 20 74 b1 45 89 f5 41 f7 d5 44 03 6a 34
# RSP: 0018:ffffa7e980057d58 EFLAGS: 00010246
# RAX: 0000000000000400 RBX: 0000000000000002 RCX: 0000000000000002
# RDX: 0000000000000000 RSI: ffff977987aa5c00 RDI: 000000001b43a85f
# RBP: 0000000000000001 R08: 0000000000000000 R09: 0000000000000000
# R10: ffff977981bf0000 R11: 0000000000000000 R12: ffff977989622590
# R13: 0000000000000000 R14: 0000000000000001 R15: 0000000000000000
# FS: 0000000000000000(0000) GS:ffff9779abd00000(0000) knlGS:0000000000000000
# CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
# CR2: 0000000000000078 CR3: 0000000109b38000 CR4: 0000000000350ef0
# Skip driver specific tests
^amdgpu.*
msm_.*
nouveau_.*
panfrost_.*
^v3d.*
^vc4.*
^vmwgfx*
# Skip intel specific tests
gem_.*
i915_.*
xe_.*

View File

@ -1087,6 +1087,7 @@ static const struct drm_prop_enum_list drm_tv_mode_enum_list[] = {
{ DRM_MODE_TV_MODE_PAL_M, "PAL-M" },
{ DRM_MODE_TV_MODE_PAL_N, "PAL-N" },
{ DRM_MODE_TV_MODE_SECAM, "SECAM" },
{ DRM_MODE_TV_MODE_MONOCHROME, "Mono" },
};
DRM_ENUM_NAME_FN(drm_get_tv_mode_name, drm_tv_mode_enum_list)
@ -1858,6 +1859,12 @@ EXPORT_SYMBOL(drm_connector_attach_dp_subconnector_property);
* TV Mode is CCIR System B (aka 625-lines) together with
* the SECAM Color Encoding.
*
* Mono:
*
* Use timings appropriate to the DRM mode, including
* equalizing pulses for a 525-line or 625-line mode,
* with no pedestal or color encoding.
*
* Drivers can set up this property by calling
* drm_mode_create_tv_properties().
*/

View File

@ -531,7 +531,8 @@ static int fill_analog_mode(struct drm_device *dev,
* @interlace: whether to compute an interlaced mode
*
* This function creates a struct drm_display_mode instance suited for
* an analog TV output, for one of the usual analog TV mode.
* an analog TV output, for one of the usual analog TV modes. Where
* this is DRM_MODE_TV_MODE_MONOCHROME, a 625-line mode will be created.
*
* Note that @hdisplay is larger than the usual constraints for the PAL
* and NTSC timings, and we'll choose to ignore most timings constraints
@ -569,6 +570,8 @@ struct drm_display_mode *drm_analog_tv_mode(struct drm_device *dev,
case DRM_MODE_TV_MODE_PAL_N:
fallthrough;
case DRM_MODE_TV_MODE_SECAM:
fallthrough;
case DRM_MODE_TV_MODE_MONOCHROME:
analog = DRM_MODE_ANALOG_PAL;
break;

View File

@ -1259,8 +1259,9 @@ int drm_connector_helper_tv_get_modes(struct drm_connector *connector)
for (i = 0; i < tv_mode_property->num_values; i++)
supported_tv_modes |= BIT(tv_mode_property->values[i]);
if ((supported_tv_modes & ntsc_modes) &&
(supported_tv_modes & pal_modes)) {
if (((supported_tv_modes & ntsc_modes) &&
(supported_tv_modes & pal_modes)) ||
(supported_tv_modes & BIT(DRM_MODE_TV_MODE_MONOCHROME))) {
uint64_t default_mode;
if (drm_object_property_get_default_value(&connector->base,

View File

@ -11,6 +11,7 @@ mgag200-y := \
mgag200_g200ew3.o \
mgag200_g200se.o \
mgag200_g200wb.o \
mgag200_mode.o
mgag200_mode.o \
mgag200_vga.o
obj-$(CONFIG_DRM_MGAG200) += mgag200.o

View File

@ -2,8 +2,18 @@
#include <linux/delay.h>
#include <drm/drm_atomic_helper.h>
#include <drm/drm_edid.h>
#include <drm/drm_managed.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_drv.h"
static struct mgag200_bmc_connector *to_mgag200_bmc_connector(struct drm_connector *connector)
{
return container_of(connector, struct mgag200_bmc_connector, base);
}
void mgag200_bmc_disable_vidrst(struct mga_device *mdev)
{
u8 tmp;
@ -97,3 +107,100 @@ void mgag200_bmc_enable_vidrst(struct mga_device *mdev)
tmp &= ~0x10;
WREG_DAC(MGA1064_GEN_IO_DATA, tmp);
}
static const struct drm_encoder_funcs mgag200_bmc_encoder_funcs = {
.destroy = drm_encoder_cleanup,
};
static int mgag200_bmc_connector_helper_detect_ctx(struct drm_connector *connector,
struct drm_modeset_acquire_ctx *ctx,
bool force)
{
struct mgag200_bmc_connector *bmc_connector = to_mgag200_bmc_connector(connector);
struct drm_connector *physical_connector = bmc_connector->physical_connector;
/*
* Most user-space compositors cannot handle more than one connected
* connector per CRTC. Hence, we only mark the BMC as connected if the
* physical connector is disconnected. If the physical connector's status
* is connected or unknown, the BMC remains disconnected. This has no
* effect on the output of the BMC.
*
* FIXME: Remove this logic once user-space compositors can handle more
* than one connector per CRTC. The BMC should always be connected.
*/
if (physical_connector && physical_connector->status == connector_status_disconnected)
return connector_status_connected;
return connector_status_disconnected;
}
static int mgag200_bmc_connector_helper_get_modes(struct drm_connector *connector)
{
struct drm_device *dev = connector->dev;
struct mga_device *mdev = to_mga_device(dev);
const struct mgag200_device_info *minfo = mdev->info;
return drm_add_modes_noedid(connector, minfo->max_hdisplay, minfo->max_vdisplay);
}
static const struct drm_connector_helper_funcs mgag200_bmc_connector_helper_funcs = {
.get_modes = mgag200_bmc_connector_helper_get_modes,
.detect_ctx = mgag200_bmc_connector_helper_detect_ctx,
};
static const struct drm_connector_funcs mgag200_bmc_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state,
};
static int mgag200_bmc_connector_init(struct drm_device *dev,
struct mgag200_bmc_connector *bmc_connector,
struct drm_connector *physical_connector)
{
struct drm_connector *connector = &bmc_connector->base;
int ret;
ret = drm_connector_init(dev, connector, &mgag200_bmc_connector_funcs,
DRM_MODE_CONNECTOR_VIRTUAL);
if (ret)
return ret;
drm_connector_helper_add(connector, &mgag200_bmc_connector_helper_funcs);
bmc_connector->physical_connector = physical_connector;
return 0;
}
int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector)
{
struct drm_device *dev = &mdev->base;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder;
struct mgag200_bmc_connector *bmc_connector;
struct drm_connector *connector;
int ret;
encoder = &mdev->output.bmc.encoder;
ret = drm_encoder_init(dev, encoder, &mgag200_bmc_encoder_funcs,
DRM_MODE_ENCODER_VIRTUAL, NULL);
if (ret)
return ret;
encoder->possible_crtcs = drm_crtc_mask(crtc);
bmc_connector = &mdev->output.bmc.bmc_connector;
ret = mgag200_bmc_connector_init(dev, bmc_connector, physical_connector);
if (ret)
return ret;
connector = &bmc_connector->base;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret)
return ret;
return 0;
}

View File

@ -186,6 +186,11 @@ static inline struct mgag200_crtc_state *to_mgag200_crtc_state(struct drm_crtc_s
return container_of(base, struct mgag200_crtc_state, base);
}
struct mgag200_bmc_connector {
struct drm_connector base;
struct drm_connector *physical_connector;
};
enum mga_type {
G200_PCI,
G200_AGP,
@ -283,8 +288,16 @@ struct mga_device {
struct drm_plane primary_plane;
struct drm_crtc crtc;
struct drm_encoder encoder;
struct drm_connector connector;
struct {
struct {
struct drm_encoder encoder;
struct drm_connector connector;
} vga;
struct {
struct drm_encoder encoder;
struct mgag200_bmc_connector bmc_connector;
} bmc;
} output;
};
static inline struct mga_device *to_mga_device(struct drm_device *dev)
@ -417,27 +430,18 @@ void mgag200_crtc_atomic_destroy_state(struct drm_crtc *crtc, struct drm_crtc_st
.atomic_duplicate_state = mgag200_crtc_atomic_duplicate_state, \
.atomic_destroy_state = mgag200_crtc_atomic_destroy_state
#define MGAG200_DAC_ENCODER_FUNCS \
.destroy = drm_encoder_cleanup
#define MGAG200_VGA_CONNECTOR_HELPER_FUNCS \
.get_modes = drm_connector_helper_get_modes
#define MGAG200_VGA_CONNECTOR_FUNCS \
.reset = drm_atomic_helper_connector_reset, \
.fill_modes = drm_helper_probe_single_connector_modes, \
.destroy = drm_connector_cleanup, \
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state, \
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state
void mgag200_set_mode_regs(struct mga_device *mdev, const struct drm_display_mode *mode);
void mgag200_set_format_regs(struct mga_device *mdev, const struct drm_format_info *format);
void mgag200_enable_display(struct mga_device *mdev);
void mgag200_init_registers(struct mga_device *mdev);
int mgag200_mode_config_init(struct mga_device *mdev, resource_size_t vram_available);
/* mgag200_vga.c */
int mgag200_vga_output_init(struct mga_device *mdev);
/* mgag200_bmc.c */
void mgag200_bmc_disable_vidrst(struct mga_device *mdev);
void mgag200_bmc_enable_vidrst(struct mga_device *mdev);
int mgag200_bmc_output_init(struct mga_device *mdev, struct drm_connector *physical_connector);
#endif /* __MGAG200_DRV_H__ */

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static int mgag200_g200_init_pci_options(struct pci_dev *pdev)
@ -184,26 +183,11 @@ static const struct drm_crtc_funcs mgag200_g200_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -231,35 +215,9 @@ static int mgag200_g200_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -443,6 +401,7 @@ struct mga_device *mgag200_g200_device_create(struct pci_dev *pdev, const struct
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
void mgag200_g200eh_init_registers(struct mga_device *mdev)
@ -183,26 +182,11 @@ static const struct drm_crtc_funcs mgag200_g200eh_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200eh_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200eh_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200eh_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -230,35 +214,13 @@ static int mgag200_g200eh_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200eh_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200eh_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200eh_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -315,6 +277,7 @@ struct mga_device *mgag200_g200eh_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -8,7 +8,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
/*
@ -87,26 +86,11 @@ static const struct drm_crtc_funcs mgag200_g200eh3_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200eh3_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200eh3_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200eh3_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -134,35 +118,13 @@ static int mgag200_g200eh3_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200eh3_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200eh3_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200eh3_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -220,6 +182,7 @@ struct mga_device *mgag200_g200eh3_device_create(struct pci_dev *pdev,
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200er_init_registers(struct mga_device *mdev)
@ -226,26 +225,11 @@ static const struct drm_crtc_funcs mgag200_g200er_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200er_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200er_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200er_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -273,35 +257,13 @@ static int mgag200_g200er_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200er_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200er_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200er_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -354,6 +316,7 @@ struct mga_device *mgag200_g200er_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200ev_init_registers(struct mga_device *mdev)
@ -227,26 +226,11 @@ static const struct drm_crtc_funcs mgag200_g200ev_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200ev_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200ev_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200ev_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -274,35 +258,13 @@ static int mgag200_g200ev_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200ev_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200ev_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200ev_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -359,6 +321,7 @@ struct mga_device *mgag200_g200ev_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -8,7 +8,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static void mgag200_g200ew3_init_registers(struct mga_device *mdev)
@ -96,26 +95,11 @@ static const struct drm_crtc_funcs mgag200_g200ew3_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200ew3_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200ew3_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200ew3_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -143,35 +127,13 @@ static int mgag200_g200ew3_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200ew3_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200ew3_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200ew3_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -240,6 +202,7 @@ struct mga_device *mgag200_g200ew3_device_create(struct pci_dev *pdev,
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static int mgag200_g200se_init_pci_options(struct pci_dev *pdev)
@ -358,26 +357,11 @@ static const struct drm_crtc_funcs mgag200_g200se_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200se_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200se_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200se_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -405,35 +389,13 @@ static int mgag200_g200se_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200se_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200se_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200se_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -559,6 +521,7 @@ struct mga_device *mgag200_g200se_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -9,7 +9,6 @@
#include <drm/drm_gem_atomic_helper.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
void mgag200_g200wb_init_registers(struct mga_device *mdev)
@ -230,26 +229,11 @@ static const struct drm_crtc_funcs mgag200_g200wb_crtc_funcs = {
MGAG200_CRTC_FUNCS,
};
static const struct drm_encoder_funcs mgag200_g200wb_dac_encoder_funcs = {
MGAG200_DAC_ENCODER_FUNCS,
};
static const struct drm_connector_helper_funcs mgag200_g200wb_vga_connector_helper_funcs = {
MGAG200_VGA_CONNECTOR_HELPER_FUNCS,
};
static const struct drm_connector_funcs mgag200_g200wb_vga_connector_funcs = {
MGAG200_VGA_CONNECTOR_FUNCS,
};
static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_plane *primary_plane = &mdev->primary_plane;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder = &mdev->encoder;
struct drm_connector *connector = &mdev->connector;
struct i2c_adapter *ddc;
int ret;
ret = drm_universal_plane_init(dev, primary_plane, 0,
@ -277,35 +261,13 @@ static int mgag200_g200wb_pipeline_init(struct mga_device *mdev)
drm_mode_crtc_set_gamma_size(crtc, MGAG200_LUT_SIZE);
drm_crtc_enable_color_mgmt(crtc, 0, false, MGAG200_LUT_SIZE);
encoder->possible_crtcs = drm_crtc_mask(crtc);
ret = drm_encoder_init(dev, encoder, &mgag200_g200wb_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
ret = mgag200_vga_output_init(mdev);
if (ret)
return ret;
}
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
ret = mgag200_bmc_output_init(mdev, &mdev->output.vga.connector);
if (ret)
return ret;
}
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_g200wb_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_g200wb_vga_connector_helper_funcs);
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}
@ -364,6 +326,7 @@ struct mga_device *mgag200_g200wb_device_create(struct pci_dev *pdev, const stru
return ERR_PTR(ret);
drm_mode_config_reset(dev);
drm_kms_helper_poll_init(dev);
return mdev;
}

View File

@ -0,0 +1,72 @@
// SPDX-License-Identifier: GPL-2.0-only
#include <drm/drm_atomic_helper.h>
#include <drm/drm_modeset_helper_vtables.h>
#include <drm/drm_probe_helper.h>
#include "mgag200_ddc.h"
#include "mgag200_drv.h"
static const struct drm_encoder_funcs mgag200_dac_encoder_funcs = {
.destroy = drm_encoder_cleanup
};
static const struct drm_connector_helper_funcs mgag200_vga_connector_helper_funcs = {
.get_modes = drm_connector_helper_get_modes,
.detect_ctx = drm_connector_helper_detect_from_ddc
};
static const struct drm_connector_funcs mgag200_vga_connector_funcs = {
.reset = drm_atomic_helper_connector_reset,
.fill_modes = drm_helper_probe_single_connector_modes,
.destroy = drm_connector_cleanup,
.atomic_duplicate_state = drm_atomic_helper_connector_duplicate_state,
.atomic_destroy_state = drm_atomic_helper_connector_destroy_state
};
int mgag200_vga_output_init(struct mga_device *mdev)
{
struct drm_device *dev = &mdev->base;
struct drm_crtc *crtc = &mdev->crtc;
struct drm_encoder *encoder;
struct drm_connector *connector;
struct i2c_adapter *ddc;
int ret;
encoder = &mdev->output.vga.encoder;
ret = drm_encoder_init(dev, encoder, &mgag200_dac_encoder_funcs,
DRM_MODE_ENCODER_DAC, NULL);
if (ret) {
drm_err(dev, "drm_encoder_init() failed: %d\n", ret);
return ret;
}
encoder->possible_crtcs = drm_crtc_mask(crtc);
ddc = mgag200_ddc_create(mdev);
if (IS_ERR(ddc)) {
ret = PTR_ERR(ddc);
drm_err(dev, "failed to add DDC bus: %d\n", ret);
return ret;
}
connector = &mdev->output.vga.connector;
ret = drm_connector_init_with_ddc(dev, connector,
&mgag200_vga_connector_funcs,
DRM_MODE_CONNECTOR_VGA, ddc);
if (ret) {
drm_err(dev, "drm_connector_init_with_ddc() failed: %d\n", ret);
return ret;
}
drm_connector_helper_add(connector, &mgag200_vga_connector_helper_funcs);
connector->polled = DRM_CONNECTOR_POLL_CONNECT |
DRM_CONNECTOR_POLL_DISCONNECT;
ret = drm_connector_attach_encoder(connector, encoder);
if (ret) {
drm_err(dev, "drm_connector_attach_encoder() failed: %d\n", ret);
return ret;
}
return 0;
}

View File

@ -898,7 +898,7 @@ nouveau_bo_move_m2mf(struct ttm_buffer_object *bo, int evict,
* Without this the operation can timeout and we'll fallback to a
* software copy, which might take several minutes to finish.
*/
nouveau_fence_wait(fence, false, false);
nouveau_fence_wait(fence, false);
ret = ttm_bo_move_accel_cleanup(bo, &fence->base, evict, false,
new_reg);
nouveau_fence_unref(&fence);

View File

@ -72,7 +72,7 @@ nouveau_channel_idle(struct nouveau_channel *chan)
ret = nouveau_fence_new(&fence, chan);
if (!ret) {
ret = nouveau_fence_wait(fence, false, false);
ret = nouveau_fence_wait(fence, false);
nouveau_fence_unref(&fence);
}

View File

@ -128,7 +128,7 @@ static void nouveau_dmem_page_free(struct page *page)
static void nouveau_dmem_fence_done(struct nouveau_fence **fence)
{
if (fence) {
nouveau_fence_wait(*fence, true, false);
nouveau_fence_wait(*fence, false);
nouveau_fence_unref(fence);
} else {
/*

View File

@ -188,7 +188,7 @@ nouveau_exec_job_timeout(struct nouveau_job *job)
return DRM_GPU_SCHED_STAT_NOMINAL;
}
static struct nouveau_job_ops nouveau_exec_job_ops = {
static const struct nouveau_job_ops nouveau_exec_job_ops = {
.submit = nouveau_exec_job_submit,
.armed_submit = nouveau_exec_job_armed_submit,
.run = nouveau_exec_job_run,

View File

@ -311,39 +311,11 @@ nouveau_fence_wait_legacy(struct dma_fence *f, bool intr, long wait)
return timeout - t;
}
static int
nouveau_fence_wait_busy(struct nouveau_fence *fence, bool intr)
{
int ret = 0;
while (!nouveau_fence_done(fence)) {
if (time_after_eq(jiffies, fence->timeout)) {
ret = -EBUSY;
break;
}
__set_current_state(intr ?
TASK_INTERRUPTIBLE :
TASK_UNINTERRUPTIBLE);
if (intr && signal_pending(current)) {
ret = -ERESTARTSYS;
break;
}
}
__set_current_state(TASK_RUNNING);
return ret;
}
int
nouveau_fence_wait(struct nouveau_fence *fence, bool lazy, bool intr)
nouveau_fence_wait(struct nouveau_fence *fence, bool intr)
{
long ret;
if (!lazy)
return nouveau_fence_wait_busy(fence, intr);
ret = dma_fence_wait_timeout(&fence->base, intr, 15 * HZ);
if (ret < 0)
return ret;

View File

@ -23,7 +23,7 @@ void nouveau_fence_unref(struct nouveau_fence **);
int nouveau_fence_emit(struct nouveau_fence *);
bool nouveau_fence_done(struct nouveau_fence *);
int nouveau_fence_wait(struct nouveau_fence *, bool lazy, bool intr);
int nouveau_fence_wait(struct nouveau_fence *, bool intr);
int nouveau_fence_sync(struct nouveau_bo *, struct nouveau_channel *, bool exclusive, bool intr);
struct nouveau_fence_chan {

View File

@ -928,7 +928,7 @@ revalidate:
}
if (sync) {
if (!(ret = nouveau_fence_wait(fence, false, false))) {
if (!(ret = nouveau_fence_wait(fence, false))) {
if ((ret = dma_fence_get_status(&fence->base)) == 1)
ret = 0;
}

View File

@ -42,7 +42,7 @@ struct nouveau_job_args {
u32 count;
} out_sync;
struct nouveau_job_ops *ops;
const struct nouveau_job_ops *ops;
};
struct nouveau_job {
@ -73,7 +73,7 @@ struct nouveau_job {
u32 count;
} out_sync;
struct nouveau_job_ops {
const struct nouveau_job_ops {
/* If .submit() returns without any error, it is guaranteed that
* armed_submit() is called.
*/

View File

@ -1534,7 +1534,7 @@ nouveau_uvmm_bind_job_cleanup(struct nouveau_job *job)
nouveau_uvmm_bind_job_put(bind_job);
}
static struct nouveau_job_ops nouveau_bind_job_ops = {
static const struct nouveau_job_ops nouveau_bind_job_ops = {
.submit = nouveau_uvmm_bind_job_submit,
.armed_submit = nouveau_uvmm_bind_job_armed_submit,
.run = nouveau_uvmm_bind_job_run,

View File

@ -1045,33 +1045,6 @@ static const struct panel_desc auo_b116xak01 = {
},
};
static const struct drm_display_mode auo_b133han05_mode = {
.clock = 142600,
.hdisplay = 1920,
.hsync_start = 1920 + 58,
.hsync_end = 1920 + 58 + 42,
.htotal = 1920 + 58 + 42 + 60,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 5,
.vtotal = 1080 + 3 + 5 + 54,
};
static const struct panel_desc auo_b133han05 = {
.modes = &auo_b133han05_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 293,
.height = 165,
},
.delay = {
.hpd_reliable = 100,
.enable = 20,
.unprepare = 50,
},
};
static const struct drm_display_mode auo_b133htn01_mode = {
.clock = 150660,
.hdisplay = 1920,
@ -1121,33 +1094,6 @@ static const struct panel_desc auo_b133xtn01 = {
},
};
static const struct drm_display_mode auo_b140han06_mode = {
.clock = 141000,
.hdisplay = 1920,
.hsync_start = 1920 + 16,
.hsync_end = 1920 + 16 + 16,
.htotal = 1920 + 16 + 16 + 152,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 14,
.vtotal = 1080 + 3 + 14 + 19,
};
static const struct panel_desc auo_b140han06 = {
.modes = &auo_b140han06_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 309,
.height = 174,
},
.delay = {
.hpd_reliable = 100,
.enable = 20,
.unprepare = 50,
},
};
static const struct drm_display_mode boe_nv101wxmn51_modes[] = {
{
.clock = 71900,
@ -1414,33 +1360,6 @@ static const struct panel_desc innolux_p120zdg_bf1 = {
},
};
static const struct drm_display_mode ivo_m133nwf4_r0_mode = {
.clock = 138778,
.hdisplay = 1920,
.hsync_start = 1920 + 24,
.hsync_end = 1920 + 24 + 48,
.htotal = 1920 + 24 + 48 + 88,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 12,
.vtotal = 1080 + 3 + 12 + 17,
.flags = DRM_MODE_FLAG_PHSYNC | DRM_MODE_FLAG_PVSYNC,
};
static const struct panel_desc ivo_m133nwf4_r0 = {
.modes = &ivo_m133nwf4_r0_mode,
.num_modes = 1,
.bpc = 8,
.size = {
.width = 294,
.height = 165,
},
.delay = {
.hpd_absent = 200,
.unprepare = 500,
},
};
static const struct drm_display_mode kingdisplay_kd116n21_30nv_a010_mode = {
.clock = 81000,
.hdisplay = 1366,
@ -1689,97 +1608,39 @@ static const struct panel_desc sharp_lq123p1jx31 = {
},
};
static const struct drm_display_mode sharp_lq140m1jw46_mode[] = {
{
.clock = 346500,
.hdisplay = 1920,
.hsync_start = 1920 + 48,
.hsync_end = 1920 + 48 + 32,
.htotal = 1920 + 48 + 32 + 80,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 5,
.vtotal = 1080 + 3 + 5 + 69,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
}, {
.clock = 144370,
.hdisplay = 1920,
.hsync_start = 1920 + 48,
.hsync_end = 1920 + 48 + 32,
.htotal = 1920 + 48 + 32 + 80,
.vdisplay = 1080,
.vsync_start = 1080 + 3,
.vsync_end = 1080 + 3 + 5,
.vtotal = 1080 + 3 + 5 + 69,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
},
};
static const struct panel_desc sharp_lq140m1jw46 = {
.modes = sharp_lq140m1jw46_mode,
.num_modes = ARRAY_SIZE(sharp_lq140m1jw46_mode),
.bpc = 8,
.size = {
.width = 309,
.height = 174,
},
.delay = {
.hpd_absent = 80,
.enable = 50,
.unprepare = 500,
},
};
static const struct drm_display_mode starry_kr122ea0sra_mode = {
.clock = 147000,
.hdisplay = 1920,
.hsync_start = 1920 + 16,
.hsync_end = 1920 + 16 + 16,
.htotal = 1920 + 16 + 16 + 32,
.vdisplay = 1200,
.vsync_start = 1200 + 15,
.vsync_end = 1200 + 15 + 2,
.vtotal = 1200 + 15 + 2 + 18,
.flags = DRM_MODE_FLAG_NVSYNC | DRM_MODE_FLAG_NHSYNC,
};
static const struct panel_desc starry_kr122ea0sra = {
.modes = &starry_kr122ea0sra_mode,
.num_modes = 1,
.size = {
.width = 263,
.height = 164,
},
.delay = {
/* TODO: should be hpd-absent and no-hpd should be set? */
.hpd_reliable = 10 + 200,
.enable = 50,
.unprepare = 10 + 500,
},
};
static const struct of_device_id platform_of_match[] = {
{
/* Must be first */
.compatible = "edp-panel",
}, {
},
/*
* Do not add panels to the list below unless they cannot be handled by
* the generic edp-panel compatible.
*
* The only two valid reasons are:
* - Because of the panel issues (e.g. broken EDID or broken
* identification).
* - Because the eDP drivers didn't wire up the AUX bus properly.
* NOTE that, though this is a marginally valid reason,
* some justification needs to be made for why the platform can't
* wire up the AUX bus properly.
*
* In all other cases the platform should use the aux-bus and declare
* the panel using the 'edp-panel' compatible as a device on the AUX
* bus.
*/
{
.compatible = "auo,b101ean01",
.data = &auo_b101ean01,
}, {
.compatible = "auo,b116xa01",
.data = &auo_b116xak01,
}, {
.compatible = "auo,b133han05",
.data = &auo_b133han05,
}, {
.compatible = "auo,b133htn01",
.data = &auo_b133htn01,
}, {
.compatible = "auo,b133xtn01",
.data = &auo_b133xtn01,
}, {
.compatible = "auo,b140han06",
.data = &auo_b140han06,
}, {
.compatible = "boe,nv101wxmn51",
.data = &boe_nv101wxmn51,
@ -1807,9 +1668,6 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "innolux,p120zdg-bf1",
.data = &innolux_p120zdg_bf1,
}, {
.compatible = "ivo,m133nwf4-r0",
.data = &ivo_m133nwf4_r0,
}, {
.compatible = "kingdisplay,kd116n21-30nv-a010",
.data = &kingdisplay_kd116n21_30nv_a010,
@ -1840,12 +1698,6 @@ static const struct of_device_id platform_of_match[] = {
}, {
.compatible = "sharp,lq123p1jx31",
.data = &sharp_lq123p1jx31,
}, {
.compatible = "sharp,lq140m1jw46",
.data = &sharp_lq140m1jw46,
}, {
.compatible = "starry,kr122ea0sra",
.data = &starry_kr122ea0sra,
}, {
/* sentinel */
}
@ -1897,6 +1749,12 @@ static const struct panel_delay delay_200_500_e80_d50 = {
.disable = 50,
};
static const struct panel_delay delay_80_500_e50 = {
.hpd_absent = 80,
.unprepare = 500,
.enable = 50,
};
static const struct panel_delay delay_100_500_e200 = {
.hpd_absent = 100,
.unprepare = 500,
@ -2105,7 +1963,7 @@ static const struct edp_panel_entry edp_panels[] = {
EDP_PANEL_ENTRY('S', 'D', 'C', 0x416d, &delay_100_500_e200, "ATNA45AF01"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1511, &delay_200_500_e50, "LQ140M1JW48"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &sharp_lq140m1jw46.delay, "LQ140M1JW46"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x1523, &delay_80_500_e50, "LQ140M1JW46"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x153a, &delay_200_500_e50, "LQ140T1JH01"),
EDP_PANEL_ENTRY('S', 'H', 'P', 0x154c, &delay_200_500_p2e100, "LQ116M1JW10"),

View File

@ -777,6 +777,15 @@ static const struct panfrost_compatible mediatek_mt8186_data = {
.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
};
/* MT8188 uses the same power domains and power supplies as MT8183 */
static const struct panfrost_compatible mediatek_mt8188_data = {
.num_supplies = ARRAY_SIZE(mediatek_mt8183_b_supplies) - 1,
.supply_names = mediatek_mt8183_b_supplies,
.num_pm_domains = ARRAY_SIZE(mediatek_mt8183_pm_domains),
.pm_domain_names = mediatek_mt8183_pm_domains,
.pm_features = BIT(GPU_PM_CLK_DIS) | BIT(GPU_PM_VREG_OFF),
};
static const char * const mediatek_mt8192_supplies[] = { "mali", NULL };
static const char * const mediatek_mt8192_pm_domains[] = { "core0", "core1", "core2",
"core3", "core4" };
@ -808,6 +817,7 @@ static const struct of_device_id dt_match[] = {
{ .compatible = "mediatek,mt8183-mali", .data = &mediatek_mt8183_data },
{ .compatible = "mediatek,mt8183b-mali", .data = &mediatek_mt8183_b_data },
{ .compatible = "mediatek,mt8186-mali", .data = &mediatek_mt8186_data },
{ .compatible = "mediatek,mt8188-mali", .data = &mediatek_mt8188_data },
{ .compatible = "mediatek,mt8192-mali", .data = &mediatek_mt8192_data },
{}
};

View File

@ -8,6 +8,7 @@
#include <drm/drm_atomic_helper.h>
#include <drm/drm_blend.h>
#include <drm/drm_crtc.h>
#include <drm/drm_fb_dma_helper.h>
#include <drm/drm_fourcc.h>
#include <drm/drm_framebuffer.h>
#include <drm/drm_gem_atomic_helper.h>
@ -166,6 +167,14 @@ static const struct drm_plane_helper_funcs tidss_plane_helper_funcs = {
.atomic_disable = tidss_plane_atomic_disable,
};
static const struct drm_plane_helper_funcs tidss_primary_plane_helper_funcs = {
.atomic_check = tidss_plane_atomic_check,
.atomic_update = tidss_plane_atomic_update,
.atomic_enable = tidss_plane_atomic_enable,
.atomic_disable = tidss_plane_atomic_disable,
.get_scanout_buffer = drm_fb_dma_get_scanout_buffer,
};
static const struct drm_plane_funcs tidss_plane_funcs = {
.update_plane = drm_atomic_helper_update_plane,
.disable_plane = drm_atomic_helper_disable_plane,
@ -211,7 +220,10 @@ struct tidss_plane *tidss_plane_create(struct tidss_device *tidss,
if (ret < 0)
goto err;
drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
if (type == DRM_PLANE_TYPE_PRIMARY)
drm_plane_helper_add(&tplane->plane, &tidss_primary_plane_helper_funcs);
else
drm_plane_helper_add(&tplane->plane, &tidss_plane_helper_funcs);
drm_plane_create_zpos_property(&tplane->plane, tidss->num_planes, 0,
num_planes - 1);

View File

@ -256,10 +256,10 @@ struct zynqmp_dp_link_config {
* @fmt: format identifier string
*/
struct zynqmp_dp_mode {
const char *fmt;
int pclock;
u8 bw_code;
u8 lane_cnt;
int pclock;
const char *fmt;
};
/**
@ -296,27 +296,27 @@ struct zynqmp_dp_config {
* @train_set: set of training data
*/
struct zynqmp_dp {
struct drm_dp_aux aux;
struct drm_bridge bridge;
struct work_struct hpd_work;
struct drm_bridge *next_bridge;
struct device *dev;
struct zynqmp_dpsub *dpsub;
void __iomem *iomem;
struct reset_control *reset;
int irq;
struct drm_bridge bridge;
struct drm_bridge *next_bridge;
struct zynqmp_dp_config config;
struct drm_dp_aux aux;
struct phy *phy[ZYNQMP_DP_MAX_LANES];
u8 num_lanes;
struct delayed_work hpd_work;
enum drm_connector_status status;
int irq;
bool enabled;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
struct zynqmp_dp_link_config link_config;
struct zynqmp_dp_mode mode;
struct zynqmp_dp_link_config link_config;
struct zynqmp_dp_config config;
u8 dpcd[DP_RECEIVER_CAP_SIZE];
u8 train_set[ZYNQMP_DP_MAX_LANES];
u8 num_lanes;
};
static inline struct zynqmp_dp *bridge_to_dp(struct drm_bridge *bridge)
@ -1482,7 +1482,7 @@ static void zynqmp_dp_bridge_atomic_disable(struct drm_bridge *bridge,
struct zynqmp_dp *dp = bridge_to_dp(bridge);
dp->enabled = false;
cancel_delayed_work(&dp->hpd_work);
cancel_work(&dp->hpd_work);
zynqmp_dp_write(dp, ZYNQMP_DP_MAIN_STREAM_ENABLE, 0);
drm_dp_dpcd_writeb(&dp->aux, DP_SET_POWER, DP_SET_POWER_D3);
zynqmp_dp_write(dp, ZYNQMP_DP_TX_PHY_POWER_DOWN,
@ -1648,8 +1648,7 @@ void zynqmp_dp_disable_vblank(struct zynqmp_dp *dp)
static void zynqmp_dp_hpd_work_func(struct work_struct *work)
{
struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp,
hpd_work.work);
struct zynqmp_dp *dp = container_of(work, struct zynqmp_dp, hpd_work);
enum drm_connector_status status;
status = zynqmp_dp_bridge_detect(&dp->bridge);
@ -1685,7 +1684,7 @@ static irqreturn_t zynqmp_dp_irq_handler(int irq, void *data)
zynqmp_dpsub_drm_handle_vblank(dp->dpsub);
if (status & ZYNQMP_DP_INT_HPD_EVENT)
schedule_delayed_work(&dp->hpd_work, 0);
schedule_work(&dp->hpd_work);
if (status & ZYNQMP_DP_INT_HPD_IRQ) {
int ret;
@ -1727,7 +1726,7 @@ int zynqmp_dp_probe(struct zynqmp_dpsub *dpsub)
dp->dpsub = dpsub;
dp->status = connector_status_disconnected;
INIT_DELAYED_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
INIT_WORK(&dp->hpd_work, zynqmp_dp_hpd_work_func);
/* Acquire all resources (IOMEM, IRQ and PHYs). */
res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "dp");
@ -1832,7 +1831,7 @@ void zynqmp_dp_remove(struct zynqmp_dpsub *dpsub)
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, ZYNQMP_DP_INT_ALL);
disable_irq(dp->irq);
cancel_delayed_work_sync(&dp->hpd_work);
cancel_work_sync(&dp->hpd_work);
zynqmp_dp_write(dp, ZYNQMP_DP_TRANSMITTER_ENABLE, 0);
zynqmp_dp_write(dp, ZYNQMP_DP_INT_DS, 0xffffffff);

View File

@ -269,6 +269,7 @@ static int zynqmp_dpsub_probe(struct platform_device *pdev)
return 0;
err_disp:
drm_bridge_remove(dpsub->bridge);
zynqmp_disp_remove(dpsub);
err_dp:
zynqmp_dp_remove(dpsub);

View File

@ -120,9 +120,13 @@ static void zynqmp_dpsub_plane_atomic_update(struct drm_plane *plane,
zynqmp_disp_blend_set_global_alpha(dpsub->disp, true,
plane->state->alpha >> 8);
/* Enable or re-enable the plane if the format has changed. */
if (format_changed)
zynqmp_disp_layer_enable(layer);
/*
* Unconditionally enable the layer, as it may have been disabled
* previously either explicitly to reconfigure layer format, or
* implicitly after DPSUB reset during display mode change. DRM
* framework calls this callback for enabled planes only.
*/
zynqmp_disp_layer_enable(layer);
}
static const struct drm_plane_helper_funcs zynqmp_dpsub_plane_helper_funcs = {
@ -433,23 +437,28 @@ static int zynqmp_dpsub_kms_init(struct zynqmp_dpsub *dpsub)
DRM_BRIDGE_ATTACH_NO_CONNECTOR);
if (ret) {
dev_err(dpsub->dev, "failed to attach bridge to encoder\n");
return ret;
goto err_encoder;
}
/* Create the connector for the chain of bridges. */
connector = drm_bridge_connector_init(&dpsub->drm->dev, encoder);
if (IS_ERR(connector)) {
dev_err(dpsub->dev, "failed to created connector\n");
return PTR_ERR(connector);
ret = PTR_ERR(connector);
goto err_encoder;
}
ret = drm_connector_attach_encoder(connector, encoder);
if (ret < 0) {
dev_err(dpsub->dev, "failed to attach connector to encoder\n");
return ret;
goto err_encoder;
}
return 0;
err_encoder:
drm_encoder_cleanup(encoder);
return ret;
}
static void zynqmp_dpsub_drm_release(struct drm_device *drm, void *res)
@ -529,5 +538,6 @@ void zynqmp_dpsub_drm_cleanup(struct zynqmp_dpsub *dpsub)
drm_dev_unregister(drm);
drm_atomic_helper_shutdown(drm);
drm_encoder_cleanup(&dpsub->drm->encoder);
drm_kms_helper_poll_fini(drm);
}

View File

@ -201,6 +201,13 @@ enum drm_connector_tv_mode {
*/
DRM_MODE_TV_MODE_SECAM,
/**
* @DRM_MODE_TV_MODE_MONOCHROME: Use timings appropriate to
* the DRM mode, including equalizing pulses for a 525-line
* or 625-line mode, with no pedestal or color encoding.
*/
DRM_MODE_TV_MODE_MONOCHROME,
/**
* @DRM_MODE_TV_MODE_MAX: Number of analog TV output modes.
*
@ -929,6 +936,67 @@ struct drm_connector_hdmi_infoframe {
bool set;
};
/*
* struct drm_connector_hdmi_state - HDMI state container
*/
struct drm_connector_hdmi_state {
/**
* @broadcast_rgb: Connector property to pass the
* Broadcast RGB selection value.
*/
enum drm_hdmi_broadcast_rgb broadcast_rgb;
/**
* @infoframes: HDMI Infoframes matching that state
*/
struct {
/**
* @avi: AVI Infoframes structure matching our
* state.
*/
struct drm_connector_hdmi_infoframe avi;
/**
* @hdr_drm: DRM (Dynamic Range and Mastering)
* Infoframes structure matching our state.
*/
struct drm_connector_hdmi_infoframe hdr_drm;
/**
* @spd: SPD Infoframes structure matching our
* state.
*/
struct drm_connector_hdmi_infoframe spd;
/**
* @vendor: HDMI Vendor Infoframes structure
* matching our state.
*/
struct drm_connector_hdmi_infoframe hdmi;
} infoframes;
/**
* @is_limited_range: Is the output supposed to use a limited
* RGB Quantization Range or not?
*/
bool is_limited_range;
/**
* @output_bpc: Bits per color channel to output.
*/
unsigned int output_bpc;
/**
* @output_format: Pixel format to output in.
*/
enum hdmi_colorspace output_format;
/**
* @tmds_char_rate: TMDS Character Rate, in Hz.
*/
unsigned long long tmds_char_rate;
};
/**
* struct drm_connector_state - mutable connector state
*/
@ -1078,63 +1146,7 @@ struct drm_connector_state {
* @hdmi: HDMI-related variable and properties. Filled by
* @drm_atomic_helper_connector_hdmi_check().
*/
struct {
/**
* @broadcast_rgb: Connector property to pass the
* Broadcast RGB selection value.
*/
enum drm_hdmi_broadcast_rgb broadcast_rgb;
/**
* @infoframes: HDMI Infoframes matching that state
*/
struct {
/**
* @avi: AVI Infoframes structure matching our
* state.
*/
struct drm_connector_hdmi_infoframe avi;
/**
* @hdr_drm: DRM (Dynamic Range and Mastering)
* Infoframes structure matching our state.
*/
struct drm_connector_hdmi_infoframe hdr_drm;
/**
* @spd: SPD Infoframes structure matching our
* state.
*/
struct drm_connector_hdmi_infoframe spd;
/**
* @vendor: HDMI Vendor Infoframes structure
* matching our state.
*/
struct drm_connector_hdmi_infoframe hdmi;
} infoframes;
/**
* @is_limited_range: Is the output supposed to use a limited
* RGB Quantization Range or not?
*/
bool is_limited_range;
/**
* @output_bpc: Bits per color channel to output.
*/
unsigned int output_bpc;
/**
* @output_format: Pixel format to output in.
*/
enum hdmi_colorspace output_format;
/**
* @tmds_char_rate: TMDS Character Rate, in Hz.
*/
unsigned long long tmds_char_rate;
} hdmi;
struct drm_connector_hdmi_state hdmi;
};
/**
@ -1656,6 +1668,51 @@ struct drm_cmdline_mode {
bool tv_mode_specified;
};
/*
* struct drm_connector_hdmi - DRM Connector HDMI-related structure
*/
struct drm_connector_hdmi {
#define DRM_CONNECTOR_HDMI_VENDOR_LEN 8
/**
* @vendor: HDMI Controller Vendor Name
*/
unsigned char vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] __nonstring;
#define DRM_CONNECTOR_HDMI_PRODUCT_LEN 16
/**
* @product: HDMI Controller Product Name
*/
unsigned char product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] __nonstring;
/**
* @supported_formats: Bitmask of @hdmi_colorspace
* supported by the controller.
*/
unsigned long supported_formats;
/**
* @funcs: HDMI connector Control Functions
*/
const struct drm_connector_hdmi_funcs *funcs;
/**
* @infoframes: Current Infoframes output by the connector
*/
struct {
/**
* @lock: Mutex protecting against concurrent access to
* the infoframes, most notably between KMS and ALSA.
*/
struct mutex lock;
/**
* @audio: Current Audio Infoframes structure. Protected
* by @lock.
*/
struct drm_connector_hdmi_infoframe audio;
} infoframes;
};
/**
* struct drm_connector - central DRM connector control structure
*
@ -2068,47 +2125,7 @@ struct drm_connector {
/**
* @hdmi: HDMI-related variable and properties.
*/
struct {
#define DRM_CONNECTOR_HDMI_VENDOR_LEN 8
/**
* @vendor: HDMI Controller Vendor Name
*/
unsigned char vendor[DRM_CONNECTOR_HDMI_VENDOR_LEN] __nonstring;
#define DRM_CONNECTOR_HDMI_PRODUCT_LEN 16
/**
* @product: HDMI Controller Product Name
*/
unsigned char product[DRM_CONNECTOR_HDMI_PRODUCT_LEN] __nonstring;
/**
* @supported_formats: Bitmask of @hdmi_colorspace
* supported by the controller.
*/
unsigned long supported_formats;
/**
* @funcs: HDMI connector Control Functions
*/
const struct drm_connector_hdmi_funcs *funcs;
/**
* @infoframes: Current Infoframes output by the connector
*/
struct {
/**
* @lock: Mutex protecting against concurrent access to
* the infoframes, most notably between KMS and ALSA.
*/
struct mutex lock;
/**
* @audio: Current Audio Infoframes structure. Protected
* by @lock.
*/
struct drm_connector_hdmi_infoframe audio;
} infoframes;
} hdmi;
struct drm_connector_hdmi hdmi;
};
#define obj_to_connector(x) container_of(x, struct drm_connector, base)

View File

@ -23,8 +23,8 @@ struct dma_heap;
struct dma_heap_ops {
struct dma_buf *(*allocate)(struct dma_heap *heap,
unsigned long len,
unsigned long fd_flags,
unsigned long heap_flags);
u32 fd_flags,
u64 heap_flags);
};
/**