Skip to content

Commit

Permalink
drm/msm/dpu: replace IRQ lookup with the data in hw catalog
Browse files Browse the repository at this point in the history
The IRQ table in the dpu_hw_interrupts.h is big, ugly, and hard to
maintain. There are only few interrupts used from that table. Newer
generations use different IRQ locations. Move this data to hw catalog.

Signed-off-by: Dmitry Baryshkov <dmitry.baryshkov@linaro.org>
Reviewed-by: Abhinav Kumar <abhinavk@codeaurora.org>
Link: https://lore.kernel.org/r/20210516202910.2141079-5-dmitry.baryshkov@linaro.org
[fixup tracepoint compile warns/err]
Signed-off-by: Rob Clark <robdclark@chromium.org>
  • Loading branch information
Dmitry Baryshkov authored and Rob Clark committed Jun 23, 2021
1 parent 597762d commit 667e998
Show file tree
Hide file tree
Showing 11 changed files with 234 additions and 288 deletions.
20 changes: 5 additions & 15 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,16 +43,6 @@ static void dpu_core_irq_callback_handler(void *arg, int irq_idx)
spin_unlock_irqrestore(&dpu_kms->irq_obj.cb_lock, irq_flags);
}

int dpu_core_irq_idx_lookup(struct dpu_kms *dpu_kms,
enum dpu_intr_type intr_type, u32 instance_idx)
{
if (!dpu_kms->hw_intr || !dpu_kms->hw_intr->ops.irq_idx_lookup)
return -EINVAL;

return dpu_kms->hw_intr->ops.irq_idx_lookup(dpu_kms->hw_intr,
intr_type, instance_idx);
}

/**
* _dpu_core_irq_enable - enable core interrupt given by the index
* @dpu_kms: Pointer to dpu kms context
Expand All @@ -70,7 +60,7 @@ static int _dpu_core_irq_enable(struct dpu_kms *dpu_kms, int irq_idx)
return -EINVAL;
}

if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
Expand Down Expand Up @@ -133,7 +123,7 @@ static int _dpu_core_irq_disable(struct dpu_kms *dpu_kms, int irq_idx)
return -EINVAL;
}

if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
Expand Down Expand Up @@ -208,7 +198,7 @@ int dpu_core_irq_register_callback(struct dpu_kms *dpu_kms, int irq_idx,
return -EINVAL;
}

if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
Expand Down Expand Up @@ -243,7 +233,7 @@ int dpu_core_irq_unregister_callback(struct dpu_kms *dpu_kms, int irq_idx,
return -EINVAL;
}

if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->irq_idx_tbl_size) {
if (irq_idx < 0 || irq_idx >= dpu_kms->hw_intr->total_irqs) {
DPU_ERROR("invalid IRQ index: [%d]\n", irq_idx);
return -EINVAL;
}
Expand Down Expand Up @@ -328,7 +318,7 @@ void dpu_core_irq_preinstall(struct dpu_kms *dpu_kms)
spin_lock_init(&dpu_kms->irq_obj.cb_lock);

/* Create irq callbacks for all possible irq_idx */
dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->irq_idx_tbl_size;
dpu_kms->irq_obj.total_irqs = dpu_kms->hw_intr->total_irqs;
dpu_kms->irq_obj.irq_cb_tbl = kcalloc(dpu_kms->irq_obj.total_irqs,
sizeof(struct list_head), GFP_KERNEL);
dpu_kms->irq_obj.enable_counts = kcalloc(dpu_kms->irq_obj.total_irqs,
Expand Down
13 changes: 0 additions & 13 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_core_irq.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,19 +29,6 @@ void dpu_core_irq_uninstall(struct dpu_kms *dpu_kms);
*/
irqreturn_t dpu_core_irq(struct dpu_kms *dpu_kms);

/**
* dpu_core_irq_idx_lookup - IRQ helper function for lookup irq_idx from HW
* interrupt mapping table.
* @dpu_kms: DPU handle
* @intr_type: DPU HW interrupt type for lookup
* @instance_idx: DPU HW block instance defined in dpu_hw_mdss.h
* @return: irq_idx or -EINVAL when fail to lookup
*/
int dpu_core_irq_idx_lookup(
struct dpu_kms *dpu_kms,
enum dpu_intr_type intr_type,
uint32_t instance_idx);

/**
* dpu_core_irq_enable - IRQ helper function for enabling one or more IRQs
* @dpu_kms: DPU handle
Expand Down
64 changes: 26 additions & 38 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ void dpu_encoder_helper_report_irq_timeout(struct dpu_encoder_phys *phys_enc,
}

static int dpu_encoder_helper_wait_event_timeout(int32_t drm_id,
int32_t hw_id, struct dpu_encoder_wait_info *info);
u32 irq_idx, struct dpu_encoder_wait_info *info);

int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
enum dpu_intr_idx intr_idx,
Expand All @@ -274,27 +274,27 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,

/* return EWOULDBLOCK since we know the wait isn't necessary */
if (phys_enc->enable_state == DPU_ENC_DISABLED) {
DRM_ERROR("encoder is disabled id=%u, intr=%d, hw=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_ERROR("encoder is disabled id=%u, intr=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx);
return -EWOULDBLOCK;
}

if (irq->irq_idx < 0) {
DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, hw=%d, irq=%s",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_DEBUG_KMS("skip irq wait id=%u, intr=%d, irq=%s",
DRMID(phys_enc->parent), intr_idx,
irq->name);
return 0;
}

DRM_DEBUG_KMS("id=%u, intr=%d, hw=%d, irq=%d, pp=%d, pending_cnt=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_DEBUG_KMS("id=%u, intr=%d, irq=%d, pp=%d, pending_cnt=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx, phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(wait_info->atomic_cnt));

ret = dpu_encoder_helper_wait_event_timeout(
DRMID(phys_enc->parent),
irq->hw_idx,
irq->irq_idx,
wait_info);

if (ret <= 0) {
Expand All @@ -304,9 +304,9 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
unsigned long flags;

DRM_DEBUG_KMS("irq not triggered id=%u, intr=%d, "
"hw=%d, irq=%d, pp=%d, atomic_cnt=%d",
"irq=%d, pp=%d, atomic_cnt=%d",
DRMID(phys_enc->parent), intr_idx,
irq->hw_idx, irq->irq_idx,
irq->irq_idx,
phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(wait_info->atomic_cnt));
local_irq_save(flags);
Expand All @@ -316,16 +316,16 @@ int dpu_encoder_helper_wait_for_irq(struct dpu_encoder_phys *phys_enc,
} else {
ret = -ETIMEDOUT;
DRM_DEBUG_KMS("irq timeout id=%u, intr=%d, "
"hw=%d, irq=%d, pp=%d, atomic_cnt=%d",
"irq=%d, pp=%d, atomic_cnt=%d",
DRMID(phys_enc->parent), intr_idx,
irq->hw_idx, irq->irq_idx,
irq->irq_idx,
phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(wait_info->atomic_cnt));
}
} else {
ret = 0;
trace_dpu_enc_irq_wait_success(DRMID(phys_enc->parent),
intr_idx, irq->hw_idx, irq->irq_idx,
intr_idx, irq->irq_idx,
phys_enc->hw_pp->idx - PINGPONG_0,
atomic_read(wait_info->atomic_cnt));
}
Expand All @@ -345,19 +345,9 @@ int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc,
}
irq = &phys_enc->irq[intr_idx];

if (irq->irq_idx >= 0) {
DPU_DEBUG_PHYS(phys_enc,
"skipping already registered irq %s type %d\n",
irq->name, irq->intr_type);
return 0;
}

irq->irq_idx = dpu_core_irq_idx_lookup(phys_enc->dpu_kms,
irq->intr_type, irq->hw_idx);
if (irq->irq_idx < 0) {
DPU_ERROR_PHYS(phys_enc,
"failed to lookup IRQ index for %s type:%d\n",
irq->name, irq->intr_type);
"invalid IRQ index:%d\n", irq->irq_idx);
return -EINVAL;
}

Expand All @@ -373,8 +363,8 @@ int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc,

ret = dpu_core_irq_enable(phys_enc->dpu_kms, &irq->irq_idx, 1);
if (ret) {
DRM_ERROR("enable failed id=%u, intr=%d, hw=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_ERROR("enable failed id=%u, intr=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx);
dpu_core_irq_unregister_callback(phys_enc->dpu_kms,
irq->irq_idx, &irq->cb);
Expand All @@ -383,7 +373,7 @@ int dpu_encoder_helper_register_irq(struct dpu_encoder_phys *phys_enc,
}

trace_dpu_enc_irq_register_success(DRMID(phys_enc->parent), intr_idx,
irq->hw_idx, irq->irq_idx);
irq->irq_idx);

return ret;
}
Expand All @@ -398,31 +388,29 @@ int dpu_encoder_helper_unregister_irq(struct dpu_encoder_phys *phys_enc,

/* silently skip irqs that weren't registered */
if (irq->irq_idx < 0) {
DRM_ERROR("duplicate unregister id=%u, intr=%d, hw=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_ERROR("duplicate unregister id=%u, intr=%d, irq=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx);
return 0;
}

ret = dpu_core_irq_disable(phys_enc->dpu_kms, &irq->irq_idx, 1);
if (ret) {
DRM_ERROR("disable failed id=%u, intr=%d, hw=%d, irq=%d ret=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_ERROR("disable failed id=%u, intr=%d, irq=%d ret=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx, ret);
}

ret = dpu_core_irq_unregister_callback(phys_enc->dpu_kms, irq->irq_idx,
&irq->cb);
if (ret) {
DRM_ERROR("unreg cb fail id=%u, intr=%d, hw=%d, irq=%d ret=%d",
DRMID(phys_enc->parent), intr_idx, irq->hw_idx,
DRM_ERROR("unreg cb fail id=%u, intr=%d, irq=%d ret=%d",
DRMID(phys_enc->parent), intr_idx,
irq->irq_idx, ret);
}

trace_dpu_enc_irq_unregister_success(DRMID(phys_enc->parent), intr_idx,
irq->hw_idx, irq->irq_idx);

irq->irq_idx = -EINVAL;
irq->irq_idx);

return 0;
}
Expand Down Expand Up @@ -1543,7 +1531,7 @@ void dpu_encoder_helper_trigger_start(struct dpu_encoder_phys *phys_enc)

static int dpu_encoder_helper_wait_event_timeout(
int32_t drm_id,
int32_t hw_id,
u32 irq_idx,
struct dpu_encoder_wait_info *info)
{
int rc = 0;
Expand All @@ -1556,7 +1544,7 @@ static int dpu_encoder_helper_wait_event_timeout(
atomic_read(info->atomic_cnt) == 0, jiffies);
time = ktime_to_ms(ktime_get());

trace_dpu_enc_wait_event_timeout(drm_id, hw_id, rc, time,
trace_dpu_enc_wait_event_timeout(drm_id, irq_idx, rc, time,
expected_time,
atomic_read(info->atomic_cnt));
/* If we timed out, counter is valid and time is less, wait again */
Expand Down
2 changes: 0 additions & 2 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys.h
Original file line number Diff line number Diff line change
Expand Up @@ -167,7 +167,6 @@ enum dpu_intr_idx {
* @name: string name of interrupt
* @intr_type: Encoder interrupt type
* @intr_idx: Encoder interrupt enumeration
* @hw_idx: HW Block ID
* @irq_idx: IRQ interface lookup index from DPU IRQ framework
* will be -EINVAL if IRQ is not registered
* @irq_cb: interrupt callback
Expand All @@ -176,7 +175,6 @@ struct dpu_encoder_irq {
const char *name;
enum dpu_intr_type intr_type;
enum dpu_intr_idx intr_idx;
int hw_idx;
int irq_idx;
struct dpu_irq_callback cb;
};
Expand Down
36 changes: 12 additions & 24 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_cmd.c
Original file line number Diff line number Diff line change
Expand Up @@ -144,35 +144,14 @@ static void dpu_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx)
phys_enc);
}

static void _dpu_encoder_phys_cmd_setup_irq_hw_idx(
struct dpu_encoder_phys *phys_enc)
{
struct dpu_encoder_irq *irq;

irq = &phys_enc->irq[INTR_IDX_CTL_START];
irq->hw_idx = phys_enc->hw_ctl->idx;
irq->irq_idx = -EINVAL;

irq = &phys_enc->irq[INTR_IDX_PINGPONG];
irq->hw_idx = phys_enc->hw_pp->idx;
irq->irq_idx = -EINVAL;

irq = &phys_enc->irq[INTR_IDX_RDPTR];
irq->hw_idx = phys_enc->hw_pp->idx;
irq->irq_idx = -EINVAL;

irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
irq->hw_idx = phys_enc->intf_idx;
irq->irq_idx = -EINVAL;
}

static void dpu_encoder_phys_cmd_mode_set(
struct dpu_encoder_phys *phys_enc,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
struct dpu_encoder_phys_cmd *cmd_enc =
to_dpu_encoder_phys_cmd(phys_enc);
struct dpu_encoder_irq *irq;

if (!mode || !adj_mode) {
DPU_ERROR("invalid args\n");
Expand All @@ -182,7 +161,17 @@ static void dpu_encoder_phys_cmd_mode_set(
DPU_DEBUG_CMDENC(cmd_enc, "caching mode:\n");
drm_mode_debug_printmodeline(adj_mode);

_dpu_encoder_phys_cmd_setup_irq_hw_idx(phys_enc);
irq = &phys_enc->irq[INTR_IDX_CTL_START];
irq->irq_idx = phys_enc->hw_ctl->caps->intr_start;

irq = &phys_enc->irq[INTR_IDX_PINGPONG];
irq->irq_idx = phys_enc->hw_pp->caps->intr_done;

irq = &phys_enc->irq[INTR_IDX_RDPTR];
irq->irq_idx = phys_enc->hw_pp->caps->intr_rdptr;

irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
irq->irq_idx = phys_enc->hw_intf->cap->intr_underrun;
}

static int _dpu_encoder_phys_cmd_handle_ppdone_timeout(
Expand Down Expand Up @@ -799,7 +788,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_cmd_init(
irq = &phys_enc->irq[i];
INIT_LIST_HEAD(&irq->cb.list);
irq->irq_idx = -EINVAL;
irq->hw_idx = -EINVAL;
irq->cb.arg = phys_enc;
}

Expand Down
31 changes: 8 additions & 23 deletions drivers/gpu/drm/msm/disp/dpu1/dpu_encoder_phys_vid.c
Original file line number Diff line number Diff line change
Expand Up @@ -364,38 +364,24 @@ static bool dpu_encoder_phys_vid_needs_single_flush(
return phys_enc->split_role != ENC_ROLE_SOLO;
}

static void _dpu_encoder_phys_vid_setup_irq_hw_idx(
struct dpu_encoder_phys *phys_enc)
{
struct dpu_encoder_irq *irq;

/*
* Initialize irq->hw_idx only when irq is not registered.
* Prevent invalidating irq->irq_idx as modeset may be
* called many times during dfps.
*/

irq = &phys_enc->irq[INTR_IDX_VSYNC];
if (irq->irq_idx < 0)
irq->hw_idx = phys_enc->intf_idx;

irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
if (irq->irq_idx < 0)
irq->hw_idx = phys_enc->intf_idx;
}

static void dpu_encoder_phys_vid_mode_set(
struct dpu_encoder_phys *phys_enc,
struct drm_display_mode *mode,
struct drm_display_mode *adj_mode)
{
struct dpu_encoder_irq *irq;

if (adj_mode) {
phys_enc->cached_mode = *adj_mode;
drm_mode_debug_printmodeline(adj_mode);
DPU_DEBUG_VIDENC(phys_enc, "caching mode:\n");
}

_dpu_encoder_phys_vid_setup_irq_hw_idx(phys_enc);
irq = &phys_enc->irq[INTR_IDX_VSYNC];
irq->irq_idx = phys_enc->hw_intf->cap->intr_vsync;

irq = &phys_enc->irq[INTR_IDX_UNDERRUN];
irq->irq_idx = phys_enc->hw_intf->cap->intr_underrun;
}

static int dpu_encoder_phys_vid_control_vblank_irq(
Expand Down Expand Up @@ -642,7 +628,7 @@ static void dpu_encoder_phys_vid_irq_control(struct dpu_encoder_phys *phys_enc,

if (enable) {
ret = dpu_encoder_phys_vid_control_vblank_irq(phys_enc, true);
if (ret)
if (WARN_ON(ret))
return;

dpu_encoder_helper_register_irq(phys_enc, INTR_IDX_UNDERRUN);
Expand Down Expand Up @@ -744,7 +730,6 @@ struct dpu_encoder_phys *dpu_encoder_phys_vid_init(
irq = &phys_enc->irq[i];
INIT_LIST_HEAD(&irq->cb.list);
irq->irq_idx = -EINVAL;
irq->hw_idx = -EINVAL;
irq->cb.arg = phys_enc;
}

Expand Down
Loading

0 comments on commit 667e998

Please sign in to comment.