summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJeykumar Sankaran <jsanka@codeaurora.org>2016-11-02 12:34:29 -0700
committerJeykumar Sankaran <jsanka@codeaurora.org>2016-11-10 14:56:54 -0800
commitb8811d64d847539dca50833e9159ec897e01868e (patch)
treeb482a32f730a2737ee4d735b3d8f47ff4a9b8316
parent66f38a4e0a00b35a60edc3a84a5d1104ca2c63ff (diff)
drm/msm/sde: handle pingpong blocks from virtual encoder
Pingpong blocks are needed for both video and command mode panels for supporting DSC compression. DSC programming requires modifying registers in pingpong block. Pingpong blocks need not necessarily be mapped 1-to-1 with interfaces for DSC merge and 3D Mux topologies. This change stores and maintains the HW pingpong blocks from virtual encoder. Change-Id: I2e31c6a9d31e0142eb83df956aa70b425a1e6d7e Signed-off-by: Jeykumar Sankaran <jsanka@codeaurora.org>
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder.c20
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys.h4
-rw-r--r--drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c59
3 files changed, 43 insertions, 40 deletions
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder.c b/drivers/gpu/drm/msm/sde/sde_encoder.c
index b4757add7dae..37daea0b9f41 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder.c
@@ -43,6 +43,8 @@
#define MAX_PHYS_ENCODERS_PER_VIRTUAL \
(MAX_H_TILES_PER_DISPLAY * NUM_PHYS_ENCODER_TYPES)
+#define MAX_CHANNELS_PER_ENC 2
+
/* Wait timeout sized on worst case of 4 60fps frames ~= 67ms */
#define WAIT_TIMEOUT_MSEC 67
@@ -59,6 +61,8 @@
* @phys_encs: Container of physical encoders managed.
* @cur_master: Pointer to the current master in this mode. Optimization
* Only valid after enable. Cleared as disable.
+ * @hw_pp Handle to the pingpong blocks used for the display. No.
+ * pingpong blocks can be different than num_phys_encs.
* @crtc_vblank_cb: Callback into the upper layer / CRTC for
* notification of the VBLANK
* @crtc_vblank_cb_data: Data from upper layer for VBLANK notification
@@ -89,6 +93,7 @@ struct sde_encoder_virt {
unsigned int num_phys_encs;
struct sde_encoder_phys *phys_encs[MAX_PHYS_ENCODERS_PER_VIRTUAL];
struct sde_encoder_phys *cur_master;
+ struct sde_hw_pingpong *hw_pp[MAX_CHANNELS_PER_ENC];
void (*crtc_vblank_cb)(void *);
void *crtc_vblank_cb_data;
@@ -326,6 +331,7 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
struct sde_kms *sde_kms;
struct list_head *connector_list;
struct drm_connector *conn = NULL, *conn_iter;
+ struct sde_rm_hw_iter pp_iter;
int i = 0, ret;
if (!drm_enc) {
@@ -363,10 +369,24 @@ static void sde_encoder_virt_mode_set(struct drm_encoder *drm_enc,
return;
}
+ sde_rm_init_hw_iter(&pp_iter, drm_enc->base.id, SDE_HW_BLK_PINGPONG);
+ for (i = 0; i < MAX_CHANNELS_PER_ENC; i++) {
+ sde_enc->hw_pp[i] = NULL;
+ if (!sde_rm_get_hw(&sde_kms->rm, &pp_iter))
+ break;
+ sde_enc->hw_pp[i] = (struct sde_hw_pingpong *) pp_iter.hw;
+ }
+
for (i = 0; i < sde_enc->num_phys_encs; i++) {
struct sde_encoder_phys *phys = sde_enc->phys_encs[i];
if (phys) {
+ if (!sde_enc->hw_pp[i]) {
+ SDE_ERROR_ENC(sde_enc,
+ "invalid pingpong block for the encoder\n");
+ return;
+ }
+ phys->hw_pp = sde_enc->hw_pp[i];
phys->connector = conn->state->connector;
if (phys->ops.mode_set)
phys->ops.mode_set(phys, mode, adj_mode);
diff --git a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
index b9761940786f..5dc0b290ef13 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys.h
@@ -154,6 +154,7 @@ enum sde_intr_idx {
* @hw_ctl: Hardware interface to the ctl registers
* @hw_cdm: Hardware interface to the cdm registers
* @cdm_cfg: Chroma-down hardware configuration
+ * @hw_pp: Hardware interface to the ping pong registers
* @sde_kms: Pointer to the sde_kms top level
* @cached_mode: DRM mode cached at mode_set time, acted on in enable
* @enabled: Whether the encoder has enabled and running a mode
@@ -175,6 +176,7 @@ struct sde_encoder_phys {
struct sde_hw_ctl *hw_ctl;
struct sde_hw_cdm *hw_cdm;
struct sde_hw_cdm_cfg cdm_cfg;
+ struct sde_hw_pingpong *hw_pp;
struct sde_kms *sde_kms;
struct drm_display_mode cached_mode;
enum sde_enc_split_role split_role;
@@ -210,7 +212,6 @@ struct sde_encoder_phys_vid {
* @base: Baseclass physical encoder structure
* @intf_idx: Intf Block index used by this phys encoder
* @stream_sel: Stream selection for multi-stream interfaces
- * @hw_pp: Hardware interface to the ping pong registers
* @pp_rd_ptr_irq_idx: IRQ signifying panel's frame read pointer
* For CMD encoders, VBLANK is driven by the PP RD Done IRQ
* @pp_tx_done_irq_idx: IRQ signifying frame transmission to panel complete
@@ -227,7 +228,6 @@ struct sde_encoder_phys_cmd {
struct sde_encoder_phys base;
int intf_idx;
int stream_sel;
- struct sde_hw_pingpong *hw_pp;
int irq_idx[INTR_IDX_MAX];
struct sde_irq_callback irq_cb[INTR_IDX_MAX];
wait_queue_head_t pp_tx_done_wq;
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 bdd9239fed95..24e85289fae8 100644
--- a/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
+++ b/drivers/gpu/drm/msm/sde/sde_encoder_phys_cmd.c
@@ -98,23 +98,6 @@ static void sde_encoder_phys_cmd_mode_set(
phys_enc->hw_ctl = NULL;
return;
}
-
- sde_rm_init_hw_iter(&iter, phys_enc->parent->base.id,
- SDE_HW_BLK_PINGPONG);
- for (i = 0; i <= instance; i++) {
- sde_rm_get_hw(rm, &iter);
- if (i == instance)
- cmd_enc->hw_pp = (struct sde_hw_pingpong *) iter.hw;
- }
-
- if (IS_ERR_OR_NULL(cmd_enc->hw_pp)) {
- SDE_ERROR_CMDENC(cmd_enc, "failed to init pingpong: %ld\n",
- PTR_ERR(cmd_enc->hw_pp));
- cmd_enc->hw_pp = NULL;
- phys_enc->hw_ctl = NULL;
- return;
- }
-
}
static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
@@ -128,7 +111,7 @@ static void sde_encoder_phys_cmd_pp_tx_done_irq(void *arg, int irq_idx)
phys_enc = &cmd_enc->base;
new_pending_cnt = atomic_dec_return(&cmd_enc->pending_cnt);
- MSM_EVT(DEV(phys_enc), cmd_enc->hw_pp->idx, new_pending_cnt);
+ MSM_EVT(DEV(phys_enc), phys_enc->hw_pp->idx, new_pending_cnt);
/* Signal any waiting atomic commit thread */
wake_up_all(&cmd_enc->pp_tx_done_wq);
@@ -180,12 +163,12 @@ static int sde_encoder_phys_cmd_register_irq(struct sde_encoder_phys *phys_enc,
}
cmd_enc->irq_idx[idx] = sde_core_irq_idx_lookup(phys_enc->sde_kms,
- intr_type, cmd_enc->hw_pp->idx);
+ intr_type, phys_enc->hw_pp->idx);
if (cmd_enc->irq_idx[idx] < 0) {
SDE_ERROR_CMDENC(cmd_enc,
"failed to lookup IRQ index for %s with pp=%d\n",
irq_name,
- cmd_enc->hw_pp->idx - PINGPONG_0);
+ phys_enc->hw_pp->idx - PINGPONG_0);
return -EINVAL;
}
@@ -205,7 +188,7 @@ static int sde_encoder_phys_cmd_register_irq(struct sde_encoder_phys *phys_enc,
SDE_ERROR_CMDENC(cmd_enc,
"failed to enable IRQ for %s, pp %d, irq_idx %d\n",
irq_name,
- cmd_enc->hw_pp->idx - PINGPONG_0,
+ phys_enc->hw_pp->idx - PINGPONG_0,
cmd_enc->irq_idx[idx]);
cmd_enc->irq_idx[idx] = -EINVAL;
@@ -217,7 +200,7 @@ static int sde_encoder_phys_cmd_register_irq(struct sde_encoder_phys *phys_enc,
SDE_DEBUG_CMDENC(cmd_enc, "registered IRQ %s for pp %d, irq_idx %d\n",
irq_name,
- cmd_enc->hw_pp->idx - PINGPONG_0,
+ phys_enc->hw_pp->idx - PINGPONG_0,
cmd_enc->irq_idx[idx]);
return ret;
@@ -239,7 +222,7 @@ static int sde_encoder_phys_cmd_unregister_irq(
cmd_enc->irq_idx[idx], &cmd_enc->irq_cb[idx]);
SDE_DEBUG_CMDENC(cmd_enc, "unregistered IRQ for pp %d, irq_idx %d\n",
- cmd_enc->hw_pp->idx - PINGPONG_0,
+ phys_enc->hw_pp->idx - PINGPONG_0,
cmd_enc->irq_idx[idx]);
return 0;
@@ -262,10 +245,10 @@ static void sde_encoder_phys_cmd_tearcheck_config(
return;
}
- SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", cmd_enc->hw_pp->idx - PINGPONG_0);
+ SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
- if (!cmd_enc->hw_pp->ops.setup_tearcheck ||
- !cmd_enc->hw_pp->ops.enable_tearcheck) {
+ if (!phys_enc->hw_pp->ops.setup_tearcheck ||
+ !phys_enc->hw_pp->ops.enable_tearcheck) {
SDE_DEBUG_CMDENC(cmd_enc, "tearcheck not supported\n");
return;
}
@@ -304,23 +287,23 @@ static void sde_encoder_phys_cmd_tearcheck_config(
SDE_DEBUG_CMDENC(cmd_enc,
"tc %d vsync_clk_speed_hz %u vtotal %u vrefresh %u\n",
- cmd_enc->hw_pp->idx - PINGPONG_0, vsync_hz,
+ phys_enc->hw_pp->idx - PINGPONG_0, vsync_hz,
mode->vtotal, mode->vrefresh);
SDE_DEBUG_CMDENC(cmd_enc,
"tc %d enable %u start_pos %u rd_ptr_irq %u\n",
- cmd_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos,
+ phys_enc->hw_pp->idx - PINGPONG_0, tc_enable, tc_cfg.start_pos,
tc_cfg.rd_ptr_irq);
SDE_DEBUG_CMDENC(cmd_enc,
"tc %d hw_vsync_mode %u vsync_count %u vsync_init_val %u\n",
- cmd_enc->hw_pp->idx - PINGPONG_0, tc_cfg.hw_vsync_mode,
+ phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.hw_vsync_mode,
tc_cfg.vsync_count, tc_cfg.vsync_init_val);
SDE_DEBUG_CMDENC(cmd_enc,
"tc %d cfgheight %u thresh_start %u thresh_cont %u\n",
- cmd_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height,
+ phys_enc->hw_pp->idx - PINGPONG_0, tc_cfg.sync_cfg_height,
tc_cfg.sync_threshold_start, tc_cfg.sync_threshold_continue);
- cmd_enc->hw_pp->ops.setup_tearcheck(cmd_enc->hw_pp, &tc_cfg);
- cmd_enc->hw_pp->ops.enable_tearcheck(cmd_enc->hw_pp, tc_enable);
+ phys_enc->hw_pp->ops.setup_tearcheck(phys_enc->hw_pp, &tc_cfg);
+ phys_enc->hw_pp->ops.enable_tearcheck(phys_enc->hw_pp, tc_enable);
}
static void sde_encoder_phys_cmd_pingpong_config(
@@ -337,7 +320,7 @@ static void sde_encoder_phys_cmd_pingpong_config(
}
SDE_DEBUG_CMDENC(cmd_enc, "pp %d, enabling mode:\n",
- cmd_enc->hw_pp->idx - PINGPONG_0);
+ phys_enc->hw_pp->idx - PINGPONG_0);
drm_mode_debug_printmodeline(&phys_enc->cached_mode);
intf_cfg.intf = cmd_enc->intf_idx;
@@ -444,7 +427,7 @@ static void sde_encoder_phys_cmd_enable(struct sde_encoder_phys *phys_enc)
SDE_ERROR("invalid encoder\n");
return;
}
- SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", cmd_enc->hw_pp->idx - PINGPONG_0);
+ SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
if (WARN_ON(phys_enc->enable_state == SDE_ENC_ENABLED))
return;
@@ -506,7 +489,7 @@ static void sde_encoder_phys_cmd_disable(struct sde_encoder_phys *phys_enc)
SDE_ERROR("invalid encoder\n");
return;
}
- SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", cmd_enc->hw_pp->idx - PINGPONG_0);
+ SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
if (WARN_ON(phys_enc->enable_state == SDE_ENC_DISABLED))
return;
@@ -578,7 +561,7 @@ static void sde_encoder_phys_cmd_prepare_for_kickoff(
SDE_ERROR("invalid encoder\n");
return;
}
- SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", cmd_enc->hw_pp->idx - PINGPONG_0);
+ SDE_DEBUG_CMDENC(cmd_enc, "pp %d\n", phys_enc->hw_pp->idx - PINGPONG_0);
/*
* Mark kickoff request as outstanding. If there are more than one,
@@ -590,9 +573,9 @@ static void sde_encoder_phys_cmd_prepare_for_kickoff(
if (*need_to_wait)
SDE_DEBUG_CMDENC(cmd_enc,
"pp %d needs to wait, new_pending_cnt %d",
- cmd_enc->hw_pp->idx - PINGPONG_0,
+ phys_enc->hw_pp->idx - PINGPONG_0,
new_pending_cnt);
- MSM_EVT(DEV(phys_enc), cmd_enc->hw_pp->idx, new_pending_cnt);
+ MSM_EVT(DEV(phys_enc), phys_enc->hw_pp->idx, new_pending_cnt);
}
static void sde_encoder_phys_cmd_init_ops(