disp: msm: sde: add support for dynamic encoder IRQs
This change adds support for dynamically enabling and disabling additional physical encoder IRQs. Change-Id: I500fa69d1b8b8df39fd608391c906257efdea63b Signed-off-by: Nilaan Gunabalachandran <quic_ngunabal@quicinc.com>
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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>
|
||||||
@@ -1735,6 +1735,9 @@ void sde_encoder_irq_control(struct drm_encoder *drm_enc, bool enable)
|
|||||||
|
|
||||||
if (phys && phys->ops.irq_control)
|
if (phys && phys->ops.irq_control)
|
||||||
phys->ops.irq_control(phys, enable);
|
phys->ops.irq_control(phys, enable);
|
||||||
|
|
||||||
|
if (phys && phys->ops.dynamic_irq_control)
|
||||||
|
phys->ops.dynamic_irq_control(phys, enable);
|
||||||
}
|
}
|
||||||
sde_kms_cpu_vote_for_irq(sde_encoder_get_kms(drm_enc), enable);
|
sde_kms_cpu_vote_for_irq(sde_encoder_get_kms(drm_enc), enable);
|
||||||
|
|
||||||
@@ -5201,6 +5204,9 @@ static int _sde_encoder_init_debugfs(struct drm_encoder *drm_enc)
|
|||||||
debugfs_create_u32("frame_trigger_mode", 0400, sde_enc->debugfs_root,
|
debugfs_create_u32("frame_trigger_mode", 0400, sde_enc->debugfs_root,
|
||||||
&sde_enc->frame_trigger_mode);
|
&sde_enc->frame_trigger_mode);
|
||||||
|
|
||||||
|
debugfs_create_x32("dynamic_irqs_config", 0600, sde_enc->debugfs_root,
|
||||||
|
(u32 *)&sde_enc->dynamic_irqs_config);
|
||||||
|
|
||||||
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
for (i = 0; i < sde_enc->num_phys_encs; i++)
|
||||||
if (sde_enc->phys_encs[i] &&
|
if (sde_enc->phys_encs[i] &&
|
||||||
sde_enc->phys_encs[i]->ops.late_register)
|
sde_enc->phys_encs[i]->ops.late_register)
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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>
|
||||||
@@ -55,6 +55,10 @@
|
|||||||
/* below this fps limit, timeouts are adjusted based on fps */
|
/* below this fps limit, timeouts are adjusted based on fps */
|
||||||
#define DEFAULT_TIMEOUT_FPS_THRESHOLD 24
|
#define DEFAULT_TIMEOUT_FPS_THRESHOLD 24
|
||||||
|
|
||||||
|
#define SDE_ENC_IRQ_REGISTERED(phys_enc, idx) \
|
||||||
|
((!(phys_enc) || ((idx) < 0) || ((idx) >= INTR_IDX_MAX)) ? \
|
||||||
|
0 : ((phys_enc)->irq[(idx)].irq_idx >= 0))
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encoder functions and data types
|
* Encoder functions and data types
|
||||||
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
* @intfs: Interfaces this encoder is using, INTF_MODE_NONE if unused
|
||||||
@@ -186,6 +190,7 @@ enum sde_enc_rc_states {
|
|||||||
* encoder due to autorefresh concurrency.
|
* encoder due to autorefresh concurrency.
|
||||||
* @ctl_done_supported boolean flag to indicate the availability of
|
* @ctl_done_supported boolean flag to indicate the availability of
|
||||||
* ctl done irq support for the hardware
|
* ctl done irq support for the hardware
|
||||||
|
* @dynamic_irqs_config bitmask config to enable encoder dynamic irqs
|
||||||
*/
|
*/
|
||||||
struct sde_encoder_virt {
|
struct sde_encoder_virt {
|
||||||
struct drm_encoder base;
|
struct drm_encoder base;
|
||||||
@@ -254,6 +259,8 @@ struct sde_encoder_virt {
|
|||||||
bool delay_kickoff;
|
bool delay_kickoff;
|
||||||
bool autorefresh_solver_disable;
|
bool autorefresh_solver_disable;
|
||||||
bool ctl_done_supported;
|
bool ctl_done_supported;
|
||||||
|
|
||||||
|
unsigned long dynamic_irqs_config;
|
||||||
};
|
};
|
||||||
|
|
||||||
#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)
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -65,6 +65,14 @@ enum sde_enc_enable_state {
|
|||||||
SDE_ENC_ERR_NEEDS_HW_RESET
|
SDE_ENC_ERR_NEEDS_HW_RESET
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum sde_enc_irqs {
|
||||||
|
SDE_ENC_CMD_TE_ASSERT,
|
||||||
|
SDE_ENC_CMD_TE_DEASSERT,
|
||||||
|
SDE_ENC_CMD_TEAR_DETECT,
|
||||||
|
|
||||||
|
SDE_ENC_IRQ_MAX
|
||||||
|
};
|
||||||
|
|
||||||
struct sde_encoder_phys;
|
struct sde_encoder_phys;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -182,6 +190,7 @@ struct sde_encoder_phys_ops {
|
|||||||
u32 *misr_value);
|
u32 *misr_value);
|
||||||
void (*hw_reset)(struct sde_encoder_phys *phys_enc);
|
void (*hw_reset)(struct sde_encoder_phys *phys_enc);
|
||||||
void (*irq_control)(struct sde_encoder_phys *phys, bool enable);
|
void (*irq_control)(struct sde_encoder_phys *phys, bool enable);
|
||||||
|
void (*dynamic_irq_control)(struct sde_encoder_phys *phys, bool enable);
|
||||||
void (*update_split_role)(struct sde_encoder_phys *phys_enc,
|
void (*update_split_role)(struct sde_encoder_phys *phys_enc,
|
||||||
enum sde_enc_split_role role);
|
enum sde_enc_split_role role);
|
||||||
void (*control_te)(struct sde_encoder_phys *phys_enc, bool enable);
|
void (*control_te)(struct sde_encoder_phys *phys_enc, bool enable);
|
||||||
@@ -218,6 +227,9 @@ struct sde_encoder_phys_ops {
|
|||||||
* autorefresh has triggered a double buffer flip
|
* autorefresh has triggered a double buffer flip
|
||||||
* @INTR_IDX_WRPTR: Writepointer start interrupt for cmd mode panel
|
* @INTR_IDX_WRPTR: Writepointer start interrupt for cmd mode panel
|
||||||
* @INTR_IDX_WB_LINEPTR: Programmable lineptr interrupt for WB
|
* @INTR_IDX_WB_LINEPTR: Programmable lineptr interrupt for WB
|
||||||
|
* @INTF_IDX_TEAR_DETECT: Tear detect interrupt
|
||||||
|
* @INTR_IDX_TE_ASSERT: TE Assert interrupt
|
||||||
|
* @INTR_IDX_TE_DEASSERT: TE Deassert interrupt
|
||||||
*/
|
*/
|
||||||
enum sde_intr_idx {
|
enum sde_intr_idx {
|
||||||
INTR_IDX_VSYNC,
|
INTR_IDX_VSYNC,
|
||||||
@@ -237,6 +249,9 @@ enum sde_intr_idx {
|
|||||||
INTR_IDX_PP_CWB2_OVFL,
|
INTR_IDX_PP_CWB2_OVFL,
|
||||||
INTR_IDX_WRPTR,
|
INTR_IDX_WRPTR,
|
||||||
INTR_IDX_WB_LINEPTR,
|
INTR_IDX_WB_LINEPTR,
|
||||||
|
INTF_IDX_TEAR_DETECT,
|
||||||
|
INTR_IDX_TE_ASSERT,
|
||||||
|
INTR_IDX_TE_DEASSERT,
|
||||||
INTR_IDX_MAX,
|
INTR_IDX_MAX,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -396,6 +396,63 @@ static void sde_encoder_phys_cmd_wr_ptr_irq(void *arg, int irq_idx)
|
|||||||
SDE_ATRACE_END("wr_ptr_irq");
|
SDE_ATRACE_END("wr_ptr_irq");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sde_encoder_phys_cmd_tear_detect_irq(void *arg, int irq_idx)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = arg;
|
||||||
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
|
|
||||||
|
if (!phys_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||||
|
if (!cmd_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDE_ATRACE_BEGIN("tear_detect_irq");
|
||||||
|
|
||||||
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent));
|
||||||
|
|
||||||
|
SDE_ATRACE_END("tear_detect_irq");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sde_encoder_phys_cmd_te_assert_irq(void *arg, int irq_idx)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = arg;
|
||||||
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
|
|
||||||
|
if (!phys_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||||
|
if (!cmd_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDE_ATRACE_BEGIN("te_assert_irq");
|
||||||
|
|
||||||
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent));
|
||||||
|
|
||||||
|
SDE_ATRACE_END("te_assert_irq");
|
||||||
|
}
|
||||||
|
|
||||||
|
static void sde_encoder_phys_cmd_te_deassert_irq(void *arg, int irq_idx)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = arg;
|
||||||
|
struct sde_encoder_phys_cmd *cmd_enc;
|
||||||
|
|
||||||
|
if (!phys_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
cmd_enc = to_sde_encoder_phys_cmd(phys_enc);
|
||||||
|
if (!cmd_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDE_ATRACE_BEGIN("te_deassert_irq");
|
||||||
|
|
||||||
|
SDE_EVT32_IRQ(DRMID(phys_enc->parent));
|
||||||
|
|
||||||
|
SDE_ATRACE_END("te_deassert_irq");
|
||||||
|
}
|
||||||
|
|
||||||
static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
||||||
struct sde_encoder_phys *phys_enc)
|
struct sde_encoder_phys *phys_enc)
|
||||||
{
|
{
|
||||||
@@ -441,6 +498,22 @@ static void _sde_encoder_phys_cmd_setup_irq_hw_idx(
|
|||||||
irq->hw_idx = phys_enc->hw_intf->idx;
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
else
|
else
|
||||||
irq->hw_idx = phys_enc->hw_pp->idx;
|
irq->hw_idx = phys_enc->hw_pp->idx;
|
||||||
|
|
||||||
|
irq = &phys_enc->irq[INTF_IDX_TEAR_DETECT];
|
||||||
|
if (phys_enc->has_intf_te)
|
||||||
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
|
else
|
||||||
|
irq->hw_idx = phys_enc->hw_pp->idx;
|
||||||
|
|
||||||
|
if (phys_enc->has_intf_te) {
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_TE_ASSERT];
|
||||||
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
|
|
||||||
|
if (test_bit(SDE_INTF_TE_DEASSERT_DETECT, &phys_enc->hw_intf->cap->features)) {
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_TE_DEASSERT];
|
||||||
|
irq->hw_idx = phys_enc->hw_intf->idx;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sde_encoder_phys_cmd_cont_splash_mode_set(
|
static void sde_encoder_phys_cmd_cont_splash_mode_set(
|
||||||
@@ -926,6 +999,49 @@ end:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void sde_encoder_phys_cmd_dynamic_irq_control(struct sde_encoder_phys *phys_enc, bool enable)
|
||||||
|
{
|
||||||
|
struct sde_encoder_virt *sde_enc;
|
||||||
|
|
||||||
|
if (!phys_enc)
|
||||||
|
return;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pingpong split slaves do not register for IRQs
|
||||||
|
* check old and new topologies
|
||||||
|
*/
|
||||||
|
if (_sde_encoder_phys_is_ppsplit_slave(phys_enc) ||
|
||||||
|
_sde_encoder_phys_is_disabling_ppsplit_slave(phys_enc))
|
||||||
|
return;
|
||||||
|
|
||||||
|
sde_enc = to_sde_encoder_virt(phys_enc->parent);
|
||||||
|
|
||||||
|
if (enable) {
|
||||||
|
if (test_bit(SDE_ENC_CMD_TEAR_DETECT, &sde_enc->dynamic_irqs_config))
|
||||||
|
sde_encoder_helper_register_irq(phys_enc, INTF_IDX_TEAR_DETECT);
|
||||||
|
|
||||||
|
if (test_bit(SDE_ENC_CMD_TE_ASSERT, &sde_enc->dynamic_irqs_config) &&
|
||||||
|
phys_enc->has_intf_te)
|
||||||
|
sde_encoder_helper_register_irq(phys_enc, INTR_IDX_TE_ASSERT);
|
||||||
|
|
||||||
|
if (test_bit(SDE_ENC_CMD_TE_DEASSERT, &sde_enc->dynamic_irqs_config) &&
|
||||||
|
test_bit(SDE_INTF_TE_DEASSERT_DETECT,
|
||||||
|
&phys_enc->hw_intf->cap->features) &&
|
||||||
|
phys_enc->has_intf_te)
|
||||||
|
sde_encoder_helper_register_irq(phys_enc, INTR_IDX_TE_DEASSERT);
|
||||||
|
} else {
|
||||||
|
if (SDE_ENC_IRQ_REGISTERED(phys_enc, INTF_IDX_TEAR_DETECT))
|
||||||
|
sde_encoder_helper_unregister_irq(phys_enc, INTF_IDX_TEAR_DETECT);
|
||||||
|
|
||||||
|
if (SDE_ENC_IRQ_REGISTERED(phys_enc, INTR_IDX_TE_ASSERT))
|
||||||
|
sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_TE_ASSERT);
|
||||||
|
|
||||||
|
if (test_bit(SDE_INTF_TE_DEASSERT_DETECT, &phys_enc->hw_intf->cap->features) &&
|
||||||
|
SDE_ENC_IRQ_REGISTERED(phys_enc, INTR_IDX_TE_DEASSERT))
|
||||||
|
sde_encoder_helper_unregister_irq(phys_enc, INTR_IDX_TE_DEASSERT);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
void sde_encoder_phys_cmd_irq_control(struct sde_encoder_phys *phys_enc,
|
||||||
bool enable)
|
bool enable)
|
||||||
{
|
{
|
||||||
@@ -2135,6 +2251,7 @@ static void sde_encoder_phys_cmd_init_ops(struct sde_encoder_phys_ops *ops)
|
|||||||
ops->needs_single_flush = sde_encoder_phys_needs_single_flush;
|
ops->needs_single_flush = sde_encoder_phys_needs_single_flush;
|
||||||
ops->hw_reset = sde_encoder_helper_hw_reset;
|
ops->hw_reset = sde_encoder_helper_hw_reset;
|
||||||
ops->irq_control = sde_encoder_phys_cmd_irq_control;
|
ops->irq_control = sde_encoder_phys_cmd_irq_control;
|
||||||
|
ops->dynamic_irq_control = sde_encoder_phys_cmd_dynamic_irq_control;
|
||||||
ops->update_split_role = sde_encoder_phys_cmd_update_split_role;
|
ops->update_split_role = sde_encoder_phys_cmd_update_split_role;
|
||||||
ops->restore = sde_encoder_phys_cmd_enable_helper;
|
ops->restore = sde_encoder_phys_cmd_enable_helper;
|
||||||
ops->control_te = sde_encoder_phys_cmd_connect_te;
|
ops->control_te = sde_encoder_phys_cmd_connect_te;
|
||||||
@@ -2159,49 +2276,10 @@ static inline bool sde_encoder_phys_cmd_intf_te_supported(
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
static void _sde_encoder_phys_cmd_init_irqs(struct sde_encoder_phys *phys_enc)
|
||||||
struct sde_enc_phys_init_params *p)
|
|
||||||
{
|
{
|
||||||
struct sde_encoder_phys *phys_enc = NULL;
|
|
||||||
struct sde_encoder_phys_cmd *cmd_enc = NULL;
|
|
||||||
struct sde_hw_mdp *hw_mdp;
|
|
||||||
struct sde_encoder_irq *irq;
|
struct sde_encoder_irq *irq;
|
||||||
int i, ret = 0;
|
int i;
|
||||||
|
|
||||||
SDE_DEBUG("intf %d\n", p->intf_idx - INTF_0);
|
|
||||||
|
|
||||||
cmd_enc = kzalloc(sizeof(*cmd_enc), GFP_KERNEL);
|
|
||||||
if (!cmd_enc) {
|
|
||||||
ret = -ENOMEM;
|
|
||||||
SDE_ERROR("failed to allocate\n");
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
phys_enc = &cmd_enc->base;
|
|
||||||
|
|
||||||
hw_mdp = sde_rm_get_mdp(&p->sde_kms->rm);
|
|
||||||
if (IS_ERR_OR_NULL(hw_mdp)) {
|
|
||||||
ret = PTR_ERR(hw_mdp);
|
|
||||||
SDE_ERROR("failed to get mdptop\n");
|
|
||||||
goto fail_mdp_init;
|
|
||||||
}
|
|
||||||
phys_enc->hw_mdptop = hw_mdp;
|
|
||||||
phys_enc->intf_idx = p->intf_idx;
|
|
||||||
|
|
||||||
phys_enc->parent = p->parent;
|
|
||||||
phys_enc->parent_ops = p->parent_ops;
|
|
||||||
phys_enc->sde_kms = p->sde_kms;
|
|
||||||
phys_enc->split_role = p->split_role;
|
|
||||||
phys_enc->intf_mode = INTF_MODE_CMD;
|
|
||||||
phys_enc->enc_spinlock = p->enc_spinlock;
|
|
||||||
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
|
||||||
cmd_enc->stream_sel = 0;
|
|
||||||
phys_enc->enable_state = SDE_ENC_DISABLED;
|
|
||||||
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
|
||||||
sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
|
|
||||||
phys_enc->comp_type = p->comp_type;
|
|
||||||
|
|
||||||
phys_enc->has_intf_te = sde_encoder_phys_cmd_intf_te_supported(
|
|
||||||
phys_enc->sde_kms->catalog, phys_enc->intf_idx);
|
|
||||||
|
|
||||||
for (i = 0; i < INTR_IDX_MAX; i++) {
|
for (i = 0; i < INTR_IDX_MAX; i++) {
|
||||||
irq = &phys_enc->irq[i];
|
irq = &phys_enc->irq[i];
|
||||||
@@ -2261,6 +2339,75 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
|||||||
irq->intr_type = SDE_IRQ_TYPE_PING_PONG_WR_PTR;
|
irq->intr_type = SDE_IRQ_TYPE_PING_PONG_WR_PTR;
|
||||||
irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq;
|
irq->cb.func = sde_encoder_phys_cmd_wr_ptr_irq;
|
||||||
|
|
||||||
|
irq = &phys_enc->irq[INTF_IDX_TEAR_DETECT];
|
||||||
|
irq->intr_idx = INTF_IDX_TEAR_DETECT;
|
||||||
|
irq->name = "te_tear_detect";
|
||||||
|
if (phys_enc->has_intf_te)
|
||||||
|
irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_TEAR_DETECT;
|
||||||
|
else
|
||||||
|
irq->intr_type = SDE_IRQ_TYPE_PING_PONG_TEAR_CHECK;
|
||||||
|
irq->cb.func = sde_encoder_phys_cmd_tear_detect_irq;
|
||||||
|
|
||||||
|
if (phys_enc->has_intf_te) {
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_TE_ASSERT];
|
||||||
|
irq->intr_idx = INTR_IDX_TE_ASSERT;
|
||||||
|
irq->name = "te_assert";
|
||||||
|
irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_TE_ASSERT;
|
||||||
|
irq->cb.func = sde_encoder_phys_cmd_te_assert_irq;
|
||||||
|
|
||||||
|
irq = &phys_enc->irq[INTR_IDX_TE_DEASSERT];
|
||||||
|
irq->intr_idx = INTR_IDX_TE_DEASSERT;
|
||||||
|
irq->name = "te_deassert";
|
||||||
|
irq->intr_type = SDE_IRQ_TYPE_INTF_TEAR_TE_DEASSERT;
|
||||||
|
irq->cb.func = sde_encoder_phys_cmd_te_deassert_irq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sde_encoder_phys *sde_encoder_phys_cmd_init(
|
||||||
|
struct sde_enc_phys_init_params *p)
|
||||||
|
{
|
||||||
|
struct sde_encoder_phys *phys_enc = NULL;
|
||||||
|
struct sde_encoder_phys_cmd *cmd_enc = NULL;
|
||||||
|
struct sde_hw_mdp *hw_mdp;
|
||||||
|
int i, ret = 0;
|
||||||
|
|
||||||
|
SDE_DEBUG("intf %d\n", p->intf_idx - INTF_0);
|
||||||
|
|
||||||
|
cmd_enc = kzalloc(sizeof(*cmd_enc), GFP_KERNEL);
|
||||||
|
if (!cmd_enc) {
|
||||||
|
ret = -ENOMEM;
|
||||||
|
SDE_ERROR("failed to allocate\n");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
phys_enc = &cmd_enc->base;
|
||||||
|
|
||||||
|
hw_mdp = sde_rm_get_mdp(&p->sde_kms->rm);
|
||||||
|
if (IS_ERR_OR_NULL(hw_mdp)) {
|
||||||
|
ret = PTR_ERR(hw_mdp);
|
||||||
|
SDE_ERROR("failed to get mdptop\n");
|
||||||
|
goto fail_mdp_init;
|
||||||
|
}
|
||||||
|
phys_enc->hw_mdptop = hw_mdp;
|
||||||
|
phys_enc->intf_idx = p->intf_idx;
|
||||||
|
|
||||||
|
phys_enc->parent = p->parent;
|
||||||
|
phys_enc->parent_ops = p->parent_ops;
|
||||||
|
phys_enc->sde_kms = p->sde_kms;
|
||||||
|
phys_enc->split_role = p->split_role;
|
||||||
|
phys_enc->intf_mode = INTF_MODE_CMD;
|
||||||
|
phys_enc->enc_spinlock = p->enc_spinlock;
|
||||||
|
phys_enc->vblank_ctl_lock = p->vblank_ctl_lock;
|
||||||
|
cmd_enc->stream_sel = 0;
|
||||||
|
phys_enc->enable_state = SDE_ENC_DISABLED;
|
||||||
|
phys_enc->kickoff_timeout_ms = DEFAULT_KICKOFF_TIMEOUT_MS;
|
||||||
|
sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
|
||||||
|
phys_enc->comp_type = p->comp_type;
|
||||||
|
|
||||||
|
phys_enc->has_intf_te = sde_encoder_phys_cmd_intf_te_supported(
|
||||||
|
phys_enc->sde_kms->catalog, phys_enc->intf_idx);
|
||||||
|
|
||||||
|
_sde_encoder_phys_cmd_init_irqs(phys_enc);
|
||||||
|
|
||||||
atomic_set(&phys_enc->vblank_refcount, 0);
|
atomic_set(&phys_enc->vblank_refcount, 0);
|
||||||
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
atomic_set(&phys_enc->pending_kickoff_cnt, 0);
|
||||||
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
|
atomic_set(&phys_enc->pending_retire_fence_cnt, 0);
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -2505,6 +2505,7 @@ static int sde_intf_parse_dt(struct device_node *np,
|
|||||||
set_bit(SDE_INTF_TE_32BIT, &intf->features);
|
set_bit(SDE_INTF_TE_32BIT, &intf->features);
|
||||||
set_bit(SDE_INTF_TE_SINGLE_UPDATE, &intf->features);
|
set_bit(SDE_INTF_TE_SINGLE_UPDATE, &intf->features);
|
||||||
set_bit(SDE_INTF_WD_LTJ_CTL, &intf->features);
|
set_bit(SDE_INTF_WD_LTJ_CTL, &intf->features);
|
||||||
|
set_bit(SDE_INTF_TE_DEASSERT_DETECT, &intf->features);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -619,6 +619,7 @@ enum {
|
|||||||
* @SDE_INTF_AVR_STATUS INTF block has AVR_STATUS field in AVR_CONTROL register
|
* @SDE_INTF_AVR_STATUS INTF block has AVR_STATUS field in AVR_CONTROL register
|
||||||
* @SDE_INTF_WD_JITTER INTF block has WD timer jitter support
|
* @SDE_INTF_WD_JITTER INTF block has WD timer jitter support
|
||||||
* @SDE_INTF_WD_LTJ_CTL INTF block has WD long term jitter control support
|
* @SDE_INTF_WD_LTJ_CTL INTF block has WD long term jitter control support
|
||||||
|
* @SDE_INTF_TE_DEASSERT_DETECT INTF block has TE Deassert detect support
|
||||||
* @SDE_INTF_MAX
|
* @SDE_INTF_MAX
|
||||||
*/
|
*/
|
||||||
enum {
|
enum {
|
||||||
@@ -636,6 +637,7 @@ enum {
|
|||||||
SDE_INTF_AVR_STATUS,
|
SDE_INTF_AVR_STATUS,
|
||||||
SDE_INTF_WD_JITTER,
|
SDE_INTF_WD_JITTER,
|
||||||
SDE_INTF_WD_LTJ_CTL,
|
SDE_INTF_WD_LTJ_CTL,
|
||||||
|
SDE_INTF_TE_DEASSERT_DETECT,
|
||||||
SDE_INTF_MAX
|
SDE_INTF_MAX
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
// SPDX-License-Identifier: GPL-2.0-only
|
// SPDX-License-Identifier: GPL-2.0-only
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -171,6 +171,7 @@
|
|||||||
#define SDE_INTR_INTF_TEAR_RD_PTR BIT(2)
|
#define SDE_INTR_INTF_TEAR_RD_PTR BIT(2)
|
||||||
#define SDE_INTR_INTF_TEAR_TE_DETECTED BIT(3)
|
#define SDE_INTR_INTF_TEAR_TE_DETECTED BIT(3)
|
||||||
#define SDE_INTR_INTF_TEAR_TEAR_DETECTED BIT(4)
|
#define SDE_INTR_INTF_TEAR_TEAR_DETECTED BIT(4)
|
||||||
|
#define SDE_INTR_INTF_TEAR_TE_DEASSERT_DETECTED BIT(6)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* LTM interrupt status bit definitions
|
* LTM interrupt status bit definitions
|
||||||
@@ -379,8 +380,12 @@ static struct sde_irq_type sde_irq_intf_te_map[] = {
|
|||||||
SDE_INTR_INTF_TEAR_WR_PTR, -1},
|
SDE_INTR_INTF_TEAR_WR_PTR, -1},
|
||||||
{ SDE_IRQ_TYPE_INTF_TEAR_RD_PTR, -1,
|
{ SDE_IRQ_TYPE_INTF_TEAR_RD_PTR, -1,
|
||||||
SDE_INTR_INTF_TEAR_RD_PTR, -1},
|
SDE_INTR_INTF_TEAR_RD_PTR, -1},
|
||||||
{ SDE_IRQ_TYPE_INTF_TEAR_TEAR_CHECK, -1,
|
{ SDE_IRQ_TYPE_INTF_TEAR_TEAR_DETECT, -1,
|
||||||
SDE_INTR_INTF_TEAR_TEAR_DETECTED, -1},
|
SDE_INTR_INTF_TEAR_TEAR_DETECTED, -1},
|
||||||
|
{ SDE_IRQ_TYPE_INTF_TEAR_TE_ASSERT, -1,
|
||||||
|
SDE_INTR_INTF_TEAR_TE_DETECTED, -1},
|
||||||
|
{ SDE_IRQ_TYPE_INTF_TEAR_TE_DEASSERT, -1,
|
||||||
|
SDE_INTR_INTF_TEAR_TE_DEASSERT_DETECTED, -1},
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct sde_irq_type sde_irq_ltm_map[] = {
|
static struct sde_irq_type sde_irq_ltm_map[] = {
|
||||||
|
@@ -1,6 +1,6 @@
|
|||||||
/* SPDX-License-Identifier: GPL-2.0-only */
|
/* SPDX-License-Identifier: GPL-2.0-only */
|
||||||
/*
|
/*
|
||||||
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
|
* Copyright (c) 2021-2023 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.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -54,8 +54,9 @@
|
|||||||
* @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
|
||||||
* @SDE_IRQ_TYPE_INTF_TEAR_TEAR_CHECK: INTF Tear Tear check
|
* @SDE_IRQ_TYPE_INTF_TEAR_TEAR_DETECT: INTF Tear Tear detection
|
||||||
* @SDE_IRQ_TYPE_INTF_TEAR_TE_CHECK: INTF Tear TE detection
|
* @SDE_IRQ_TYPE_INTF_TEAR_TE_ASSERT: INTF Tear TE Assert detection
|
||||||
|
* @SDE_IRQ_TYPE_INTF_TEAR_TE_DEASSERT: INTF Tear TE Deassert detection
|
||||||
* @SDE_IRQ_TYPE_LTM_STATS_DONE: LTM stats done interrupt
|
* @SDE_IRQ_TYPE_LTM_STATS_DONE: LTM stats done interrupt
|
||||||
* @SDE_IRQ_TYPE_LTM_STATS_WB_PB: LTM stats WB push back interrupt
|
* @SDE_IRQ_TYPE_LTM_STATS_WB_PB: LTM stats WB push back interrupt
|
||||||
* @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt for WB
|
* @SDE_IRQ_TYPE_PROG_LINE: Programmable Line interrupt for WB
|
||||||
@@ -93,8 +94,9 @@ enum sde_intr_type {
|
|||||||
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,
|
||||||
SDE_IRQ_TYPE_INTF_TEAR_TEAR_CHECK,
|
SDE_IRQ_TYPE_INTF_TEAR_TEAR_DETECT,
|
||||||
SDE_IRQ_TYPE_INTF_TEAR_TE_CHECK,
|
SDE_IRQ_TYPE_INTF_TEAR_TE_ASSERT,
|
||||||
|
SDE_IRQ_TYPE_INTF_TEAR_TE_DEASSERT,
|
||||||
SDE_IRQ_TYPE_LTM_STATS_DONE,
|
SDE_IRQ_TYPE_LTM_STATS_DONE,
|
||||||
SDE_IRQ_TYPE_LTM_STATS_WB_PB,
|
SDE_IRQ_TYPE_LTM_STATS_WB_PB,
|
||||||
SDE_IRQ_TYPE_WB_PROG_LINE,
|
SDE_IRQ_TYPE_WB_PROG_LINE,
|
||||||
|
Reference in New Issue
Block a user