summaryrefslogtreecommitdiff
path: root/drivers/gpu
diff options
context:
space:
mode:
authorDhaval Patel <pdhaval@codeaurora.org>2016-11-01 10:38:47 -0700
committerGerrit - the friendly Code Review server <code-review@localhost>2016-11-01 10:38:47 -0700
commit0101431cb63ff6d4a2828f59977d6208e9677b4a (patch)
treeba230cff17b9acd83da8b17d8bd9ffc44b984486 /drivers/gpu
parentc3e05abca5fabd7580be1378c5165a8b8f523f98 (diff)
parent290e6a16b448e9e79c16a1077fa2d6843704e0f8 (diff)
Merge "drm/msm/sde: update vblank and underrun isr handling" into dev/msm-4.4-drm_kms
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/drm/msm/sde/sde_core_irq.c35
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c22
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h33
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c82
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c96
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c4
6 files changed, 180 insertions, 92 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_core_irq.c b/drivers/gpu/drm/msm/sde/sde_core_irq.c
index 6e3310165b36..82d464916e52 100644
--- a/drivers/gpu/drm/msm/sde/sde_core_irq.c
+++ b/drivers/gpu/drm/msm/sde/sde_core_irq.c
@@ -42,11 +42,6 @@ static void sde_core_irq_callback_handler(void *arg, int irq_idx)
irq_idx);
}
-static void sde_core_irq_intf_error_handler(void *arg, int irq_idx)
-{
- SDE_ERROR("INTF underrun detected, irq_idx=%d\n", irq_idx);
-}
-
int sde_core_irq_idx_lookup(struct sde_kms *sde_kms,
enum sde_intr_type intr_type, u32 instance_idx)
{
@@ -191,36 +186,6 @@ void sde_core_irq_preinstall(struct sde_kms *sde_kms)
int sde_core_irq_postinstall(struct sde_kms *sde_kms)
{
- struct msm_drm_private *priv;
- struct sde_irq_callback irq_cb;
- int irq_idx;
- int i;
-
- if (!sde_kms) {
- SDE_ERROR("invalid sde_kms\n");
- return -EINVAL;
- } else if (!sde_kms->dev) {
- SDE_ERROR("invalid drm device\n");
- return -EINVAL;
- } else if (!sde_kms->dev->dev_private) {
- SDE_ERROR("invalid device private\n");
- return -EINVAL;
- }
- priv = sde_kms->dev->dev_private;
-
- irq_cb.func = sde_core_irq_intf_error_handler;
- irq_cb.arg = sde_kms;
-
- /* Register interface underrun callback */
- sde_power_resource_enable(&priv->phandle, sde_kms->core_client, true);
- for (i = 0; i < sde_kms->catalog->intf_count; i++) {
- irq_idx = sde_core_irq_idx_lookup(sde_kms,
- SDE_IRQ_TYPE_INTF_UNDER_RUN, i+INTF_0);
- sde_core_irq_register_callback(sde_kms, irq_idx, &irq_cb);
- sde_core_irq_enable(sde_kms, &irq_idx, 1);
- }
- sde_power_resource_enable(&priv->phandle, sde_kms->core_client, false);
-
return 0;
}
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index 56eae31da3ad..d9bc339d98b1 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -395,6 +395,9 @@ static void sde_encoder_virt_enable(struct drm_encoder *drm_enc)
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
if (phys) {
+ atomic_set(&phys->vsync_cnt, 0);
+ atomic_set(&phys->underrun_cnt, 0);
+
if (phys->ops.enable)
phys->ops.enable(phys);
@@ -445,6 +448,8 @@ static void sde_encoder_virt_disable(struct drm_encoder *drm_enc)
if (phys->ops.disable && !phys->ops.is_master(phys))
phys->ops.disable(phys);
phys->connector = NULL;
+ atomic_set(&phys->vsync_cnt, 0);
+ atomic_set(&phys->underrun_cnt, 0);
}
}
@@ -497,12 +502,13 @@ static enum sde_wb sde_encoder_get_wb(struct sde_mdss_cfg *catalog,
return WB_MAX;
}
-static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc)
+static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc,
+ struct sde_encoder_phys *phy_enc)
{
struct sde_encoder_virt *sde_enc = NULL;
unsigned long lock_flags;
- if (!drm_enc)
+ if (!drm_enc || !phy_enc)
return;
sde_enc = to_sde_encoder_virt(drm_enc);
@@ -511,6 +517,17 @@ static void sde_encoder_vblank_callback(struct drm_encoder *drm_enc)
if (sde_enc->crtc_vblank_cb)
sde_enc->crtc_vblank_cb(sde_enc->crtc_vblank_cb_data);
spin_unlock_irqrestore(&sde_enc->spin_lock, lock_flags);
+
+ atomic_inc(&phy_enc->vsync_cnt);
+}
+
+static void sde_encoder_underrun_callback(struct drm_encoder *drm_enc,
+ struct sde_encoder_phys *phy_enc)
+{
+ if (!phy_enc)
+ return;
+
+ atomic_inc(&phy_enc->underrun_cnt);
}
void sde_encoder_register_vblank_callback(struct drm_encoder *drm_enc,
@@ -838,6 +855,7 @@ static int sde_encoder_setup_display(struct sde_encoder_virt *sde_enc,
enum sde_intf_type intf_type;
struct sde_encoder_virt_ops parent_ops = {
sde_encoder_vblank_callback,
+ sde_encoder_underrun_callback,
sde_encoder_handle_phys_enc_ready_for_kickoff
};
struct sde_enc_phys_init_params phys_params;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index 3b379aee7dad..1171fcfb22f7 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -46,11 +46,16 @@ struct sde_encoder_phys;
* provides for the physical encoders to use to callback.
* @handle_vblank_virt: Notify virtual encoder of vblank IRQ reception
* Note: This is called from IRQ handler context.
+ * @handle_underrun_virt: Notify virtual encoder of underrun IRQ reception
+ * Note: This is called from IRQ handler context.
* @handle_ready_for_kickoff: Notify virtual encoder that this phys encoder
* is now ready for the next kickoff.
*/
struct sde_encoder_virt_ops {
- void (*handle_vblank_virt)(struct drm_encoder *);
+ void (*handle_vblank_virt)(struct drm_encoder *,
+ struct sde_encoder_phys *phys);
+ void (*handle_underrun_virt)(struct drm_encoder *,
+ struct sde_encoder_phys *phys);
void (*handle_ready_for_kickoff)(struct drm_encoder *,
struct sde_encoder_phys *phys);
};
@@ -123,6 +128,21 @@ enum sde_enc_enable_state {
};
/**
+ * enum sde_intr_idx - sde encoder interrupt index
+ * @INTR_IDX_VSYNC: Vsync interrupt for video 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_RDPTR: Readpointer done interrupt for cmd mode panel
+ */
+enum sde_intr_idx {
+ INTR_IDX_VSYNC,
+ INTR_IDX_PINGPONG,
+ INTR_IDX_UNDERRUN,
+ INTR_IDX_RDPTR,
+ INTR_IDX_MAX,
+};
+
+/**
* struct sde_encoder_phys - physical encoder that drives a single INTF block
* tied to a specific panel / sub-panel. Abstract type, sub-classed by
* phys_vid or phys_cmd for video mode or command mode encs respectively.
@@ -139,9 +159,12 @@ enum sde_enc_enable_state {
* @enabled: Whether the encoder has enabled and running a mode
* @split_role: Role to play in a split-panel configuration
* @intf_mode: Interface mode
+ * @intf_idx: Interface index on sde hardware
* @spin_lock: Lock for IRQ purposes
* @enable_state: Enable state tracking
* @vblank_refcount: Reference count of vblank request
+ * @vsync_cnt: Vsync count for the physical encoder
+ * @underrun_cnt: Underrun count for the physical encoder
*/
struct sde_encoder_phys {
struct drm_encoder *parent;
@@ -156,9 +179,12 @@ struct sde_encoder_phys {
struct drm_display_mode cached_mode;
enum sde_enc_split_role split_role;
enum sde_intf_mode intf_mode;
+ enum sde_intf intf_idx;
spinlock_t spin_lock;
enum sde_enc_enable_state enable_state;
atomic_t vblank_refcount;
+ atomic_t vsync_cnt;
+ atomic_t underrun_cnt;
};
/**
@@ -171,7 +197,7 @@ struct sde_encoder_phys {
*/
struct sde_encoder_phys_vid {
struct sde_encoder_phys base;
- int irq_idx;
+ int irq_idx[INTR_IDX_MAX];
struct sde_hw_intf *hw_intf;
struct completion vblank_completion;
};
@@ -199,8 +225,7 @@ struct sde_encoder_phys_cmd {
int intf_idx;
int stream_sel;
struct sde_hw_pingpong *hw_pp;
- int pp_rd_ptr_irq_idx;
- int pp_tx_done_irq_idx;
+ int irq_idx[INTR_IDX_MAX];
wait_queue_head_t pp_tx_done_wq;
atomic_t pending_cnt;
};
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
index 139285d66b10..2d93ad09e787 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -133,7 +133,8 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
wake_up_all(&cmd_enc->pp_tx_done_wq);
/* Trigger a pending flush */
- phys_enc->parent_ops.handle_ready_for_kickoff(phys_enc->parent,
+ if (phys_enc->parent_ops.handle_ready_for_kickoff)
+ phys_enc->parent_ops.handle_ready_for_kickoff(phys_enc->parent,
phys_enc);
}
@@ -145,15 +146,28 @@ static void sde_encoder_phys_cmd_pp_rd_ptr_irq(void *arg, int irq_idx)
if (!cmd_enc)
return;
- phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent);
+ if (phys_enc->parent_ops.handle_vblank_virt)
+ phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+ phys_enc);
}
-static int sde_encoder_phys_cmd_register_pp_irq(
- struct sde_encoder_phys *phys_enc,
- enum sde_intr_type intr_type,
- int *irq_idx,
- void (*irq_func)(void *, int),
- const char *irq_name)
+static void sde_encoder_phys_cmd_underrun_irq(void *arg, int irq_idx)
+{
+ struct sde_encoder_phys_cmd *cmd_enc = arg;
+ struct sde_encoder_phys *phys_enc;
+
+ if (!cmd_enc)
+ return;
+
+ phys_enc = &cmd_enc->base;
+ if (phys_enc->parent_ops.handle_underrun_virt)
+ phys_enc->parent_ops.handle_underrun_virt(phys_enc->parent,
+ phys_enc);
+}
+
+static int sde_encoder_phys_cmd_register_irq(struct sde_encoder_phys *phys_enc,
+ enum sde_intr_type intr_type, int *irq_idx,
+ void (*irq_func)(void *, int), const char *irq_name)
{
struct sde_encoder_phys_cmd *cmd_enc =
to_sde_encoder_phys_cmd(phys_enc);
@@ -208,7 +222,7 @@ static int sde_encoder_phys_cmd_register_pp_irq(
return ret;
}
-static int sde_encoder_phys_cmd_unregister_pp_irq(
+static int sde_encoder_phys_cmd_unregister_irq(
struct sde_encoder_phys *phys_enc,
int irq_idx)
{
@@ -381,7 +395,7 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
/* Slave encoders don't report vblank */
if (!sde_encoder_phys_cmd_is_master(phys_enc))
- return 0;
+ goto end;
SDE_DEBUG_CMDENC(cmd_enc, "[%pS] enable=%d/%d\n",
__builtin_return_address(0),
@@ -391,15 +405,25 @@ static int sde_encoder_phys_cmd_control_vblank_irq(
atomic_read(&phys_enc->vblank_refcount));
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
- ret = sde_encoder_phys_cmd_register_pp_irq(phys_enc,
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
SDE_IRQ_TYPE_PING_PONG_RD_PTR,
- &cmd_enc->pp_rd_ptr_irq_idx,
+ &cmd_enc->irq_idx[INTR_IDX_PINGPONG],
sde_encoder_phys_cmd_pp_rd_ptr_irq,
"pp_rd_ptr");
else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
- ret = sde_encoder_phys_cmd_unregister_pp_irq(phys_enc,
- cmd_enc->pp_rd_ptr_irq_idx);
-
+ ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_PINGPONG]);
+
+ if (enable)
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_PING_PONG_RD_PTR,
+ &cmd_enc->irq_idx[INTR_IDX_RDPTR],
+ sde_encoder_phys_cmd_pp_rd_ptr_irq, "pp_rd_ptr");
+ else
+ ret = sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_RDPTR]);
+
+end:
if (ret)
SDE_ERROR_CMDENC(cmd_enc,
"control vblank irq error %d, enable %d\n",
@@ -437,19 +461,30 @@ static void sde_encoder_phys_cmd_enable(struct sde_encoder_phys *phys_enc)
sde_encoder_phys_cmd_pingpong_config(phys_enc);
/* Both master and slave need to register for pp_tx_done */
- ret = sde_encoder_phys_cmd_register_pp_irq(phys_enc,
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
SDE_IRQ_TYPE_PING_PONG_COMP,
- &cmd_enc->pp_tx_done_irq_idx,
+ &cmd_enc->irq_idx[INTR_IDX_PINGPONG],
sde_encoder_phys_cmd_pp_tx_done_irq,
"pp_tx_done");
-
if (ret)
return;
ret = sde_encoder_phys_cmd_control_vblank_irq(phys_enc, true);
if (ret) {
- sde_encoder_phys_cmd_unregister_pp_irq(phys_enc,
- cmd_enc->pp_tx_done_irq_idx);
+ sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_PINGPONG]);
+ return;
+ }
+
+ ret = sde_encoder_phys_cmd_register_irq(phys_enc,
+ SDE_IRQ_TYPE_INTF_UNDER_RUN,
+ &cmd_enc->irq_idx[INTR_IDX_UNDERRUN],
+ sde_encoder_phys_cmd_underrun_irq,
+ "underrun");
+ if (ret) {
+ sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
+ sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_PINGPONG]);
return;
}
@@ -476,9 +511,11 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
if (WARN_ON(phys_enc->enable_state == SDE_ENC_DISABLED))
return;
- sde_encoder_phys_cmd_unregister_pp_irq(phys_enc,
- cmd_enc->pp_tx_done_irq_idx);
+ sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_UNDERRUN]);
sde_encoder_phys_cmd_control_vblank_irq(phys_enc, false);
+ sde_encoder_phys_cmd_unregister_irq(phys_enc,
+ cmd_enc->irq_idx[INTR_IDX_PINGPONG]);
atomic_set(&cmd_enc->pending_cnt, 0);
wake_up_all(&cmd_enc->pp_tx_done_wq);
@@ -604,6 +641,7 @@ struct sde_encoder_phys *sde_encoder_phys_cmd_init(
phys_enc->hw_mdptop = hw_mdp;
cmd_enc->intf_idx = p->intf_idx;
+ phys_enc->intf_idx = p->intf_idx;
sde_encoder_phys_cmd_init_ops(&phys_enc->ops);
phys_enc->parent = p->parent;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
index 9289d5fa2e33..49712c33a5bc 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_vid.c
@@ -308,12 +308,28 @@ static void sde_encoder_phys_vid_vblank_irq(void *arg, int irq_idx)
return;
phys_enc = &vid_enc->base;
- phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent);
+ if (phys_enc->parent_ops.handle_vblank_virt)
+ phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+ phys_enc);
/* signal VBLANK completion */
complete_all(&vid_enc->vblank_completion);
}
+static void sde_encoder_phys_vid_underrun_irq(void *arg, int irq_idx)
+{
+ struct sde_encoder_phys_vid *vid_enc = arg;
+ struct sde_encoder_phys *phys_enc;
+
+ if (!vid_enc)
+ return;
+
+ phys_enc = &vid_enc->base;
+ if (phys_enc->parent_ops.handle_underrun_virt)
+ phys_enc->parent_ops.handle_underrun_virt(phys_enc->parent,
+ phys_enc);
+}
+
static bool sde_encoder_phys_vid_needs_split_flush(
struct sde_encoder_phys *phys_enc)
{
@@ -346,7 +362,9 @@ static void _sde_encoder_phys_vid_split_config(
}
}
-static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc)
+static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc,
+ enum sde_intr_type intr_type, int *irq_idx,
+ void (*irq_func)(void *, int), const char *irq_name)
{
struct sde_encoder_phys_vid *vid_enc =
to_sde_encoder_phys_vid(phys_enc);
@@ -358,59 +376,62 @@ static int sde_encoder_phys_vid_register_irq(struct sde_encoder_phys *phys_enc)
return -EINVAL;
}
- vid_enc->irq_idx = sde_core_irq_idx_lookup(phys_enc->sde_kms,
- SDE_IRQ_TYPE_INTF_VSYNC, vid_enc->hw_intf->idx);
- if (vid_enc->irq_idx < 0) {
+ *irq_idx = sde_core_irq_idx_lookup(phys_enc->sde_kms, intr_type,
+ vid_enc->hw_intf->idx);
+ if (*irq_idx < 0) {
SDE_ERROR_VIDENC(vid_enc,
- "failed to lookup IRQ index for INTF_VSYNC\n");
+ "failed to lookup IRQ index for %s type:%d\n", irq_name,
+ intr_type);
return -EINVAL;
}
- irq_cb.func = sde_encoder_phys_vid_vblank_irq;
+ irq_cb.func = irq_func;
irq_cb.arg = vid_enc;
- ret = sde_core_irq_register_callback(phys_enc->sde_kms,
- vid_enc->irq_idx, &irq_cb);
+ ret = sde_core_irq_register_callback(phys_enc->sde_kms, *irq_idx,
+ &irq_cb);
if (ret) {
SDE_ERROR_VIDENC(vid_enc,
- "failed to register IRQ callback INTF_VSYNC");
+ "failed to register IRQ callback for %s\n", irq_name);
return ret;
}
- ret = sde_core_irq_enable(phys_enc->sde_kms, &vid_enc->irq_idx, 1);
+ ret = sde_core_irq_enable(phys_enc->sde_kms, irq_idx, true);
if (ret) {
SDE_ERROR_VIDENC(vid_enc,
- "enable IRQ for INTF_VSYNC failed, irq_idx %d\n",
- vid_enc->irq_idx);
- vid_enc->irq_idx = -EINVAL;
+ "enable IRQ for intr:%s failed, irq_idx %d\n",
+ irq_name, *irq_idx);
+ *irq_idx = -EINVAL;
- /* Unregister callback on IRQ enable failure */
+ /* unregister callback on IRQ enable failure */
sde_core_irq_register_callback(phys_enc->sde_kms,
- vid_enc->irq_idx, NULL);
+ *irq_idx, NULL);
return ret;
}
- SDE_DEBUG_VIDENC(vid_enc, "registered %d\n", vid_enc->irq_idx);
+ SDE_DEBUG_VIDENC(vid_enc, "registered irq %s idx: %d\n",
+ irq_name, *irq_idx);
return ret;
}
static int sde_encoder_phys_vid_unregister_irq(
- struct sde_encoder_phys *phys_enc)
+ struct sde_encoder_phys *phys_enc, int irq_idx)
{
struct sde_encoder_phys_vid *vid_enc =
to_sde_encoder_phys_vid(phys_enc);
if (!phys_enc) {
SDE_ERROR("invalid encoder\n");
- return -EINVAL;
+ goto end;
}
- sde_core_irq_register_callback(phys_enc->sde_kms, vid_enc->irq_idx,
- NULL);
- sde_core_irq_disable(phys_enc->sde_kms, &vid_enc->irq_idx, 1);
+ sde_core_irq_disable(phys_enc->sde_kms, &irq_idx, 1);
+
+ sde_core_irq_register_callback(phys_enc->sde_kms, irq_idx, NULL);
- SDE_DEBUG_VIDENC(vid_enc, "unregistered %d\n", vid_enc->irq_idx);
+ SDE_DEBUG_VIDENC(vid_enc, "unregistered %d\n", irq_idx);
+end:
return 0;
}
@@ -477,9 +498,13 @@ static int sde_encoder_phys_vid_control_vblank_irq(
atomic_read(&phys_enc->vblank_refcount));
if (enable && atomic_inc_return(&phys_enc->vblank_refcount) == 1)
- ret = sde_encoder_phys_vid_register_irq(phys_enc);
+ ret = sde_encoder_phys_vid_register_irq(phys_enc,
+ SDE_IRQ_TYPE_INTF_VSYNC,
+ &vid_enc->irq_idx[INTR_IDX_VSYNC],
+ sde_encoder_phys_vid_vblank_irq, "vsync_irq");
else if (!enable && atomic_dec_return(&phys_enc->vblank_refcount) == 0)
- ret = sde_encoder_phys_vid_unregister_irq(phys_enc);
+ ret = sde_encoder_phys_vid_unregister_irq(phys_enc,
+ vid_enc->irq_idx[INTR_IDX_VSYNC]);
if (ret)
SDE_ERROR_VIDENC(vid_enc,
@@ -496,6 +521,7 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc)
struct sde_hw_intf *intf = vid_enc->hw_intf;
struct sde_hw_ctl *ctl = phys_enc->hw_ctl;
u32 flush_mask = 0;
+ int ret;
if (!phys_enc) {
SDE_ERROR("invalid encoder\n");
@@ -517,7 +543,18 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc)
_sde_encoder_phys_vid_split_config(phys_enc, false);
sde_encoder_phys_vid_setup_timing_engine(phys_enc);
- sde_encoder_phys_vid_control_vblank_irq(phys_enc, true);
+ ret = sde_encoder_phys_vid_control_vblank_irq(phys_enc, true);
+ if (ret)
+ goto end;
+
+ ret = sde_encoder_phys_vid_register_irq(phys_enc,
+ SDE_IRQ_TYPE_INTF_UNDER_RUN,
+ &vid_enc->irq_idx[INTR_IDX_UNDERRUN],
+ sde_encoder_phys_vid_underrun_irq, "underrun");
+ if (ret) {
+ sde_encoder_phys_vid_control_vblank_irq(phys_enc, false);
+ goto end;
+ }
ctl->ops.get_bitmask_intf(ctl, &flush_mask, intf->idx);
ctl->ops.update_pending_flush(ctl, flush_mask);
@@ -528,6 +565,9 @@ static void sde_encoder_phys_vid_enable(struct sde_encoder_phys *phys_enc)
/* ctl_flush & timing engine enable will be triggered by framework */
if (phys_enc->enable_state == SDE_ENC_DISABLED)
phys_enc->enable_state = SDE_ENC_ENABLING;
+
+end:
+ return;
}
static void sde_encoder_phys_vid_disable(struct sde_encoder_phys *phys_enc)
@@ -717,7 +757,6 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
ret = -ENOMEM;
goto fail;
}
- vid_enc->irq_idx = -EINVAL;
init_completion(&vid_enc->vblank_completion);
phys_enc = &vid_enc->base;
@@ -729,6 +768,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
goto fail;
}
phys_enc->hw_mdptop = hw_mdp;
+ phys_enc->intf_idx = p->intf_idx;
/**
* hw_intf resource permanently assigned to this encoder
@@ -763,7 +803,7 @@ struct sde_encoder_phys *sde_encoder_phys_vid_init(
atomic_set(&phys_enc->vblank_refcount, 0);
phys_enc->enable_state = SDE_ENC_DISABLED;
- SDE_DEBUG_VIDENC(vid_enc, "created\n");
+ SDE_DEBUG_VIDENC(vid_enc, "created intf idx:%d\n", p->intf_idx);
return phys_enc;
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
index eb77169ac54d..eb854916c05e 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_wb.c
@@ -543,7 +543,8 @@ static void sde_encoder_phys_wb_done_irq(void *arg, int irq_idx)
complete_all(&wb_enc->wbdone_complete);
- phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent);
+ phys_enc->parent_ops.handle_vblank_virt(phys_enc->parent,
+ phys_enc);
}
/**
@@ -1067,6 +1068,7 @@ struct sde_encoder_phys *sde_encoder_phys_wb_init(
phys_enc->sde_kms = p->sde_kms;
phys_enc->split_role = p->split_role;
phys_enc->intf_mode = INTF_MODE_WB_LINE;
+ phys_enc->intf_idx = p->intf_idx;
spin_lock_init(&phys_enc->spin_lock);
ret = sde_encoder_phys_wb_init_debugfs(phys_enc, p->sde_kms);