disp: msm: sde: add support for CTL done irq
From Kalama, the HW scheduler abstracts the low level PP_DONE/WB_DONE interrupts and generates a common CTL_DONE interrupt per hw ctl. This saves the software the irq latency delays to process the frame complete operations when multiple encoders are involved. If supported, this change enables and waits for the CTL_DONE interrupt instead of PP_DONE and WB_DONE. This change adds support to wait for CTL_DONE irq in only command mode panels as we don't drive two WB blocks with single CTL. Change-Id: I084d6bfb6a9fb0b48f912fe5787401c460ec5b56 Signed-off-by: Jeykumar Sankaran <quic_jeykumar@quicinc.com>
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2014-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
@@ -3504,7 +3505,8 @@ static void sde_encoder_frame_done_callback(
|
|||||||
|
|
||||||
if (event & (SDE_ENCODER_FRAME_EVENT_DONE
|
if (event & (SDE_ENCODER_FRAME_EVENT_DONE
|
||||||
| SDE_ENCODER_FRAME_EVENT_ERROR
|
| SDE_ENCODER_FRAME_EVENT_ERROR
|
||||||
| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode) {
|
| SDE_ENCODER_FRAME_EVENT_PANEL_DEAD) && is_cmd_mode
|
||||||
|
&& !sde_encoder_check_ctl_done_support(drm_enc)) {
|
||||||
|
|
||||||
if (ready_phys->connector)
|
if (ready_phys->connector)
|
||||||
topology = sde_connector_get_topology_name(
|
topology = sde_connector_get_topology_name(
|
||||||
@@ -5099,6 +5101,9 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
|
|||||||
sde_enc->input_event_enabled = test_bit(SDE_FEATURE_TOUCH_WAKEUP,
|
sde_enc->input_event_enabled = test_bit(SDE_FEATURE_TOUCH_WAKEUP,
|
||||||
sde_kms->catalog->features);
|
sde_kms->catalog->features);
|
||||||
|
|
||||||
|
sde_enc->ctl_done_supported = test_bit(SDE_FEATURE_CTL_DONE,
|
||||||
|
sde_kms->catalog->features);
|
||||||
|
|
||||||
mutex_lock(&sde_enc->enc_lock);
|
mutex_lock(&sde_enc->enc_lock);
|
||||||
for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
|
for (i = 0; i < disp_info->num_of_h_tiles && !ret; i++) {
|
||||||
/*
|
/*
|
||||||
|
@@ -1,4 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
* Copyright (C) 2013 Red Hat
|
* Copyright (C) 2013 Red Hat
|
||||||
* Author: Rob Clark <robdclark@gmail.com>
|
* Author: Rob Clark <robdclark@gmail.com>
|
||||||
@@ -182,6 +183,8 @@ enum sde_enc_rc_states {
|
|||||||
* next update is triggered.
|
* next update is triggered.
|
||||||
* @autorefresh_solver_disable It tracks if solver state is disabled from this
|
* @autorefresh_solver_disable It tracks if solver state is disabled from this
|
||||||
* encoder due to autorefresh concurrency.
|
* encoder due to autorefresh concurrency.
|
||||||
|
* @ctl_done_supported boolean flag to indicate the availability of
|
||||||
|
* ctl done irq support for the hardware
|
||||||
*/
|
*/
|
||||||
struct sde_encoder_virt {
|
struct sde_encoder_virt {
|
||||||
struct drm_encoder base;
|
struct drm_encoder base;
|
||||||
@@ -248,6 +251,7 @@ struct sde_encoder_virt {
|
|||||||
struct msm_mode_info mode_info;
|
struct msm_mode_info mode_info;
|
||||||
bool delay_kickoff;
|
bool delay_kickoff;
|
||||||
bool autorefresh_solver_disable;
|
bool autorefresh_solver_disable;
|
||||||
|
bool ctl_done_supported;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
|
#define to_sde_encoder_virt(x) container_of(x, struct sde_encoder_virt, base)
|
||||||
@@ -524,6 +528,19 @@ bool sde_encoder_is_primary_display(struct drm_encoder *enc);
|
|||||||
*/
|
*/
|
||||||
bool sde_encoder_is_built_in_display(struct drm_encoder *enc);
|
bool sde_encoder_is_built_in_display(struct drm_encoder *enc);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* sde_encoder_check_ctl_done_support - checks if ctl_done irq is available
|
||||||
|
* for the display
|
||||||
|
* @drm_enc: Pointer to drm encoder structure
|
||||||
|
* @Return: true if scheduler update is enabled
|
||||||
|
*/
|
||||||
|
static inline bool sde_encoder_check_ctl_done_support(struct drm_encoder *drm_enc)
|
||||||
|
{
|
||||||
|
struct sde_encoder_virt *sde_enc = to_sde_encoder_virt(drm_enc);
|
||||||
|
|
||||||
|
return sde_enc && sde_enc->ctl_done_supported;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* sde_encoder_is_dsi_display - checks if underlying display is DSI
|
* sde_encoder_is_dsi_display - checks if underlying display is DSI
|
||||||
* display or not.
|
* display or not.
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -195,6 +196,8 @@ struct sde_encoder_phys_ops {
|
|||||||
* @INTR_IDX_VSYNC: Vsync interrupt for video mode panel
|
* @INTR_IDX_VSYNC: Vsync interrupt for video mode panel
|
||||||
* @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel
|
* @INTR_IDX_PINGPONG: Pingpong done interrupt for cmd mode panel
|
||||||
* @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel
|
* @INTR_IDX_UNDERRUN: Underrun interrupt for video and cmd mode panel
|
||||||
|
* @INTR_IDX_CTL_START:Control start interrupt to indicate the frame start
|
||||||
|
* @INTR_IDX_CTL_DONE: Control done interrupt indicating the control path being idle
|
||||||
* @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel
|
* @INTR_IDX_RDPTR: Readpointer done interrupt for cmd mode panel
|
||||||
* @INTR_IDX_WB_DONE: Writeback done interrupt for WB
|
* @INTR_IDX_WB_DONE: Writeback done interrupt for WB
|
||||||
* @INTR_IDX_PP1_OVFL: Pingpong overflow interrupt on PP1 for Concurrent WB
|
* @INTR_IDX_PP1_OVFL: Pingpong overflow interrupt on PP1 for Concurrent WB
|
||||||
@@ -213,6 +216,7 @@ enum sde_intr_idx {
|
|||||||
INTR_IDX_PINGPONG,
|
INTR_IDX_PINGPONG,
|
||||||
INTR_IDX_UNDERRUN,
|
INTR_IDX_UNDERRUN,
|
||||||
INTR_IDX_CTL_START,
|
INTR_IDX_CTL_START,
|
||||||
|
INTR_IDX_CTL_DONE,
|
||||||
INTR_IDX_RDPTR,
|
INTR_IDX_RDPTR,
|
||||||
INTR_IDX_AUTOREFRESH_DONE,
|
INTR_IDX_AUTOREFRESH_DONE,
|
||||||
INTR_IDX_WB_DONE,
|
INTR_IDX_WB_DONE,
|
||||||
@@ -400,7 +404,7 @@ struct sde_encoder_phys_cmd_te_timestamp {
|
|||||||
* mode specific operations
|
* mode specific operations
|
||||||
* @base: Baseclass physical encoder structure
|
* @base: Baseclass physical encoder structure
|
||||||
* @stream_sel: Stream selection for multi-stream interfaces
|
* @stream_sel: Stream selection for multi-stream interfaces
|
||||||
* @pp_timeout_report_cnt: number of pingpong done irq timeout errors
|
* @frame_tx_timeout_report_cnt: number of pp_done/ctl_done irq timeout errors
|
||||||
* @autorefresh: autorefresh feature state
|
* @autorefresh: autorefresh feature state
|
||||||
* @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
|
* @pending_vblank_cnt: Atomic counter tracking pending wait for VBLANK
|
||||||
* @pending_vblank_wq: Wait queue for blocking until VBLANK received
|
* @pending_vblank_wq: Wait queue for blocking until VBLANK received
|
||||||
@@ -411,7 +415,7 @@ struct sde_encoder_phys_cmd_te_timestamp {
|
|||||||
struct sde_encoder_phys_cmd {
|
struct sde_encoder_phys_cmd {
|
||||||
struct sde_encoder_phys base;
|
struct sde_encoder_phys base;
|
||||||
int stream_sel;
|
int stream_sel;
|
||||||
int pp_timeout_report_cnt;
|
int frame_tx_timeout_report_cnt;
|
||||||
struct sde_encoder_phys_cmd_autorefresh autorefresh;
|
struct sde_encoder_phys_cmd_autorefresh autorefresh;
|
||||||
atomic_t pending_vblank_cnt;
|
atomic_t pending_vblank_cnt;
|
||||||
wait_queue_head_t pending_vblank_wq;
|
wait_queue_head_t pending_vblank_wq;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -170,30 +171,24 @@ static void _sde_encoder_phys_cmd_update_intf_cfg(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
|
static void _sde_encoder_phys_signal_frame_done(struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys *phys_enc = arg;
|
|
||||||
struct sde_encoder_phys_cmd *cmd_enc;
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
struct sde_hw_ctl *ctl;
|
struct sde_hw_ctl *ctl;
|
||||||
u32 scheduler_status = INVALID_CTL_STATUS, event = 0;
|
u32 scheduler_status = INVALID_CTL_STATUS, event = 0;
|
||||||
|
|
||||||
if (!phys_enc || !phys_enc->hw_pp)
|
|
||||||
return;
|
|
||||||
|
|
||||||
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||||
ctl = phys_enc->hw_ctl;
|
ctl = phys_enc->hw_ctl;
|
||||||
|
|
||||||
SDE_ATRACE_BEGIN("pp_done_irq");
|
|
||||||
|
|
||||||
/* notify all synchronous clients first, then asynchronous clients */
|
/* notify all synchronous clients first, then asynchronous clients */
|
||||||
if (phys_enc->parent_ops.handle_frame_done &&
|
if (phys_enc->parent_ops.handle_frame_done &&
|
||||||
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
|
atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0)) {
|
||||||
event = SDE_ENCODER_FRAME_EVENT_DONE |
|
event = SDE_ENCODER_FRAME_EVENT_DONE |
|
||||||
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
|
SDE_ENCODER_FRAME_EVENT_SIGNAL_RELEASE_FENCE;
|
||||||
spin_lock(phys_enc->enc_spinlock);
|
spin_lock(phys_enc->enc_spinlock);
|
||||||
phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
|
phys_enc->parent_ops.handle_frame_done(phys_enc->parent,
|
||||||
phys_enc, event);
|
phys_enc, event);
|
||||||
if (cmd_enc->pp_timeout_report_cnt)
|
if (cmd_enc->frame_tx_timeout_report_cnt)
|
||||||
phys_enc->recovered = true;
|
phys_enc->recovered = true;
|
||||||
spin_unlock(phys_enc->enc_spinlock);
|
spin_unlock(phys_enc->enc_spinlock);
|
||||||
}
|
}
|
||||||
@@ -201,11 +196,38 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
|
|||||||
if (ctl && ctl->ops.get_scheduler_status)
|
if (ctl && ctl->ops.get_scheduler_status)
|
||||||
scheduler_status = ctl->ops.get_scheduler_status(ctl);
|
scheduler_status = ctl->ops.get_scheduler_status(ctl);
|
||||||
|
|
||||||
SDE_EVT32_IRQ(DRMID(phys_enc->parent),
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent), ctl->idx - CTL_0,
|
||||||
phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status);
|
phys_enc->hw_pp->idx - PINGPONG_0, event, scheduler_status);
|
||||||
|
|
||||||
/* Signal any waiting atomic commit thread */
|
/* Signal any waiting atomic commit thread */
|
||||||
wake_up_all(&phys_enc->pending_kickoff_wq);
|
wake_up_all(&phys_enc->pending_kickoff_wq);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sde_encoder_phys_cmd_ctl_done_irq(void *arg, int irq_idx)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = arg;
|
||||||
|
|
||||||
|
if (!phys_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDE_ATRACE_BEGIN("ctl_done_irq");
|
||||||
|
|
||||||
|
_sde_encoder_phys_signal_frame_done(phys_enc);
|
||||||
|
|
||||||
|
SDE_ATRACE_END("ctl_done_irq");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = arg;
|
||||||
|
|
||||||
|
if (!phys_enc || !phys_enc->hw_pp)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDE_ATRACE_BEGIN("pp_done_irq");
|
||||||
|
|
||||||
|
_sde_encoder_phys_signal_frame_done(phys_enc);
|
||||||
|
|
||||||
SDE_ATRACE_END("pp_done_irq");
|
SDE_ATRACE_END("pp_done_irq");
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -337,6 +359,9 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
|||||||
irq = &phys_enc->irq[INTR_IDX_CTL_START];
|
irq = &phys_enc->irq[INTR_IDX_CTL_START];
|
||||||
irq->hw_idx = phys_enc->hw_ctl->idx;
|
irq->hw_idx = phys_enc->hw_ctl->idx;
|
||||||
|
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_CTL_DONE];
|
||||||
|
irq->hw_idx = phys_enc->hw_ctl->idx;
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
||||||
irq->hw_idx = phys_enc->hw_pp->idx;
|
irq->hw_idx = phys_enc->hw_pp->idx;
|
||||||
|
|
||||||
@@ -457,7 +482,7 @@ static void sde_encoder_phys_cmd_mode_set(
|
|||||||
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
|
sde_encoder_helper_get_kickoff_timeout_ms(phys_enc->parent);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
static int _sde_encoder_phys_cmd_handle_framedone_timeout(
|
||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys_cmd *cmd_enc =
|
struct sde_encoder_phys_cmd *cmd_enc =
|
||||||
@@ -479,11 +504,11 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
|||||||
if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0))
|
if (!atomic_add_unless(&phys_enc->pending_kickoff_cnt, -1, 0))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
cmd_enc->pp_timeout_report_cnt++;
|
cmd_enc->frame_tx_timeout_report_cnt++;
|
||||||
pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1;
|
pending_kickoff_cnt = atomic_read(&phys_enc->pending_kickoff_cnt) + 1;
|
||||||
|
|
||||||
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
||||||
cmd_enc->pp_timeout_report_cnt,
|
cmd_enc->frame_tx_timeout_report_cnt,
|
||||||
pending_kickoff_cnt,
|
pending_kickoff_cnt,
|
||||||
frame_event);
|
frame_event);
|
||||||
|
|
||||||
@@ -492,7 +517,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
|||||||
goto exit;
|
goto exit;
|
||||||
|
|
||||||
/* to avoid flooding, only log first time, and "dead" time */
|
/* to avoid flooding, only log first time, and "dead" time */
|
||||||
if (cmd_enc->pp_timeout_report_cnt == 1) {
|
if (cmd_enc->frame_tx_timeout_report_cnt == 1) {
|
||||||
SDE_ERROR_CMDENC(cmd_enc,
|
SDE_ERROR_CMDENC(cmd_enc,
|
||||||
"pp:%d kickoff timed out ctl %d koff_cnt %d\n",
|
"pp:%d kickoff timed out ctl %d koff_cnt %d\n",
|
||||||
phys_enc->hw_pp->idx - PINGPONG_0,
|
phys_enc->hw_pp->idx - PINGPONG_0,
|
||||||
@@ -517,7 +542,7 @@ static int _sde_encoder_phys_cmd_handle_ppdone_timeout(
|
|||||||
if (recovery_events)
|
if (recovery_events)
|
||||||
sde_connector_event_notify(conn, DRM_EVENT_SDE_HW_RECOVERY,
|
sde_connector_event_notify(conn, DRM_EVENT_SDE_HW_RECOVERY,
|
||||||
sizeof(uint8_t), SDE_RECOVERY_CAPTURE);
|
sizeof(uint8_t), SDE_RECOVERY_CAPTURE);
|
||||||
else if (cmd_enc->pp_timeout_report_cnt)
|
else if (cmd_enc->frame_tx_timeout_report_cnt)
|
||||||
SDE_DBG_DUMP(0x0, "panic");
|
SDE_DBG_DUMP(0x0, "panic");
|
||||||
|
|
||||||
/* request a ctl reset before the next kickoff */
|
/* request a ctl reset before the next kickoff */
|
||||||
@@ -701,6 +726,7 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
struct sde_encoder_wait_info wait_info = {0};
|
struct sde_encoder_wait_info wait_info = {0};
|
||||||
|
enum sde_intr_idx intr_idx;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
if (!phys_enc) {
|
if (!phys_enc) {
|
||||||
@@ -722,13 +748,14 @@ static int _sde_encoder_phys_cmd_wait_for_idle(
|
|||||||
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
|
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
ret = sde_encoder_helper_wait_for_irq(phys_enc, INTR_IDX_PINGPONG,
|
intr_idx = sde_encoder_check_ctl_done_support(phys_enc->parent) ?
|
||||||
&wait_info);
|
INTR_IDX_CTL_DONE : INTR_IDX_PINGPONG;
|
||||||
|
|
||||||
|
ret = sde_encoder_helper_wait_for_irq(phys_enc, intr_idx, &wait_info);
|
||||||
if (ret == -ETIMEDOUT) {
|
if (ret == -ETIMEDOUT) {
|
||||||
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
|
if (_sde_encoder_phys_cmd_is_scheduler_idle(phys_enc))
|
||||||
return 0;
|
return 0;
|
||||||
|
_sde_encoder_phys_cmd_handle_framedone_timeout(phys_enc);
|
||||||
_sde_encoder_phys_cmd_handle_ppdone_timeout(phys_enc);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
@@ -834,6 +861,7 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
|||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys_cmd *cmd_enc;
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
|
bool ctl_done_supported = false;
|
||||||
|
|
||||||
if (!phys_enc)
|
if (!phys_enc)
|
||||||
return;
|
return;
|
||||||
@@ -851,8 +879,12 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
|||||||
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
SDE_EVT32(DRMID(phys_enc->parent), phys_enc->hw_pp->idx - PINGPONG_0,
|
||||||
enable, atomic_read(&phys_enc->vblank_refcount));
|
enable, atomic_read(&phys_enc->vblank_refcount));
|
||||||
|
|
||||||
|
ctl_done_supported = sde_encoder_check_ctl_done_support(phys_enc->parent);
|
||||||
|
|
||||||
if (enable) {
|
if (enable) {
|
||||||
sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG);
|
if (!ctl_done_supported)
|
||||||
|
sde_encoder_helper_register_irq(phys_enc, INTR_IDX_PINGPONG);
|
||||||
|
|
||||||
sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
|
sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
|
||||||
|
|
||||||
if (sde_encoder_phys_cmd_is_master(phys_enc)) {
|
if (sde_encoder_phys_cmd_is_master(phys_enc)) {
|
||||||
@@ -860,6 +892,8 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
|||||||
INTR_IDX_WRPTR);
|
INTR_IDX_WRPTR);
|
||||||
sde_encoder_helper_register_irq(phys_enc,
|
sde_encoder_helper_register_irq(phys_enc,
|
||||||
INTR_IDX_AUTOREFRESH_DONE);
|
INTR_IDX_AUTOREFRESH_DONE);
|
||||||
|
if (ctl_done_supported)
|
||||||
|
sde_encoder_helper_register_irq(phys_enc, INTR_IDX_CTL_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
@@ -868,10 +902,14 @@ void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
|||||||
INTR_IDX_WRPTR);
|
INTR_IDX_WRPTR);
|
||||||
sde_encoder_helper_unregister_irq(phys_enc,
|
sde_encoder_helper_unregister_irq(phys_enc,
|
||||||
INTR_IDX_AUTOREFRESH_DONE);
|
INTR_IDX_AUTOREFRESH_DONE);
|
||||||
|
if (ctl_done_supported)
|
||||||
|
sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_CTL_DONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
|
sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
|
||||||
sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG);
|
|
||||||
|
if (!ctl_done_supported)
|
||||||
|
sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_PINGPONG);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1337,13 +1375,13 @@ static int sde_encoder_phys_cmd_prepare_for_kickoff(
|
|||||||
if (phys_enc->recovered) {
|
if (phys_enc->recovered) {
|
||||||
recovery_events = sde_encoder_recovery_events_enabled(
|
recovery_events = sde_encoder_recovery_events_enabled(
|
||||||
phys_enc->parent);
|
phys_enc->parent);
|
||||||
if (cmd_enc->pp_timeout_report_cnt && recovery_events)
|
if (cmd_enc->frame_tx_timeout_report_cnt && recovery_events)
|
||||||
sde_connector_event_notify(phys_enc->connector,
|
sde_connector_event_notify(phys_enc->connector,
|
||||||
DRM_EVENT_SDE_HW_RECOVERY,
|
DRM_EVENT_SDE_HW_RECOVERY,
|
||||||
sizeof(uint8_t),
|
sizeof(uint8_t),
|
||||||
SDE_RECOVERY_SUCCESS);
|
SDE_RECOVERY_SUCCESS);
|
||||||
|
|
||||||
cmd_enc->pp_timeout_report_cnt = 0;
|
cmd_enc->frame_tx_timeout_report_cnt = 0;
|
||||||
phys_enc->recovered = false;
|
phys_enc->recovered = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1988,6 +2026,12 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
|||||||
irq->intr_idx = INTR_IDX_CTL_START;
|
irq->intr_idx = INTR_IDX_CTL_START;
|
||||||
irq->cb.func = NULL;
|
irq->cb.func = NULL;
|
||||||
|
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_CTL_DONE];
|
||||||
|
irq->name = "ctl_done";
|
||||||
|
irq->intr_type = SDE_IRQ_TYPE_CTL_DONE;
|
||||||
|
irq->intr_idx = INTR_IDX_CTL_DONE;
|
||||||
|
irq->cb.func = sde_encoder_phys_cmd_ctl_done_irq;
|
||||||
|
|
||||||
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
irq = &phys_enc->irq[INTR_IDX_PINGPONG];
|
||||||
irq->name = "pp_done";
|
irq->name = "pp_done";
|
||||||
irq->intr_type = SDE_IRQ_TYPE_PING_PONG_COMP;
|
irq->intr_type = SDE_IRQ_TYPE_PING_PONG_COMP;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -5226,6 +5227,7 @@ static int _sde_hardware_pre_caps(struct sde_mdss_cfg *sde_cfg, uint32_t hw_rev)
|
|||||||
set_bit(SDE_FEATURE_HW_VSYNC_TS, sde_cfg->features);
|
set_bit(SDE_FEATURE_HW_VSYNC_TS, sde_cfg->features);
|
||||||
set_bit(SDE_FEATURE_AVR_STEP, sde_cfg->features);
|
set_bit(SDE_FEATURE_AVR_STEP, sde_cfg->features);
|
||||||
set_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features);
|
set_bit(SDE_FEATURE_VBIF_CLK_SPLIT, sde_cfg->features);
|
||||||
|
set_bit(SDE_FEATURE_CTL_DONE, sde_cfg->features);
|
||||||
sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache = true;
|
sde_cfg->sc_cfg[SDE_SYS_CACHE_DISP].has_sys_cache = true;
|
||||||
sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH;
|
sde_cfg->allowed_dsc_reservation_switch = SDE_DP_DSC_RESERVATION_SWITCH;
|
||||||
sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2;
|
sde_cfg->autorefresh_disable_seq = AUTOREFRESH_DISABLE_SEQ2;
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2015-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -676,6 +677,7 @@ enum {
|
|||||||
* @SDE_FEATURE_TRUSTED_VM Trusted VM supported
|
* @SDE_FEATURE_TRUSTED_VM Trusted VM supported
|
||||||
* @SDE_FEATURE_UBWC_STATS UBWC statistics supported
|
* @SDE_FEATURE_UBWC_STATS UBWC statistics supported
|
||||||
* @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
|
* @SDE_FEATURE_VBIF_CLK_SPLIT VBIF clock split supported
|
||||||
|
* @SDE_FEATURE_CTL_DONE Support for CTL DONE irq
|
||||||
* @SDE_FEATURE_MAX: MAX features value
|
* @SDE_FEATURE_MAX: MAX features value
|
||||||
*/
|
*/
|
||||||
enum sde_mdss_features {
|
enum sde_mdss_features {
|
||||||
@@ -716,6 +718,7 @@ enum sde_mdss_features {
|
|||||||
SDE_FEATURE_TRUSTED_VM,
|
SDE_FEATURE_TRUSTED_VM,
|
||||||
SDE_FEATURE_UBWC_STATS,
|
SDE_FEATURE_UBWC_STATS,
|
||||||
SDE_FEATURE_VBIF_CLK_SPLIT,
|
SDE_FEATURE_VBIF_CLK_SPLIT,
|
||||||
|
SDE_FEATURE_CTL_DONE,
|
||||||
SDE_FEATURE_MAX
|
SDE_FEATURE_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -91,6 +92,16 @@
|
|||||||
#define SDE_INTR_CTL_4_START BIT(13)
|
#define SDE_INTR_CTL_4_START BIT(13)
|
||||||
#define SDE_INTR_CTL_5_START BIT(23)
|
#define SDE_INTR_CTL_5_START BIT(23)
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Ctl done interrupt status bit definitions
|
||||||
|
*/
|
||||||
|
#define SDE_INTR_CTL_0_DONE BIT(0)
|
||||||
|
#define SDE_INTR_CTL_1_DONE BIT(1)
|
||||||
|
#define SDE_INTR_CTL_2_DONE BIT(2)
|
||||||
|
#define SDE_INTR_CTL_3_DONE BIT(3)
|
||||||
|
#define SDE_INTR_CTL_4_DONE BIT(4)
|
||||||
|
#define SDE_INTR_CTL_5_DONE BIT(5)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Concurrent WB overflow interrupt status bit definitions
|
* Concurrent WB overflow interrupt status bit definitions
|
||||||
*/
|
*/
|
||||||
@@ -283,6 +294,19 @@ static struct sde_irq_type sde_irq_intr2_map[] = {
|
|||||||
{ SDE_IRQ_TYPE_CTL_START, CTL_5,
|
{ SDE_IRQ_TYPE_CTL_START, CTL_5,
|
||||||
SDE_INTR_CTL_5_START, -1},
|
SDE_INTR_CTL_5_START, -1},
|
||||||
|
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_0,
|
||||||
|
SDE_INTR_CTL_0_DONE, -1},
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_1,
|
||||||
|
SDE_INTR_CTL_1_DONE, -1},
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_2,
|
||||||
|
SDE_INTR_CTL_2_DONE, -1},
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_3,
|
||||||
|
SDE_INTR_CTL_3_DONE, -1},
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_4,
|
||||||
|
SDE_INTR_CTL_4_DONE, -1},
|
||||||
|
{ SDE_IRQ_TYPE_CTL_DONE, CTL_5,
|
||||||
|
SDE_INTR_CTL_5_DONE, -1},
|
||||||
|
|
||||||
{ SDE_IRQ_TYPE_CWB_OVERFLOW, PINGPONG_CWB_0, SDE_INTR_CWB_OVERFLOW, -1},
|
{ SDE_IRQ_TYPE_CWB_OVERFLOW, PINGPONG_CWB_0, SDE_INTR_CWB_OVERFLOW, -1},
|
||||||
|
|
||||||
{ SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_4,
|
{ SDE_IRQ_TYPE_PING_PONG_COMP, PINGPONG_4,
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
|
* Copyright (c) 2021 Qualcomm Innovation Center, Inc. All rights reserved.
|
||||||
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
|
* Copyright (c) 2016-2019, 2021, The Linux Foundation. All rights reserved.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -49,6 +50,7 @@
|
|||||||
* @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt
|
* @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt
|
||||||
* @SDE_IRQ_TYPE_AD4_BL_DONE: AD4 backlight
|
* @SDE_IRQ_TYPE_AD4_BL_DONE: AD4 backlight
|
||||||
* @SDE_IRQ_TYPE_CTL_START: Control start
|
* @SDE_IRQ_TYPE_CTL_START: Control start
|
||||||
|
* @SDE_IRQ_TYPE_CTL_DONE: Frame transfer complete
|
||||||
* @SDE_IRQ_TYPE_INTF_TEAR_RD_PTR: INTF Tear read pointer
|
* @SDE_IRQ_TYPE_INTF_TEAR_RD_PTR: INTF Tear read pointer
|
||||||
* @SDE_IRQ_TYPE_INTF_TEAR_WR_PTR: INTF Tear write pointer
|
* @SDE_IRQ_TYPE_INTF_TEAR_WR_PTR: INTF Tear write pointer
|
||||||
* @SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF: INTF Tear auto refresh
|
* @SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF: INTF Tear auto refresh
|
||||||
@@ -87,6 +89,7 @@ enum sde_intr_type {
|
|||||||
SDE_IRQ_TYPE_PROG_LINE,
|
SDE_IRQ_TYPE_PROG_LINE,
|
||||||
SDE_IRQ_TYPE_AD4_BL_DONE,
|
SDE_IRQ_TYPE_AD4_BL_DONE,
|
||||||
SDE_IRQ_TYPE_CTL_START,
|
SDE_IRQ_TYPE_CTL_START,
|
||||||
|
SDE_IRQ_TYPE_CTL_DONE,
|
||||||
SDE_IRQ_TYPE_INTF_TEAR_RD_PTR,
|
SDE_IRQ_TYPE_INTF_TEAR_RD_PTR,
|
||||||
SDE_IRQ_TYPE_INTF_TEAR_WR_PTR,
|
SDE_IRQ_TYPE_INTF_TEAR_WR_PTR,
|
||||||
SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF,
|
SDE_IRQ_TYPE_INTF_TEAR_AUTO_REF,
|
||||||
|
Referens i nytt ärende
Block a user